libnl  3.2.3
/build/buildd/libnl3-3.2.3/lib/socket.c
00001 /*
00002  * lib/socket.c         Netlink Socket
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup core
00014  * @defgroup socket Socket
00015  * @{
00016  */
00017 
00018 #include <pthread.h>
00019 
00020 #include <netlink-local.h>
00021 #include <netlink/netlink.h>
00022 #include <netlink/utils.h>
00023 #include <netlink/handlers.h>
00024 #include <netlink/msg.h>
00025 #include <netlink/attr.h>
00026 
00027 static int default_cb = NL_CB_DEFAULT;
00028 
00029 static void __init init_default_cb(void)
00030 {
00031         char *nlcb;
00032 
00033         if ((nlcb = getenv("NLCB"))) {
00034                 if (!strcasecmp(nlcb, "default"))
00035                         default_cb = NL_CB_DEFAULT;
00036                 else if (!strcasecmp(nlcb, "verbose"))
00037                         default_cb = NL_CB_VERBOSE;
00038                 else if (!strcasecmp(nlcb, "debug"))
00039                         default_cb = NL_CB_DEBUG;
00040                 else {
00041                         fprintf(stderr, "Unknown value for NLCB, valid values: "
00042                                 "{default | verbose | debug}\n");
00043                 }
00044         }
00045 }
00046 
00047 static uint32_t used_ports_map[32];
00048 static pthread_mutex_t port_map_mutex = PTHREAD_MUTEX_INITIALIZER;
00049 
00050 static uint32_t generate_local_port(void)
00051 {
00052         int i, n;
00053         uint32_t pid = getpid() & 0x3FFFFF;
00054 
00055         pthread_mutex_lock(&port_map_mutex);
00056 
00057         for (i = 0; i < 32; i++) {
00058                 if (used_ports_map[i] == 0xFFFFFFFF)
00059                         continue;
00060 
00061                 for (n = 0; n < 32; n++) {
00062                         if (1UL & (used_ports_map[i] >> n))
00063                                 continue;
00064 
00065                         used_ports_map[i] |= (1UL << n);
00066                         n += (i * 32);
00067 
00068                         /* PID_MAX_LIMIT is currently at 2^22, leaving 10 bit
00069                          * to, i.e. 1024 unique ports per application. */
00070 
00071                         pthread_mutex_unlock(&port_map_mutex);
00072 
00073                         return pid + (n << 22);
00074                 }
00075         }
00076 
00077         pthread_mutex_unlock(&port_map_mutex);
00078 
00079         /* Out of sockets in our own PID namespace, what to do? FIXME */
00080         return UINT_MAX;
00081 }
00082 
00083 static void release_local_port(uint32_t port)
00084 {
00085         int nr;
00086 
00087         if (port == UINT_MAX)
00088                 return;
00089         
00090         nr = port >> 22;
00091 
00092         pthread_mutex_lock(&port_map_mutex);
00093         used_ports_map[nr / 32] &= ~(1 << (nr % 32));
00094         pthread_mutex_unlock(&port_map_mutex);
00095 }
00096 
00097 /**
00098  * @name Allocation
00099  * @{
00100  */
00101 
00102 static struct nl_sock *__alloc_socket(struct nl_cb *cb)
00103 {
00104         struct nl_sock *sk;
00105 
00106         sk = calloc(1, sizeof(*sk));
00107         if (!sk)
00108                 return NULL;
00109 
00110         sk->s_fd = -1;
00111         sk->s_cb = cb;
00112         sk->s_local.nl_family = AF_NETLINK;
00113         sk->s_peer.nl_family = AF_NETLINK;
00114         sk->s_seq_expect = sk->s_seq_next = time(0);
00115         sk->s_local.nl_pid = generate_local_port();
00116         if (sk->s_local.nl_pid == UINT_MAX) {
00117                 nl_socket_free(sk);
00118                 return NULL;
00119         }
00120 
00121         return sk;
00122 }
00123 
00124 /**
00125  * Allocate new netlink socket
00126  *
00127  * @return Newly allocated netlink socket or NULL.
00128  */
00129 struct nl_sock *nl_socket_alloc(void)
00130 {
00131         struct nl_cb *cb;
00132         
00133         cb = nl_cb_alloc(default_cb);
00134         if (!cb)
00135                 return NULL;
00136 
00137         return __alloc_socket(cb);
00138 }
00139 
00140 /**
00141  * Allocate new socket with custom callbacks
00142  * @arg cb              Callback handler
00143  *
00144  * The reference to the callback handler is taken into account
00145  * automatically, it is released again upon calling nl_socket_free().
00146  *
00147  *@return Newly allocted socket handle or NULL.
00148  */
00149 struct nl_sock *nl_socket_alloc_cb(struct nl_cb *cb)
00150 {
00151         if (cb == NULL)
00152                 BUG();
00153 
00154         return __alloc_socket(nl_cb_get(cb));
00155 }
00156 
00157 /**
00158  * Free a netlink socket.
00159  * @arg sk              Netlink socket.
00160  */
00161 void nl_socket_free(struct nl_sock *sk)
00162 {
00163         if (!sk)
00164                 return;
00165 
00166         if (sk->s_fd >= 0)
00167                 close(sk->s_fd);
00168 
00169         if (!(sk->s_flags & NL_OWN_PORT))
00170                 release_local_port(sk->s_local.nl_pid);
00171 
00172         nl_cb_put(sk->s_cb);
00173         free(sk);
00174 }
00175 
00176 /** @} */
00177 
00178 /**
00179  * @name Sequence Numbers
00180  * @{
00181  */
00182 
00183 static int noop_seq_check(struct nl_msg *msg, void *arg)
00184 {
00185         return NL_OK;
00186 }
00187 
00188 
00189 /**
00190  * Disable sequence number checking.
00191  * @arg sk              Netlink socket.
00192  *
00193  * Disables checking of sequence numbers on the netlink socket This is
00194  * required to allow messages to be processed which were not requested by
00195  * a preceding request message, e.g. netlink events.
00196  *
00197  * @note This function modifies the NL_CB_SEQ_CHECK configuration in
00198  * the callback handle associated with the socket.
00199  */
00200 void nl_socket_disable_seq_check(struct nl_sock *sk)
00201 {
00202         nl_cb_set(sk->s_cb, NL_CB_SEQ_CHECK,
00203                   NL_CB_CUSTOM, noop_seq_check, NULL);
00204 }
00205 
00206 /**
00207  * Use next sequence number
00208  * @arg sk              Netlink socket.
00209  *
00210  * Uses the next available sequence number and increases the counter
00211  * by one for subsequent calls.
00212  *
00213  * @return Unique serial sequence number
00214  */
00215 unsigned int nl_socket_use_seq(struct nl_sock *sk)
00216 {
00217         return sk->s_seq_next++;
00218 }
00219 
00220 /**
00221  * Disable automatic request for ACK
00222  * @arg sk              Netlink socket.
00223  *
00224  * The default behaviour of a socket is to request an ACK for
00225  * each message sent to allow for the caller to synchronize to
00226  * the completion of the netlink operation. This function
00227  * disables this behaviour and will result in requests being
00228  * sent which will not have the NLM_F_ACK flag set automatically.
00229  * However, it is still possible for the caller to set the
00230  * NLM_F_ACK flag explicitely.
00231  */
00232 void nl_socket_disable_auto_ack(struct nl_sock *sk)
00233 {
00234         sk->s_flags |= NL_NO_AUTO_ACK;
00235 }
00236 
00237 /**
00238  * Enable automatic request for ACK (default)
00239  * @arg sk              Netlink socket.
00240  * @see nl_socket_disable_auto_ack
00241  */
00242 void nl_socket_enable_auto_ack(struct nl_sock *sk)
00243 {
00244         sk->s_flags &= ~NL_NO_AUTO_ACK;
00245 }
00246 
00247 /** @} */
00248 
00249 /**
00250  * @name Source Idenficiation
00251  * @{
00252  */
00253 
00254 uint32_t nl_socket_get_local_port(const struct nl_sock *sk)
00255 {
00256         return sk->s_local.nl_pid;
00257 }
00258 
00259 /**
00260  * Set local port of socket
00261  * @arg sk              Netlink socket.
00262  * @arg port            Local port identifier
00263  *
00264  * Assigns a local port identifier to the socket. If port is 0
00265  * a unique port identifier will be generated automatically.
00266  */
00267 void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port)
00268 {
00269         if (port == 0) {
00270                 port = generate_local_port(); 
00271                 /*
00272                  * Release local port after generation of a new one to be
00273                  * able to change local port using nl_socket_set_local_port(, 0)
00274                  */
00275                 if (!(sk->s_flags & NL_OWN_PORT))
00276                         release_local_port(sk->s_local.nl_pid);
00277                 else
00278                         sk->s_flags &= ~NL_OWN_PORT;
00279         } else  {
00280                 if (!(sk->s_flags & NL_OWN_PORT))
00281                         release_local_port(sk->s_local.nl_pid);
00282                 sk->s_flags |= NL_OWN_PORT;
00283         }
00284 
00285         sk->s_local.nl_pid = port;
00286 }
00287 
00288 /** @} */
00289 
00290 /**
00291  * @name Group Subscriptions
00292  * @{
00293  */
00294 
00295 /**
00296  * Join groups
00297  * @arg sk              Netlink socket
00298  * @arg group           Group identifier
00299  *
00300  * Joins the specified groups using the modern socket option which
00301  * is available since kernel version 2.6.14. It allows joining an
00302  * almost arbitary number of groups without limitation.  The list
00303  * of groups has to be terminated by 0 (%NFNLGRP_NONE).
00304  *
00305  * Make sure to use the correct group definitions as the older
00306  * bitmask definitions for nl_join_groups() are likely to still
00307  * be present for backward compatibility reasons.
00308  *
00309  * @return 0 on sucess or a negative error code.
00310  */
00311 int nl_socket_add_memberships(struct nl_sock *sk, int group, ...)
00312 {
00313         int err;
00314         va_list ap;
00315 
00316         if (sk->s_fd == -1)
00317                 return -NLE_BAD_SOCK;
00318 
00319         va_start(ap, group);
00320 
00321         while (group != 0) {
00322                 if (group < 0)
00323                         return -NLE_INVAL;
00324 
00325                 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
00326                                                  &group, sizeof(group));
00327                 if (err < 0)
00328                         return -nl_syserr2nlerr(errno);
00329 
00330                 group = va_arg(ap, int);
00331         }
00332 
00333         va_end(ap);
00334 
00335         return 0;
00336 }
00337 
00338 int nl_socket_add_membership(struct nl_sock *sk, int group)
00339 {
00340         return nl_socket_add_memberships(sk, group, 0);
00341 }
00342 
00343 /**
00344  * Leave groups
00345  * @arg sk              Netlink socket
00346  * @arg group           Group identifier
00347  *
00348  * Leaves the specified groups using the modern socket option
00349  * which is available since kernel version 2.6.14. The list of groups
00350  * has to terminated by 0 (%NFNLGRP_NONE).
00351  *
00352  * @see nl_socket_add_membership
00353  * @return 0 on success or a negative error code.
00354  */
00355 int nl_socket_drop_memberships(struct nl_sock *sk, int group, ...)
00356 {
00357         int err;
00358         va_list ap;
00359 
00360         if (sk->s_fd == -1)
00361                 return -NLE_BAD_SOCK;
00362 
00363         va_start(ap, group);
00364 
00365         while (group != 0) {
00366                 if (group < 0)
00367                         return -NLE_INVAL;
00368 
00369                 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
00370                                                  &group, sizeof(group));
00371                 if (err < 0)
00372                         return -nl_syserr2nlerr(errno);
00373 
00374                 group = va_arg(ap, int);
00375         }
00376 
00377         va_end(ap);
00378 
00379         return 0;
00380 }
00381 
00382 int nl_socket_drop_membership(struct nl_sock *sk, int group)
00383 {
00384         return nl_socket_drop_memberships(sk, group, 0);
00385 }
00386 
00387 
00388 /**
00389  * Join multicast groups (deprecated)
00390  * @arg sk              Netlink socket.
00391  * @arg groups          Bitmask of groups to join.
00392  *
00393  * This function defines the old way of joining multicast group which
00394  * has to be done prior to calling nl_connect(). It works on any kernel
00395  * version but is very limited as only 32 groups can be joined.
00396  */
00397 void nl_join_groups(struct nl_sock *sk, int groups)
00398 {
00399         sk->s_local.nl_groups |= groups;
00400 }
00401 
00402 
00403 /** @} */
00404 
00405 /**
00406  * @name Peer Identfication
00407  * @{
00408  */
00409 
00410 uint32_t nl_socket_get_peer_port(const struct nl_sock *sk)
00411 {
00412         return sk->s_peer.nl_pid;
00413 }
00414 
00415 void nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port)
00416 {
00417         sk->s_peer.nl_pid = port;
00418 }
00419 
00420 uint32_t nl_socket_get_peer_groups(const struct nl_sock *sk)
00421 {
00422         return sk->s_peer.nl_groups;
00423 }
00424 
00425 void nl_socket_set_peer_groups(struct nl_sock *sk, uint32_t groups)
00426 {
00427         sk->s_peer.nl_groups = groups;
00428 }
00429 
00430 
00431 
00432 /** @} */
00433 
00434 /**
00435  * @name File Descriptor
00436  * @{
00437  */
00438 
00439 int nl_socket_get_fd(const struct nl_sock *sk)
00440 {
00441         return sk->s_fd;
00442 }
00443 
00444 /**
00445  * Set file descriptor of socket to non-blocking state
00446  * @arg sk              Netlink socket.
00447  *
00448  * @return 0 on success or a negative error code.
00449  */
00450 int nl_socket_set_nonblocking(const struct nl_sock *sk)
00451 {
00452         if (sk->s_fd == -1)
00453                 return -NLE_BAD_SOCK;
00454 
00455         if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0)
00456                 return -nl_syserr2nlerr(errno);
00457 
00458         return 0;
00459 }
00460 
00461 /**
00462  * Enable use of MSG_PEEK when reading from socket
00463  * @arg sk              Netlink socket.
00464  */
00465 void nl_socket_enable_msg_peek(struct nl_sock *sk)
00466 {
00467         sk->s_flags |= NL_MSG_PEEK;
00468 }
00469 
00470 /**
00471  * Disable use of MSG_PEEK when reading from socket
00472  * @arg sk              Netlink socket.
00473  */
00474 void nl_socket_disable_msg_peek(struct nl_sock *sk)
00475 {
00476         sk->s_flags &= ~NL_MSG_PEEK;
00477 }
00478 
00479 /** @} */
00480 
00481 /**
00482  * @name Callback Handler
00483  * @{
00484  */
00485 
00486 struct nl_cb *nl_socket_get_cb(const struct nl_sock *sk)
00487 {
00488         return nl_cb_get(sk->s_cb);
00489 }
00490 
00491 void nl_socket_set_cb(struct nl_sock *sk, struct nl_cb *cb)
00492 {
00493         nl_cb_put(sk->s_cb);
00494         sk->s_cb = nl_cb_get(cb);
00495 }
00496 
00497 /**
00498  * Modify the callback handler associated with the socket
00499  * @arg sk              Netlink socket.
00500  * @arg type            which type callback to set
00501  * @arg kind            kind of callback
00502  * @arg func            callback function
00503  * @arg arg             argument to be passed to callback function
00504  *
00505  * @see nl_cb_set
00506  */
00507 int nl_socket_modify_cb(struct nl_sock *sk, enum nl_cb_type type,
00508                         enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func,
00509                         void *arg)
00510 {
00511         return nl_cb_set(sk->s_cb, type, kind, func, arg);
00512 }
00513 
00514 /**
00515  * Modify the error callback handler associated with the socket
00516  * @arg sk              Netlink socket.
00517  * @arg kind            kind of callback
00518  * @arg func            callback function
00519  * @arg arg             argument to be passed to callback function
00520  *
00521  * @see nl_cb_err
00522  */
00523 int nl_socket_modify_err_cb(struct nl_sock *sk, enum nl_cb_kind kind,
00524                             nl_recvmsg_err_cb_t func, void *arg)
00525 {
00526         return nl_cb_err(sk->s_cb, kind, func, arg);
00527 }
00528 
00529 /** @} */
00530 
00531 /**
00532  * @name Utilities
00533  * @{
00534  */
00535 
00536 /**
00537  * Set socket buffer size of netlink socket.
00538  * @arg sk              Netlink socket.
00539  * @arg rxbuf           New receive socket buffer size in bytes.
00540  * @arg txbuf           New transmit socket buffer size in bytes.
00541  *
00542  * Sets the socket buffer size of a netlink socket to the specified
00543  * values \c rxbuf and \c txbuf. Providing a value of \c 0 assumes a
00544  * good default value.
00545  *
00546  * @note It is not required to call this function prior to nl_connect().
00547  * @return 0 on sucess or a negative error code.
00548  */
00549 int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf)
00550 {
00551         int err;
00552 
00553         if (rxbuf <= 0)
00554                 rxbuf = 32768;
00555 
00556         if (txbuf <= 0)
00557                 txbuf = 32768;
00558 
00559         if (sk->s_fd == -1)
00560                 return -NLE_BAD_SOCK;
00561         
00562         err = setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF,
00563                          &txbuf, sizeof(txbuf));
00564         if (err < 0)
00565                 return -nl_syserr2nlerr(errno);
00566 
00567         err = setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF,
00568                          &rxbuf, sizeof(rxbuf));
00569         if (err < 0)
00570                 return -nl_syserr2nlerr(errno);
00571 
00572         sk->s_flags |= NL_SOCK_BUFSIZE_SET;
00573 
00574         return 0;
00575 }
00576 
00577 /**
00578  * Enable/disable credential passing on netlink socket.
00579  * @arg sk              Netlink socket.
00580  * @arg state           New state (0 - disabled, 1 - enabled)
00581  *
00582  * @return 0 on success or a negative error code
00583  */
00584 int nl_socket_set_passcred(struct nl_sock *sk, int state)
00585 {
00586         int err;
00587 
00588         if (sk->s_fd == -1)
00589                 return -NLE_BAD_SOCK;
00590 
00591         err = setsockopt(sk->s_fd, SOL_SOCKET, SO_PASSCRED,
00592                          &state, sizeof(state));
00593         if (err < 0)
00594                 return -nl_syserr2nlerr(errno);
00595 
00596         if (state)
00597                 sk->s_flags |= NL_SOCK_PASSCRED;
00598         else
00599                 sk->s_flags &= ~NL_SOCK_PASSCRED;
00600 
00601         return 0;
00602 }
00603 
00604 /**
00605  * Enable/disable receival of additional packet information
00606  * @arg sk              Netlink socket.
00607  * @arg state           New state (0 - disabled, 1 - enabled)
00608  *
00609  * @return 0 on success or a negative error code
00610  */
00611 int nl_socket_recv_pktinfo(struct nl_sock *sk, int state)
00612 {
00613         int err;
00614 
00615         if (sk->s_fd == -1)
00616                 return -NLE_BAD_SOCK;
00617 
00618         err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_PKTINFO,
00619                          &state, sizeof(state));
00620         if (err < 0)
00621                 return -nl_syserr2nlerr(errno);
00622 
00623         return 0;
00624 }
00625 
00626 /** @} */
00627 
00628 /** @} */