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