1 /* libnfnetlink.c: generic library for communication with netfilter 2 * 3 * (C) 2002-2006 by Harald Welte <laforge (at) gnumonks.org> 4 * (C) 2006-2011 by Pablo Neira Ayuso <pablo (at) netfilter.org> 5 * 6 * Based on some original ideas from Jay Schulist <jschlst (at) samba.org> 7 * 8 * Development of this code funded by Astaro AG (http://www.astaro.com) 9 * 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License version 2 as published 12 * by the Free Software Foundation. 13 * 14 * 2005-09-14 Pablo Neira Ayuso <pablo (at) netfilter.org>: 15 * Define structure nfnlhdr 16 * Added __be64_to_cpu function 17 * Use NFA_TYPE macro to get the attribute type 18 * 19 * 2006-01-14 Harald Welte <laforge (at) netfilter.org>: 20 * introduce nfnl_subsys_handle 21 * 22 * 2006-01-15 Pablo Neira Ayuso <pablo (at) netfilter.org>: 23 * set missing subsys_id in nfnl_subsys_open 24 * set missing nfnlh->local.nl_pid in nfnl_open 25 * 26 * 2006-01-26 Harald Welte <laforge (at) netfilter.org>: 27 * remove bogus nfnlh->local.nl_pid from nfnl_open ;) 28 * add 16bit attribute functions 29 * 30 * 2006-07-03 Pablo Neira Ayuso <pablo (at) netfilter.org>: 31 * add iterator API 32 * add replacements for nfnl_listen and nfnl_talk 33 * fix error handling 34 * add assertions 35 * add documentation 36 * minor cleanups 37 */ 38 39 #include <stdlib.h> 40 #include <stdio.h> 41 #include <unistd.h> 42 #include <errno.h> 43 #include <string.h> 44 #include <time.h> 45 #include <netinet/in.h> 46 #include <assert.h> 47 #include <linux/types.h> 48 #include <sys/socket.h> 49 #include <sys/uio.h> 50 51 #include <linux/netlink.h> 52 53 #include <libnfnetlink/libnfnetlink.h> 54 55 #ifndef NETLINK_ADD_MEMBERSHIP 56 #define NETLINK_ADD_MEMBERSHIP 1 57 #endif 58 59 #ifndef SOL_NETLINK 60 #define SOL_NETLINK 270 61 #endif 62 63 64 #define nfnl_error(format, args...) \ 65 fprintf(stderr, "%s: " format "\n", __FUNCTION__, ## args) 66 67 #ifdef _NFNL_DEBUG 68 #define nfnl_debug_dump_packet nfnl_dump_packet 69 #else 70 #define nfnl_debug_dump_packet(a, b, ...) 71 #endif 72 73 struct nfnl_subsys_handle { 74 struct nfnl_handle *nfnlh; 75 u_int32_t subscriptions; 76 u_int8_t subsys_id; 77 u_int8_t cb_count; 78 struct nfnl_callback *cb; /* array of callbacks */ 79 }; 80 81 #define NFNL_MAX_SUBSYS 16 /* enough for now */ 82 83 #define NFNL_F_SEQTRACK_ENABLED (1 << 0) 84 85 struct nfnl_handle { 86 int fd; 87 struct sockaddr_nl local; 88 struct sockaddr_nl peer; 89 u_int32_t subscriptions; 90 u_int32_t seq; 91 u_int32_t dump; 92 u_int32_t rcv_buffer_size; /* for nfnl_catch */ 93 u_int32_t flags; 94 struct nlmsghdr *last_nlhdr; 95 struct nfnl_subsys_handle subsys[NFNL_MAX_SUBSYS+1]; 96 }; 97 98 void nfnl_dump_packet(struct nlmsghdr *nlh, int received_len, char *desc) 99 { 100 void *nlmsg_data = NLMSG_DATA(nlh); 101 struct nfattr *nfa = NFM_NFA(NLMSG_DATA(nlh)); 102 int len = NFM_PAYLOAD(nlh); 103 104 printf("%s called from %s\n", __FUNCTION__, desc); 105 printf(" nlmsghdr = %p, received_len = %u\n", nlh, received_len); 106 printf(" NLMSG_DATA(nlh) = %p (+%td bytes)\n", nlmsg_data, 107 (nlmsg_data - (void *)nlh)); 108 printf(" NFM_NFA(NLMSG_DATA(nlh)) = %p (+%td bytes)\n", 109 nfa, ((void *)nfa - (void *)nlh)); 110 printf(" NFM_PAYLOAD(nlh) = %u\n", len); 111 printf(" nlmsg_type = %u, nlmsg_len = %u, nlmsg_seq = %u " 112 "nlmsg_flags = 0x%x\n", nlh->nlmsg_type, nlh->nlmsg_len, 113 nlh->nlmsg_seq, nlh->nlmsg_flags); 114 115 while (NFA_OK(nfa, len)) { 116 printf(" nfa@%p: nfa_type=%u, nfa_len=%u\n", 117 nfa, NFA_TYPE(nfa), nfa->nfa_len); 118 nfa = NFA_NEXT(nfa,len); 119 } 120 } 121 122 /** 123 * nfnl_fd - returns the descriptor that identifies the socket 124 * @nfnlh: nfnetlink handler 125 * 126 * Use this function if you need to interact with the socket. Common 127 * scenarios are the use of poll()/select() to achieve multiplexation. 128 */ 129 int nfnl_fd(struct nfnl_handle *h) 130 { 131 assert(h); 132 return h->fd; 133 } 134 135 /** 136 * nfnl_portid - returns the Netlink port ID of this socket 137 * @h: nfnetlink handler 138 */ 139 unsigned int nfnl_portid(const struct nfnl_handle *h) 140 { 141 assert(h); 142 return h->local.nl_pid; 143 } 144 145 static int recalc_rebind_subscriptions(struct nfnl_handle *nfnlh) 146 { 147 int i, err; 148 u_int32_t new_subscriptions = nfnlh->subscriptions; 149 150 for (i = 0; i < NFNL_MAX_SUBSYS; i++) 151 new_subscriptions |= nfnlh->subsys[i].subscriptions; 152 153 nfnlh->local.nl_groups = new_subscriptions; 154 err = bind(nfnlh->fd, (struct sockaddr *)&nfnlh->local, 155 sizeof(nfnlh->local)); 156 if (err == -1) 157 return -1; 158 159 nfnlh->subscriptions = new_subscriptions; 160 161 return 0; 162 } 163 164 /** 165 * nfnl_open - open a nfnetlink handler 166 * 167 * This function creates a nfnetlink handler, this is required to establish 168 * a communication between the userspace and the nfnetlink system. 169 * 170 * On success, a valid address that points to a nfnl_handle structure 171 * is returned. On error, NULL is returned and errno is set approapiately. 172 */ 173 struct nfnl_handle *nfnl_open(void) 174 { 175 struct nfnl_handle *nfnlh; 176 unsigned int addr_len; 177 178 nfnlh = malloc(sizeof(*nfnlh)); 179 if (!nfnlh) 180 return NULL; 181 182 memset(nfnlh, 0, sizeof(*nfnlh)); 183 nfnlh->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER); 184 if (nfnlh->fd == -1) 185 goto err_free; 186 187 nfnlh->local.nl_family = AF_NETLINK; 188 nfnlh->peer.nl_family = AF_NETLINK; 189 190 addr_len = sizeof(nfnlh->local); 191 getsockname(nfnlh->fd, (struct sockaddr *)&nfnlh->local, &addr_len); 192 if (addr_len != sizeof(nfnlh->local)) { 193 errno = EINVAL; 194 goto err_close; 195 } 196 if (nfnlh->local.nl_family != AF_NETLINK) { 197 errno = EINVAL; 198 goto err_close; 199 } 200 nfnlh->seq = time(NULL); 201 nfnlh->rcv_buffer_size = NFNL_BUFFSIZE; 202 203 /* don't set pid here, only first socket of process has real pid !!! 204 * binding to pid '0' will default */ 205 206 /* let us do the initial bind */ 207 if (recalc_rebind_subscriptions(nfnlh) < 0) 208 goto err_close; 209 210 /* use getsockname to get the netlink pid that the kernel assigned us */ 211 addr_len = sizeof(nfnlh->local); 212 getsockname(nfnlh->fd, (struct sockaddr *)&nfnlh->local, &addr_len); 213 if (addr_len != sizeof(nfnlh->local)) { 214 errno = EINVAL; 215 goto err_close; 216 } 217 /* sequence tracking enabled by default */ 218 nfnlh->flags |= NFNL_F_SEQTRACK_ENABLED; 219 220 return nfnlh; 221 222 err_close: 223 close(nfnlh->fd); 224 err_free: 225 free(nfnlh); 226 return NULL; 227 } 228 229 /** 230 * nfnl_set_sequence_tracking - set netlink sequence tracking 231 * @h: nfnetlink handler 232 */ 233 void nfnl_set_sequence_tracking(struct nfnl_handle *h) 234 { 235 h->flags |= NFNL_F_SEQTRACK_ENABLED; 236 } 237 238 /** 239 * nfnl_unset_sequence_tracking - set netlink sequence tracking 240 * @h: nfnetlink handler 241 */ 242 void nfnl_unset_sequence_tracking(struct nfnl_handle *h) 243 { 244 h->flags &= ~NFNL_F_SEQTRACK_ENABLED; 245 } 246 247 /** 248 * nfnl_set_rcv_buffer_size - set the size of the receive buffer 249 * @h: libnfnetlink handler 250 * @size: buffer size 251 * 252 * This function sets the size of the receive buffer size, i.e. the size 253 * of the buffer used by nfnl_recv. Default value is 4096 bytes. 254 */ 255 void nfnl_set_rcv_buffer_size(struct nfnl_handle *h, unsigned int size) 256 { 257 h->rcv_buffer_size = size; 258 } 259 260 /** 261 * nfnl_subsys_open - open a netlink subsystem 262 * @nfnlh: libnfnetlink handle 263 * @subsys_id: which nfnetlink subsystem we are interested in 264 * @cb_count: number of callbacks that are used maximum. 265 * @subscriptions: netlink groups we want to be subscribed to 266 * 267 * This function creates a subsystem handler that contains the set of 268 * callbacks that handle certain types of messages coming from a netfilter 269 * subsystem. Initially the callback set is empty, you can register callbacks 270 * via nfnl_callback_register(). 271 * 272 * On error, NULL is returned and errno is set appropiately. On success, 273 * a valid address that points to a nfnl_subsys_handle structure is returned. 274 */ 275 struct nfnl_subsys_handle * 276 nfnl_subsys_open(struct nfnl_handle *nfnlh, u_int8_t subsys_id, 277 u_int8_t cb_count, u_int32_t subscriptions) 278 { 279 struct nfnl_subsys_handle *ssh; 280 281 assert(nfnlh); 282 283 if (subsys_id > NFNL_MAX_SUBSYS) { 284 errno = ENOENT; 285 return NULL; 286 } 287 288 ssh = &nfnlh->subsys[subsys_id]; 289 if (ssh->cb) { 290 errno = EBUSY; 291 return NULL; 292 } 293 294 ssh->cb = calloc(cb_count, sizeof(*(ssh->cb))); 295 if (!ssh->cb) 296 return NULL; 297 298 ssh->nfnlh = nfnlh; 299 ssh->cb_count = cb_count; 300 ssh->subscriptions = subscriptions; 301 ssh->subsys_id = subsys_id; 302 303 /* although now we have nfnl_join to subscribe to certain 304 * groups, just keep this to ensure compatibility */ 305 if (recalc_rebind_subscriptions(nfnlh) < 0) { 306 free(ssh->cb); 307 ssh->cb = NULL; 308 return NULL; 309 } 310 311 return ssh; 312 } 313 314 /** 315 * nfnl_subsys_close - close a nfnetlink subsys handler 316 * @ssh: nfnetlink subsystem handler 317 * 318 * Release all the callbacks registered in a subsystem handler. 319 */ 320 void nfnl_subsys_close(struct nfnl_subsys_handle *ssh) 321 { 322 assert(ssh); 323 324 ssh->subscriptions = 0; 325 ssh->cb_count = 0; 326 if (ssh->cb) { 327 free(ssh->cb); 328 ssh->cb = NULL; 329 } 330 } 331 332 /** 333 * nfnl_close - close a nfnetlink handler 334 * @nfnlh: nfnetlink handler 335 * 336 * This function closes the nfnetlink handler. On success, 0 is returned. 337 * On error, -1 is returned and errno is set appropiately. 338 */ 339 int nfnl_close(struct nfnl_handle *nfnlh) 340 { 341 int i, ret; 342 343 assert(nfnlh); 344 345 for (i = 0; i < NFNL_MAX_SUBSYS; i++) 346 nfnl_subsys_close(&nfnlh->subsys[i]); 347 348 ret = close(nfnlh->fd); 349 if (ret < 0) 350 return ret; 351 352 free(nfnlh); 353 354 return 0; 355 } 356 357 /** 358 * nfnl_join - join a nfnetlink multicast group 359 * @nfnlh: nfnetlink handler 360 * @group: group we want to join 361 * 362 * This function is used to join a certain multicast group. It must be 363 * called once the nfnetlink handler has been created. If any doubt, 364 * just use it if you have to listen to nfnetlink events. 365 * 366 * On success, 0 is returned. On error, -1 is returned and errno is set 367 * approapiately. 368 */ 369 int nfnl_join(const struct nfnl_handle *nfnlh, unsigned int group) 370 { 371 assert(nfnlh); 372 return setsockopt(nfnlh->fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, 373 &group, sizeof(group)); 374 } 375 376 /** 377 * nfnl_send - send a nfnetlink message through netlink socket 378 * @nfnlh: nfnetlink handler 379 * @n: netlink message 380 * 381 * On success, the number of bytes is returned. On error, -1 is returned 382 * and errno is set appropiately. 383 */ 384 int nfnl_send(struct nfnl_handle *nfnlh, struct nlmsghdr *n) 385 { 386 assert(nfnlh); 387 assert(n); 388 389 nfnl_debug_dump_packet(n, n->nlmsg_len+sizeof(*n), "nfnl_send"); 390 391 return sendto(nfnlh->fd, n, n->nlmsg_len, 0, 392 (struct sockaddr *)&nfnlh->peer, sizeof(nfnlh->peer)); 393 } 394 395 int nfnl_sendmsg(const struct nfnl_handle *nfnlh, const struct msghdr *msg, 396 unsigned int flags) 397 { 398 assert(nfnlh); 399 assert(msg); 400 401 return sendmsg(nfnlh->fd, msg, flags); 402 } 403 404 int nfnl_sendiov(const struct nfnl_handle *nfnlh, const struct iovec *iov, 405 unsigned int num, unsigned int flags) 406 { 407 struct msghdr msg; 408 409 assert(nfnlh); 410 411 msg.msg_name = (struct sockaddr *) &nfnlh->peer; 412 msg.msg_namelen = sizeof(nfnlh->peer); 413 msg.msg_iov = (struct iovec *) iov; 414 msg.msg_iovlen = num; 415 msg.msg_control = NULL; 416 msg.msg_controllen = 0; 417 msg.msg_flags = 0; 418 419 return nfnl_sendmsg(nfnlh, &msg, flags); 420 } 421 422 /** 423 * nfnl_fill_hdr - fill in netlink and nfnetlink header 424 * @nfnlh: nfnetlink handle 425 * @nlh: netlink message to be filled in 426 * @len: length of _payload_ bytes (not including nfgenmsg) 427 * @family: AF_INET / ... 428 * @res_id: resource id 429 * @msg_type: nfnetlink message type (without subsystem) 430 * @msg_flags: netlink message flags 431 * 432 * This function sets up appropiately the nfnetlink header. See that the 433 * pointer to the netlink message passed must point to a memory region of 434 * at least the size of struct nlmsghdr + struct nfgenmsg. 435 */ 436 void nfnl_fill_hdr(struct nfnl_subsys_handle *ssh, 437 struct nlmsghdr *nlh, unsigned int len, 438 u_int8_t family, 439 u_int16_t res_id, 440 u_int16_t msg_type, 441 u_int16_t msg_flags) 442 { 443 assert(ssh); 444 assert(nlh); 445 446 struct nfgenmsg *nfg = (void *)nlh + sizeof(*nlh); 447 448 nlh->nlmsg_len = NLMSG_LENGTH(len+sizeof(*nfg)); 449 nlh->nlmsg_type = (ssh->subsys_id<<8)|msg_type; 450 nlh->nlmsg_flags = msg_flags; 451 nlh->nlmsg_pid = 0; 452 453 if (ssh->nfnlh->flags & NFNL_F_SEQTRACK_ENABLED) { 454 nlh->nlmsg_seq = ++ssh->nfnlh->seq; 455 /* kernel uses sequence number zero for events */ 456 if (!ssh->nfnlh->seq) 457 nlh->nlmsg_seq = ssh->nfnlh->seq = time(NULL); 458 } else { 459 /* unset sequence number, ignore it */ 460 nlh->nlmsg_seq = 0; 461 } 462 463 nfg->nfgen_family = family; 464 nfg->version = NFNETLINK_V0; 465 nfg->res_id = htons(res_id); 466 } 467 468 struct nfattr * 469 nfnl_parse_hdr(const struct nfnl_handle *nfnlh, 470 const struct nlmsghdr *nlh, 471 struct nfgenmsg **genmsg) 472 { 473 if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nfgenmsg))) 474 return NULL; 475 476 if (nlh->nlmsg_len == NLMSG_LENGTH(sizeof(struct nfgenmsg))) { 477 if (genmsg) 478 *genmsg = (void *)nlh + sizeof(*nlh); 479 return NULL; 480 } 481 482 if (genmsg) 483 *genmsg = (void *)nlh + sizeof(*nlh); 484 485 return (void *)nlh + NLMSG_LENGTH(sizeof(struct nfgenmsg)); 486 } 487 488 /** 489 * nfnl_recv - receive data from a nfnetlink subsystem 490 * @h: nfnetlink handler 491 * @buf: buffer where the data will be stored 492 * @len: size of the buffer 493 * 494 * This function doesn't perform any sanity checking. So do no expect 495 * that the data is well-formed. Such checkings are done by the parsing 496 * functions. 497 * 498 * On success, 0 is returned. On error, -1 is returned and errno is set 499 * appropiately. 500 * 501 * Note that ENOBUFS is returned in case that nfnetlink is exhausted. In 502 * that case is possible that the information requested is incomplete. 503 */ 504 ssize_t 505 nfnl_recv(const struct nfnl_handle *h, unsigned char *buf, size_t len) 506 { 507 socklen_t addrlen; 508 int status; 509 struct sockaddr_nl peer; 510 511 assert(h); 512 assert(buf); 513 assert(len > 0); 514 515 if (len < sizeof(struct nlmsgerr) 516 || len < sizeof(struct nlmsghdr)) { 517 errno = EBADMSG; 518 return -1; 519 } 520 521 addrlen = sizeof(h->peer); 522 status = recvfrom(h->fd, buf, len, 0, (struct sockaddr *)&peer, 523 &addrlen); 524 if (status <= 0) 525 return status; 526 527 if (addrlen != sizeof(peer)) { 528 errno = EINVAL; 529 return -1; 530 } 531 532 if (peer.nl_pid != 0) { 533 errno = ENOMSG; 534 return -1; 535 } 536 537 return status; 538 } 539 /** 540 * nfnl_listen: listen for one or more netlink messages 541 * @nfnhl: libnfnetlink handle 542 * @handler: callback function to be called for every netlink message 543 * - the callback handler should normally return 0 544 * - but may return a negative error code which will cause 545 * nfnl_listen to return immediately with the same error code 546 * - or return a postivie error code which will cause 547 * nfnl_listen to return after it has finished processing all 548 * the netlink messages in the current packet 549 * Thus a positive error code will terminate nfnl_listen "soon" 550 * without any loss of data, a negative error code will terminate 551 * nfnl_listen "very soon" and throw away data already read from 552 * the netlink socket. 553 * @jarg: opaque argument passed on to callback 554 * 555 * This function is used to receive and process messages coming from an open 556 * nfnetlink handler like events or information request via nfnl_send(). 557 * 558 * On error, -1 is returned, unfortunately errno is not always set 559 * appropiately. For that reason, the use of this function is DEPRECATED. 560 * Please, use nfnl_receive_process() instead. 561 */ 562 int nfnl_listen(struct nfnl_handle *nfnlh, 563 int (*handler)(struct sockaddr_nl *, struct nlmsghdr *n, 564 void *), void *jarg) 565 { 566 struct sockaddr_nl nladdr; 567 char buf[NFNL_BUFFSIZE] __attribute__ ((aligned)); 568 struct iovec iov; 569 int remain; 570 struct nlmsghdr *h; 571 struct nlmsgerr *msgerr; 572 int quit=0; 573 574 struct msghdr msg = { 575 .msg_name = &nladdr, 576 .msg_namelen = sizeof(nladdr), 577 .msg_iov = &iov, 578 .msg_iovlen = 1, 579 }; 580 581 memset(&nladdr, 0, sizeof(nladdr)); 582 nladdr.nl_family = AF_NETLINK; 583 iov.iov_base = buf; 584 iov.iov_len = sizeof(buf); 585 586 while (! quit) { 587 remain = recvmsg(nfnlh->fd, &msg, 0); 588 if (remain < 0) { 589 if (errno == EINTR) 590 continue; 591 /* Bad file descriptor */ 592 else if (errno == EBADF) 593 break; 594 else if (errno == EAGAIN) 595 break; 596 nfnl_error("recvmsg overrun: %s", strerror(errno)); 597 continue; 598 } 599 if (remain == 0) { 600 nfnl_error("EOF on netlink"); 601 return -1; 602 } 603 if (msg.msg_namelen != sizeof(nladdr)) { 604 nfnl_error("Bad sender address len (%d)", 605 msg.msg_namelen); 606 return -1; 607 } 608 609 for (h = (struct nlmsghdr *)buf; remain >= sizeof(*h);) { 610 int err; 611 int len = h->nlmsg_len; 612 int l = len - sizeof(*h); 613 614 if (l < 0 || len > remain) { 615 if (msg.msg_flags & MSG_TRUNC) { 616 nfnl_error("MSG_TRUNC"); 617 return -1; 618 } 619 nfnl_error("Malformed msg (len=%d)", len); 620 return -1; 621 } 622 623 /* end of messages reached, let's return */ 624 if (h->nlmsg_type == NLMSG_DONE) 625 return 0; 626 627 /* Break the loop if success is explicitely 628 * reported via NLM_F_ACK flag set */ 629 if (h->nlmsg_type == NLMSG_ERROR) { 630 msgerr = NLMSG_DATA(h); 631 return msgerr->error; 632 } 633 634 err = handler(&nladdr, h, jarg); 635 if (err < 0) 636 return err; 637 quit |= err; 638 639 /* FIXME: why not _NEXT macros, etc.? */ 640 //h = NLMSG_NEXT(h, remain); 641 remain -= NLMSG_ALIGN(len); 642 h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len)); 643 } 644 if (msg.msg_flags & MSG_TRUNC) { 645 nfnl_error("MSG_TRUNC"); 646 continue; 647 } 648 if (remain) { 649 nfnl_error("remnant size %d", remain); 650 return -1; 651 } 652 } 653 654 return quit; 655 } 656 657 /** 658 * nfnl_talk - send a request and then receive and process messages returned 659 * @nfnlh: nfnetelink handler 660 * @n: netlink message that contains the request 661 * @peer: peer PID 662 * @groups: netlink groups 663 * @junk: callback called if out-of-sequence messages were received 664 * @jarg: data for the junk callback 665 * 666 * This function is used to request an action that does not returns any 667 * information. On error, a negative value is returned, errno could be 668 * set appropiately. For that reason, the use of this function is DEPRECATED. 669 * Please, use nfnl_query() instead. 670 */ 671 int nfnl_talk(struct nfnl_handle *nfnlh, struct nlmsghdr *n, pid_t peer, 672 unsigned groups, struct nlmsghdr *answer, 673 int (*junk)(struct sockaddr_nl *, struct nlmsghdr *n, void *), 674 void *jarg) 675 { 676 char buf[NFNL_BUFFSIZE] __attribute__ ((aligned)); 677 struct sockaddr_nl nladdr; 678 struct nlmsghdr *h; 679 unsigned int seq; 680 int status; 681 struct iovec iov = { 682 n, n->nlmsg_len 683 }; 684 struct msghdr msg = { 685 .msg_name = &nladdr, 686 .msg_namelen = sizeof(nladdr), 687 .msg_iov = &iov, 688 .msg_iovlen = 1, 689 }; 690 691 memset(&nladdr, 0, sizeof(nladdr)); 692 nladdr.nl_family = AF_NETLINK; 693 nladdr.nl_pid = peer; 694 nladdr.nl_groups = groups; 695 696 n->nlmsg_seq = seq = ++nfnlh->seq; 697 /* FIXME: why ? */ 698 if (!answer) 699 n->nlmsg_flags |= NLM_F_ACK; 700 701 status = sendmsg(nfnlh->fd, &msg, 0); 702 if (status < 0) { 703 nfnl_error("sendmsg(netlink) %s", strerror(errno)); 704 return -1; 705 } 706 iov.iov_base = buf; 707 iov.iov_len = sizeof(buf); 708 709 while (1) { 710 status = recvmsg(nfnlh->fd, &msg, 0); 711 if (status < 0) { 712 if (errno == EINTR) 713 continue; 714 nfnl_error("recvmsg over-run"); 715 continue; 716 } 717 if (status == 0) { 718 nfnl_error("EOF on netlink"); 719 return -1; 720 } 721 if (msg.msg_namelen != sizeof(nladdr)) { 722 nfnl_error("Bad sender address len %d", 723 msg.msg_namelen); 724 return -1; 725 } 726 727 for (h = (struct nlmsghdr *)buf; status >= sizeof(*h); ) { 728 int len = h->nlmsg_len; 729 int l = len - sizeof(*h); 730 int err; 731 732 if (l < 0 || len > status) { 733 if (msg.msg_flags & MSG_TRUNC) { 734 nfnl_error("Truncated message\n"); 735 return -1; 736 } 737 nfnl_error("Malformed message: len=%d\n", len); 738 return -1; /* FIXME: libnetlink exits here */ 739 } 740 741 if (h->nlmsg_pid != nfnlh->local.nl_pid || 742 h->nlmsg_seq != seq) { 743 if (junk) { 744 err = junk(&nladdr, h, jarg); 745 if (err < 0) 746 return err; 747 } 748 goto cont; 749 } 750 751 if (h->nlmsg_type == NLMSG_ERROR) { 752 struct nlmsgerr *err = NLMSG_DATA(h); 753 if (l < sizeof(struct nlmsgerr)) 754 nfnl_error("ERROR truncated\n"); 755 else { 756 errno = -err->error; 757 if (errno == 0) { 758 if (answer) 759 memcpy(answer, h, h->nlmsg_len); 760 return 0; 761 } 762 perror("NFNETLINK answers"); 763 } 764 return err->error; 765 } 766 if (answer) { 767 memcpy(answer, h, h->nlmsg_len); 768 return 0; 769 } 770 771 nfnl_error("Unexpected reply!\n"); 772 cont: 773 status -= NLMSG_ALIGN(len); 774 h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len)); 775 } 776 if (msg.msg_flags & MSG_TRUNC) { 777 nfnl_error("Messages truncated\n"); 778 continue; 779 } 780 if (status) 781 nfnl_error("Remnant of size %d\n", status); 782 } 783 } 784 785 /** 786 * nfnl_addattr_l - Add variable length attribute to nlmsghdr 787 * @n: netlink message header to which attribute is to be added 788 * @maxlen: maximum length of netlink message header 789 * @type: type of new attribute 790 * @data: content of new attribute 791 * @len: attribute length 792 */ 793 int nfnl_addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, 794 int alen) 795 { 796 int len = NFA_LENGTH(alen); 797 struct nfattr *nfa; 798 799 assert(n); 800 assert(maxlen > 0); 801 assert(type >= 0); 802 803 if ((NLMSG_ALIGN(n->nlmsg_len) + len) > maxlen) { 804 errno = ENOSPC; 805 return -1; 806 } 807 808 nfa = NLMSG_TAIL(n); 809 nfa->nfa_type = type; 810 nfa->nfa_len = len; 811 memcpy(NFA_DATA(nfa), data, alen); 812 n->nlmsg_len = (NLMSG_ALIGN(n->nlmsg_len) + NFA_ALIGN(len)); 813 return 0; 814 } 815 816 /** 817 * nfnl_nfa_addattr_l - Add variable length attribute to struct nfattr 818 * 819 * @nfa: struct nfattr 820 * @maxlen: maximal length of nfattr buffer 821 * @type: type for new attribute 822 * @data: content of new attribute 823 * @alen: length of new attribute 824 * 825 */ 826 int nfnl_nfa_addattr_l(struct nfattr *nfa, int maxlen, int type, 827 const void *data, int alen) 828 { 829 struct nfattr *subnfa; 830 int len = NFA_LENGTH(alen); 831 832 assert(nfa); 833 assert(maxlen > 0); 834 assert(type >= 0); 835 836 if (NFA_ALIGN(nfa->nfa_len) + len > maxlen) { 837 errno = ENOSPC; 838 return -1; 839 } 840 841 subnfa = (struct nfattr *)(((char *)nfa) + NFA_ALIGN(nfa->nfa_len)); 842 subnfa->nfa_type = type; 843 subnfa->nfa_len = len; 844 memcpy(NFA_DATA(subnfa), data, alen); 845 nfa->nfa_len = NFA_ALIGN(nfa->nfa_len) + len; 846 847 return 0; 848 } 849 850 /** 851 * nfnl_addattr8 - Add u_int8_t attribute to nlmsghdr 852 * 853 * @n: netlink message header to which attribute is to be added 854 * @maxlen: maximum length of netlink message header 855 * @type: type of new attribute 856 * @data: content of new attribute 857 */ 858 int nfnl_addattr8(struct nlmsghdr *n, int maxlen, int type, u_int8_t data) 859 { 860 assert(n); 861 assert(maxlen > 0); 862 assert(type >= 0); 863 864 return nfnl_addattr_l(n, maxlen, type, &data, sizeof(data)); 865 } 866 867 /** 868 * nfnl_nfa_addattr16 - Add u_int16_t attribute to struct nfattr 869 * 870 * @nfa: struct nfattr 871 * @maxlen: maximal length of nfattr buffer 872 * @type: type for new attribute 873 * @data: content of new attribute 874 * 875 */ 876 int nfnl_nfa_addattr16(struct nfattr *nfa, int maxlen, int type, 877 u_int16_t data) 878 { 879 assert(nfa); 880 assert(maxlen > 0); 881 assert(type >= 0); 882 883 return nfnl_nfa_addattr_l(nfa, maxlen, type, &data, sizeof(data)); 884 } 885 886 /** 887 * nfnl_addattr16 - Add u_int16_t attribute to nlmsghdr 888 * 889 * @n: netlink message header to which attribute is to be added 890 * @maxlen: maximum length of netlink message header 891 * @type: type of new attribute 892 * @data: content of new attribute 893 * 894 */ 895 int nfnl_addattr16(struct nlmsghdr *n, int maxlen, int type, 896 u_int16_t data) 897 { 898 assert(n); 899 assert(maxlen > 0); 900 assert(type >= 0); 901 902 return nfnl_addattr_l(n, maxlen, type, &data, sizeof(data)); 903 } 904 905 /** 906 * nfnl_nfa_addattr32 - Add u_int32_t attribute to struct nfattr 907 * 908 * @nfa: struct nfattr 909 * @maxlen: maximal length of nfattr buffer 910 * @type: type for new attribute 911 * @data: content of new attribute 912 * 913 */ 914 int nfnl_nfa_addattr32(struct nfattr *nfa, int maxlen, int type, 915 u_int32_t data) 916 { 917 assert(nfa); 918 assert(maxlen > 0); 919 assert(type >= 0); 920 921 return nfnl_nfa_addattr_l(nfa, maxlen, type, &data, sizeof(data)); 922 } 923 924 /** 925 * nfnl_addattr32 - Add u_int32_t attribute to nlmsghdr 926 * 927 * @n: netlink message header to which attribute is to be added 928 * @maxlen: maximum length of netlink message header 929 * @type: type of new attribute 930 * @data: content of new attribute 931 * 932 */ 933 int nfnl_addattr32(struct nlmsghdr *n, int maxlen, int type, 934 u_int32_t data) 935 { 936 assert(n); 937 assert(maxlen > 0); 938 assert(type >= 0); 939 940 return nfnl_addattr_l(n, maxlen, type, &data, sizeof(data)); 941 } 942 943 /** 944 * nfnl_parse_attr - Parse a list of nfattrs into a pointer array 945 * 946 * @tb: pointer array, will be filled in (output) 947 * @max: size of pointer array 948 * @nfa: pointer to list of nfattrs 949 * @len: length of 'nfa' 950 * 951 * The returned value is equal to the number of remaining bytes of the netlink 952 * message that cannot be parsed. 953 */ 954 int nfnl_parse_attr(struct nfattr *tb[], int max, struct nfattr *nfa, int len) 955 { 956 assert(tb); 957 assert(max > 0); 958 assert(nfa); 959 960 memset(tb, 0, sizeof(struct nfattr *) * max); 961 962 while (NFA_OK(nfa, len)) { 963 if (NFA_TYPE(nfa) <= max) 964 tb[NFA_TYPE(nfa)-1] = nfa; 965 nfa = NFA_NEXT(nfa,len); 966 } 967 968 return len; 969 } 970 971 /** 972 * nfnl_build_nfa_iovec - Build two iovec's from tag, length and value 973 * 974 * @iov: pointer to array of two 'struct iovec' (caller-allocated) 975 * @nfa: pointer to 'struct nfattr' (caller-allocated) 976 * @type: type (tag) of attribute 977 * @len: length of value 978 * @val: pointer to buffer containing 'value' 979 * 980 */ 981 void nfnl_build_nfa_iovec(struct iovec *iov, struct nfattr *nfa, 982 u_int16_t type, u_int32_t len, unsigned char *val) 983 { 984 assert(iov); 985 assert(nfa); 986 987 /* Set the attribut values */ 988 nfa->nfa_len = sizeof(struct nfattr) + len; 989 nfa->nfa_type = type; 990 991 iov[0].iov_base = nfa; 992 iov[0].iov_len = sizeof(*nfa); 993 iov[1].iov_base = val; 994 iov[1].iov_len = NFA_ALIGN(len); 995 } 996 997 #ifndef SO_RCVBUFFORCE 998 #define SO_RCVBUFFORCE (33) 999 #endif 1000 1001 /** 1002 * nfnl_rcvbufsiz - set the socket buffer size 1003 * @h: nfnetlink handler 1004 * @size: size of the buffer we want to set 1005 * 1006 * This function sets the new size of the socket buffer. Use this setting 1007 * to increase the socket buffer size if your system is reporting ENOBUFS 1008 * errors. 1009 * 1010 * This function returns the new size of the socket buffer. 1011 */ 1012 unsigned int nfnl_rcvbufsiz(const struct nfnl_handle *h, unsigned int size) 1013 { 1014 int status; 1015 socklen_t socklen = sizeof(size); 1016 unsigned int read_size = 0; 1017 1018 assert(h); 1019 1020 /* first we try the FORCE option, which is introduced in kernel 1021 * 2.6.14 to give "root" the ability to override the system wide 1022 * maximum */ 1023 status = setsockopt(h->fd, SOL_SOCKET, SO_RCVBUFFORCE, &size, socklen); 1024 if (status < 0) { 1025 /* if this didn't work, we try at least to get the system 1026 * wide maximum (or whatever the user requested) */ 1027 setsockopt(h->fd, SOL_SOCKET, SO_RCVBUF, &size, socklen); 1028 } 1029 getsockopt(h->fd, SOL_SOCKET, SO_RCVBUF, &read_size, &socklen); 1030 1031 return read_size; 1032 } 1033 1034 /** 1035 * nfnl_get_msg_first - get the first message of a multipart netlink message 1036 * @h: nfnetlink handle 1037 * @buf: data received that we want to process 1038 * @len: size of the data received 1039 * 1040 * This function returns a pointer to the first netlink message contained 1041 * in the chunk of data received from certain nfnetlink subsystem. 1042 * 1043 * On success, a valid address that points to the netlink message is returned. 1044 * On error, NULL is returned. 1045 */ 1046 struct nlmsghdr *nfnl_get_msg_first(struct nfnl_handle *h, 1047 const unsigned char *buf, 1048 size_t len) 1049 { 1050 struct nlmsghdr *nlh; 1051 1052 assert(h); 1053 assert(buf); 1054 assert(len > 0); 1055 1056 /* first message in buffer */ 1057 nlh = (struct nlmsghdr *)buf; 1058 if (!NLMSG_OK(nlh, len)) 1059 return NULL; 1060 h->last_nlhdr = nlh; 1061 1062 return nlh; 1063 } 1064 1065 struct nlmsghdr *nfnl_get_msg_next(struct nfnl_handle *h, 1066 const unsigned char *buf, 1067 size_t len) 1068 { 1069 struct nlmsghdr *nlh; 1070 size_t remain_len; 1071 1072 assert(h); 1073 assert(buf); 1074 assert(len > 0); 1075 1076 /* if last header in handle not inside this buffer, 1077 * drop reference to last header */ 1078 if (!h->last_nlhdr || 1079 (unsigned char *)h->last_nlhdr >= (buf + len) || 1080 (unsigned char *)h->last_nlhdr < buf) { 1081 h->last_nlhdr = NULL; 1082 return NULL; 1083 } 1084 1085 /* n-th part of multipart message */ 1086 if (h->last_nlhdr->nlmsg_type == NLMSG_DONE || 1087 h->last_nlhdr->nlmsg_flags & NLM_F_MULTI) { 1088 /* if last part in multipart message or no 1089 * multipart message at all, return */ 1090 h->last_nlhdr = NULL; 1091 return NULL; 1092 } 1093 1094 remain_len = (len - ((unsigned char *)h->last_nlhdr - buf)); 1095 nlh = NLMSG_NEXT(h->last_nlhdr, remain_len); 1096 1097 if (!NLMSG_OK(nlh, remain_len)) { 1098 h->last_nlhdr = NULL; 1099 return NULL; 1100 } 1101 1102 h->last_nlhdr = nlh; 1103 1104 return nlh; 1105 } 1106 1107 /** 1108 * nfnl_callback_register - register a callback for a certain message type 1109 * @ssh: nfnetlink subsys handler 1110 * @type: subsys call 1111 * @cb: nfnetlink callback to be registered 1112 * 1113 * On success, 0 is returned. On error, -1 is returned and errno is set 1114 * appropiately. 1115 */ 1116 int nfnl_callback_register(struct nfnl_subsys_handle *ssh, 1117 u_int8_t type, struct nfnl_callback *cb) 1118 { 1119 assert(ssh); 1120 assert(cb); 1121 1122 if (type >= ssh->cb_count) { 1123 errno = EINVAL; 1124 return -1; 1125 } 1126 1127 memcpy(&ssh->cb[type], cb, sizeof(*cb)); 1128 1129 return 0; 1130 } 1131 1132 /** 1133 * nfnl_callback_unregister - unregister a certain callback 1134 * @ssh: nfnetlink subsys handler 1135 * @type: subsys call 1136 * 1137 * On sucess, 0 is returned. On error, -1 is returned and errno is 1138 * set appropiately. 1139 */ 1140 int nfnl_callback_unregister(struct nfnl_subsys_handle *ssh, u_int8_t type) 1141 { 1142 assert(ssh); 1143 1144 if (type >= ssh->cb_count) { 1145 errno = EINVAL; 1146 return -1; 1147 } 1148 1149 ssh->cb[type].call = NULL; 1150 1151 return 0; 1152 } 1153 1154 int nfnl_check_attributes(const struct nfnl_handle *h, 1155 const struct nlmsghdr *nlh, 1156 struct nfattr *nfa[]) 1157 { 1158 assert(h); 1159 assert(nlh); 1160 assert(nfa); 1161 1162 int min_len; 1163 u_int8_t type = NFNL_MSG_TYPE(nlh->nlmsg_type); 1164 u_int8_t subsys_id = NFNL_SUBSYS_ID(nlh->nlmsg_type); 1165 const struct nfnl_subsys_handle *ssh; 1166 struct nfnl_callback *cb; 1167 1168 if (subsys_id > NFNL_MAX_SUBSYS) 1169 return -EINVAL; 1170 1171 ssh = &h->subsys[subsys_id]; 1172 cb = &ssh->cb[type]; 1173 1174 #if 1 1175 /* checks need to be enabled as soon as this is called from 1176 * somebody else than __nfnl_handle_msg */ 1177 if (type >= ssh->cb_count) 1178 return -EINVAL; 1179 1180 min_len = NLMSG_SPACE(sizeof(struct nfgenmsg)); 1181 if (nlh->nlmsg_len < min_len) 1182 return -EINVAL; 1183 #endif 1184 memset(nfa, 0, sizeof(struct nfattr *) * cb->attr_count); 1185 1186 if (nlh->nlmsg_len > min_len) { 1187 struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh)); 1188 int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); 1189 1190 while (NFA_OK(attr, attrlen)) { 1191 unsigned int flavor = NFA_TYPE(attr); 1192 if (flavor) { 1193 if (flavor > cb->attr_count) { 1194 /* we have received an attribute from 1195 * the kernel which we don't understand 1196 * yet. We have to silently ignore this 1197 * for the sake of future compatibility */ 1198 attr = NFA_NEXT(attr, attrlen); 1199 continue; 1200 } 1201 nfa[flavor - 1] = attr; 1202 } 1203 attr = NFA_NEXT(attr, attrlen); 1204 } 1205 } 1206 1207 return 0; 1208 } 1209 1210 static int __nfnl_handle_msg(struct nfnl_handle *h, struct nlmsghdr *nlh, 1211 int len) 1212 { 1213 struct nfnl_subsys_handle *ssh; 1214 u_int8_t type = NFNL_MSG_TYPE(nlh->nlmsg_type); 1215 u_int8_t subsys_id = NFNL_SUBSYS_ID(nlh->nlmsg_type); 1216 int err = 0; 1217 1218 if (subsys_id > NFNL_MAX_SUBSYS) 1219 return -1; 1220 1221 ssh = &h->subsys[subsys_id]; 1222 1223 if (nlh->nlmsg_len < NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct nfgenmsg)))) 1224 return -1; 1225 1226 if (type >= ssh->cb_count) 1227 return -1; 1228 1229 if (ssh->cb[type].attr_count) { 1230 struct nfattr *nfa[ssh->cb[type].attr_count]; 1231 1232 err = nfnl_check_attributes(h, nlh, nfa); 1233 if (err < 0) 1234 return err; 1235 if (ssh->cb[type].call) 1236 return ssh->cb[type].call(nlh, nfa, ssh->cb[type].data); 1237 } 1238 return 0; 1239 } 1240 1241 int nfnl_handle_packet(struct nfnl_handle *h, char *buf, int len) 1242 { 1243 1244 while (len >= NLMSG_SPACE(0)) { 1245 u_int32_t rlen; 1246 struct nlmsghdr *nlh = (struct nlmsghdr *)buf; 1247 1248 if (nlh->nlmsg_len < sizeof(struct nlmsghdr) 1249 || len < nlh->nlmsg_len) 1250 return -1; 1251 1252 rlen = NLMSG_ALIGN(nlh->nlmsg_len); 1253 if (rlen > len) 1254 rlen = len; 1255 1256 if (__nfnl_handle_msg(h, nlh, rlen) < 0) 1257 return -1; 1258 1259 len -= rlen; 1260 buf += rlen; 1261 } 1262 return 0; 1263 } 1264 1265 static int nfnl_is_error(struct nfnl_handle *h, struct nlmsghdr *nlh) 1266 { 1267 /* This message is an ACK or a DONE */ 1268 if (nlh->nlmsg_type == NLMSG_ERROR || 1269 (nlh->nlmsg_type == NLMSG_DONE && 1270 nlh->nlmsg_flags & NLM_F_MULTI)) { 1271 if (nlh->nlmsg_len < NLMSG_ALIGN(sizeof(struct nlmsgerr))) { 1272 errno = EBADMSG; 1273 return 1; 1274 } 1275 errno = -(*((int *)NLMSG_DATA(nlh))); 1276 return 1; 1277 } 1278 return 0; 1279 } 1280 1281 /* On error, -1 is returned and errno is set appropiately. On success, 1282 * 0 is returned if there is no more data to process, >0 if there is 1283 * more data to process */ 1284 static int nfnl_step(struct nfnl_handle *h, struct nlmsghdr *nlh) 1285 { 1286 struct nfnl_subsys_handle *ssh; 1287 u_int8_t type = NFNL_MSG_TYPE(nlh->nlmsg_type); 1288 u_int8_t subsys_id = NFNL_SUBSYS_ID(nlh->nlmsg_type); 1289 1290 /* Is this an error message? */ 1291 if (nfnl_is_error(h, nlh)) { 1292 /* This is an ACK */ 1293 if (errno == 0) 1294 return 0; 1295 /* This an error message */ 1296 return -1; 1297 } 1298 1299 /* nfnetlink sanity checks: check for nfgenmsg size */ 1300 if (nlh->nlmsg_len < NLMSG_SPACE(sizeof(struct nfgenmsg))) { 1301 errno = ENOSPC; 1302 return -1; 1303 } 1304 1305 if (subsys_id > NFNL_MAX_SUBSYS) { 1306 errno = ENOENT; 1307 return -1; 1308 } 1309 1310 ssh = &h->subsys[subsys_id]; 1311 if (!ssh) { 1312 errno = ENOENT; 1313 return -1; 1314 } 1315 1316 if (type >= ssh->cb_count) { 1317 errno = ENOENT; 1318 return -1; 1319 } 1320 1321 if (ssh->cb[type].attr_count) { 1322 int err; 1323 struct nfattr *tb[ssh->cb[type].attr_count]; 1324 struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh)); 1325 int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg)); 1326 int len = nlh->nlmsg_len - NLMSG_ALIGN(min_len); 1327 1328 err = nfnl_parse_attr(tb, ssh->cb[type].attr_count, attr, len); 1329 if (err == -1) 1330 return -1; 1331 1332 if (ssh->cb[type].call) { 1333 /* 1334 * On error, the callback returns NFNL_CB_FAILURE and 1335 * errno must be explicitely set. On success, 1336 * NFNL_CB_STOP is returned and we're done, otherwise 1337 * NFNL_CB_CONTINUE means that we want to continue 1338 * data processing. 1339 */ 1340 return ssh->cb[type].call(nlh, 1341 tb, 1342 ssh->cb[type].data); 1343 } 1344 } 1345 /* no callback set, continue data processing */ 1346 return 1; 1347 } 1348 1349 /** 1350 * nfnl_process - process data coming from a nfnetlink system 1351 * @h: nfnetlink handler 1352 * @buf: buffer that contains the netlink message 1353 * @len: size of the data contained in the buffer (not the buffer size) 1354 * 1355 * This function processes all the nfnetlink messages contained inside a 1356 * buffer. It performs the appropiate sanity checks and passes the message 1357 * to a certain handler that is registered via register_callback(). 1358 * 1359 * On success, NFNL_CB_STOP is returned if the data processing has finished. 1360 * If a value NFNL_CB_CONTINUE is returned, then there is more data to 1361 * process. On error, NFNL_CB_CONTINUE is returned and errno is set to the 1362 * appropiate value. 1363 * 1364 * In case that the callback returns NFNL_CB_FAILURE, errno may be set by 1365 * the library client. If your callback decides not to process data anymore 1366 * for any reason, then it must return NFNL_CB_STOP. Otherwise, if the 1367 * callback continues the processing NFNL_CB_CONTINUE is returned. 1368 */ 1369 int nfnl_process(struct nfnl_handle *h, const unsigned char *buf, size_t len) 1370 { 1371 int ret = 0; 1372 struct nlmsghdr *nlh = (struct nlmsghdr *)buf; 1373 1374 assert(h); 1375 assert(buf); 1376 assert(len > 0); 1377 1378 /* check for out of sequence message */ 1379 if (nlh->nlmsg_seq && nlh->nlmsg_seq != h->seq) { 1380 errno = EILSEQ; 1381 return -1; 1382 } 1383 while (len >= NLMSG_SPACE(0) && NLMSG_OK(nlh, len)) { 1384 1385 ret = nfnl_step(h, nlh); 1386 if (ret <= NFNL_CB_STOP) 1387 break; 1388 1389 nlh = NLMSG_NEXT(nlh, len); 1390 } 1391 return ret; 1392 } 1393 1394 /* 1395 * New parsing functions based on iterators 1396 */ 1397 1398 struct nfnl_iterator { 1399 struct nlmsghdr *nlh; 1400 unsigned int len; 1401 }; 1402 1403 /** 1404 * nfnl_iterator_create: create an nfnetlink iterator 1405 * @h: nfnetlink handler 1406 * @buf: buffer that contains data received from a nfnetlink system 1407 * @len: size of the data contained in the buffer (not the buffer size) 1408 * 1409 * This function creates an iterator that can be used to parse nfnetlink 1410 * message one by one. The iterator gives more control to the programmer 1411 * in the messages processing. 1412 * 1413 * On success, a valid address is returned. On error, NULL is returned 1414 * and errno is set to the appropiate value. 1415 */ 1416 struct nfnl_iterator * 1417 nfnl_iterator_create(const struct nfnl_handle *h, 1418 const char *buf, 1419 size_t len) 1420 { 1421 struct nlmsghdr *nlh; 1422 struct nfnl_iterator *it; 1423 1424 assert(h); 1425 assert(buf); 1426 assert(len > 0); 1427 1428 it = malloc(sizeof(struct nfnl_iterator)); 1429 if (!it) { 1430 errno = ENOMEM; 1431 return NULL; 1432 } 1433 1434 /* first message in buffer */ 1435 nlh = (struct nlmsghdr *)buf; 1436 if (len < NLMSG_SPACE(0) || !NLMSG_OK(nlh, len)) { 1437 free(it); 1438 errno = EBADMSG; 1439 return NULL; 1440 } 1441 it->nlh = nlh; 1442 it->len = len; 1443 1444 return it; 1445 } 1446 1447 /** 1448 * nfnl_iterator_destroy - destroy a nfnetlink iterator 1449 * @it: nfnetlink iterator 1450 * 1451 * This function destroys a certain iterator. Nothing is returned. 1452 */ 1453 void nfnl_iterator_destroy(struct nfnl_iterator *it) 1454 { 1455 assert(it); 1456 free(it); 1457 } 1458 1459 /** 1460 * nfnl_iterator_process - process a nfnetlink message 1461 * @h: nfnetlink handler 1462 * @it: nfnetlink iterator that contains the current message to be proccesed 1463 * 1464 * This function process just the current message selected by the iterator. 1465 * On success, a value greater or equal to zero is returned. On error, 1466 * -1 is returned and errno is appropiately set. 1467 */ 1468 int nfnl_iterator_process(struct nfnl_handle *h, struct nfnl_iterator *it) 1469 { 1470 assert(h); 1471 assert(it->nlh); 1472 1473 /* check for out of sequence message */ 1474 if (it->nlh->nlmsg_seq && it->nlh->nlmsg_seq != h->seq) { 1475 errno = EILSEQ; 1476 return -1; 1477 } 1478 if (it->len < NLMSG_SPACE(0) || !NLMSG_OK(it->nlh, it->len)) { 1479 errno = EBADMSG; 1480 return -1; 1481 } 1482 return nfnl_step(h, it->nlh); 1483 } 1484 1485 /** 1486 * nfnl_iterator_next - get the next message hold by the iterator 1487 * @h: nfnetlink handler 1488 * @it: nfnetlink iterator that contains the current message processed 1489 * 1490 * This function update the current message to be processed pointer. 1491 * It returns NFNL_CB_CONTINUE if there is still more messages to be 1492 * processed, otherwise NFNL_CB_STOP is returned. 1493 */ 1494 int nfnl_iterator_next(const struct nfnl_handle *h, struct nfnl_iterator *it) 1495 { 1496 assert(h); 1497 assert(it); 1498 1499 it->nlh = NLMSG_NEXT(it->nlh, it->len); 1500 if (!it->nlh) 1501 return 0; 1502 return 1; 1503 } 1504 1505 /** 1506 * nfnl_catch - get responses from the nfnetlink system and process them 1507 * @h: nfnetlink handler 1508 * 1509 * This function handles the data received from the nfnetlink system. 1510 * For example, events generated by one of the subsystems. The message 1511 * is passed to the callback registered via callback_register(). Note that 1512 * this a replacement of nfnl_listen and its use is recommended. 1513 * 1514 * On success, 0 is returned. On error, a -1 is returned. If you do not 1515 * want to listen to events anymore, then your callback must return 1516 * NFNL_CB_STOP. 1517 * 1518 * Note that ENOBUFS is returned in case that nfnetlink is exhausted. In 1519 * that case is possible that the information requested is incomplete. 1520 */ 1521 int nfnl_catch(struct nfnl_handle *h) 1522 { 1523 int ret; 1524 1525 assert(h); 1526 1527 while (1) { 1528 unsigned char buf[h->rcv_buffer_size] 1529 __attribute__ ((aligned)); 1530 1531 ret = nfnl_recv(h, buf, sizeof(buf)); 1532 if (ret == -1) { 1533 /* interrupted syscall must retry */ 1534 if (errno == EINTR) 1535 continue; 1536 break; 1537 } 1538 1539 ret = nfnl_process(h, buf, ret); 1540 if (ret <= NFNL_CB_STOP) 1541 break; 1542 } 1543 1544 return ret; 1545 } 1546 1547 /** 1548 * nfnl_query - request/response communication challenge 1549 * @h: nfnetlink handler 1550 * @nlh: nfnetlink message to be sent 1551 * 1552 * This function sends a nfnetlink message to a certain subsystem and 1553 * receives the response messages associated, such messages are passed to 1554 * the callback registered via register_callback(). Note that this function 1555 * is a replacement for nfnl_talk, its use is recommended. 1556 * 1557 * On success, 0 is returned. On error, a negative is returned. If your 1558 * does not want to listen to events anymore, then your callback must 1559 * return NFNL_CB_STOP. 1560 * 1561 * Note that ENOBUFS is returned in case that nfnetlink is exhausted. In 1562 * that case is possible that the information requested is incomplete. 1563 */ 1564 int nfnl_query(struct nfnl_handle *h, struct nlmsghdr *nlh) 1565 { 1566 assert(h); 1567 assert(nlh); 1568 1569 if (nfnl_send(h, nlh) == -1) 1570 return -1; 1571 1572 return nfnl_catch(h); 1573 } 1574