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