Home | History | Annotate | Download | only in lib
      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-2008 Thomas Graf <tgraf (at) suug.ch>
     10  */
     11 
     12 /**
     13  * @ingroup core
     14  * @defgroup socket Socket
     15  * @{
     16  */
     17 
     18 #include <netlink-local.h>
     19 #include <netlink/netlink.h>
     20 #include <netlink/utils.h>
     21 #include <netlink/handlers.h>
     22 #include <netlink/msg.h>
     23 #include <netlink/attr.h>
     24 
     25 static int default_cb = NL_CB_DEFAULT;
     26 
     27 static void __init init_default_cb(void)
     28 {
     29 	char *nlcb;
     30 
     31 	if ((nlcb = getenv("NLCB"))) {
     32 		if (!strcasecmp(nlcb, "default"))
     33 			default_cb = NL_CB_DEFAULT;
     34 		else if (!strcasecmp(nlcb, "verbose"))
     35 			default_cb = NL_CB_VERBOSE;
     36 		else if (!strcasecmp(nlcb, "debug"))
     37 			default_cb = NL_CB_DEBUG;
     38 		else {
     39 			fprintf(stderr, "Unknown value for NLCB, valid values: "
     40 				"{default | verbose | debug}\n");
     41 		}
     42 	}
     43 }
     44 
     45 static uint32_t used_ports_map[32];
     46 
     47 static uint32_t generate_local_port(void)
     48 {
     49 	int i, n;
     50 	uint32_t pid = getpid() & 0x3FFFFF;
     51 
     52 	for (i = 0; i < 32; i++) {
     53 		if (used_ports_map[i] == 0xFFFFFFFF)
     54 			continue;
     55 
     56 		for (n = 0; n < 32; n++) {
     57 			if (1UL & (used_ports_map[i] >> n))
     58 				continue;
     59 
     60 			used_ports_map[i] |= (1UL << n);
     61 			n += (i * 32);
     62 
     63 			/* PID_MAX_LIMIT is currently at 2^22, leaving 10 bit
     64 			 * to, i.e. 1024 unique ports per application. */
     65 			return pid + (n << 22);
     66 
     67 		}
     68 	}
     69 
     70 	/* Out of sockets in our own PID namespace, what to do? FIXME */
     71 	return UINT_MAX;
     72 }
     73 
     74 static void release_local_port(uint32_t port)
     75 {
     76 	int nr;
     77 
     78 	if (port == UINT_MAX)
     79 		return;
     80 
     81 	nr = port >> 22;
     82 	used_ports_map[nr / 32] &= ~(1 << nr % 32);
     83 }
     84 
     85 /**
     86  * @name Allocation
     87  * @{
     88  */
     89 
     90 static struct nl_sock *__alloc_socket(struct nl_cb *cb)
     91 {
     92 	struct nl_sock *sk;
     93 
     94 	sk = calloc(1, sizeof(*sk));
     95 	if (!sk)
     96 		return NULL;
     97 
     98 	sk->s_fd = -1;
     99 	sk->s_cb = cb;
    100 	sk->s_local.nl_family = AF_NETLINK;
    101 	sk->s_peer.nl_family = AF_NETLINK;
    102 	sk->s_seq_expect = sk->s_seq_next = time(0);
    103 	sk->s_local.nl_pid = generate_local_port();
    104 	if (sk->s_local.nl_pid == UINT_MAX) {
    105 		nl_socket_free(sk);
    106 		return NULL;
    107 	}
    108 
    109 	return sk;
    110 }
    111 
    112 /**
    113  * Allocate new netlink socket
    114  *
    115  * @return Newly allocated netlink socket or NULL.
    116  */
    117 struct nl_sock *nl_socket_alloc(void)
    118 {
    119 	struct nl_cb *cb;
    120 
    121 	cb = nl_cb_alloc(default_cb);
    122 	if (!cb)
    123 		return NULL;
    124 
    125 	return __alloc_socket(cb);
    126 }
    127 
    128 /**
    129  * Allocate new socket with custom callbacks
    130  * @arg cb		Callback handler
    131  *
    132  * The reference to the callback handler is taken into account
    133  * automatically, it is released again upon calling nl_socket_free().
    134  *
    135  *@return Newly allocted socket handle or NULL.
    136  */
    137 struct nl_sock *nl_socket_alloc_cb(struct nl_cb *cb)
    138 {
    139 	if (cb == NULL)
    140 		BUG();
    141 
    142 	return __alloc_socket(nl_cb_get(cb));
    143 }
    144 
    145 /**
    146  * Free a netlink socket.
    147  * @arg sk		Netlink socket.
    148  */
    149 void nl_socket_free(struct nl_sock *sk)
    150 {
    151 	if (!sk)
    152 		return;
    153 
    154 	if (sk->s_fd >= 0)
    155 		close(sk->s_fd);
    156 
    157 	if (!(sk->s_flags & NL_OWN_PORT))
    158 		release_local_port(sk->s_local.nl_pid);
    159 
    160 	nl_cb_put(sk->s_cb);
    161 	free(sk);
    162 }
    163 
    164 /** @} */
    165 
    166 /**
    167  * @name Sequence Numbers
    168  * @{
    169  */
    170 
    171 static int noop_seq_check(struct nl_msg *msg, void *arg)
    172 {
    173 	return NL_OK;
    174 }
    175 
    176 
    177 /**
    178  * Disable sequence number checking.
    179  * @arg sk		Netlink socket.
    180  *
    181  * Disables checking of sequence numbers on the netlink socket This is
    182  * required to allow messages to be processed which were not requested by
    183  * a preceding request message, e.g. netlink events.
    184  *
    185  * @note This function modifies the NL_CB_SEQ_CHECK configuration in
    186  * the callback handle associated with the socket.
    187  */
    188 void nl_socket_disable_seq_check(struct nl_sock *sk)
    189 {
    190 	nl_cb_set(sk->s_cb, NL_CB_SEQ_CHECK,
    191 		  NL_CB_CUSTOM, noop_seq_check, NULL);
    192 }
    193 
    194 /**
    195  * Use next sequence number
    196  * @arg sk		Netlink socket.
    197  *
    198  * Uses the next available sequence number and increases the counter
    199  * by one for subsequent calls.
    200  *
    201  * @return Unique serial sequence number
    202  */
    203 unsigned int nl_socket_use_seq(struct nl_sock *sk)
    204 {
    205 	return sk->s_seq_next++;
    206 }
    207 
    208 /**
    209  * Disable automatic request for ACK
    210  * @arg sk		Netlink socket.
    211  *
    212  * The default behaviour of a socket is to request an ACK for
    213  * each message sent to allow for the caller to synchronize to
    214  * the completion of the netlink operation. This function
    215  * disables this behaviour and will result in requests being
    216  * sent which will not have the NLM_F_ACK flag set automatically.
    217  * However, it is still possible for the caller to set the
    218  * NLM_F_ACK flag explicitely.
    219  */
    220 void nl_socket_disable_auto_ack(struct nl_sock *sk)
    221 {
    222 	sk->s_flags |= NL_NO_AUTO_ACK;
    223 }
    224 
    225 /**
    226  * Enable automatic request for ACK (default)
    227  * @arg sk		Netlink socket.
    228  * @see nl_socket_disable_auto_ack
    229  */
    230 void nl_socket_enable_auto_ack(struct nl_sock *sk)
    231 {
    232 	sk->s_flags &= ~NL_NO_AUTO_ACK;
    233 }
    234 
    235 /** @} */
    236 
    237 /**
    238  * @name Source Idenficiation
    239  * @{
    240  */
    241 
    242 uint32_t nl_socket_get_local_port(struct nl_sock *sk)
    243 {
    244 	return sk->s_local.nl_pid;
    245 }
    246 
    247 /**
    248  * Set local port of socket
    249  * @arg sk		Netlink socket.
    250  * @arg port		Local port identifier
    251  *
    252  * Assigns a local port identifier to the socket. If port is 0
    253  * a unique port identifier will be generated automatically.
    254  */
    255 void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port)
    256 {
    257 	if (port == 0) {
    258 		port = generate_local_port();
    259 		sk->s_flags &= ~NL_OWN_PORT;
    260 	} else  {
    261 		if (!(sk->s_flags & NL_OWN_PORT))
    262 			release_local_port(sk->s_local.nl_pid);
    263 		sk->s_flags |= NL_OWN_PORT;
    264 	}
    265 
    266 	sk->s_local.nl_pid = port;
    267 }
    268 
    269 /** @} */
    270 
    271 /**
    272  * @name Group Subscriptions
    273  * @{
    274  */
    275 
    276 /**
    277  * Join groups
    278  * @arg sk		Netlink socket
    279  * @arg group		Group identifier
    280  *
    281  * Joins the specified groups using the modern socket option which
    282  * is available since kernel version 2.6.14. It allows joining an
    283  * almost arbitary number of groups without limitation.  The list
    284  * of groups has to be terminated by 0 (%NFNLGRP_NONE).
    285  *
    286  * Make sure to use the correct group definitions as the older
    287  * bitmask definitions for nl_join_groups() are likely to still
    288  * be present for backward compatibility reasons.
    289  *
    290  * @return 0 on sucess or a negative error code.
    291  */
    292 int nl_socket_add_memberships(struct nl_sock *sk, int group, ...)
    293 {
    294 	int err;
    295 	va_list ap;
    296 
    297 	if (sk->s_fd == -1)
    298 		return -NLE_BAD_SOCK;
    299 
    300 	va_start(ap, group);
    301 
    302 	while (group != 0) {
    303 		if (group < 0)
    304 			return -NLE_INVAL;
    305 
    306 		err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
    307 						 &group, sizeof(group));
    308 		if (err < 0)
    309 			return -nl_syserr2nlerr(errno);
    310 
    311 		group = va_arg(ap, int);
    312 	}
    313 
    314 	va_end(ap);
    315 
    316 	return 0;
    317 }
    318 
    319 int nl_socket_add_membership(struct nl_sock *sk, int group)
    320 {
    321 	return nl_socket_add_memberships(sk, group, 0);
    322 }
    323 
    324 /**
    325  * Leave groups
    326  * @arg sk		Netlink socket
    327  * @arg group		Group identifier
    328  *
    329  * Leaves the specified groups using the modern socket option
    330  * which is available since kernel version 2.6.14. The list of groups
    331  * has to terminated by 0 (%NFNLGRP_NONE).
    332  *
    333  * @see nl_socket_add_membership
    334  * @return 0 on success or a negative error code.
    335  */
    336 int nl_socket_drop_memberships(struct nl_sock *sk, int group, ...)
    337 {
    338 	int err;
    339 	va_list ap;
    340 
    341 	if (sk->s_fd == -1)
    342 		return -NLE_BAD_SOCK;
    343 
    344 	va_start(ap, group);
    345 
    346 	while (group != 0) {
    347 		if (group < 0)
    348 			return -NLE_INVAL;
    349 
    350 		err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
    351 						 &group, sizeof(group));
    352 		if (err < 0)
    353 			return -nl_syserr2nlerr(errno);
    354 
    355 		group = va_arg(ap, int);
    356 	}
    357 
    358 	va_end(ap);
    359 
    360 	return 0;
    361 }
    362 
    363 int nl_socket_drop_membership(struct nl_sock *sk, int group)
    364 {
    365 	return nl_socket_drop_memberships(sk, group, 0);
    366 }
    367 
    368 
    369 /**
    370  * Join multicast groups (deprecated)
    371  * @arg sk		Netlink socket.
    372  * @arg groups		Bitmask of groups to join.
    373  *
    374  * This function defines the old way of joining multicast group which
    375  * has to be done prior to calling nl_connect(). It works on any kernel
    376  * version but is very limited as only 32 groups can be joined.
    377  */
    378 void nl_join_groups(struct nl_sock *sk, int groups)
    379 {
    380 	sk->s_local.nl_groups |= groups;
    381 }
    382 
    383 
    384 /** @} */
    385 
    386 /**
    387  * @name Peer Identfication
    388  * @{
    389  */
    390 
    391 uint32_t nl_socket_get_peer_port(struct nl_sock *sk)
    392 {
    393 	return sk->s_peer.nl_pid;
    394 }
    395 
    396 void nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port)
    397 {
    398 	sk->s_peer.nl_pid = port;
    399 }
    400 
    401 /** @} */
    402 
    403 /**
    404  * @name File Descriptor
    405  * @{
    406  */
    407 
    408 int nl_socket_get_fd(struct nl_sock *sk)
    409 {
    410 	return sk->s_fd;
    411 }
    412 
    413 /**
    414  * Set file descriptor of socket to non-blocking state
    415  * @arg sk		Netlink socket.
    416  *
    417  * @return 0 on success or a negative error code.
    418  */
    419 int nl_socket_set_nonblocking(struct nl_sock *sk)
    420 {
    421 	if (sk->s_fd == -1)
    422 		return -NLE_BAD_SOCK;
    423 
    424 	if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0)
    425 		return -nl_syserr2nlerr(errno);
    426 
    427 	return 0;
    428 }
    429 
    430 /**
    431  * Enable use of MSG_PEEK when reading from socket
    432  * @arg sk		Netlink socket.
    433  */
    434 void nl_socket_enable_msg_peek(struct nl_sock *sk)
    435 {
    436 	sk->s_flags |= NL_MSG_PEEK;
    437 }
    438 
    439 /**
    440  * Disable use of MSG_PEEK when reading from socket
    441  * @arg sk		Netlink socket.
    442  */
    443 void nl_socket_disable_msg_peek(struct nl_sock *sk)
    444 {
    445 	sk->s_flags &= ~NL_MSG_PEEK;
    446 }
    447 
    448 /** @} */
    449 
    450 /**
    451  * @name Callback Handler
    452  * @{
    453  */
    454 
    455 struct nl_cb *nl_socket_get_cb(struct nl_sock *sk)
    456 {
    457 	return nl_cb_get(sk->s_cb);
    458 }
    459 
    460 void nl_socket_set_cb(struct nl_sock *sk, struct nl_cb *cb)
    461 {
    462 	nl_cb_put(sk->s_cb);
    463 	sk->s_cb = nl_cb_get(cb);
    464 }
    465 
    466 /**
    467  * Modify the callback handler associated to the socket
    468  * @arg sk		Netlink socket.
    469  * @arg type		which type callback to set
    470  * @arg kind		kind of callback
    471  * @arg func		callback function
    472  * @arg arg		argument to be passwd to callback function
    473  *
    474  * @see nl_cb_set
    475  */
    476 int nl_socket_modify_cb(struct nl_sock *sk, enum nl_cb_type type,
    477 			enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func,
    478 			void *arg)
    479 {
    480 	return nl_cb_set(sk->s_cb, type, kind, func, arg);
    481 }
    482 
    483 /** @} */
    484 
    485 /**
    486  * @name Utilities
    487  * @{
    488  */
    489 
    490 /**
    491  * Set socket buffer size of netlink socket.
    492  * @arg sk		Netlink socket.
    493  * @arg rxbuf		New receive socket buffer size in bytes.
    494  * @arg txbuf		New transmit socket buffer size in bytes.
    495  *
    496  * Sets the socket buffer size of a netlink socket to the specified
    497  * values \c rxbuf and \c txbuf. Providing a value of \c 0 assumes a
    498  * good default value.
    499  *
    500  * @note It is not required to call this function prior to nl_connect().
    501  * @return 0 on sucess or a negative error code.
    502  */
    503 int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf)
    504 {
    505 	int err;
    506 
    507 	if (rxbuf <= 0)
    508 		rxbuf = 32768;
    509 
    510 	if (txbuf <= 0)
    511 		txbuf = 32768;
    512 
    513 	if (sk->s_fd == -1)
    514 		return -NLE_BAD_SOCK;
    515 
    516 	err = setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF,
    517 			 &txbuf, sizeof(txbuf));
    518 	if (err < 0)
    519 		return -nl_syserr2nlerr(errno);
    520 
    521 	err = setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF,
    522 			 &rxbuf, sizeof(rxbuf));
    523 	if (err < 0)
    524 		return -nl_syserr2nlerr(errno);
    525 
    526 	sk->s_flags |= NL_SOCK_BUFSIZE_SET;
    527 
    528 	return 0;
    529 }
    530 
    531 /**
    532  * Enable/disable credential passing on netlink socket.
    533  * @arg sk		Netlink socket.
    534  * @arg state		New state (0 - disabled, 1 - enabled)
    535  *
    536  * @return 0 on success or a negative error code
    537  */
    538 int nl_socket_set_passcred(struct nl_sock *sk, int state)
    539 {
    540 	int err;
    541 
    542 	if (sk->s_fd == -1)
    543 		return -NLE_BAD_SOCK;
    544 
    545 	err = setsockopt(sk->s_fd, SOL_SOCKET, SO_PASSCRED,
    546 			 &state, sizeof(state));
    547 	if (err < 0)
    548 		return -nl_syserr2nlerr(errno);
    549 
    550 	if (state)
    551 		sk->s_flags |= NL_SOCK_PASSCRED;
    552 	else
    553 		sk->s_flags &= ~NL_SOCK_PASSCRED;
    554 
    555 	return 0;
    556 }
    557 
    558 /**
    559  * Enable/disable receival of additional packet information
    560  * @arg sk		Netlink socket.
    561  * @arg state		New state (0 - disabled, 1 - enabled)
    562  *
    563  * @return 0 on success or a negative error code
    564  */
    565 int nl_socket_recv_pktinfo(struct nl_sock *sk, int state)
    566 {
    567 	int err;
    568 
    569 	if (sk->s_fd == -1)
    570 		return -NLE_BAD_SOCK;
    571 
    572 	err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_PKTINFO,
    573 			 &state, sizeof(state));
    574 	if (err < 0)
    575 		return -nl_syserr2nlerr(errno);
    576 
    577 	return 0;
    578 }
    579 
    580 /** @} */
    581 
    582 /** @} */
    583