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