1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3 * Copyright (c) 2003-2012 Thomas Graf <[email protected]>
4 */
5
6 /**
7 * @ingroup core_types
8 * @defgroup socket Socket
9 *
10 * Representation of a netlink socket
11 *
12 * Related sections in the development guide:
13 * - @core_doc{core_sockets, Netlink Sockets}
14 *
15 * @{
16 *
17 * Header
18 * ------
19 * ~~~~{.c}
20 * #include <netlink/socket.h>
21 * ~~~~
22 */
23
24 #include "nl-default.h"
25
26 #include <fcntl.h>
27 #include <limits.h>
28 #include <sys/socket.h>
29
30 #include <netlink/netlink.h>
31 #include <netlink/utils.h>
32 #include <netlink/handlers.h>
33 #include <netlink/msg.h>
34 #include <netlink/attr.h>
35
36 #include "nl-core.h"
37 #include "nl-priv-dynamic-core/nl-core.h"
38 #include "nl-aux-core/nl-core.h"
39
40 #ifndef SOL_NETLINK
41 #define SOL_NETLINK 270
42 #endif
43
44 static int default_cb = NL_CB_DEFAULT;
45
init_default_cb(void)46 static void _nl_init init_default_cb(void)
47 {
48 char *nlcb;
49
50 if ((nlcb = getenv("NLCB"))) {
51 if (!strcasecmp(nlcb, "default"))
52 default_cb = NL_CB_DEFAULT;
53 else if (!strcasecmp(nlcb, "verbose"))
54 default_cb = NL_CB_VERBOSE;
55 else if (!strcasecmp(nlcb, "debug"))
56 default_cb = NL_CB_DEBUG;
57 else {
58 fprintf(stderr, "Unknown value for NLCB, valid values: "
59 "{default | verbose | debug}\n");
60 }
61 }
62 }
63
_badrandom_from_time(void)64 static uint32_t _badrandom_from_time(void)
65 {
66 uint32_t result;
67 uint64_t v64;
68 time_t t;
69
70 t = time(NULL);
71 v64 = (uint64_t)t;
72 result = (uint32_t)v64;
73
74 /* XOR with the upper bits. Otherwise, coverity warns about only
75 * considering 32 bit from time_t. Use the inverse, so that for the
76 * most part the bits don't change. */
77 result ^= (~(v64 >> 32));
78
79 return result;
80 }
81
82 static uint32_t used_ports_map[32];
83 static NL_RW_LOCK(port_map_lock);
84
generate_local_port(void)85 static uint32_t generate_local_port(void)
86 {
87 int i, j, m;
88 uint32_t n;
89 static uint16_t idx_state = 0;
90 uint32_t pid = getpid() & 0x3FFFFF;
91
92 nl_write_lock(&port_map_lock);
93
94 if (idx_state == 0) {
95 uint32_t t = _badrandom_from_time();
96
97 /* from time to time (on average each 2^15 calls), the idx_state will
98 * be zero again. No problem, just "seed" anew with time(). */
99 idx_state = t ^ (t >> 16) ^ 0x3047;
100 } else
101 idx_state = idx_state + 20011; /* add prime number */
102
103 i = idx_state >> 5;
104 n = idx_state;
105 for (j = 0; j < 32; j++) {
106 /* walk the index somewhat randomized, with always leaving the block
107 * #0 as last. The reason is that libnl-1 will start at block #0,
108 * so just leave the first 32 ports preferably for libnl-1 owned sockets
109 * (this is relevant only if the applications ends up using both versions
110 * of the library and doesn't hurt otherwise). */
111 if (j == 31)
112 i = 0;
113 else
114 i = (((i-1) + 7) % 31) + 1;
115
116 if (used_ports_map[i] == 0xFFFFFFFF)
117 continue;
118
119 for (m = 0; m < 32; m++) {
120 n = (n + 13u) % 32u;
121 if (1UL & (used_ports_map[i] >> n))
122 continue;
123
124 used_ports_map[i] |= (1UL << n);
125 n += (i * 32);
126
127 /* PID_MAX_LIMIT is currently at 2^22, leaving 10 bit
128 * to, i.e. 1024 unique ports per application. */
129
130 nl_write_unlock(&port_map_lock);
131
132 /* ensure we don't return zero. */
133 pid = pid + (n << 22);
134 return pid ? pid : 1024;
135 }
136 }
137
138 nl_write_unlock(&port_map_lock);
139 return 0;
140 }
141
release_local_port(uint32_t port)142 static void release_local_port(uint32_t port)
143 {
144 int nr;
145 uint32_t mask;
146
147 BUG_ON(port == 0);
148
149 nr = port >> 22;
150 mask = 1UL << (nr % 32);
151 nr /= 32;
152
153 nl_write_lock(&port_map_lock);
154 BUG_ON((used_ports_map[nr] & mask) != mask);
155 used_ports_map[nr] &= ~mask;
156 nl_write_unlock(&port_map_lock);
157 }
158
159 /** \cond skip */
_nl_socket_used_ports_release_all(const uint32_t * used_ports)160 void _nl_socket_used_ports_release_all(const uint32_t *used_ports)
161 {
162 int i;
163
164 for (i = 0; i < 32; i++) {
165 if (used_ports[i] != 0) {
166 nl_write_lock(&port_map_lock);
167 for (; i < 32; i++) {
168 BUG_ON((used_ports_map[i] & used_ports[i]) != used_ports[i]);
169 used_ports_map[i] &= ~(used_ports[i]);
170 }
171 nl_write_unlock(&port_map_lock);
172 return;
173 }
174 }
175 }
176
_nl_socket_used_ports_set(uint32_t * used_ports,uint32_t port)177 void _nl_socket_used_ports_set(uint32_t *used_ports, uint32_t port)
178 {
179 int nr;
180 int32_t mask;
181
182 nr = port >> 22;
183 mask = 1UL << (nr % 32);
184 nr /= 32;
185
186 /*
187 BUG_ON(port == 0 || (getpid() & 0x3FFFFF) != (port & 0x3FFFFF));
188 BUG_ON(used_ports[nr] & mask);
189 */
190
191 used_ports[nr] |= mask;
192 }
193 /** \endcond */
194
195 /**
196 * @name Allocation
197 * @{
198 */
199
__alloc_socket(struct nl_cb * cb)200 static struct nl_sock *__alloc_socket(struct nl_cb *cb)
201 {
202 struct nl_sock *sk;
203
204 sk = calloc(1, sizeof(*sk));
205 if (!sk)
206 return NULL;
207
208 sk->s_fd = -1;
209 sk->s_cb = nl_cb_get(cb);
210 sk->s_local.nl_family = AF_NETLINK;
211 sk->s_peer.nl_family = AF_NETLINK;
212 sk->s_seq_next = _badrandom_from_time();
213 sk->s_seq_expect = sk->s_seq_next;
214
215 /* the port is 0 (unspecified), meaning NL_OWN_PORT */
216 sk->s_flags = NL_OWN_PORT;
217
218 return sk;
219 }
220
221 /**
222 * Allocate new netlink socket
223 *
224 * @return Newly allocated netlink socket or NULL.
225 */
nl_socket_alloc(void)226 struct nl_sock *nl_socket_alloc(void)
227 {
228 struct nl_cb *cb;
229 struct nl_sock *sk;
230
231 cb = nl_cb_alloc(default_cb);
232 if (!cb)
233 return NULL;
234
235 /* will increment cb reference count on success */
236 sk = __alloc_socket(cb);
237
238 nl_cb_put(cb);
239
240 return sk;
241 }
242
243 /**
244 * Allocate new socket with custom callbacks
245 * @arg cb Callback handler
246 *
247 * The reference to the callback handler is taken into account
248 * automatically, it is released again upon calling nl_socket_free().
249 *
250 *@return Newly allocted socket handle or NULL.
251 */
nl_socket_alloc_cb(struct nl_cb * cb)252 struct nl_sock *nl_socket_alloc_cb(struct nl_cb *cb)
253 {
254 if (cb == NULL)
255 BUG();
256
257 return __alloc_socket(cb);
258 }
259
260 /**
261 * Free a netlink socket.
262 * @arg sk Netlink socket.
263 */
nl_socket_free(struct nl_sock * sk)264 void nl_socket_free(struct nl_sock *sk)
265 {
266 if (!sk)
267 return;
268
269 if (sk->s_fd >= 0)
270 close(sk->s_fd);
271
272 if (!(sk->s_flags & NL_OWN_PORT))
273 release_local_port(sk->s_local.nl_pid);
274
275 nl_cb_put(sk->s_cb);
276 free(sk);
277 }
278
279 /** @} */
280
281 /**
282 * @name Sequence Numbers
283 * @{
284 */
285
noop_seq_check(struct nl_msg * msg,void * arg)286 static int noop_seq_check(struct nl_msg *msg, void *arg)
287 {
288 return NL_OK;
289 }
290
291
292 /**
293 * Disable sequence number checking.
294 * @arg sk Netlink socket.
295 *
296 * Disables checking of sequence numbers on the netlink socket This is
297 * required to allow messages to be processed which were not requested by
298 * a preceding request message, e.g. netlink events.
299 *
300 * @note This function modifies the NL_CB_SEQ_CHECK configuration in
301 * the callback handle associated with the socket.
302 */
nl_socket_disable_seq_check(struct nl_sock * sk)303 void nl_socket_disable_seq_check(struct nl_sock *sk)
304 {
305 nl_cb_set(sk->s_cb, NL_CB_SEQ_CHECK,
306 NL_CB_CUSTOM, noop_seq_check, NULL);
307 }
308
309 /**
310 * Use next sequence number
311 * @arg sk Netlink socket.
312 *
313 * Uses the next available sequence number and increases the counter
314 * by one for subsequent calls.
315 *
316 * @return Unique serial sequence number
317 */
nl_socket_use_seq(struct nl_sock * sk)318 unsigned int nl_socket_use_seq(struct nl_sock *sk)
319 {
320 if (sk->s_seq_next == UINT_MAX) {
321 sk->s_seq_next = 0;
322 return UINT_MAX;
323 }
324 return sk->s_seq_next++;
325 }
326
327 /**
328 * Disable automatic request for ACK
329 * @arg sk Netlink socket.
330 *
331 * The default behaviour of a socket is to request an ACK for
332 * each message sent to allow for the caller to synchronize to
333 * the completion of the netlink operation. This function
334 * disables this behaviour and will result in requests being
335 * sent which will not have the NLM_F_ACK flag set automatically.
336 * However, it is still possible for the caller to set the
337 * NLM_F_ACK flag explicitely.
338 */
nl_socket_disable_auto_ack(struct nl_sock * sk)339 void nl_socket_disable_auto_ack(struct nl_sock *sk)
340 {
341 sk->s_flags |= NL_NO_AUTO_ACK;
342 }
343
344 /**
345 * Enable automatic request for ACK (default)
346 * @arg sk Netlink socket.
347 * @see nl_socket_disable_auto_ack
348 */
nl_socket_enable_auto_ack(struct nl_sock * sk)349 void nl_socket_enable_auto_ack(struct nl_sock *sk)
350 {
351 sk->s_flags &= ~NL_NO_AUTO_ACK;
352 }
353
354 /** @} */
355
356 /** \cond skip */
_nl_socket_is_local_port_unspecified(struct nl_sock * sk)357 int _nl_socket_is_local_port_unspecified(struct nl_sock *sk)
358 {
359 return (sk->s_local.nl_pid == 0);
360 }
361
_nl_socket_set_local_port_no_release(struct nl_sock * sk,int generate_other)362 uint32_t _nl_socket_set_local_port_no_release(struct nl_sock *sk, int generate_other)
363 {
364 uint32_t port;
365
366 /* reset the port to generate_local_port(), but do not release
367 * the previously generated port. */
368
369 if (generate_other)
370 port = generate_local_port();
371 else
372 port = 0;
373 sk->s_local.nl_pid = port;
374 if (port == 0) {
375 /* failed to find an unsed port. Restore the socket to have an
376 * unspecified port. */
377 sk->s_flags |= NL_OWN_PORT;
378 } else
379 sk->s_flags &= ~NL_OWN_PORT;
380 return port;
381 }
382 /** \endcond */
383
384 /**
385 * @name Source Idenficiation
386 * @{
387 */
388
nl_socket_get_local_port(const struct nl_sock * sk)389 uint32_t nl_socket_get_local_port(const struct nl_sock *sk)
390 {
391 if (sk->s_local.nl_pid == 0) {
392 struct nl_sock *sk_mutable = (struct nl_sock *) sk;
393
394 /* modify the const argument sk. This is justified, because
395 * nobody ever saw the local_port from externally. So, we
396 * initilize it on first use.
397 *
398 * Note that this also means that you cannot call this function
399 * from multiple threads without synchronization. But nl_sock
400 * is not automatically threadsafe anyway, so the user is not
401 * allowed to do that.
402 */
403 sk_mutable->s_local.nl_pid = generate_local_port();
404 if (sk_mutable->s_local.nl_pid == 0) {
405 /* could not generate a local port. Assign UINT32_MAX to preserve
406 * backward compatibility. A user who cares can clear that anyway
407 * with nl_socket_set_local_port(). */
408 sk_mutable->s_local.nl_pid = UINT32_MAX;
409 sk_mutable->s_flags |= NL_OWN_PORT;
410 } else
411 sk_mutable->s_flags &= ~NL_OWN_PORT;
412 }
413 return sk->s_local.nl_pid;
414 }
415
416 /**
417 * Set local port of socket
418 * @arg sk Netlink socket.
419 * @arg port Local port identifier
420 *
421 * Assigns a local port identifier to the socket.
422 *
423 * If port is 0, the port is reset to 'unspecified' as it is after newly
424 * calling nl_socket_alloc().
425 * Unspecified means, that the port will be generated automatically later
426 * on first use (either on nl_socket_get_local_port() or nl_connect()).
427 */
nl_socket_set_local_port(struct nl_sock * sk,uint32_t port)428 void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port)
429 {
430 if (!(sk->s_flags & NL_OWN_PORT))
431 release_local_port(sk->s_local.nl_pid);
432 sk->s_flags |= NL_OWN_PORT;
433 sk->s_local.nl_pid = port;
434 }
435
436 /** @} */
437
438 /**
439 * @name Group Subscriptions
440 * @{
441 */
442
443 /**
444 * Join groups
445 * @arg sk Netlink socket
446 * @arg group Group identifier
447 *
448 * Joins the specified groups using the modern socket option which
449 * is available since kernel version 2.6.14. It allows joining an
450 * almost arbitary number of groups without limitation. The list
451 * of groups has to be terminated by 0 (%NFNLGRP_NONE).
452 *
453 * Make sure to use the correct group definitions as the older
454 * bitmask definitions for nl_join_groups() are likely to still
455 * be present for backward compatibility reasons.
456 *
457 * @return 0 on success or a negative error code.
458 */
nl_socket_add_memberships(struct nl_sock * sk,int group,...)459 int nl_socket_add_memberships(struct nl_sock *sk, int group, ...)
460 {
461 int err;
462 va_list ap;
463
464 if (sk->s_fd == -1)
465 return -NLE_BAD_SOCK;
466
467 va_start(ap, group);
468
469 while (group != 0) {
470 if (group < 0) {
471 va_end(ap);
472 return -NLE_INVAL;
473 }
474
475 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
476 &group, sizeof(group));
477 if (err < 0) {
478 va_end(ap);
479 NL_DBG(4, "nl_socket_add_memberships(%p): setsockopt() failed with %d (%s)\n",
480 sk, errno, nl_strerror_l(errno));
481 return -nl_syserr2nlerr(errno);
482 }
483
484 group = va_arg(ap, int);
485 }
486
487 va_end(ap);
488
489 return 0;
490 }
491
nl_socket_add_membership(struct nl_sock * sk,int group)492 int nl_socket_add_membership(struct nl_sock *sk, int group)
493 {
494 return nl_socket_add_memberships(sk, group, 0);
495 }
496
497 /**
498 * Leave groups
499 * @arg sk Netlink socket
500 * @arg group Group identifier
501 *
502 * Leaves the specified groups using the modern socket option
503 * which is available since kernel version 2.6.14. The list of groups
504 * has to terminated by 0 (%NFNLGRP_NONE).
505 *
506 * @see nl_socket_add_membership
507 * @return 0 on success or a negative error code.
508 */
nl_socket_drop_memberships(struct nl_sock * sk,int group,...)509 int nl_socket_drop_memberships(struct nl_sock *sk, int group, ...)
510 {
511 int err;
512 va_list ap;
513
514 if (sk->s_fd == -1)
515 return -NLE_BAD_SOCK;
516
517 va_start(ap, group);
518
519 while (group != 0) {
520 if (group < 0) {
521 va_end(ap);
522 return -NLE_INVAL;
523 }
524
525 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
526 &group, sizeof(group));
527 if (err < 0) {
528 va_end(ap);
529 NL_DBG(4, "nl_socket_drop_memberships(%p): setsockopt() failed with %d (%s)\n",
530 sk, errno, nl_strerror_l(errno));
531 return -nl_syserr2nlerr(errno);
532 }
533
534 group = va_arg(ap, int);
535 }
536
537 va_end(ap);
538
539 return 0;
540 }
541
nl_socket_drop_membership(struct nl_sock * sk,int group)542 int nl_socket_drop_membership(struct nl_sock *sk, int group)
543 {
544 return nl_socket_drop_memberships(sk, group, 0);
545 }
546
547
548 /**
549 * Join multicast groups (deprecated)
550 * @arg sk Netlink socket.
551 * @arg groups Bitmask of groups to join.
552 *
553 * This function defines the old way of joining multicast group which
554 * has to be done prior to calling nl_connect(). It works on any kernel
555 * version but is very limited as only 32 groups can be joined.
556 */
nl_join_groups(struct nl_sock * sk,int groups)557 void nl_join_groups(struct nl_sock *sk, int groups)
558 {
559 sk->s_local.nl_groups |= groups;
560 }
561
562
563 /** @} */
564
565 /**
566 * @name Peer Identfication
567 * @{
568 */
569
nl_socket_get_peer_port(const struct nl_sock * sk)570 uint32_t nl_socket_get_peer_port(const struct nl_sock *sk)
571 {
572 return sk->s_peer.nl_pid;
573 }
574
nl_socket_set_peer_port(struct nl_sock * sk,uint32_t port)575 void nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port)
576 {
577 sk->s_peer.nl_pid = port;
578 }
579
nl_socket_get_peer_groups(const struct nl_sock * sk)580 uint32_t nl_socket_get_peer_groups(const struct nl_sock *sk)
581 {
582 return sk->s_peer.nl_groups;
583 }
584
nl_socket_set_peer_groups(struct nl_sock * sk,uint32_t groups)585 void nl_socket_set_peer_groups(struct nl_sock *sk, uint32_t groups)
586 {
587 sk->s_peer.nl_groups = groups;
588 }
589
590
591
592 /** @} */
593
594 /**
595 * @name File Descriptor
596 * @{
597 */
598
599 /**
600 * Return the file descriptor of the backing socket
601 * @arg sk Netlink socket
602 *
603 * Only valid after calling nl_connect() to create and bind the respective
604 * socket.
605 *
606 * @return File descriptor or -1 if not available.
607 */
nl_socket_get_fd(const struct nl_sock * sk)608 int nl_socket_get_fd(const struct nl_sock *sk)
609 {
610 return sk->s_fd;
611 }
612
613 /**
614 * Set the socket file descriptor externally which initializes the
615 * socket similar to nl_connect().
616 *
617 * @arg sk Netlink socket (required)
618 * @arg protocol The socket protocol (optional). Linux 2.6.32 supports
619 * the socket option SO_PROTOCOL. In this case, you can set
620 * protocol to a negative value and let it autodetect.
621 * If you set it to a non-negative value, the detected protocol
622 * must match the one provided.
623 * To support older kernels, you must specify the protocol.
624 * @arg fd Socket file descriptor to use (required)
625 *
626 * Set the socket file descriptor. @fd must be valid and bind'ed.
627 *
628 * This is an alternative to nl_connect(). nl_connect() creates, binds and
629 * sets the socket. With this function you can set the socket to an externally
630 * created file descriptor.
631 *
632 * @see nl_connect()
633 *
634 * @return 0 on success or a negative error code. On error, @fd is not closed but
635 * possibly unusable.
636 *
637 * @retval -NLE_BAD_SOCK Netlink socket is already connected
638 * @retval -NLE_INVAL Socket is of unexpected type
639 */
nl_socket_set_fd(struct nl_sock * sk,int protocol,int fd)640 int nl_socket_set_fd(struct nl_sock *sk, int protocol, int fd)
641 {
642 int err = 0;
643 socklen_t addrlen;
644 struct sockaddr_nl local = { 0 };
645 int so_type = -1, so_protocol = -1;
646
647 if (sk->s_fd != -1)
648 return -NLE_BAD_SOCK;
649 if (fd < 0)
650 return -NLE_INVAL;
651
652 addrlen = sizeof(local);
653 err = getsockname(fd, (struct sockaddr *) &local,
654 &addrlen);
655 if (err < 0) {
656 NL_DBG(4, "nl_socket_set_fd(%p,%d): getsockname() failed with %d (%s)\n",
657 sk, fd, errno, nl_strerror_l(errno));
658 return -nl_syserr2nlerr(errno);
659 }
660 if (addrlen != sizeof(local))
661 return -NLE_INVAL;
662 if (local.nl_family != AF_NETLINK) {
663 NL_DBG(4, "nl_socket_set_fd(%p,%d): getsockname() returned family %d instead of %d (AF_NETLINK)\n",
664 sk, fd, local.nl_family, AF_NETLINK);
665 return -NLE_INVAL;
666 }
667
668 addrlen = sizeof(so_type);
669 err = getsockopt(fd, SOL_SOCKET, SO_TYPE, &so_type, &addrlen);
670 if (err < 0) {
671 NL_DBG(4, "nl_socket_set_fd(%p,%d): getsockopt() for SO_TYPE failed with %d (%s)\n",
672 sk, fd, errno, nl_strerror_l(errno));
673 return -nl_syserr2nlerr(errno);
674 }
675 if (addrlen != sizeof(so_type))
676 return -NLE_INVAL;
677 if (so_type != SOCK_RAW) {
678 NL_DBG(4, "nl_socket_set_fd(%p,%d): getsockopt() returned SO_TYPE %d instead of %d (SOCK_RAW)\n",
679 sk, fd, so_type, SOCK_RAW);
680 return -NLE_INVAL;
681 }
682
683 #if SO_PROTOCOL
684 addrlen = sizeof(so_protocol);
685 err = getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &so_protocol, &addrlen);
686 if (err < 0) {
687 if (errno == ENOPROTOOPT)
688 goto no_so_protocol;
689 NL_DBG(4, "nl_socket_set_fd(%p,%d): getsockopt() for SO_PROTOCOL failed with %d (%s)\n",
690 sk, fd, errno, nl_strerror_l(errno));
691 return -nl_syserr2nlerr(errno);
692 }
693 if (addrlen != sizeof(so_protocol))
694 return -NLE_INVAL;
695 if (protocol >= 0 && protocol != so_protocol) {
696 NL_DBG(4, "nl_socket_set_fd(%p,%d): getsockopt() for SO_PROTOCOL returned %d instead of %d\n",
697 sk, fd, so_protocol, protocol);
698 return -NLE_INVAL;
699 }
700
701 if (0)
702 #endif
703 {
704 no_so_protocol:
705 if (protocol < 0) {
706 NL_DBG(4, "nl_socket_set_fd(%p,%d): unknown protocol and unable to detect it via SO_PROTOCOL socket option\n",
707 sk, fd);
708 return -NLE_INVAL;
709 }
710 so_protocol = protocol;
711 }
712
713 nl_socket_set_local_port (sk, local.nl_pid);
714 sk->s_local = local;
715 sk->s_fd = fd;
716 sk->s_proto = so_protocol;
717
718 return 0;
719 }
720
721 /**
722 * Set file descriptor of socket to non-blocking state
723 * @arg sk Netlink socket.
724 *
725 * @return 0 on success or a negative error code.
726 */
nl_socket_set_nonblocking(const struct nl_sock * sk)727 int nl_socket_set_nonblocking(const struct nl_sock *sk)
728 {
729 if (sk->s_fd == -1)
730 return -NLE_BAD_SOCK;
731
732 if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0) {
733 NL_DBG(4, "nl_socket_set_nonblocking(%p): fcntl() failed with %d (%s)\n",
734 sk, errno, nl_strerror_l(errno));
735 return -nl_syserr2nlerr(errno);
736 }
737
738 return 0;
739 }
740
741 /**
742 * Enable use of MSG_PEEK when reading from socket
743 * @arg sk Netlink socket.
744 *
745 * See also NL_CAPABILITY_NL_RECVMSGS_PEEK_BY_DEFAULT capability
746 */
nl_socket_enable_msg_peek(struct nl_sock * sk)747 void nl_socket_enable_msg_peek(struct nl_sock *sk)
748 {
749 sk->s_flags |= (NL_MSG_PEEK | NL_MSG_PEEK_EXPLICIT);
750 }
751
752 /**
753 * Disable use of MSG_PEEK when reading from socket
754 * @arg sk Netlink socket.
755 *
756 * See also NL_CAPABILITY_NL_RECVMSGS_PEEK_BY_DEFAULT capability
757 */
nl_socket_disable_msg_peek(struct nl_sock * sk)758 void nl_socket_disable_msg_peek(struct nl_sock *sk)
759 {
760 sk->s_flags |= NL_MSG_PEEK_EXPLICIT;
761 sk->s_flags &= ~NL_MSG_PEEK;
762 }
763
764 /** @} */
765
766 /**
767 * @name Callback Handler
768 * @{
769 */
770
nl_socket_get_cb(const struct nl_sock * sk)771 struct nl_cb *nl_socket_get_cb(const struct nl_sock *sk)
772 {
773 return nl_cb_get(sk->s_cb);
774 }
775
nl_socket_set_cb(struct nl_sock * sk,struct nl_cb * cb)776 void nl_socket_set_cb(struct nl_sock *sk, struct nl_cb *cb)
777 {
778 if (cb == NULL)
779 BUG();
780
781 nl_cb_put(sk->s_cb);
782 sk->s_cb = nl_cb_get(cb);
783 }
784
785 /**
786 * Modify the callback handler associated with the socket
787 * @arg sk Netlink socket.
788 * @arg type which type callback to set
789 * @arg kind kind of callback
790 * @arg func callback function
791 * @arg arg argument to be passed to callback function
792 *
793 * @see nl_cb_set
794 */
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)795 int nl_socket_modify_cb(struct nl_sock *sk, enum nl_cb_type type,
796 enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func,
797 void *arg)
798 {
799 return nl_cb_set(sk->s_cb, type, kind, func, arg);
800 }
801
802 /**
803 * Modify the error callback handler associated with the socket
804 * @arg sk Netlink socket.
805 * @arg kind kind of callback
806 * @arg func callback function
807 * @arg arg argument to be passed to callback function
808 *
809 * @see nl_cb_err
810 */
nl_socket_modify_err_cb(struct nl_sock * sk,enum nl_cb_kind kind,nl_recvmsg_err_cb_t func,void * arg)811 int nl_socket_modify_err_cb(struct nl_sock *sk, enum nl_cb_kind kind,
812 nl_recvmsg_err_cb_t func, void *arg)
813 {
814 return nl_cb_err(sk->s_cb, kind, func, arg);
815 }
816
817 /** @} */
818
819 /**
820 * @name Utilities
821 * @{
822 */
823
824 /**
825 * Set socket buffer size of netlink socket.
826 * @arg sk Netlink socket.
827 * @arg rxbuf New receive socket buffer size in bytes.
828 * @arg txbuf New transmit socket buffer size in bytes.
829 *
830 * Sets the socket buffer size of a netlink socket to the specified
831 * values \c rxbuf and \c txbuf. Providing a value of \c 0 assumes a
832 * good default value.
833 *
834 * @note It is not required to call this function prior to nl_connect().
835 * @return 0 on success or a negative error code.
836 */
nl_socket_set_buffer_size(struct nl_sock * sk,int rxbuf,int txbuf)837 int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf)
838 {
839 int err;
840
841 if (rxbuf <= 0)
842 rxbuf = 32768;
843
844 if (txbuf <= 0)
845 txbuf = 32768;
846
847 if (sk->s_fd == -1)
848 return -NLE_BAD_SOCK;
849
850 err = setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF,
851 &txbuf, sizeof(txbuf));
852 if (err < 0) {
853 NL_DBG(4, "nl_socket_set_buffer_size(%p): setsockopt() failed with %d (%s)\n",
854 sk, errno, nl_strerror_l(errno));
855 return -nl_syserr2nlerr(errno);
856 }
857
858 err = setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF,
859 &rxbuf, sizeof(rxbuf));
860 if (err < 0) {
861 NL_DBG(4, "nl_socket_set_buffer_size(%p): setsockopt() failed with %d (%s)\n",
862 sk, errno, nl_strerror_l(errno));
863 return -nl_syserr2nlerr(errno);
864 }
865
866 return 0;
867 }
868
869 /**
870 * Set default message buffer size of netlink socket.
871 * @arg sk Netlink socket.
872 * @arg bufsize Default message buffer size in bytes.
873 *
874 * Sets the default message buffer size to the specified length in bytes.
875 * The default message buffer size limits the maximum message size the
876 * socket will be able to receive. It is generally recommneded to specify
877 * a buffer size no less than the size of a memory page.
878 *
879 * Setting the @bufsize to zero means to use a default of 4 times getpagesize().
880 *
881 * When MSG_PEEK is enabled, the buffer size is used for the initial choice
882 * of the buffer while peeking. It still makes sense to choose an optimal value
883 * to avoid realloc().
884 *
885 * When MSG_PEEK is disabled, the buffer size is important because a too small
886 * size will lead to failure of receiving the message via nl_recvmsgs().
887 *
888 * By default, MSG_PEEK is enabled unless the user calls either nl_socket_disable_msg_peek()/
889 * nl_socket_enable_msg_peek() or sets the message buffer size to a positive value.
890 * See capability NL_CAPABILITY_NL_RECVMSGS_PEEK_BY_DEFAULT for that.
891 *
892 * @return 0 on success or a negative error code.
893 */
nl_socket_set_msg_buf_size(struct nl_sock * sk,size_t bufsize)894 int nl_socket_set_msg_buf_size(struct nl_sock *sk, size_t bufsize)
895 {
896 sk->s_bufsize = bufsize;
897
898 return 0;
899 }
900
901 /**
902 * Get default message buffer size of netlink socket.
903 * @arg sk Netlink socket.
904 *
905 * @return Size of default message buffer.
906 */
nl_socket_get_msg_buf_size(struct nl_sock * sk)907 size_t nl_socket_get_msg_buf_size(struct nl_sock *sk)
908 {
909 return sk->s_bufsize;
910 }
911
912 /**
913 * Enable/disable credential passing on netlink socket.
914 * @arg sk Netlink socket.
915 * @arg state New state (0 - disabled, 1 - enabled)
916 *
917 * @return 0 on success or a negative error code
918 */
nl_socket_set_passcred(struct nl_sock * sk,int state)919 int nl_socket_set_passcred(struct nl_sock *sk, int state)
920 {
921 int err;
922
923 if (sk->s_fd == -1)
924 return -NLE_BAD_SOCK;
925
926 err = setsockopt(sk->s_fd, SOL_SOCKET, SO_PASSCRED,
927 &state, sizeof(state));
928 if (err < 0) {
929 NL_DBG(4, "nl_socket_set_passcred(%p): setsockopt() failed with %d (%s)\n",
930 sk, errno, nl_strerror_l(errno));
931 return -nl_syserr2nlerr(errno);
932 }
933
934 if (state)
935 sk->s_flags |= NL_SOCK_PASSCRED;
936 else
937 sk->s_flags &= ~NL_SOCK_PASSCRED;
938
939 return 0;
940 }
941
942 /**
943 * Enable/disable receival of additional packet information
944 * @arg sk Netlink socket.
945 * @arg state New state (0 - disabled, 1 - enabled)
946 *
947 * @return 0 on success or a negative error code
948 */
nl_socket_recv_pktinfo(struct nl_sock * sk,int state)949 int nl_socket_recv_pktinfo(struct nl_sock *sk, int state)
950 {
951 int err;
952
953 if (sk->s_fd == -1)
954 return -NLE_BAD_SOCK;
955
956 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_PKTINFO,
957 &state, sizeof(state));
958 if (err < 0) {
959 NL_DBG(4, "nl_socket_recv_pktinfo(%p): setsockopt() failed with %d (%s)\n",
960 sk, errno, nl_strerror_l(errno));
961 return -nl_syserr2nlerr(errno);
962 }
963
964 return 0;
965 }
966
967 /** @} */
968
969 /** @} */
970