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