• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
37 static int default_cb = NL_CB_DEFAULT;
38 
init_default_cb(void)39 static 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 
57 static uint32_t used_ports_map[32];
58 static NL_RW_LOCK(port_map_lock);
59 
generate_local_port(void)60 static 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 
release_local_port(uint32_t port)117 static 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 */
_nl_socket_used_ports_release_all(const uint32_t * used_ports)135 void _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 
_nl_socket_used_ports_set(uint32_t * used_ports,uint32_t port)152 void _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 
__alloc_socket(struct nl_cb * cb)175 static 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  */
nl_socket_alloc(void)200 struct 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  */
nl_socket_alloc_cb(struct nl_cb * cb)226 struct 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  */
nl_socket_free(struct nl_sock * sk)238 void 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 
noop_seq_check(struct nl_msg * msg,void * arg)260 static 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  */
nl_socket_disable_seq_check(struct nl_sock * sk)277 void 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  */
nl_socket_use_seq(struct nl_sock * sk)292 unsigned 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  */
nl_socket_disable_auto_ack(struct nl_sock * sk)309 void 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  */
nl_socket_enable_auto_ack(struct nl_sock * sk)319 void 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 */
_nl_socket_is_local_port_unspecified(struct nl_sock * sk)327 int _nl_socket_is_local_port_unspecified(struct nl_sock *sk)
328 {
329 	return (sk->s_local.nl_pid == 0);
330 }
331 
_nl_socket_set_local_port_no_release(struct nl_sock * sk,int generate_other)332 uint32_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 
nl_socket_get_local_port(const struct nl_sock * sk)359 uint32_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  */
nl_socket_set_local_port(struct nl_sock * sk,uint32_t port)398 void 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 sucess or a negative error code.
428  */
nl_socket_add_memberships(struct nl_sock * sk,int group,...)429 int 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 
nl_socket_add_membership(struct nl_sock * sk,int group)462 int 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  */
nl_socket_drop_memberships(struct nl_sock * sk,int group,...)479 int 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 
nl_socket_drop_membership(struct nl_sock * sk,int group)512 int 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  */
nl_join_groups(struct nl_sock * sk,int groups)527 void 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 
nl_socket_get_peer_port(const struct nl_sock * sk)540 uint32_t nl_socket_get_peer_port(const struct nl_sock *sk)
541 {
542 	return sk->s_peer.nl_pid;
543 }
544 
nl_socket_set_peer_port(struct nl_sock * sk,uint32_t port)545 void nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port)
546 {
547 	sk->s_peer.nl_pid = port;
548 }
549 
nl_socket_get_peer_groups(const struct nl_sock * sk)550 uint32_t nl_socket_get_peer_groups(const struct nl_sock *sk)
551 {
552 	return sk->s_peer.nl_groups;
553 }
554 
nl_socket_set_peer_groups(struct nl_sock * sk,uint32_t groups)555 void 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  */
nl_socket_get_fd(const struct nl_sock * sk)578 int 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  */
nl_socket_set_fd(struct nl_sock * sk,int protocol,int fd)610 int 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 	{
674 no_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  */
nl_socket_set_nonblocking(const struct nl_sock * sk)697 int 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  */
nl_socket_enable_msg_peek(struct nl_sock * sk)717 void 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  */
nl_socket_disable_msg_peek(struct nl_sock * sk)728 void 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 
nl_socket_get_cb(const struct nl_sock * sk)741 struct nl_cb *nl_socket_get_cb(const struct nl_sock *sk)
742 {
743 	return nl_cb_get(sk->s_cb);
744 }
745 
nl_socket_set_cb(struct nl_sock * sk,struct nl_cb * cb)746 void 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  */
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)765 int 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  */
nl_socket_modify_err_cb(struct nl_sock * sk,enum nl_cb_kind kind,nl_recvmsg_err_cb_t func,void * arg)781 int 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 sucess or a negative error code.
806  */
nl_socket_set_buffer_size(struct nl_sock * sk,int rxbuf,int txbuf)807 int 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  */
nl_socket_set_msg_buf_size(struct nl_sock * sk,size_t bufsize)864 int 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  */
nl_socket_get_msg_buf_size(struct nl_sock * sk)877 size_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  */
nl_socket_set_passcred(struct nl_sock * sk,int state)889 int 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  */
nl_socket_recv_pktinfo(struct nl_sock * sk,int state)919 int 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 /** @} */
940