1 /*
2 * lib/socket.c Netlink Socket
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation version 2.1
7 * of the License.
8 *
9 * Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
10 */
11
12 /**
13 * @ingroup core_types
14 * @defgroup socket Socket
15 *
16 * Representation of a netlink socket
17 *
18 * Related sections in the development guide:
19 * - @core_doc{core_sockets, Netlink Sockets}
20 *
21 * @{
22 *
23 * Header
24 * ------
25 * ~~~~{.c}
26 * #include <netlink/socket.h>
27 * ~~~~
28 */
29
30 #include "defs.h"
31
32 #include <netlink-private/netlink.h>
33 #include <netlink-private/socket.h>
34 #include <netlink/netlink.h>
35 #include <netlink/utils.h>
36 #include <netlink/handlers.h>
37 #include <netlink/msg.h>
38 #include <netlink/attr.h>
39
40 static int default_cb = NL_CB_DEFAULT;
41
init_default_cb(void)42 static void __init init_default_cb(void)
43 {
44 char *nlcb;
45
46 if ((nlcb = getenv("NLCB"))) {
47 if (!strcasecmp(nlcb, "default"))
48 default_cb = NL_CB_DEFAULT;
49 else if (!strcasecmp(nlcb, "verbose"))
50 default_cb = NL_CB_VERBOSE;
51 else if (!strcasecmp(nlcb, "debug"))
52 default_cb = NL_CB_DEBUG;
53 else {
54 fprintf(stderr, "Unknown value for NLCB, valid values: "
55 "{default | verbose | debug}\n");
56 }
57 }
58 }
59
60 static uint32_t used_ports_map[32];
61 static NL_RW_LOCK(port_map_lock);
62
generate_local_port(void)63 static uint32_t generate_local_port(void)
64 {
65 int i, j, n, m;
66 static uint16_t idx_state = 0;
67 uint32_t pid = getpid() & 0x3FFFFF;
68
69 nl_write_lock(&port_map_lock);
70
71 if (idx_state == 0) {
72 uint32_t t = time(NULL);
73
74 /* from time to time (on average each 2^15 calls), the idx_state will
75 * be zero again. No problem, just "seed" anew with time(). */
76 idx_state = t ^ (t >> 16) ^ 0x3047;
77 } else
78 idx_state = idx_state + 20011; /* add prime number */
79
80 i = idx_state >> 5;
81 n = idx_state;
82 for (j = 0; j < 32; j++) {
83 /* walk the index somewhat randomized, with always leaving the block
84 * #0 as last. The reason is that libnl-1 will start at block #0,
85 * so just leave the first 32 ports preferably for libnl-1 owned sockets
86 * (this is relevant only if the applications ends up using both versions
87 * of the library and doesn't hurt otherwise). */
88 if (j == 31)
89 i = 0;
90 else
91 i = (((i-1) + 7) % 31) + 1;
92
93 if (used_ports_map[i] == 0xFFFFFFFF)
94 continue;
95
96 for (m = 0; m < 32; m++) {
97 n = (n + 13) % 32;
98 if (1UL & (used_ports_map[i] >> n))
99 continue;
100
101 used_ports_map[i] |= (1UL << n);
102 n += (i * 32);
103
104 /* PID_MAX_LIMIT is currently at 2^22, leaving 10 bit
105 * to, i.e. 1024 unique ports per application. */
106
107 nl_write_unlock(&port_map_lock);
108
109 return pid + (((uint32_t)n) << 22);
110 }
111 }
112
113 nl_write_unlock(&port_map_lock);
114
115 /* Out of sockets in our own PID namespace, what to do? FIXME */
116 NL_DBG(1, "Warning: Ran out of unique local port namespace\n");
117 return UINT32_MAX;
118 }
119
release_local_port(uint32_t port)120 static void release_local_port(uint32_t port)
121 {
122 int nr;
123 uint32_t mask;
124
125 if (port == UINT32_MAX)
126 return;
127
128 BUG_ON(port == 0);
129
130 nr = port >> 22;
131 mask = 1UL << (nr % 32);
132 nr /= 32;
133
134 nl_write_lock(&port_map_lock);
135 BUG_ON((used_ports_map[nr] & mask) != mask);
136 used_ports_map[nr] &= ~mask;
137 nl_write_unlock(&port_map_lock);
138 }
139
140 /** \cond skip */
_nl_socket_used_ports_release_all(const uint32_t * used_ports)141 void _nl_socket_used_ports_release_all(const uint32_t *used_ports)
142 {
143 int i;
144
145 for (i = 0; i < 32; i++) {
146 if (used_ports[i] != 0) {
147 nl_write_lock(&port_map_lock);
148 for (; i < 32; i++) {
149 BUG_ON((used_ports_map[i] & used_ports[i]) != used_ports[i]);
150 used_ports_map[i] &= ~(used_ports[i]);
151 }
152 nl_write_unlock(&port_map_lock);
153 return;
154 }
155 }
156 }
157
_nl_socket_used_ports_set(uint32_t * used_ports,uint32_t port)158 void _nl_socket_used_ports_set(uint32_t *used_ports, uint32_t port)
159 {
160 int nr;
161 int32_t mask;
162
163 nr = port >> 22;
164 mask = 1UL << (nr % 32);
165 nr /= 32;
166
167 /*
168 BUG_ON(port == UINT32_MAX || port == 0 || (getpid() & 0x3FFFFF) != (port & 0x3FFFFF));
169 BUG_ON(used_ports[nr] & mask);
170 */
171
172 used_ports[nr] |= mask;
173 }
174 /** \endcond */
175
176 /**
177 * @name Allocation
178 * @{
179 */
180
__alloc_socket(struct nl_cb * cb)181 static struct nl_sock *__alloc_socket(struct nl_cb *cb)
182 {
183 struct nl_sock *sk;
184
185 sk = calloc(1, sizeof(*sk));
186 if (!sk)
187 return NULL;
188
189 sk->s_fd = -1;
190 sk->s_cb = nl_cb_get(cb);
191 sk->s_local.nl_family = AF_NETLINK;
192 sk->s_peer.nl_family = AF_NETLINK;
193 sk->s_seq_expect = sk->s_seq_next = time(0);
194
195 /* the port is 0 (unspecified), meaning NL_OWN_PORT */
196 sk->s_flags = NL_OWN_PORT;
197
198 return sk;
199 }
200
201 /**
202 * Allocate new netlink socket
203 *
204 * @return Newly allocated netlink socket or NULL.
205 */
nl_socket_alloc(void)206 struct nl_sock *nl_socket_alloc(void)
207 {
208 struct nl_cb *cb;
209 struct nl_sock *sk;
210
211 cb = nl_cb_alloc(default_cb);
212 if (!cb)
213 return NULL;
214
215 /* will increment cb reference count on success */
216 sk = __alloc_socket(cb);
217
218 nl_cb_put(cb);
219
220 return sk;
221 }
222
223 /**
224 * Allocate new socket with custom callbacks
225 * @arg cb Callback handler
226 *
227 * The reference to the callback handler is taken into account
228 * automatically, it is released again upon calling nl_socket_free().
229 *
230 *@return Newly allocted socket handle or NULL.
231 */
nl_socket_alloc_cb(struct nl_cb * cb)232 struct nl_sock *nl_socket_alloc_cb(struct nl_cb *cb)
233 {
234 if (cb == NULL)
235 BUG();
236
237 return __alloc_socket(cb);
238 }
239
240 /**
241 * Free a netlink socket.
242 * @arg sk Netlink socket.
243 */
nl_socket_free(struct nl_sock * sk)244 void nl_socket_free(struct nl_sock *sk)
245 {
246 if (!sk)
247 return;
248
249 if (sk->s_fd >= 0)
250 close(sk->s_fd);
251
252 if (!(sk->s_flags & NL_OWN_PORT))
253 release_local_port(sk->s_local.nl_pid);
254
255 nl_cb_put(sk->s_cb);
256 free(sk);
257 }
258
259 /** @} */
260
261 /**
262 * @name Sequence Numbers
263 * @{
264 */
265
noop_seq_check(struct nl_msg * msg,void * arg)266 static int noop_seq_check(struct nl_msg *msg, void *arg)
267 {
268 return NL_OK;
269 }
270
271
272 /**
273 * Disable sequence number checking.
274 * @arg sk Netlink socket.
275 *
276 * Disables checking of sequence numbers on the netlink socket This is
277 * required to allow messages to be processed which were not requested by
278 * a preceding request message, e.g. netlink events.
279 *
280 * @note This function modifies the NL_CB_SEQ_CHECK configuration in
281 * the callback handle associated with the socket.
282 */
nl_socket_disable_seq_check(struct nl_sock * sk)283 void nl_socket_disable_seq_check(struct nl_sock *sk)
284 {
285 nl_cb_set(sk->s_cb, NL_CB_SEQ_CHECK,
286 NL_CB_CUSTOM, noop_seq_check, NULL);
287 }
288
289 /**
290 * Use next sequence number
291 * @arg sk Netlink socket.
292 *
293 * Uses the next available sequence number and increases the counter
294 * by one for subsequent calls.
295 *
296 * @return Unique serial sequence number
297 */
nl_socket_use_seq(struct nl_sock * sk)298 unsigned int nl_socket_use_seq(struct nl_sock *sk)
299 {
300 return sk->s_seq_next++;
301 }
302
303 /**
304 * Disable automatic request for ACK
305 * @arg sk Netlink socket.
306 *
307 * The default behaviour of a socket is to request an ACK for
308 * each message sent to allow for the caller to synchronize to
309 * the completion of the netlink operation. This function
310 * disables this behaviour and will result in requests being
311 * sent which will not have the NLM_F_ACK flag set automatically.
312 * However, it is still possible for the caller to set the
313 * NLM_F_ACK flag explicitely.
314 */
nl_socket_disable_auto_ack(struct nl_sock * sk)315 void nl_socket_disable_auto_ack(struct nl_sock *sk)
316 {
317 sk->s_flags |= NL_NO_AUTO_ACK;
318 }
319
320 /**
321 * Enable automatic request for ACK (default)
322 * @arg sk Netlink socket.
323 * @see nl_socket_disable_auto_ack
324 */
nl_socket_enable_auto_ack(struct nl_sock * sk)325 void nl_socket_enable_auto_ack(struct nl_sock *sk)
326 {
327 sk->s_flags &= ~NL_NO_AUTO_ACK;
328 }
329
330 /** @} */
331
332 /** \cond skip */
_nl_socket_is_local_port_unspecified(struct nl_sock * sk)333 int _nl_socket_is_local_port_unspecified(struct nl_sock *sk)
334 {
335 return (sk->s_local.nl_pid == 0);
336 }
337
_nl_socket_generate_local_port_no_release(struct nl_sock * sk)338 uint32_t _nl_socket_generate_local_port_no_release(struct nl_sock *sk)
339 {
340 uint32_t port;
341
342 /* reset the port to generate_local_port(), but do not release
343 * the previously generated port. */
344
345 port = generate_local_port();
346 sk->s_flags &= ~NL_OWN_PORT;
347 sk->s_local.nl_pid = port;
348 return port;
349 }
350 /** \endcond */
351
352 /**
353 * @name Source Idenficiation
354 * @{
355 */
356
nl_socket_get_local_port(const struct nl_sock * sk)357 uint32_t nl_socket_get_local_port(const struct nl_sock *sk)
358 {
359 if (sk->s_local.nl_pid == 0) {
360 /* modify the const argument sk. This is justified, because
361 * nobody ever saw the local_port from externally. So, we
362 * initilize it on first use.
363 *
364 * Note that this also means that you cannot call this function
365 * from multiple threads without synchronization. But nl_sock
366 * is not automatically threadsafe anyway, so the user is not
367 * allowed to do that.
368 */
369 return _nl_socket_generate_local_port_no_release((struct nl_sock *) sk);
370 }
371 return sk->s_local.nl_pid;
372 }
373
374 /**
375 * Set local port of socket
376 * @arg sk Netlink socket.
377 * @arg port Local port identifier
378 *
379 * Assigns a local port identifier to the socket.
380 *
381 * If port is 0, the port is reset to 'unspecified' as it is after newly
382 * calling nl_socket_alloc().
383 * Unspecified means, that the port will be generated automatically later
384 * on first use (either on nl_socket_get_local_port() or nl_connect()).
385 */
nl_socket_set_local_port(struct nl_sock * sk,uint32_t port)386 void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port)
387 {
388 if (!(sk->s_flags & NL_OWN_PORT))
389 release_local_port(sk->s_local.nl_pid);
390 sk->s_flags |= NL_OWN_PORT;
391 sk->s_local.nl_pid = port;
392 }
393
394 /** @} */
395
396 /**
397 * @name Group Subscriptions
398 * @{
399 */
400
401 /**
402 * Join groups
403 * @arg sk Netlink socket
404 * @arg group Group identifier
405 *
406 * Joins the specified groups using the modern socket option which
407 * is available since kernel version 2.6.14. It allows joining an
408 * almost arbitary number of groups without limitation. The list
409 * of groups has to be terminated by 0 (%NFNLGRP_NONE).
410 *
411 * Make sure to use the correct group definitions as the older
412 * bitmask definitions for nl_join_groups() are likely to still
413 * be present for backward compatibility reasons.
414 *
415 * @return 0 on sucess or a negative error code.
416 */
nl_socket_add_memberships(struct nl_sock * sk,int group,...)417 int nl_socket_add_memberships(struct nl_sock *sk, int group, ...)
418 {
419 int err;
420 va_list ap;
421
422 if (sk->s_fd == -1)
423 return -NLE_BAD_SOCK;
424
425 va_start(ap, group);
426
427 while (group != 0) {
428 if (group < 0) {
429 va_end(ap);
430 return -NLE_INVAL;
431 }
432
433 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
434 &group, sizeof(group));
435 if (err < 0) {
436 va_end(ap);
437 return -nl_syserr2nlerr(errno);
438 }
439
440 group = va_arg(ap, int);
441 }
442
443 va_end(ap);
444
445 return 0;
446 }
447
nl_socket_add_membership(struct nl_sock * sk,int group)448 int nl_socket_add_membership(struct nl_sock *sk, int group)
449 {
450 return nl_socket_add_memberships(sk, group, 0);
451 }
452
453 /**
454 * Leave groups
455 * @arg sk Netlink socket
456 * @arg group Group identifier
457 *
458 * Leaves the specified groups using the modern socket option
459 * which is available since kernel version 2.6.14. The list of groups
460 * has to terminated by 0 (%NFNLGRP_NONE).
461 *
462 * @see nl_socket_add_membership
463 * @return 0 on success or a negative error code.
464 */
nl_socket_drop_memberships(struct nl_sock * sk,int group,...)465 int nl_socket_drop_memberships(struct nl_sock *sk, int group, ...)
466 {
467 int err;
468 va_list ap;
469
470 if (sk->s_fd == -1)
471 return -NLE_BAD_SOCK;
472
473 va_start(ap, group);
474
475 while (group != 0) {
476 if (group < 0) {
477 va_end(ap);
478 return -NLE_INVAL;
479 }
480
481 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
482 &group, sizeof(group));
483 if (err < 0) {
484 va_end(ap);
485 return -nl_syserr2nlerr(errno);
486 }
487
488 group = va_arg(ap, int);
489 }
490
491 va_end(ap);
492
493 return 0;
494 }
495
nl_socket_drop_membership(struct nl_sock * sk,int group)496 int nl_socket_drop_membership(struct nl_sock *sk, int group)
497 {
498 return nl_socket_drop_memberships(sk, group, 0);
499 }
500
501
502 /**
503 * Join multicast groups (deprecated)
504 * @arg sk Netlink socket.
505 * @arg groups Bitmask of groups to join.
506 *
507 * This function defines the old way of joining multicast group which
508 * has to be done prior to calling nl_connect(). It works on any kernel
509 * version but is very limited as only 32 groups can be joined.
510 */
nl_join_groups(struct nl_sock * sk,int groups)511 void nl_join_groups(struct nl_sock *sk, int groups)
512 {
513 sk->s_local.nl_groups |= groups;
514 }
515
516
517 /** @} */
518
519 /**
520 * @name Peer Identfication
521 * @{
522 */
523
nl_socket_get_peer_port(const struct nl_sock * sk)524 uint32_t nl_socket_get_peer_port(const struct nl_sock *sk)
525 {
526 return sk->s_peer.nl_pid;
527 }
528
nl_socket_set_peer_port(struct nl_sock * sk,uint32_t port)529 void nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port)
530 {
531 sk->s_peer.nl_pid = port;
532 }
533
nl_socket_get_peer_groups(const struct nl_sock * sk)534 uint32_t nl_socket_get_peer_groups(const struct nl_sock *sk)
535 {
536 return sk->s_peer.nl_groups;
537 }
538
nl_socket_set_peer_groups(struct nl_sock * sk,uint32_t groups)539 void nl_socket_set_peer_groups(struct nl_sock *sk, uint32_t groups)
540 {
541 sk->s_peer.nl_groups = groups;
542 }
543
544
545
546 /** @} */
547
548 /**
549 * @name File Descriptor
550 * @{
551 */
552
553 /**
554 * Return the file descriptor of the backing socket
555 * @arg sk Netlink socket
556 *
557 * Only valid after calling nl_connect() to create and bind the respective
558 * socket.
559 *
560 * @return File descriptor or -1 if not available.
561 */
nl_socket_get_fd(const struct nl_sock * sk)562 int nl_socket_get_fd(const struct nl_sock *sk)
563 {
564 return sk->s_fd;
565 }
566
567 /**
568 * Set file descriptor of socket to non-blocking state
569 * @arg sk Netlink socket.
570 *
571 * @return 0 on success or a negative error code.
572 */
nl_socket_set_nonblocking(const struct nl_sock * sk)573 int nl_socket_set_nonblocking(const struct nl_sock *sk)
574 {
575 if (sk->s_fd == -1)
576 return -NLE_BAD_SOCK;
577
578 if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0)
579 return -nl_syserr2nlerr(errno);
580
581 return 0;
582 }
583
584 /**
585 * Enable use of MSG_PEEK when reading from socket
586 * @arg sk Netlink socket.
587 */
nl_socket_enable_msg_peek(struct nl_sock * sk)588 void nl_socket_enable_msg_peek(struct nl_sock *sk)
589 {
590 sk->s_flags |= NL_MSG_PEEK;
591 }
592
593 /**
594 * Disable use of MSG_PEEK when reading from socket
595 * @arg sk Netlink socket.
596 */
nl_socket_disable_msg_peek(struct nl_sock * sk)597 void nl_socket_disable_msg_peek(struct nl_sock *sk)
598 {
599 sk->s_flags &= ~NL_MSG_PEEK;
600 }
601
602 /** @} */
603
604 /**
605 * @name Callback Handler
606 * @{
607 */
608
nl_socket_get_cb(const struct nl_sock * sk)609 struct nl_cb *nl_socket_get_cb(const struct nl_sock *sk)
610 {
611 return nl_cb_get(sk->s_cb);
612 }
613
nl_socket_set_cb(struct nl_sock * sk,struct nl_cb * cb)614 void nl_socket_set_cb(struct nl_sock *sk, struct nl_cb *cb)
615 {
616 if (cb == NULL)
617 BUG();
618
619 nl_cb_put(sk->s_cb);
620 sk->s_cb = nl_cb_get(cb);
621 }
622
623 /**
624 * Modify the callback handler associated with the socket
625 * @arg sk Netlink socket.
626 * @arg type which type callback to set
627 * @arg kind kind of callback
628 * @arg func callback function
629 * @arg arg argument to be passed to callback function
630 *
631 * @see nl_cb_set
632 */
nl_socket_modify_cb(struct nl_sock * sk,enum nl_cb_type type,enum nl_cb_kind kind,nl_recvmsg_msg_cb_t func,void * arg)633 int nl_socket_modify_cb(struct nl_sock *sk, enum nl_cb_type type,
634 enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func,
635 void *arg)
636 {
637 return nl_cb_set(sk->s_cb, type, kind, func, arg);
638 }
639
640 /**
641 * Modify the error callback handler associated with the socket
642 * @arg sk Netlink socket.
643 * @arg kind kind of callback
644 * @arg func callback function
645 * @arg arg argument to be passed to callback function
646 *
647 * @see nl_cb_err
648 */
nl_socket_modify_err_cb(struct nl_sock * sk,enum nl_cb_kind kind,nl_recvmsg_err_cb_t func,void * arg)649 int nl_socket_modify_err_cb(struct nl_sock *sk, enum nl_cb_kind kind,
650 nl_recvmsg_err_cb_t func, void *arg)
651 {
652 return nl_cb_err(sk->s_cb, kind, func, arg);
653 }
654
655 /** @} */
656
657 /**
658 * @name Utilities
659 * @{
660 */
661
662 /**
663 * Set socket buffer size of netlink socket.
664 * @arg sk Netlink socket.
665 * @arg rxbuf New receive socket buffer size in bytes.
666 * @arg txbuf New transmit socket buffer size in bytes.
667 *
668 * Sets the socket buffer size of a netlink socket to the specified
669 * values \c rxbuf and \c txbuf. Providing a value of \c 0 assumes a
670 * good default value.
671 *
672 * @note It is not required to call this function prior to nl_connect().
673 * @return 0 on sucess or a negative error code.
674 */
nl_socket_set_buffer_size(struct nl_sock * sk,int rxbuf,int txbuf)675 int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf)
676 {
677 int err;
678
679 if (rxbuf <= 0)
680 rxbuf = 32768;
681
682 if (txbuf <= 0)
683 txbuf = 32768;
684
685 if (sk->s_fd == -1)
686 return -NLE_BAD_SOCK;
687
688 err = setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF,
689 &txbuf, sizeof(txbuf));
690 if (err < 0)
691 return -nl_syserr2nlerr(errno);
692
693 err = setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF,
694 &rxbuf, sizeof(rxbuf));
695 if (err < 0)
696 return -nl_syserr2nlerr(errno);
697
698 sk->s_flags |= NL_SOCK_BUFSIZE_SET;
699
700 return 0;
701 }
702
703 /**
704 * Set default message buffer size of netlink socket.
705 * @arg sk Netlink socket.
706 * @arg bufsize Default message buffer size in bytes.
707 *
708 * Sets the default message buffer size to the specified length in bytes.
709 * The default message buffer size limits the maximum message size the
710 * socket will be able to receive. It is generally recommneded to specify
711 * a buffer size no less than the size of a memory page.
712 *
713 * @return 0 on success or a negative error code.
714 */
nl_socket_set_msg_buf_size(struct nl_sock * sk,size_t bufsize)715 int nl_socket_set_msg_buf_size(struct nl_sock *sk, size_t bufsize)
716 {
717 sk->s_bufsize = bufsize;
718
719 return 0;
720 }
721
722 /**
723 * Get default message buffer size of netlink socket.
724 * @arg sk Netlink socket.
725 *
726 * @return Size of default message buffer.
727 */
nl_socket_get_msg_buf_size(struct nl_sock * sk)728 size_t nl_socket_get_msg_buf_size(struct nl_sock *sk)
729 {
730 return sk->s_bufsize;
731 }
732
733 /**
734 * Enable/disable credential passing on netlink socket.
735 * @arg sk Netlink socket.
736 * @arg state New state (0 - disabled, 1 - enabled)
737 *
738 * @return 0 on success or a negative error code
739 */
nl_socket_set_passcred(struct nl_sock * sk,int state)740 int nl_socket_set_passcred(struct nl_sock *sk, int state)
741 {
742 int err;
743
744 if (sk->s_fd == -1)
745 return -NLE_BAD_SOCK;
746
747 err = setsockopt(sk->s_fd, SOL_SOCKET, SO_PASSCRED,
748 &state, sizeof(state));
749 if (err < 0)
750 return -nl_syserr2nlerr(errno);
751
752 if (state)
753 sk->s_flags |= NL_SOCK_PASSCRED;
754 else
755 sk->s_flags &= ~NL_SOCK_PASSCRED;
756
757 return 0;
758 }
759
760 /**
761 * Enable/disable receival of additional packet information
762 * @arg sk Netlink socket.
763 * @arg state New state (0 - disabled, 1 - enabled)
764 *
765 * @return 0 on success or a negative error code
766 */
nl_socket_recv_pktinfo(struct nl_sock * sk,int state)767 int nl_socket_recv_pktinfo(struct nl_sock *sk, int state)
768 {
769 int err;
770
771 if (sk->s_fd == -1)
772 return -NLE_BAD_SOCK;
773
774 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_PKTINFO,
775 &state, sizeof(state));
776 if (err < 0)
777 return -nl_syserr2nlerr(errno);
778
779 return 0;
780 }
781
782 /** @} */
783
784 /** @} */
785