2 * lib/socket.c Netlink Socket
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
9 * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
14 * @defgroup socket Socket
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>
25 static uint32_t used_ports_map[32];
27 static uint32_t generate_local_port(void)
30 uint32_t pid = getpid() & 0x3FFFFF;
32 for (i = 0; i < 32; i++) {
33 if (used_ports_map[i] == 0xFFFFFFFF)
36 for (n = 0; n < 32; n++) {
37 if (1UL & (used_ports_map[i] >> n))
40 used_ports_map[i] |= (1UL << n);
43 /* PID_MAX_LIMIT is currently at 2^22, leaving 10 bit
44 * to, i.e. 1024 unique ports per application. */
45 return pid + (n << 22);
50 /* Out of sockets in our own PID namespace, what to do? FIXME */
54 static void release_local_port(uint32_t port)
62 used_ports_map[nr / 32] &= ~(1 << nr % 32);
70 static struct nl_sock *__alloc_socket(struct nl_cb *cb)
74 sk = calloc(1, sizeof(*sk));
80 sk->s_local.nl_family = AF_NETLINK;
81 sk->s_peer.nl_family = AF_NETLINK;
82 sk->s_seq_expect = sk->s_seq_next = time(0);
83 sk->s_local.nl_pid = generate_local_port();
84 if (sk->s_local.nl_pid == UINT_MAX) {
93 * Allocate new netlink socket
95 * @return Newly allocated netlink socket or NULL.
97 struct nl_sock *nl_socket_alloc(void)
101 cb = nl_cb_alloc(NL_CB_DEFAULT);
105 return __alloc_socket(cb);
109 * Allocate new socket with custom callbacks
110 * @arg cb Callback handler
112 * The reference to the callback handler is taken into account
113 * automatically, it is released again upon calling nl_socket_free().
115 *@return Newly allocted socket handle or NULL.
117 struct nl_sock *nl_socket_alloc_cb(struct nl_cb *cb)
122 return __alloc_socket(nl_cb_get(cb));
126 * Free a netlink socket.
127 * @arg sk Netlink socket.
129 void nl_socket_free(struct nl_sock *sk)
137 if (!(sk->s_flags & NL_OWN_PORT))
138 release_local_port(sk->s_local.nl_pid);
147 * @name Sequence Numbers
151 static int noop_seq_check(struct nl_msg *msg, void *arg)
158 * Disable sequence number checking.
159 * @arg sk Netlink socket.
161 * Disables checking of sequence numbers on the netlink socket This is
162 * required to allow messages to be processed which were not requested by
163 * a preceding request message, e.g. netlink events.
165 * @note This function modifies the NL_CB_SEQ_CHECK configuration in
166 * the callback handle associated with the socket.
168 void nl_socket_disable_seq_check(struct nl_sock *sk)
170 nl_cb_set(sk->s_cb, NL_CB_SEQ_CHECK,
171 NL_CB_CUSTOM, noop_seq_check, NULL);
177 * Set local port of socket
178 * @arg sk Netlink socket.
179 * @arg port Local port identifier
181 * Assigns a local port identifier to the socket. If port is 0
182 * a unique port identifier will be generated automatically.
184 void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port)
187 port = generate_local_port();
188 sk->s_flags &= ~NL_OWN_PORT;
190 if (!(sk->s_flags & NL_OWN_PORT))
191 release_local_port(sk->s_local.nl_pid);
192 sk->s_flags |= NL_OWN_PORT;
195 sk->s_local.nl_pid = port;
201 * @name Group Subscriptions
207 * @arg sk Netlink socket
208 * @arg group Group identifier
210 * Joins the specified groups using the modern socket option which
211 * is available since kernel version 2.6.14. It allows joining an
212 * almost arbitary number of groups without limitation. The list
213 * of groups has to be terminated by 0 (%NFNLGRP_NONE).
215 * Make sure to use the correct group definitions as the older
216 * bitmask definitions for nl_join_groups() are likely to still
217 * be present for backward compatibility reasons.
219 * @return 0 on sucess or a negative error code.
221 int nl_socket_add_memberships(struct nl_sock *sk, int group, ...)
227 return -NLE_BAD_SOCK;
235 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
236 &group, sizeof(group));
238 return -nl_syserr2nlerr(errno);
240 group = va_arg(ap, int);
250 * @arg sk Netlink socket
251 * @arg group Group identifier
253 * Leaves the specified groups using the modern socket option
254 * which is available since kernel version 2.6.14. The list of groups
255 * has to terminated by 0 (%NFNLGRP_NONE).
257 * @see nl_socket_add_membership
258 * @return 0 on success or a negative error code.
260 int nl_socket_drop_memberships(struct nl_sock *sk, int group, ...)
266 return -NLE_BAD_SOCK;
274 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
275 &group, sizeof(group));
277 return -nl_syserr2nlerr(errno);
279 group = va_arg(ap, int);
291 * Set file descriptor of socket to non-blocking state
292 * @arg sk Netlink socket.
294 * @return 0 on success or a negative error code.
296 int nl_socket_set_nonblocking(struct nl_sock *sk)
299 return -NLE_BAD_SOCK;
301 if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0)
302 return -nl_syserr2nlerr(errno);
315 * Set socket buffer size of netlink socket.
316 * @arg sk Netlink socket.
317 * @arg rxbuf New receive socket buffer size in bytes.
318 * @arg txbuf New transmit socket buffer size in bytes.
320 * Sets the socket buffer size of a netlink socket to the specified
321 * values \c rxbuf and \c txbuf. Providing a value of \c 0 assumes a
322 * good default value.
324 * @note It is not required to call this function prior to nl_connect().
325 * @return 0 on sucess or a negative error code.
327 int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf)
338 return -NLE_BAD_SOCK;
340 err = setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF,
341 &txbuf, sizeof(txbuf));
343 return -nl_syserr2nlerr(errno);
345 err = setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF,
346 &rxbuf, sizeof(rxbuf));
348 return -nl_syserr2nlerr(errno);
350 sk->s_flags |= NL_SOCK_BUFSIZE_SET;
356 * Enable/disable credential passing on netlink socket.
357 * @arg sk Netlink socket.
358 * @arg state New state (0 - disabled, 1 - enabled)
360 * @return 0 on success or a negative error code
362 int nl_socket_set_passcred(struct nl_sock *sk, int state)
367 return -NLE_BAD_SOCK;
369 err = setsockopt(sk->s_fd, SOL_SOCKET, SO_PASSCRED,
370 &state, sizeof(state));
372 return -nl_syserr2nlerr(errno);
375 sk->s_flags |= NL_SOCK_PASSCRED;
377 sk->s_flags &= ~NL_SOCK_PASSCRED;
383 * Enable/disable receival of additional packet information
384 * @arg sk Netlink socket.
385 * @arg state New state (0 - disabled, 1 - enabled)
387 * @return 0 on success or a negative error code
389 int nl_socket_recv_pktinfo(struct nl_sock *sk, int state)
394 return -NLE_BAD_SOCK;
396 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_PKTINFO,
397 &state, sizeof(state));
399 return -nl_syserr2nlerr(errno);