xref: /aosp_15_r20/external/libnl/lib/socket.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
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