PageRenderTime 62ms CodeModel.GetById 35ms app.highlight 22ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/socket.c

https://github.com/tklauser/libnl
C | 784 lines | 360 code | 134 blank | 290 comment | 66 complexity | 90d5da8030c27d3b802002dfc6158628 MD5 | raw file
  1/*
  2 * lib/socket.c		Netlink Socket
  3 *
  4 *	This library is free software; you can redistribute it and/or
  5 *	modify it under the terms of the GNU Lesser General Public
  6 *	License as published by the Free Software Foundation version 2.1
  7 *	of the License.
  8 *
  9 * Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
 10 */
 11
 12/**
 13 * @ingroup core_types
 14 * @defgroup socket Socket
 15 *
 16 * Representation of a netlink socket
 17 *
 18 * Related sections in the development guide:
 19 * - @core_doc{core_sockets, Netlink Sockets}
 20 *
 21 * @{
 22 *
 23 * Header
 24 * ------
 25 * ~~~~{.c}
 26 * #include <netlink/socket.h>
 27 * ~~~~
 28 */
 29
 30#include "defs.h"
 31
 32#include <netlink-private/netlink.h>
 33#include <netlink-private/socket.h>
 34#include <netlink/netlink.h>
 35#include <netlink/utils.h>
 36#include <netlink/handlers.h>
 37#include <netlink/msg.h>
 38#include <netlink/attr.h>
 39
 40static int default_cb = NL_CB_DEFAULT;
 41
 42static void __init init_default_cb(void)
 43{
 44	char *nlcb;
 45
 46	if ((nlcb = getenv("NLCB"))) {
 47		if (!strcasecmp(nlcb, "default"))
 48			default_cb = NL_CB_DEFAULT;
 49		else if (!strcasecmp(nlcb, "verbose"))
 50			default_cb = NL_CB_VERBOSE;
 51		else if (!strcasecmp(nlcb, "debug"))
 52			default_cb = NL_CB_DEBUG;
 53		else {
 54			fprintf(stderr, "Unknown value for NLCB, valid values: "
 55				"{default | verbose | debug}\n");
 56		}
 57	}
 58}
 59
 60static uint32_t used_ports_map[32];
 61static NL_RW_LOCK(port_map_lock);
 62
 63static uint32_t generate_local_port(void)
 64{
 65	int i, j, n, m;
 66	static uint16_t idx_state = 0;
 67	uint32_t pid = getpid() & 0x3FFFFF;
 68
 69	nl_write_lock(&port_map_lock);
 70
 71	if (idx_state == 0) {
 72		uint32_t t = time(NULL);
 73
 74		/* from time to time (on average each 2^15 calls), the idx_state will
 75		 * be zero again. No problem, just "seed" anew with time(). */
 76		idx_state = t ^ (t >> 16) ^ 0x3047;
 77	} else
 78		idx_state = idx_state + 20011; /* add prime number */
 79
 80	i = idx_state >> 5;
 81	n = idx_state;
 82	for (j = 0; j < 32; j++) {
 83		/* walk the index somewhat randomized, with always leaving the block
 84		 * #0 as last. The reason is that libnl-1 will start at block #0,
 85		 * so just leave the first 32 ports preferably for libnl-1 owned sockets
 86		 * (this is relevant only if the applications ends up using both versions
 87		 * of the library and doesn't hurt otherwise). */
 88		if (j == 31)
 89			i = 0;
 90		else
 91			i = (((i-1) + 7) % 31) + 1;
 92
 93		if (used_ports_map[i] == 0xFFFFFFFF)
 94			continue;
 95
 96		for (m = 0; m < 32; m++) {
 97			n = (n + 13) % 32;
 98			if (1UL & (used_ports_map[i] >> n))
 99				continue;
100
101			used_ports_map[i] |= (1UL << n);
102			n += (i * 32);
103
104			/* PID_MAX_LIMIT is currently at 2^22, leaving 10 bit
105			 * to, i.e. 1024 unique ports per application. */
106
107			nl_write_unlock(&port_map_lock);
108
109			return pid + (((uint32_t)n) << 22);
110		}
111	}
112
113	nl_write_unlock(&port_map_lock);
114
115	/* Out of sockets in our own PID namespace, what to do? FIXME */
116	NL_DBG(1, "Warning: Ran out of unique local port namespace\n");
117	return UINT32_MAX;
118}
119
120static void release_local_port(uint32_t port)
121{
122	int nr;
123	uint32_t mask;
124
125	if (port == UINT32_MAX)
126		return;
127
128	BUG_ON(port == 0);
129
130	nr = port >> 22;
131	mask = 1UL << (nr % 32);
132	nr /= 32;
133
134	nl_write_lock(&port_map_lock);
135	BUG_ON((used_ports_map[nr] & mask) != mask);
136	used_ports_map[nr] &= ~mask;
137	nl_write_unlock(&port_map_lock);
138}
139
140/** \cond skip */
141void _nl_socket_used_ports_release_all(const uint32_t *used_ports)
142{
143	int i;
144
145	for (i = 0; i < 32; i++) {
146		if (used_ports[i] != 0) {
147			nl_write_lock(&port_map_lock);
148			for (; i < 32; i++) {
149				BUG_ON((used_ports_map[i] & used_ports[i]) != used_ports[i]);
150				used_ports_map[i] &= ~(used_ports[i]);
151			}
152			nl_write_unlock(&port_map_lock);
153			return;
154		}
155	}
156}
157
158void _nl_socket_used_ports_set(uint32_t *used_ports, uint32_t port)
159{
160	int nr;
161	int32_t mask;
162
163	nr = port >> 22;
164	mask = 1UL << (nr % 32);
165	nr /= 32;
166
167	/*
168	BUG_ON(port == UINT32_MAX || port == 0 || (getpid() & 0x3FFFFF) != (port & 0x3FFFFF));
169	BUG_ON(used_ports[nr] & mask);
170	*/
171
172	used_ports[nr] |= mask;
173}
174/** \endcond */
175
176/**
177 * @name Allocation
178 * @{
179 */
180
181static struct nl_sock *__alloc_socket(struct nl_cb *cb)
182{
183	struct nl_sock *sk;
184
185	sk = calloc(1, sizeof(*sk));
186	if (!sk)
187		return NULL;
188
189	sk->s_fd = -1;
190	sk->s_cb = nl_cb_get(cb);
191	sk->s_local.nl_family = AF_NETLINK;
192	sk->s_peer.nl_family = AF_NETLINK;
193	sk->s_seq_expect = sk->s_seq_next = time(NULL);
194
195	/* the port is 0 (unspecified), meaning NL_OWN_PORT */
196	sk->s_flags = NL_OWN_PORT;
197
198	return sk;
199}
200
201/**
202 * Allocate new netlink socket
203 *
204 * @return Newly allocated netlink socket or NULL.
205 */
206struct nl_sock *nl_socket_alloc(void)
207{
208	struct nl_cb *cb;
209        struct nl_sock *sk;
210
211	cb = nl_cb_alloc(default_cb);
212	if (!cb)
213		return NULL;
214
215        /* will increment cb reference count on success */
216	sk = __alloc_socket(cb);
217
218        nl_cb_put(cb);
219
220        return sk;
221}
222
223/**
224 * Allocate new socket with custom callbacks
225 * @arg cb		Callback handler
226 *
227 * The reference to the callback handler is taken into account
228 * automatically, it is released again upon calling nl_socket_free().
229 *
230 *@return Newly allocted socket handle or NULL.
231 */
232struct nl_sock *nl_socket_alloc_cb(struct nl_cb *cb)
233{
234	if (cb == NULL)
235		BUG();
236
237	return __alloc_socket(cb);
238}
239
240/**
241 * Free a netlink socket.
242 * @arg sk		Netlink socket.
243 */
244void nl_socket_free(struct nl_sock *sk)
245{
246	if (!sk)
247		return;
248
249	if (sk->s_fd >= 0)
250		close(sk->s_fd);
251
252	if (!(sk->s_flags & NL_OWN_PORT))
253		release_local_port(sk->s_local.nl_pid);
254
255	nl_cb_put(sk->s_cb);
256	free(sk);
257}
258
259/** @} */
260
261/**
262 * @name Sequence Numbers
263 * @{
264 */
265
266static int noop_seq_check(struct nl_msg *msg, void *arg)
267{
268	return NL_OK;
269}
270
271
272/**
273 * Disable sequence number checking.
274 * @arg sk		Netlink socket.
275 *
276 * Disables checking of sequence numbers on the netlink socket This is
277 * required to allow messages to be processed which were not requested by
278 * a preceding request message, e.g. netlink events.
279 *
280 * @note This function modifies the NL_CB_SEQ_CHECK configuration in
281 * the callback handle associated with the socket.
282 */
283void nl_socket_disable_seq_check(struct nl_sock *sk)
284{
285	nl_cb_set(sk->s_cb, NL_CB_SEQ_CHECK,
286		  NL_CB_CUSTOM, noop_seq_check, NULL);
287}
288
289/**
290 * Use next sequence number
291 * @arg sk		Netlink socket.
292 *
293 * Uses the next available sequence number and increases the counter
294 * by one for subsequent calls.
295 *
296 * @return Unique serial sequence number
297 */
298unsigned int nl_socket_use_seq(struct nl_sock *sk)
299{
300	return sk->s_seq_next++;
301}
302
303/**
304 * Disable automatic request for ACK
305 * @arg sk		Netlink socket.
306 *
307 * The default behaviour of a socket is to request an ACK for
308 * each message sent to allow for the caller to synchronize to
309 * the completion of the netlink operation. This function
310 * disables this behaviour and will result in requests being
311 * sent which will not have the NLM_F_ACK flag set automatically.
312 * However, it is still possible for the caller to set the
313 * NLM_F_ACK flag explicitely.
314 */
315void nl_socket_disable_auto_ack(struct nl_sock *sk)
316{
317	sk->s_flags |= NL_NO_AUTO_ACK;
318}
319
320/**
321 * Enable automatic request for ACK (default)
322 * @arg sk		Netlink socket.
323 * @see nl_socket_disable_auto_ack
324 */
325void nl_socket_enable_auto_ack(struct nl_sock *sk)
326{
327	sk->s_flags &= ~NL_NO_AUTO_ACK;
328}
329
330/** @} */
331
332/** \cond skip */
333int _nl_socket_is_local_port_unspecified(struct nl_sock *sk)
334{
335	return (sk->s_local.nl_pid == 0);
336}
337
338uint32_t _nl_socket_generate_local_port_no_release(struct nl_sock *sk)
339{
340	uint32_t port;
341
342	/* reset the port to generate_local_port(), but do not release
343	 * the previously generated port. */
344
345	port = generate_local_port();
346	sk->s_flags &= ~NL_OWN_PORT;
347	sk->s_local.nl_pid = port;
348	return port;
349}
350/** \endcond */
351
352/**
353 * @name Source Idenficiation
354 * @{
355 */
356
357uint32_t nl_socket_get_local_port(const struct nl_sock *sk)
358{
359	if (sk->s_local.nl_pid == 0) {
360		/* modify the const argument sk. This is justified, because
361		 * nobody ever saw the local_port from externally. So, we
362		 * initilize it on first use.
363		 *
364		 * Note that this also means that you cannot call this function
365		 * from multiple threads without synchronization. But nl_sock
366		 * is not automatically threadsafe anyway, so the user is not
367		 * allowed to do that.
368		 */
369		return _nl_socket_generate_local_port_no_release((struct nl_sock *) sk);
370	}
371	return sk->s_local.nl_pid;
372}
373
374/**
375 * Set local port of socket
376 * @arg sk		Netlink socket.
377 * @arg port		Local port identifier
378 *
379 * Assigns a local port identifier to the socket.
380 *
381 * If port is 0, the port is reset to 'unspecified' as it is after newly
382 * calling nl_socket_alloc().
383 * Unspecified means, that the port will be generated automatically later
384 * on first use (either on nl_socket_get_local_port() or nl_connect()).
385 */
386void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port)
387{
388	if (!(sk->s_flags & NL_OWN_PORT))
389		release_local_port(sk->s_local.nl_pid);
390	sk->s_flags |= NL_OWN_PORT;
391	sk->s_local.nl_pid = port;
392}
393
394/** @} */
395
396/**
397 * @name Group Subscriptions
398 * @{
399 */
400
401/**
402 * Join groups
403 * @arg sk		Netlink socket
404 * @arg group		Group identifier
405 *
406 * Joins the specified groups using the modern socket option which
407 * is available since kernel version 2.6.14. It allows joining an
408 * almost arbitary number of groups without limitation.  The list
409 * of groups has to be terminated by 0 (%NFNLGRP_NONE).
410 *
411 * Make sure to use the correct group definitions as the older
412 * bitmask definitions for nl_join_groups() are likely to still
413 * be present for backward compatibility reasons.
414 *
415 * @return 0 on sucess or a negative error code.
416 */
417int nl_socket_add_memberships(struct nl_sock *sk, int group, ...)
418{
419	int err;
420	va_list ap;
421
422	if (sk->s_fd == -1)
423		return -NLE_BAD_SOCK;
424
425	va_start(ap, group);
426
427	while (group != 0) {
428		if (group < 0) {
429			va_end(ap);
430			return -NLE_INVAL;
431		}
432
433		err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
434						 &group, sizeof(group));
435		if (err < 0) {
436			va_end(ap);
437			return -nl_syserr2nlerr(errno);
438		}
439
440		group = va_arg(ap, int);
441	}
442
443	va_end(ap);
444
445	return 0;
446}
447
448int nl_socket_add_membership(struct nl_sock *sk, int group)
449{
450	return nl_socket_add_memberships(sk, group, 0);
451}
452
453/**
454 * Leave groups
455 * @arg sk		Netlink socket
456 * @arg group		Group identifier
457 *
458 * Leaves the specified groups using the modern socket option
459 * which is available since kernel version 2.6.14. The list of groups
460 * has to terminated by 0 (%NFNLGRP_NONE).
461 *
462 * @see nl_socket_add_membership
463 * @return 0 on success or a negative error code.
464 */
465int nl_socket_drop_memberships(struct nl_sock *sk, int group, ...)
466{
467	int err;
468	va_list ap;
469
470	if (sk->s_fd == -1)
471		return -NLE_BAD_SOCK;
472
473	va_start(ap, group);
474
475	while (group != 0) {
476		if (group < 0) {
477			va_end(ap);
478			return -NLE_INVAL;
479		}
480
481		err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
482						 &group, sizeof(group));
483		if (err < 0) {
484			va_end(ap);
485			return -nl_syserr2nlerr(errno);
486		}
487
488		group = va_arg(ap, int);
489	}
490
491	va_end(ap);
492
493	return 0;
494}
495
496int nl_socket_drop_membership(struct nl_sock *sk, int group)
497{
498	return nl_socket_drop_memberships(sk, group, 0);
499}
500
501
502/**
503 * Join multicast groups (deprecated)
504 * @arg sk		Netlink socket.
505 * @arg groups		Bitmask of groups to join.
506 *
507 * This function defines the old way of joining multicast group which
508 * has to be done prior to calling nl_connect(). It works on any kernel
509 * version but is very limited as only 32 groups can be joined.
510 */
511void nl_join_groups(struct nl_sock *sk, int groups)
512{
513	sk->s_local.nl_groups |= groups;
514}
515
516
517/** @} */
518
519/**
520 * @name Peer Identfication
521 * @{
522 */
523
524uint32_t nl_socket_get_peer_port(const struct nl_sock *sk)
525{
526	return sk->s_peer.nl_pid;
527}
528
529void nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port)
530{
531	sk->s_peer.nl_pid = port;
532}
533
534uint32_t nl_socket_get_peer_groups(const struct nl_sock *sk)
535{
536	return sk->s_peer.nl_groups;
537}
538
539void nl_socket_set_peer_groups(struct nl_sock *sk, uint32_t groups)
540{
541	sk->s_peer.nl_groups = groups;
542}
543
544
545
546/** @} */
547
548/**
549 * @name File Descriptor
550 * @{
551 */
552
553/**
554 * Return the file descriptor of the backing socket
555 * @arg sk		Netlink socket
556 *
557 * Only valid after calling nl_connect() to create and bind the respective
558 * socket.
559 *
560 * @return File descriptor or -1 if not available.
561 */
562int nl_socket_get_fd(const struct nl_sock *sk)
563{
564	return sk->s_fd;
565}
566
567/**
568 * Set file descriptor of socket to non-blocking state
569 * @arg sk		Netlink socket.
570 *
571 * @return 0 on success or a negative error code.
572 */
573int nl_socket_set_nonblocking(const struct nl_sock *sk)
574{
575	if (sk->s_fd == -1)
576		return -NLE_BAD_SOCK;
577
578	if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0)
579		return -nl_syserr2nlerr(errno);
580
581	return 0;
582}
583
584/**
585 * Enable use of MSG_PEEK when reading from socket
586 * @arg sk		Netlink socket.
587 */
588void nl_socket_enable_msg_peek(struct nl_sock *sk)
589{
590	sk->s_flags |= NL_MSG_PEEK;
591}
592
593/**
594 * Disable use of MSG_PEEK when reading from socket
595 * @arg sk		Netlink socket.
596 */
597void nl_socket_disable_msg_peek(struct nl_sock *sk)
598{
599	sk->s_flags &= ~NL_MSG_PEEK;
600}
601
602/** @} */
603
604/**
605 * @name Callback Handler
606 * @{
607 */
608
609struct nl_cb *nl_socket_get_cb(const struct nl_sock *sk)
610{
611	return nl_cb_get(sk->s_cb);
612}
613
614void nl_socket_set_cb(struct nl_sock *sk, struct nl_cb *cb)
615{
616        if (cb == NULL)
617                BUG();
618
619	nl_cb_put(sk->s_cb);
620	sk->s_cb = nl_cb_get(cb);
621}
622
623/**
624 * Modify the callback handler associated with the socket
625 * @arg sk		Netlink socket.
626 * @arg type		which type callback to set
627 * @arg kind		kind of callback
628 * @arg func		callback function
629 * @arg arg		argument to be passed to callback function
630 *
631 * @see nl_cb_set
632 */
633int nl_socket_modify_cb(struct nl_sock *sk, enum nl_cb_type type,
634			enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func,
635			void *arg)
636{
637	return nl_cb_set(sk->s_cb, type, kind, func, arg);
638}
639
640/**
641 * Modify the error callback handler associated with the socket
642 * @arg sk		Netlink socket.
643 * @arg kind		kind of callback
644 * @arg func		callback function
645 * @arg arg		argument to be passed to callback function
646 *
647 * @see nl_cb_err
648 */
649int nl_socket_modify_err_cb(struct nl_sock *sk, enum nl_cb_kind kind,
650			    nl_recvmsg_err_cb_t func, void *arg)
651{
652	return nl_cb_err(sk->s_cb, kind, func, arg);
653}
654
655/** @} */
656
657/**
658 * @name Utilities
659 * @{
660 */
661
662/**
663 * Set socket buffer size of netlink socket.
664 * @arg sk		Netlink socket.
665 * @arg rxbuf		New receive socket buffer size in bytes.
666 * @arg txbuf		New transmit socket buffer size in bytes.
667 *
668 * Sets the socket buffer size of a netlink socket to the specified
669 * values \c rxbuf and \c txbuf. Providing a value of \c 0 assumes a
670 * good default value.
671 *
672 * @note It is not required to call this function prior to nl_connect().
673 * @return 0 on sucess or a negative error code.
674 */
675int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf)
676{
677	int err;
678
679	if (rxbuf <= 0)
680		rxbuf = 32768;
681
682	if (txbuf <= 0)
683		txbuf = 32768;
684
685	if (sk->s_fd == -1)
686		return -NLE_BAD_SOCK;
687	
688	err = setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF,
689			 &txbuf, sizeof(txbuf));
690	if (err < 0)
691		return -nl_syserr2nlerr(errno);
692
693	err = setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF,
694			 &rxbuf, sizeof(rxbuf));
695	if (err < 0)
696		return -nl_syserr2nlerr(errno);
697
698	sk->s_flags |= NL_SOCK_BUFSIZE_SET;
699
700	return 0;
701}
702
703/**
704 * Set default message buffer size of netlink socket.
705 * @arg sk		Netlink socket.
706 * @arg bufsize		Default message buffer size in bytes.
707 *
708 * Sets the default message buffer size to the specified length in bytes.
709 * The default message buffer size limits the maximum message size the
710 * socket will be able to receive. It is generally recommneded to specify
711 * a buffer size no less than the size of a memory page.
712 *
713 * @return 0 on success or a negative error code.
714 */
715int nl_socket_set_msg_buf_size(struct nl_sock *sk, size_t bufsize)
716{
717	sk->s_bufsize = bufsize;
718
719	return 0;
720}
721
722/**
723 * Get default message buffer size of netlink socket.
724 * @arg sk		Netlink socket.
725 *
726 * @return Size of default message buffer.
727 */
728size_t nl_socket_get_msg_buf_size(struct nl_sock *sk)
729{
730	return sk->s_bufsize;
731}
732
733/**
734 * Enable/disable credential passing on netlink socket.
735 * @arg sk		Netlink socket.
736 * @arg state		New state (0 - disabled, 1 - enabled)
737 *
738 * @return 0 on success or a negative error code
739 */
740int nl_socket_set_passcred(struct nl_sock *sk, int state)
741{
742	int err;
743
744	if (sk->s_fd == -1)
745		return -NLE_BAD_SOCK;
746
747	err = setsockopt(sk->s_fd, SOL_SOCKET, SO_PASSCRED,
748			 &state, sizeof(state));
749	if (err < 0)
750		return -nl_syserr2nlerr(errno);
751
752	if (state)
753		sk->s_flags |= NL_SOCK_PASSCRED;
754	else
755		sk->s_flags &= ~NL_SOCK_PASSCRED;
756
757	return 0;
758}
759
760/**
761 * Enable/disable receival of additional packet information
762 * @arg sk		Netlink socket.
763 * @arg state		New state (0 - disabled, 1 - enabled)
764 *
765 * @return 0 on success or a negative error code
766 */
767int nl_socket_recv_pktinfo(struct nl_sock *sk, int state)
768{
769	int err;
770
771	if (sk->s_fd == -1)
772		return -NLE_BAD_SOCK;
773
774	err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_PKTINFO,
775			 &state, sizeof(state));
776	if (err < 0)
777		return -nl_syserr2nlerr(errno);
778
779	return 0;
780}
781
782/** @} */
783
784/** @} */