libnl: /data/src/libnl3/lib/socket.c Source File

libnl 3.10.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 <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
44static int default_cb = NL_CB_DEFAULT;
45
46static 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
64static 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
82static uint32_t used_ports_map[32];
83static NL_RW_LOCK(port_map_lock);
84
85static 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
142static 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 */
160void _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
177void _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
200static 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 */
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 */
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 */
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
286static 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 */
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 */
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 */
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 */
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 */
357int _nl_socket_is_local_port_unspecified(struct nl_sock *sk)
358{
359 return (sk->s_local.nl_pid == 0);
360}
361
362uint32_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
389uint32_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 */
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 */
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
492int 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 */
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
542int 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 */
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
570uint32_t nl_socket_get_peer_port(const struct nl_sock *sk)
571{
572 return sk->s_peer.nl_pid;
573}
574
575void nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port)
576{
577 sk->s_peer.nl_pid = port;
578}
579
580uint32_t nl_socket_get_peer_groups(const struct nl_sock *sk)
581{
582 return sk->s_peer.nl_groups;
583}
584
585void 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 */
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 */
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 {
704no_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 */
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 */
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 */
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
771struct nl_cb *nl_socket_get_cb(const struct nl_sock *sk)
772{
773 return nl_cb_get(sk->s_cb);
774}
775
776void 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 */
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 */
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 */
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 */
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 */
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 */
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 */
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/** @} */
nl_recvmsg_err_cb_t
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
nl_cb_type
Callback types.
Definition handlers.h:87
nl_recvmsg_msg_cb_t
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
nl_cb_kind
Callback kinds.
Definition handlers.h:69
nl_cb_set
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
nl_cb_alloc
struct nl_cb * nl_cb_alloc(enum nl_cb_kind kind)
Allocate a new callback handle.
Definition handlers.c:198
nl_cb_err
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
@ NL_OK
Proceed with whatever would come next.
Definition handlers.h:58
NL_CB_SEQ_CHECK
@ NL_CB_SEQ_CHECK
Called instead of internal sequence number checking.
Definition handlers.h:105
NL_CB_DEFAULT
@ NL_CB_DEFAULT
Default handlers (quiet)
Definition handlers.h:71
NL_CB_CUSTOM
@ NL_CB_CUSTOM
Customized handler specified by the user.
Definition handlers.h:77
NL_CB_VERBOSE
@ NL_CB_VERBOSE
Verbose default handlers (error messages printed)
Definition handlers.h:73
NL_CB_DEBUG
@ NL_CB_DEBUG
Debug handlers for debugging.
Definition handlers.h:75
nl_socket_get_fd
int nl_socket_get_fd(const struct nl_sock *sk)
Return the file descriptor of the backing socket.
Definition socket.c:608
nl_socket_set_local_port
void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port)
Set local port of socket.
Definition socket.c:428
nl_socket_disable_auto_ack
void nl_socket_disable_auto_ack(struct nl_sock *sk)
Disable automatic request for ACK.
Definition socket.c:339
nl_socket_get_msg_buf_size
size_t nl_socket_get_msg_buf_size(struct nl_sock *sk)
Get default message buffer size of netlink socket.
Definition socket.c:907
nl_socket_recv_pktinfo
int nl_socket_recv_pktinfo(struct nl_sock *sk, int state)
Enable/disable receival of additional packet information.
Definition socket.c:949
nl_socket_modify_err_cb
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:811
nl_join_groups
void nl_join_groups(struct nl_sock *sk, int groups)
Join multicast groups (deprecated)
Definition socket.c:557
nl_socket_set_passcred
int nl_socket_set_passcred(struct nl_sock *sk, int state)
Enable/disable credential passing on netlink socket.
Definition socket.c:919
nl_socket_add_memberships
int nl_socket_add_memberships(struct nl_sock *sk, int group,...)
Join groups.
Definition socket.c:459
nl_socket_disable_msg_peek
void nl_socket_disable_msg_peek(struct nl_sock *sk)
Disable use of MSG_PEEK when reading from socket.
Definition socket.c:758
nl_socket_alloc
struct nl_sock * nl_socket_alloc(void)
Allocate new netlink socket.
Definition socket.c:226
nl_socket_set_msg_buf_size
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:894
nl_socket_alloc_cb
struct nl_sock * nl_socket_alloc_cb(struct nl_cb *cb)
Allocate new socket with custom callbacks.
Definition socket.c:252
nl_socket_set_nonblocking
int nl_socket_set_nonblocking(const struct nl_sock *sk)
Set file descriptor of socket to non-blocking state.
Definition socket.c:727
nl_socket_enable_auto_ack
void nl_socket_enable_auto_ack(struct nl_sock *sk)
Enable automatic request for ACK (default)
Definition socket.c:349
nl_socket_enable_msg_peek
void nl_socket_enable_msg_peek(struct nl_sock *sk)
Enable use of MSG_PEEK when reading from socket.
Definition socket.c:747
nl_socket_set_fd
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:640
nl_socket_use_seq
unsigned int nl_socket_use_seq(struct nl_sock *sk)
Use next sequence number.
Definition socket.c:318
nl_socket_disable_seq_check
void nl_socket_disable_seq_check(struct nl_sock *sk)
Disable sequence number checking.
Definition socket.c:303
nl_socket_set_buffer_size
int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf)
Set socket buffer size of netlink socket.
Definition socket.c:837
nl_socket_free
void nl_socket_free(struct nl_sock *sk)
Free a netlink socket.
Definition socket.c:264
nl_socket_drop_memberships
int nl_socket_drop_memberships(struct nl_sock *sk, int group,...)
Leave groups.
Definition socket.c:509
nl_socket_modify_cb
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:795
nl_cb
Definition nl-core.h:10