libnl 1.1
|
00001 /* 00002 * lib/socket.c Netlink Socket Handle 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-2006 Thomas Graf <tgraf@suug.ch> 00010 */ 00011 00012 /** 00013 * @ingroup nl 00014 * @defgroup socket Socket 00015 * @brief Handle representing a netlink socket. 00016 * 00017 * The socket is represented in a structure called the netlink handle, 00018 * besides the socket, it stores various settings and values related 00019 * to the socket. Every socket handle has a mandatory association with 00020 * a set of callbacks which can be used to modify the behaviour when 00021 * sending/receiving data from the socket. 00022 * 00023 * @par Socket Attributes 00024 * - \b Local \b Port: The local port is a netlink port identifying the 00025 * local endpoint. It is used as source address for outgoing messages 00026 * and will be addressed in replies. It must therefore be unique among 00027 * all userspace applications. When the socket handle is allocated, a 00028 * unique port number is generated automatically in the form of 22 bits 00029 * Process Identifier + 10 bits Arbitary Number. Therefore the library 00030 * is capable of generating 1024 unique local port numbers for every 00031 * process. If more sockets are required, the application has to manage 00032 * port numbers itself using nl_socket_set_local_port(). 00033 * - \b Group \b Subscriptions: A socket can subscribe to any number of 00034 * multicast groups. It will then receive a copy of all messages sent 00035 * to one of the groups. This method is mainly used for event notification. 00036 * Prior to kernel 2.6.14, the group subscription was done via bitmask 00037 * which limited to a total number of groups of 32. With 2.6.14 a new 00038 * method was added based on continous identifiers which supports an 00039 * arbitary number of groups. Both methods are supported, see 00040 * nl_join_groups() respectively nl_socket_add_membership() and 00041 * nl_socket_drop_membership(). 00042 * - \b Peer \b Port: The peer port is a netlink port identifying the 00043 * peer's endpoint. If no peer port is specified, the kernel will try to 00044 * autobind to a socket of the specified netlink family automatically. 00045 * This is very common as typically only one listening socket exists 00046 * on the kernel side. The peer port can be modified using 00047 * nl_socket_set_peer_port(). 00048 * - \b Peer \b Groups: 00049 * - \b File \b Descriptor: The file descriptor of the socket, it can be 00050 * accessed via nl_socket_get_fd() to change socket options or monitor 00051 * activity using poll()/select(). 00052 * - \b Protocol: Once connected, the socket is bound to stick to one 00053 * netlink family. This field is invisible, it is maintained automatically. 00054 * (See nl_connect()) 00055 * - \b Next \b Sequence \b Number: Next available sequence number to be used 00056 * for the next message being sent out. (Initial value: UNIX time when the 00057 * socket was allocated.) Sequence numbers can be used via 00058 * nl_socket_use_seq(). 00059 * - \b Expected \b Sequence \b Number: Expected sequence number in the next 00060 * message received from the socket. (Initial value: Equal to next sequence 00061 * number.) 00062 * - \b Callbacks \b Configuration: 00063 * 00064 * @par 1) Creating the netlink handle 00065 * @code 00066 * struct nl_handle *handle; 00067 * 00068 * // Allocate and initialize a new netlink handle 00069 * handle = nl_handle_alloc(); 00070 * 00071 * // Use nl_socket_get_fd() to fetch the file description, for example to 00072 * // put a socket into non-blocking i/o mode. 00073 * fcntl(nl_socket_get_fd(handle), F_SETFL, O_NONBLOCK); 00074 * @endcode 00075 * 00076 * @par 2) Group Subscriptions 00077 * @code 00078 * // Event notifications are typically sent to multicast addresses which 00079 * // represented by groups. Join a group to f.e. receive link notifications. 00080 * nl_socket_add_membership(handle, RTNLGRP_LINK); 00081 * @endcode 00082 * 00083 * @par 6) Cleaning up 00084 * @code 00085 * // Finally destroy the netlink handle 00086 * nl_handle_destroy(handle); 00087 * @endcode 00088 * 00089 * @{ 00090 */ 00091 00092 #include <netlink-local.h> 00093 #include <netlink/netlink.h> 00094 #include <netlink/utils.h> 00095 #include <netlink/handlers.h> 00096 #include <netlink/msg.h> 00097 #include <netlink/attr.h> 00098 00099 static int default_cb = NL_CB_DEFAULT; 00100 00101 static void __init init_default_cb(void) 00102 { 00103 char *nlcb; 00104 00105 if ((nlcb = getenv("NLCB"))) { 00106 if (!strcasecmp(nlcb, "default")) 00107 default_cb = NL_CB_DEFAULT; 00108 else if (!strcasecmp(nlcb, "verbose")) 00109 default_cb = NL_CB_VERBOSE; 00110 else if (!strcasecmp(nlcb, "debug")) 00111 default_cb = NL_CB_DEBUG; 00112 else { 00113 fprintf(stderr, "Unknown value for NLCB, valid values: " 00114 "{default | verbose | debug}\n"); 00115 } 00116 } 00117 } 00118 00119 static uint32_t used_ports_map[32]; 00120 00121 static uint32_t generate_local_port(void) 00122 { 00123 int i, n; 00124 uint32_t pid = getpid() & 0x3FFFFF; 00125 00126 for (i = 0; i < 32; i++) { 00127 if (used_ports_map[i] == 0xFFFFFFFF) 00128 continue; 00129 00130 for (n = 0; n < 32; n++) { 00131 if (1UL & (used_ports_map[i] >> n)) 00132 continue; 00133 00134 used_ports_map[i] |= (1UL << n); 00135 n += (i * 32); 00136 00137 /* PID_MAX_LIMIT is currently at 2^22, leaving 10 bit 00138 * to, i.e. 1024 unique ports per application. */ 00139 return pid + (n << 22); 00140 00141 } 00142 } 00143 00144 /* Out of sockets in our own PID namespace, what to do? FIXME */ 00145 return UINT_MAX; 00146 } 00147 00148 static void release_local_port(uint32_t port) 00149 { 00150 int nr; 00151 00152 if (port == UINT_MAX) 00153 return; 00154 00155 nr = port >> 22; 00156 used_ports_map[nr / 32] &= ~(1 << nr % 32); 00157 } 00158 00159 /** 00160 * @name Allocation 00161 * @{ 00162 */ 00163 00164 static struct nl_handle *__alloc_handle(struct nl_cb *cb) 00165 { 00166 struct nl_handle *handle; 00167 00168 handle = calloc(1, sizeof(*handle)); 00169 if (!handle) { 00170 nl_errno(ENOMEM); 00171 return NULL; 00172 } 00173 00174 handle->h_fd = -1; 00175 handle->h_cb = cb; 00176 handle->h_local.nl_family = AF_NETLINK; 00177 handle->h_peer.nl_family = AF_NETLINK; 00178 handle->h_seq_expect = handle->h_seq_next = time(0); 00179 handle->h_local.nl_pid = generate_local_port(); 00180 if (handle->h_local.nl_pid == UINT_MAX) { 00181 nl_handle_destroy(handle); 00182 nl_error(ENOBUFS, "Out of local ports"); 00183 return NULL; 00184 } 00185 00186 return handle; 00187 } 00188 00189 /** 00190 * Allocate new netlink socket handle. 00191 * 00192 * @return Newly allocated netlink socket handle or NULL. 00193 */ 00194 struct nl_handle *nl_handle_alloc(void) 00195 { 00196 struct nl_cb *cb; 00197 00198 cb = nl_cb_alloc(default_cb); 00199 if (!cb) { 00200 nl_errno(ENOMEM); 00201 return NULL; 00202 } 00203 00204 return __alloc_handle(cb); 00205 } 00206 00207 /** 00208 * Allocate new socket handle with custom callbacks 00209 * @arg cb Callback handler 00210 * 00211 * The reference to the callback handler is taken into account 00212 * automatically, it is released again upon calling nl_handle_destroy(). 00213 * 00214 *@return Newly allocted socket handle or NULL. 00215 */ 00216 struct nl_handle *nl_handle_alloc_cb(struct nl_cb *cb) 00217 { 00218 if (cb == NULL) 00219 BUG(); 00220 00221 return __alloc_handle(nl_cb_get(cb)); 00222 } 00223 00224 /** 00225 * Destroy netlink handle. 00226 * @arg handle Netlink handle. 00227 */ 00228 void nl_handle_destroy(struct nl_handle *handle) 00229 { 00230 if (!handle) 00231 return; 00232 00233 if (handle->h_fd >= 0) 00234 close(handle->h_fd); 00235 00236 if (!(handle->h_flags & NL_OWN_PORT)) 00237 release_local_port(handle->h_local.nl_pid); 00238 00239 nl_cb_put(handle->h_cb); 00240 free(handle); 00241 } 00242 00243 /** @} */ 00244 00245 /** 00246 * @name Sequence Numbers 00247 * @{ 00248 */ 00249 00250 static int noop_seq_check(struct nl_msg *msg, void *arg) 00251 { 00252 return NL_OK; 00253 } 00254 00255 00256 /** 00257 * Disable sequence number checking. 00258 * @arg handle Netlink handle. 00259 * 00260 * Disables checking of sequence numbers on the netlink handle. This is 00261 * required to allow messages to be processed which were not requested by 00262 * a preceding request message, e.g. netlink events. 00263 * 00264 * @note This function modifies the NL_CB_SEQ_CHECK configuration in 00265 * the callback handle associated with the socket. 00266 */ 00267 void nl_disable_sequence_check(struct nl_handle *handle) 00268 { 00269 nl_cb_set(handle->h_cb, NL_CB_SEQ_CHECK, 00270 NL_CB_CUSTOM, noop_seq_check, NULL); 00271 } 00272 00273 /** 00274 * Use next sequence number 00275 * @arg handle Netlink handle 00276 * 00277 * Uses the next available sequence number and increases the counter 00278 * by one for subsequent calls. 00279 * 00280 * @return Unique serial sequence number 00281 */ 00282 unsigned int nl_socket_use_seq(struct nl_handle *handle) 00283 { 00284 return handle->h_seq_next++; 00285 } 00286 00287 /** @} */ 00288 00289 /** 00290 * @name Source Idenficiation 00291 * @{ 00292 */ 00293 00294 uint32_t nl_socket_get_local_port(struct nl_handle *handle) 00295 { 00296 return handle->h_local.nl_pid; 00297 } 00298 00299 /** 00300 * Set local port of socket 00301 * @arg handle Netlink handle 00302 * @arg port Local port identifier 00303 * 00304 * Assigns a local port identifier to the socket. If port is 0 00305 * a unique port identifier will be generated automatically. 00306 */ 00307 void nl_socket_set_local_port(struct nl_handle *handle, uint32_t port) 00308 { 00309 if (port == 0) { 00310 port = generate_local_port(); 00311 handle->h_flags &= ~NL_OWN_PORT; 00312 } else { 00313 if (!(handle->h_flags & NL_OWN_PORT)) 00314 release_local_port(handle->h_local.nl_pid); 00315 handle->h_flags |= NL_OWN_PORT; 00316 } 00317 00318 handle->h_local.nl_pid = port; 00319 } 00320 00321 /** @} */ 00322 00323 /** 00324 * @name Group Subscriptions 00325 * @{ 00326 */ 00327 00328 /** 00329 * Join a group 00330 * @arg handle Netlink handle 00331 * @arg group Group identifier 00332 * 00333 * Joins the specified group using the modern socket option which 00334 * is available since kernel version 2.6.14. It allows joining an 00335 * almost arbitary number of groups without limitation. 00336 * 00337 * Make sure to use the correct group definitions as the older 00338 * bitmask definitions for nl_join_groups() are likely to still 00339 * be present for backward compatibility reasons. 00340 * 00341 * @return 0 on sucess or a negative error code. 00342 */ 00343 int nl_socket_add_membership(struct nl_handle *handle, int group) 00344 { 00345 int err; 00346 00347 if (handle->h_fd == -1) 00348 return nl_error(EBADFD, "Socket not connected"); 00349 00350 err = setsockopt(handle->h_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, 00351 &group, sizeof(group)); 00352 if (err < 0) 00353 return nl_error(errno, "setsockopt(NETLINK_ADD_MEMBERSHIP) " 00354 "failed"); 00355 00356 return 0; 00357 } 00358 00359 /** 00360 * Leave a group 00361 * @arg handle Netlink handle 00362 * @arg group Group identifier 00363 * 00364 * Leaves the specified group using the modern socket option 00365 * which is available since kernel version 2.6.14. 00366 * 00367 * @see nl_socket_add_membership 00368 * @return 0 on success or a negative error code. 00369 */ 00370 int nl_socket_drop_membership(struct nl_handle *handle, int group) 00371 { 00372 int err; 00373 00374 if (handle->h_fd == -1) 00375 return nl_error(EBADFD, "Socket not connected"); 00376 00377 err = setsockopt(handle->h_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP, 00378 &group, sizeof(group)); 00379 if (err < 0) 00380 return nl_error(errno, "setsockopt(NETLINK_DROP_MEMBERSHIP) " 00381 "failed"); 00382 00383 return 0; 00384 } 00385 00386 /** 00387 * Join multicast groups (deprecated) 00388 * @arg handle Netlink handle. 00389 * @arg groups Bitmask of groups to join. 00390 * 00391 * This function defines the old way of joining multicast group which 00392 * has to be done prior to calling nl_connect(). It works on any kernel 00393 * version but is very limited as only 32 groups can be joined. 00394 */ 00395 void nl_join_groups(struct nl_handle *handle, int groups) 00396 { 00397 handle->h_local.nl_groups |= groups; 00398 } 00399 00400 00401 /** @} */ 00402 00403 /** 00404 * @name Peer Identfication 00405 * @{ 00406 */ 00407 00408 uint32_t nl_socket_get_peer_port(struct nl_handle *handle) 00409 { 00410 return handle->h_peer.nl_pid; 00411 } 00412 00413 void nl_socket_set_peer_port(struct nl_handle *handle, uint32_t port) 00414 { 00415 handle->h_peer.nl_pid = port; 00416 } 00417 00418 /** @} */ 00419 00420 /** 00421 * @name File Descriptor 00422 * @{ 00423 */ 00424 00425 int nl_socket_get_fd(struct nl_handle *handle) 00426 { 00427 return handle->h_fd; 00428 } 00429 00430 /** 00431 * Set file descriptor of socket handle to non-blocking state 00432 * @arg handle Netlink socket 00433 * 00434 * @return 0 on success or a negative error code. 00435 */ 00436 int nl_socket_set_nonblocking(struct nl_handle *handle) 00437 { 00438 if (handle->h_fd == -1) 00439 return nl_error(EBADFD, "Socket not connected"); 00440 00441 if (fcntl(handle->h_fd, F_SETFL, O_NONBLOCK) < 0) 00442 return nl_error(errno, "fcntl(F_SETFL, O_NONBLOCK) failed"); 00443 00444 return 0; 00445 } 00446 00447 /** 00448 * Enable use of MSG_PEEK when reading from socket 00449 * @arg handle Netlink socket 00450 */ 00451 void nl_socket_enable_msg_peek(struct nl_handle *handle) 00452 { 00453 handle->h_flags |= NL_MSG_PEEK; 00454 } 00455 00456 /** 00457 * Disable use of MSG_PEEK when reading from socket 00458 * @arg handle Netlink socket 00459 */ 00460 void nl_socket_disable_msg_peek(struct nl_handle *handle) 00461 { 00462 handle->h_flags &= ~NL_MSG_PEEK; 00463 } 00464 00465 /** @} */ 00466 00467 /** 00468 * @name Callback Handler 00469 * @{ 00470 */ 00471 00472 struct nl_cb *nl_socket_get_cb(struct nl_handle *handle) 00473 { 00474 return nl_cb_get(handle->h_cb); 00475 } 00476 00477 void nl_socket_set_cb(struct nl_handle *handle, struct nl_cb *cb) 00478 { 00479 nl_cb_put(handle->h_cb); 00480 handle->h_cb = nl_cb_get(cb); 00481 } 00482 00483 /** 00484 * Modify the callback handler associated to the socket 00485 * @arg handle netlink handle 00486 * @arg type which type callback to set 00487 * @arg kind kind of callback 00488 * @arg func callback function 00489 * @arg arg argument to be passwd to callback function 00490 * 00491 * @see nl_cb_set 00492 */ 00493 int nl_socket_modify_cb(struct nl_handle *handle, enum nl_cb_type type, 00494 enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func, 00495 void *arg) 00496 { 00497 return nl_cb_set(handle->h_cb, type, kind, func, arg); 00498 } 00499 00500 /** @} */ 00501 00502 /** 00503 * @name Utilities 00504 * @{ 00505 */ 00506 00507 /** 00508 * Set socket buffer size of netlink handle. 00509 * @arg handle Netlink handle. 00510 * @arg rxbuf New receive socket buffer size in bytes. 00511 * @arg txbuf New transmit socket buffer size in bytes. 00512 * 00513 * Sets the socket buffer size of a netlink handle to the specified 00514 * values \c rxbuf and \c txbuf. Providing a value of \c 0 assumes a 00515 * good default value. 00516 * 00517 * @note It is not required to call this function prior to nl_connect(). 00518 * @return 0 on sucess or a negative error code. 00519 */ 00520 int nl_set_buffer_size(struct nl_handle *handle, int rxbuf, int txbuf) 00521 { 00522 int err; 00523 00524 if (rxbuf <= 0) 00525 rxbuf = 32768; 00526 00527 if (txbuf <= 0) 00528 txbuf = 32768; 00529 00530 if (handle->h_fd == -1) 00531 return nl_error(EBADFD, "Socket not connected"); 00532 00533 err = setsockopt(handle->h_fd, SOL_SOCKET, SO_SNDBUF, 00534 &txbuf, sizeof(txbuf)); 00535 if (err < 0) 00536 return nl_error(errno, "setsockopt(SO_SNDBUF) failed"); 00537 00538 err = setsockopt(handle->h_fd, SOL_SOCKET, SO_RCVBUF, 00539 &rxbuf, sizeof(rxbuf)); 00540 if (err < 0) 00541 return nl_error(errno, "setsockopt(SO_RCVBUF) failed"); 00542 00543 handle->h_flags |= NL_SOCK_BUFSIZE_SET; 00544 00545 return 0; 00546 } 00547 00548 /** 00549 * Enable/disable credential passing on netlink handle. 00550 * @arg handle Netlink handle 00551 * @arg state New state (0 - disabled, 1 - enabled) 00552 * 00553 * @return 0 on success or a negative error code 00554 */ 00555 int nl_set_passcred(struct nl_handle *handle, int state) 00556 { 00557 int err; 00558 00559 if (handle->h_fd == -1) 00560 return nl_error(EBADFD, "Socket not connected"); 00561 00562 err = setsockopt(handle->h_fd, SOL_SOCKET, SO_PASSCRED, 00563 &state, sizeof(state)); 00564 if (err < 0) 00565 return nl_error(errno, "setsockopt(SO_PASSCRED) failed"); 00566 00567 if (state) 00568 handle->h_flags |= NL_SOCK_PASSCRED; 00569 else 00570 handle->h_flags &= ~NL_SOCK_PASSCRED; 00571 00572 return 0; 00573 } 00574 00575 /** 00576 * Enable/disable receival of additional packet information 00577 * @arg handle Netlink handle 00578 * @arg state New state (0 - disabled, 1 - enabled) 00579 * 00580 * @return 0 on success or a negative error code 00581 */ 00582 int nl_socket_recv_pktinfo(struct nl_handle *handle, int state) 00583 { 00584 int err; 00585 00586 if (handle->h_fd == -1) 00587 return nl_error(EBADFD, "Socket not connected"); 00588 00589 err = setsockopt(handle->h_fd, SOL_NETLINK, NETLINK_PKTINFO, 00590 &state, sizeof(state)); 00591 if (err < 0) 00592 return nl_error(errno, "setsockopt(NETLINK_PKTINFO) failed"); 00593 00594 return 0; 00595 } 00596 00597 /** @} */ 00598 00599 /** @} */