libnl  1.1.4
socket.c
1 /*
2  * lib/socket.c Netlink Socket Handle
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-2006 Thomas Graf <tgraf@suug.ch>
10  */
11 
12 /**
13  * @ingroup nl
14  * @defgroup socket Socket
15  * @brief Handle representing a netlink socket.
16  *
17  * The socket is represented in a structure called the netlink handle,
18  * besides the socket, it stores various settings and values related
19  * to the socket. Every socket handle has a mandatory association with
20  * a set of callbacks which can be used to modify the behaviour when
21  * sending/receiving data from the socket.
22  *
23  * @par Socket Attributes
24  * - \b Local \b Port: The local port is a netlink port identifying the
25  * local endpoint. It is used as source address for outgoing messages
26  * and will be addressed in replies. It must therefore be unique among
27  * all userspace applications. When the socket handle is allocated, a
28  * unique port number is generated automatically in the form of 22 bits
29  * Process Identifier + 10 bits Arbitary Number. Therefore the library
30  * is capable of generating 1024 unique local port numbers for every
31  * process. If more sockets are required, the application has to manage
32  * port numbers itself using nl_socket_set_local_port().
33  * - \b Group \b Subscriptions: A socket can subscribe to any number of
34  * multicast groups. It will then receive a copy of all messages sent
35  * to one of the groups. This method is mainly used for event notification.
36  * Prior to kernel 2.6.14, the group subscription was done via bitmask
37  * which limited to a total number of groups of 32. With 2.6.14 a new
38  * method was added based on continous identifiers which supports an
39  * arbitary number of groups. Both methods are supported, see
40  * nl_join_groups() respectively nl_socket_add_membership() and
41  * nl_socket_drop_membership().
42  * - \b Peer \b Port: The peer port is a netlink port identifying the
43  * peer's endpoint. If no peer port is specified, the kernel will try to
44  * autobind to a socket of the specified netlink family automatically.
45  * This is very common as typically only one listening socket exists
46  * on the kernel side. The peer port can be modified using
47  * nl_socket_set_peer_port().
48  * - \b Peer \b Groups:
49  * - \b File \b Descriptor: The file descriptor of the socket, it can be
50  * accessed via nl_socket_get_fd() to change socket options or monitor
51  * activity using poll()/select().
52  * - \b Protocol: Once connected, the socket is bound to stick to one
53  * netlink family. This field is invisible, it is maintained automatically.
54  * (See nl_connect())
55  * - \b Next \b Sequence \b Number: Next available sequence number to be used
56  * for the next message being sent out. (Initial value: UNIX time when the
57  * socket was allocated.) Sequence numbers can be used via
58  * nl_socket_use_seq().
59  * - \b Expected \b Sequence \b Number: Expected sequence number in the next
60  * message received from the socket. (Initial value: Equal to next sequence
61  * number.)
62  * - \b Callbacks \b Configuration:
63  *
64  * @par 1) Creating the netlink handle
65  * @code
66  * struct nl_handle *handle;
67  *
68  * // Allocate and initialize a new netlink handle
69  * handle = nl_handle_alloc();
70  *
71  * // Use nl_socket_get_fd() to fetch the file description, for example to
72  * // put a socket into non-blocking i/o mode.
73  * fcntl(nl_socket_get_fd(handle), F_SETFL, O_NONBLOCK);
74  * @endcode
75  *
76  * @par 2) Group Subscriptions
77  * @code
78  * // Event notifications are typically sent to multicast addresses which
79  * // represented by groups. Join a group to f.e. receive link notifications.
80  * nl_socket_add_membership(handle, RTNLGRP_LINK);
81  * @endcode
82  *
83  * @par 6) Cleaning up
84  * @code
85  * // Finally destroy the netlink handle
86  * nl_handle_destroy(handle);
87  * @endcode
88  *
89  * @{
90  */
91 
92 #include "defs.h"
93 
94 #include <netlink-local.h>
95 #include <netlink/netlink.h>
96 #include <netlink/utils.h>
97 #include <netlink/handlers.h>
98 #include <netlink/msg.h>
99 #include <netlink/attr.h>
100 
101 static int default_cb = NL_CB_DEFAULT;
102 
103 static void __init init_default_cb(void)
104 {
105  char *nlcb;
106 
107  if ((nlcb = getenv("NLCB"))) {
108  if (!strcasecmp(nlcb, "default"))
109  default_cb = NL_CB_DEFAULT;
110  else if (!strcasecmp(nlcb, "verbose"))
111  default_cb = NL_CB_VERBOSE;
112  else if (!strcasecmp(nlcb, "debug"))
113  default_cb = NL_CB_DEBUG;
114  else {
115  fprintf(stderr, "Unknown value for NLCB, valid values: "
116  "{default | verbose | debug}\n");
117  }
118  }
119 }
120 
121 static uint32_t used_ports_map[32];
122 static NL_RW_LOCK(port_map_lock);
123 
124 static uint32_t generate_local_port(void)
125 {
126  int i, n;
127  uint32_t pid = getpid() & 0x3FFFFF;
128 
129  nl_write_lock(&port_map_lock);
130 
131  for (i = 0; i < 32; i++) {
132  if (used_ports_map[i] == 0xFFFFFFFF)
133  continue;
134 
135  for (n = 0; n < 32; n++) {
136  if (1UL & (used_ports_map[i] >> n))
137  continue;
138 
139  used_ports_map[i] |= (1UL << n);
140  n += (i * 32);
141 
142  /* PID_MAX_LIMIT is currently at 2^22, leaving 10 bit
143  * to, i.e. 1024 unique ports per application. */
144 
145  nl_write_unlock(&port_map_lock);
146 
147  return pid + (n << 22);
148  }
149  }
150 
151  nl_write_unlock(&port_map_lock);
152 
153  /* Out of sockets in our own PID namespace, what to do? FIXME */
154  return UINT_MAX;
155 }
156 
157 static void release_local_port(uint32_t port)
158 {
159  int nr;
160 
161  if (port == UINT_MAX)
162  return;
163 
164  nr = port >> 22;
165 
166  nl_write_lock(&port_map_lock);
167  used_ports_map[nr / 32] &= ~(1 << (nr % 32));
168  nl_write_unlock(&port_map_lock);
169 }
170 
171 /**
172  * @name Allocation
173  * @{
174  */
175 
176 static struct nl_handle *__alloc_handle(struct nl_cb *cb)
177 {
178  struct nl_handle *handle;
179 
180  handle = calloc(1, sizeof(*handle));
181  if (!handle) {
182  nl_errno(ENOMEM);
183  return NULL;
184  }
185 
186  handle->h_fd = -1;
187  handle->h_cb = nl_cb_get(cb);
188  handle->h_local.nl_family = AF_NETLINK;
189  handle->h_peer.nl_family = AF_NETLINK;
190  handle->h_seq_expect = handle->h_seq_next = time(0);
191  handle->h_local.nl_pid = generate_local_port();
192  if (handle->h_local.nl_pid == UINT_MAX) {
193  nl_handle_destroy(handle);
194  nl_error(ENOBUFS, "Out of local ports");
195  return NULL;
196  }
197 
198  return handle;
199 }
200 
201 /**
202  * Allocate new netlink socket handle.
203  *
204  * @return Newly allocated netlink socket handle or NULL.
205  */
206 struct nl_handle *nl_handle_alloc(void)
207 {
208  struct nl_cb *cb;
209  struct nl_handle *sk;
210 
211  cb = nl_cb_alloc(default_cb);
212  if (!cb) {
213  nl_errno(ENOMEM);
214  return NULL;
215  }
216 
217  /* will increment cb reference count on success */
218  sk = __alloc_handle(cb);
219 
220  nl_cb_put(cb);
221 
222  return sk;
223 }
224 
225 /**
226  * Allocate new socket handle with custom callbacks
227  * @arg cb Callback handler
228  *
229  * The reference to the callback handler is taken into account
230  * automatically, it is released again upon calling nl_handle_destroy().
231  *
232  *@return Newly allocted socket handle or NULL.
233  */
234 struct nl_handle *nl_handle_alloc_cb(struct nl_cb *cb)
235 {
236  if (cb == NULL)
237  BUG();
238 
239  return __alloc_handle(cb);
240 }
241 
242 /**
243  * Destroy netlink handle.
244  * @arg handle Netlink handle.
245  */
246 void nl_handle_destroy(struct nl_handle *handle)
247 {
248  if (!handle)
249  return;
250 
251  if (handle->h_fd >= 0)
252  close(handle->h_fd);
253 
254  if (!(handle->h_flags & NL_OWN_PORT))
255  release_local_port(handle->h_local.nl_pid);
256 
257  nl_cb_put(handle->h_cb);
258  free(handle);
259 }
260 
261 /** @} */
262 
263 /**
264  * @name Sequence Numbers
265  * @{
266  */
267 
268 static int noop_seq_check(struct nl_msg *msg, void *arg)
269 {
270  return NL_OK;
271 }
272 
273 
274 /**
275  * Disable sequence number checking.
276  * @arg handle Netlink handle.
277  *
278  * Disables checking of sequence numbers on the netlink handle. This is
279  * required to allow messages to be processed which were not requested by
280  * a preceding request message, e.g. netlink events.
281  *
282  * @note This function modifies the NL_CB_SEQ_CHECK configuration in
283  * the callback handle associated with the socket.
284  */
285 void nl_disable_sequence_check(struct nl_handle *handle)
286 {
287  nl_cb_set(handle->h_cb, NL_CB_SEQ_CHECK,
288  NL_CB_CUSTOM, noop_seq_check, NULL);
289 }
290 
291 /**
292  * Use next sequence number
293  * @arg handle Netlink handle
294  *
295  * Uses the next available sequence number and increases the counter
296  * by one for subsequent calls.
297  *
298  * @return Unique serial sequence number
299  */
300 unsigned int nl_socket_use_seq(struct nl_handle *handle)
301 {
302  return handle->h_seq_next++;
303 }
304 
305 /** @} */
306 
307 /**
308  * @name Source Idenficiation
309  * @{
310  */
311 
312 uint32_t nl_socket_get_local_port(struct nl_handle *handle)
313 {
314  return handle->h_local.nl_pid;
315 }
316 
317 /**
318  * Set local port of socket
319  * @arg handle Netlink handle
320  * @arg port Local port identifier
321  *
322  * Assigns a local port identifier to the socket. If port is 0
323  * a unique port identifier will be generated automatically.
324  */
325 void nl_socket_set_local_port(struct nl_handle *handle, uint32_t port)
326 {
327  if (port == 0) {
328  port = generate_local_port();
329  handle->h_flags &= ~NL_OWN_PORT;
330  } else {
331  if (!(handle->h_flags & NL_OWN_PORT))
332  release_local_port(handle->h_local.nl_pid);
333  handle->h_flags |= NL_OWN_PORT;
334  }
335 
336  handle->h_local.nl_pid = port;
337 }
338 
339 /** @} */
340 
341 /**
342  * @name Group Subscriptions
343  * @{
344  */
345 
346 /**
347  * Join a group
348  * @arg handle Netlink handle
349  * @arg group Group identifier
350  *
351  * Joins the specified group using the modern socket option which
352  * is available since kernel version 2.6.14. It allows joining an
353  * almost arbitary number of groups without limitation.
354  *
355  * Make sure to use the correct group definitions as the older
356  * bitmask definitions for nl_join_groups() are likely to still
357  * be present for backward compatibility reasons.
358  *
359  * @return 0 on sucess or a negative error code.
360  */
361 int nl_socket_add_membership(struct nl_handle *handle, int group)
362 {
363  int err;
364 
365  if (handle->h_fd == -1)
366  return nl_error(EBADFD, "Socket not connected");
367 
368  err = setsockopt(handle->h_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
369  &group, sizeof(group));
370  if (err < 0)
371  return nl_error(errno, "setsockopt(NETLINK_ADD_MEMBERSHIP) "
372  "failed");
373 
374  return 0;
375 }
376 
377 /**
378  * Leave a group
379  * @arg handle Netlink handle
380  * @arg group Group identifier
381  *
382  * Leaves the specified group using the modern socket option
383  * which is available since kernel version 2.6.14.
384  *
385  * @see nl_socket_add_membership
386  * @return 0 on success or a negative error code.
387  */
388 int nl_socket_drop_membership(struct nl_handle *handle, int group)
389 {
390  int err;
391 
392  if (handle->h_fd == -1)
393  return nl_error(EBADFD, "Socket not connected");
394 
395  err = setsockopt(handle->h_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
396  &group, sizeof(group));
397  if (err < 0)
398  return nl_error(errno, "setsockopt(NETLINK_DROP_MEMBERSHIP) "
399  "failed");
400 
401  return 0;
402 }
403 
404 /**
405  * Join multicast groups (deprecated)
406  * @arg handle Netlink handle.
407  * @arg groups Bitmask of groups to join.
408  *
409  * This function defines the old way of joining multicast group which
410  * has to be done prior to calling nl_connect(). It works on any kernel
411  * version but is very limited as only 32 groups can be joined.
412  */
413 void nl_join_groups(struct nl_handle *handle, int groups)
414 {
415  handle->h_local.nl_groups |= groups;
416 }
417 
418 
419 /** @} */
420 
421 /**
422  * @name Peer Identfication
423  * @{
424  */
425 
426 uint32_t nl_socket_get_peer_port(struct nl_handle *handle)
427 {
428  return handle->h_peer.nl_pid;
429 }
430 
431 void nl_socket_set_peer_port(struct nl_handle *handle, uint32_t port)
432 {
433  handle->h_peer.nl_pid = port;
434 }
435 
436 /** @} */
437 
438 /**
439  * @name File Descriptor
440  * @{
441  */
442 
443 int nl_socket_get_fd(struct nl_handle *handle)
444 {
445  return handle->h_fd;
446 }
447 
448 /**
449  * Set file descriptor of socket handle to non-blocking state
450  * @arg handle Netlink socket
451  *
452  * @return 0 on success or a negative error code.
453  */
454 int nl_socket_set_nonblocking(struct nl_handle *handle)
455 {
456  if (handle->h_fd == -1)
457  return nl_error(EBADFD, "Socket not connected");
458 
459  if (fcntl(handle->h_fd, F_SETFL, O_NONBLOCK) < 0)
460  return nl_error(errno, "fcntl(F_SETFL, O_NONBLOCK) failed");
461 
462  return 0;
463 }
464 
465 /**
466  * Enable use of MSG_PEEK when reading from socket
467  * @arg handle Netlink socket
468  */
469 void nl_socket_enable_msg_peek(struct nl_handle *handle)
470 {
471  handle->h_flags |= NL_MSG_PEEK;
472 }
473 
474 /**
475  * Disable use of MSG_PEEK when reading from socket
476  * @arg handle Netlink socket
477  */
478 void nl_socket_disable_msg_peek(struct nl_handle *handle)
479 {
480  handle->h_flags &= ~NL_MSG_PEEK;
481 }
482 
483 /** @} */
484 
485 /**
486  * @name Callback Handler
487  * @{
488  */
489 
490 struct nl_cb *nl_socket_get_cb(struct nl_handle *handle)
491 {
492  return nl_cb_get(handle->h_cb);
493 }
494 
495 void nl_socket_set_cb(struct nl_handle *handle, struct nl_cb *cb)
496 {
497  if (cb == NULL)
498  BUG();
499 
500  nl_cb_put(handle->h_cb);
501  handle->h_cb = nl_cb_get(cb);
502 }
503 
504 /**
505  * Modify the callback handler associated to the socket
506  * @arg handle netlink handle
507  * @arg type which type callback to set
508  * @arg kind kind of callback
509  * @arg func callback function
510  * @arg arg argument to be passwd to callback function
511  *
512  * @see nl_cb_set
513  */
514 int nl_socket_modify_cb(struct nl_handle *handle, enum nl_cb_type type,
515  enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func,
516  void *arg)
517 {
518  return nl_cb_set(handle->h_cb, type, kind, func, arg);
519 }
520 
521 /** @} */
522 
523 /**
524  * @name Utilities
525  * @{
526  */
527 
528 /**
529  * Set socket buffer size of netlink handle.
530  * @arg handle Netlink handle.
531  * @arg rxbuf New receive socket buffer size in bytes.
532  * @arg txbuf New transmit socket buffer size in bytes.
533  *
534  * Sets the socket buffer size of a netlink handle to the specified
535  * values \c rxbuf and \c txbuf. Providing a value of \c 0 assumes a
536  * good default value.
537  *
538  * @note It is not required to call this function prior to nl_connect().
539  * @return 0 on sucess or a negative error code.
540  */
541 int nl_set_buffer_size(struct nl_handle *handle, int rxbuf, int txbuf)
542 {
543  int err;
544 
545  if (rxbuf <= 0)
546  rxbuf = 32768;
547 
548  if (txbuf <= 0)
549  txbuf = 32768;
550 
551  if (handle->h_fd == -1)
552  return nl_error(EBADFD, "Socket not connected");
553 
554  err = setsockopt(handle->h_fd, SOL_SOCKET, SO_SNDBUF,
555  &txbuf, sizeof(txbuf));
556  if (err < 0)
557  return nl_error(errno, "setsockopt(SO_SNDBUF) failed");
558 
559  err = setsockopt(handle->h_fd, SOL_SOCKET, SO_RCVBUF,
560  &rxbuf, sizeof(rxbuf));
561  if (err < 0)
562  return nl_error(errno, "setsockopt(SO_RCVBUF) failed");
563 
564  handle->h_flags |= NL_SOCK_BUFSIZE_SET;
565 
566  return 0;
567 }
568 
569 /**
570  * Enable/disable credential passing on netlink handle.
571  * @arg handle Netlink handle
572  * @arg state New state (0 - disabled, 1 - enabled)
573  *
574  * @return 0 on success or a negative error code
575  */
576 int nl_set_passcred(struct nl_handle *handle, int state)
577 {
578  int err;
579 
580  if (handle->h_fd == -1)
581  return nl_error(EBADFD, "Socket not connected");
582 
583  err = setsockopt(handle->h_fd, SOL_SOCKET, SO_PASSCRED,
584  &state, sizeof(state));
585  if (err < 0)
586  return nl_error(errno, "setsockopt(SO_PASSCRED) failed");
587 
588  if (state)
589  handle->h_flags |= NL_SOCK_PASSCRED;
590  else
591  handle->h_flags &= ~NL_SOCK_PASSCRED;
592 
593  return 0;
594 }
595 
596 /**
597  * Enable/disable receival of additional packet information
598  * @arg handle Netlink handle
599  * @arg state New state (0 - disabled, 1 - enabled)
600  *
601  * @return 0 on success or a negative error code
602  */
603 int nl_socket_recv_pktinfo(struct nl_handle *handle, int state)
604 {
605  int err;
606 
607  if (handle->h_fd == -1)
608  return nl_error(EBADFD, "Socket not connected");
609 
610  err = setsockopt(handle->h_fd, SOL_NETLINK, NETLINK_PKTINFO,
611  &state, sizeof(state));
612  if (err < 0)
613  return nl_error(errno, "setsockopt(NETLINK_PKTINFO) failed");
614 
615  return 0;
616 }
617 
618 /** @} */
619 
620 /** @} */
void nl_socket_disable_msg_peek(struct nl_handle *handle)
Disable use of MSG_PEEK when reading from socket.
Definition: socket.c:478
void nl_disable_sequence_check(struct nl_handle *handle)
Disable sequence number checking.
Definition: socket.c:285
void nl_handle_destroy(struct nl_handle *handle)
Destroy netlink handle.
Definition: socket.c:246
Customized handler specified by the user.
Definition: handlers.h:84
void nl_join_groups(struct nl_handle *handle, int groups)
Join multicast groups (deprecated)
Definition: socket.c:413
unsigned int nl_socket_use_seq(struct nl_handle *handle)
Use next sequence number.
Definition: socket.c:300
int nl_set_passcred(struct nl_handle *handle, int state)
Enable/disable credential passing on netlink handle.
Definition: socket.c:576
int nl_socket_recv_pktinfo(struct nl_handle *handle, int state)
Enable/disable receival of additional packet information.
Definition: socket.c:603
int nl_socket_set_nonblocking(struct nl_handle *handle)
Set file descriptor of socket handle to non-blocking state.
Definition: socket.c:454
nl_cb_kind
Callback kinds.
Definition: handlers.h:76
int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func, void *arg)
Set up a callback.
Definition: handlers.c:338
int(* nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg)
nl_recvmsgs() callback for message processing customization
Definition: handlers.h:41
struct nl_handle * nl_handle_alloc(void)
Allocate new netlink socket handle.
Definition: socket.c:206
int nl_set_buffer_size(struct nl_handle *handle, int rxbuf, int txbuf)
Set socket buffer size of netlink handle.
Definition: socket.c:541
Debug handlers for debugging.
Definition: handlers.h:82
Called instead of internal sequence number checking.
Definition: handlers.h:112
struct nl_handle * nl_handle_alloc_cb(struct nl_cb *cb)
Allocate new socket handle with custom callbacks.
Definition: socket.c:234
Proceed with wathever would come next.
Definition: handlers.h:61
nl_cb_type
Callback types.
Definition: handlers.h:94
int nl_socket_drop_membership(struct nl_handle *handle, int group)
Leave a group.
Definition: socket.c:388
struct nl_cb * nl_cb_alloc(enum nl_cb_kind kind)
Allocate a new callback handle.
Definition: handlers.c:256
void nl_socket_set_local_port(struct nl_handle *handle, uint32_t port)
Set local port of socket.
Definition: socket.c:325
int nl_socket_modify_cb(struct nl_handle *handle, enum nl_cb_type type, enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func, void *arg)
Modify the callback handler associated to the socket.
Definition: socket.c:514
void nl_socket_enable_msg_peek(struct nl_handle *handle)
Enable use of MSG_PEEK when reading from socket.
Definition: socket.c:469
int nl_socket_add_membership(struct nl_handle *handle, int group)
Join a group.
Definition: socket.c:361
Default handlers (quiet)
Definition: handlers.h:78
Verbose default handlers (error messages printed)
Definition: handlers.h:80