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