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