Updates to Tomato RAF including NGINX && PHP
[tomato.git] / release / src / router / libnfnetlink / src / libnfnetlink.c
blob4b2bcd015b0a6d45d14ecf650694a9e1308a53f2
1 /* libnfnetlink.c: generic library for communication with netfilter
3 * (C) 2002-2006 by Harald Welte <laforge@gnumonks.org>
4 * (C) 2006-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
6 * Based on some original ideas from Jay Schulist <jschlst@samba.org>
8 * Development of this code funded by Astaro AG (http://www.astaro.com)
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.
14 * 2005-09-14 Pablo Neira Ayuso <pablo@netfilter.org>:
15 * Define structure nfnlhdr
16 * Added __be64_to_cpu function
17 * Use NFA_TYPE macro to get the attribute type
19 * 2006-01-14 Harald Welte <laforge@netfilter.org>:
20 * introduce nfnl_subsys_handle
22 * 2006-01-15 Pablo Neira Ayuso <pablo@netfilter.org>:
23 * set missing subsys_id in nfnl_subsys_open
24 * set missing nfnlh->local.nl_pid in nfnl_open
26 * 2006-01-26 Harald Welte <laforge@netfilter.org>:
27 * remove bogus nfnlh->local.nl_pid from nfnl_open ;)
28 * add 16bit attribute functions
30 * 2006-07-03 Pablo Neira Ayuso <pablo@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
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>
51 #include <linux/netlink.h>
53 #include <libnfnetlink/libnfnetlink.h>
55 #ifndef NETLINK_ADD_MEMBERSHIP
56 #define NETLINK_ADD_MEMBERSHIP 1
57 #endif
59 #ifndef SOL_NETLINK
60 #define SOL_NETLINK 270
61 #endif
64 #define nfnl_error(format, args...) \
65 fprintf(stderr, "%s: " format "\n", __FUNCTION__, ## args)
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
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 */
81 #define NFNL_MAX_SUBSYS 16 /* enough for now */
83 #define NFNL_F_SEQTRACK_ENABLED (1 << 0)
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];
98 void nfnl_dump_packet(struct nlmsghdr *nlh, int received_len, char *desc)
100 void *nlmsg_data = NLMSG_DATA(nlh);
101 struct nfattr *nfa = NFM_NFA(NLMSG_DATA(nlh));
102 int len = NFM_PAYLOAD(nlh);
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);
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);
123 * nfnl_fd - returns the descriptor that identifies the socket
124 * @nfnlh: nfnetlink handler
126 * Use this function if you need to interact with the socket. Common
127 * scenarios are the use of poll()/select() to achieve multiplexation.
129 int nfnl_fd(struct nfnl_handle *h)
131 assert(h);
132 return h->fd;
136 * nfnl_portid - returns the Netlink port ID of this socket
137 * @h: nfnetlink handler
139 unsigned int nfnl_portid(const struct nfnl_handle *h)
141 assert(h);
142 return h->local.nl_pid;
145 static int recalc_rebind_subscriptions(struct nfnl_handle *nfnlh)
147 int i, err;
148 u_int32_t new_subscriptions = nfnlh->subscriptions;
150 for (i = 0; i < NFNL_MAX_SUBSYS; i++)
151 new_subscriptions |= nfnlh->subsys[i].subscriptions;
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;
159 nfnlh->subscriptions = new_subscriptions;
161 return 0;
165 * nfnl_open - open a nfnetlink handler
167 * This function creates a nfnetlink handler, this is required to establish
168 * a communication between the userspace and the nfnetlink system.
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.
173 struct nfnl_handle *nfnl_open(void)
175 struct nfnl_handle *nfnlh;
176 unsigned int addr_len;
178 nfnlh = malloc(sizeof(*nfnlh));
179 if (!nfnlh)
180 return NULL;
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;
187 nfnlh->local.nl_family = AF_NETLINK;
188 nfnlh->peer.nl_family = AF_NETLINK;
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;
196 if (nfnlh->local.nl_family != AF_NETLINK) {
197 errno = EINVAL;
198 goto err_close;
200 nfnlh->seq = time(NULL);
201 nfnlh->rcv_buffer_size = NFNL_BUFFSIZE;
203 /* don't set pid here, only first socket of process has real pid !!!
204 * binding to pid '0' will default */
206 /* let us do the initial bind */
207 if (recalc_rebind_subscriptions(nfnlh) < 0)
208 goto err_close;
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;
217 /* sequence tracking enabled by default */
218 nfnlh->flags |= NFNL_F_SEQTRACK_ENABLED;
220 return nfnlh;
222 err_close:
223 close(nfnlh->fd);
224 err_free:
225 free(nfnlh);
226 return NULL;
230 * nfnl_set_sequence_tracking - set netlink sequence tracking
231 * @h: nfnetlink handler
233 void nfnl_set_sequence_tracking(struct nfnl_handle *h)
235 h->flags |= NFNL_F_SEQTRACK_ENABLED;
239 * nfnl_unset_sequence_tracking - set netlink sequence tracking
240 * @h: nfnetlink handler
242 void nfnl_unset_sequence_tracking(struct nfnl_handle *h)
244 h->flags &= ~NFNL_F_SEQTRACK_ENABLED;
248 * nfnl_set_rcv_buffer_size - set the size of the receive buffer
249 * @h: libnfnetlink handler
250 * @size: buffer size
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.
255 void nfnl_set_rcv_buffer_size(struct nfnl_handle *h, unsigned int size)
257 h->rcv_buffer_size = size;
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
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().
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.
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)
279 struct nfnl_subsys_handle *ssh;
281 assert(nfnlh);
283 if (subsys_id > NFNL_MAX_SUBSYS) {
284 errno = ENOENT;
285 return NULL;
288 ssh = &nfnlh->subsys[subsys_id];
289 if (ssh->cb) {
290 errno = EBUSY;
291 return NULL;
294 ssh->cb = calloc(cb_count, sizeof(*(ssh->cb)));
295 if (!ssh->cb)
296 return NULL;
298 ssh->nfnlh = nfnlh;
299 ssh->cb_count = cb_count;
300 ssh->subscriptions = subscriptions;
301 ssh->subsys_id = subsys_id;
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;
311 return ssh;
315 * nfnl_subsys_close - close a nfnetlink subsys handler
316 * @ssh: nfnetlink subsystem handler
318 * Release all the callbacks registered in a subsystem handler.
320 void nfnl_subsys_close(struct nfnl_subsys_handle *ssh)
322 assert(ssh);
324 ssh->subscriptions = 0;
325 ssh->cb_count = 0;
326 if (ssh->cb) {
327 free(ssh->cb);
328 ssh->cb = NULL;
333 * nfnl_close - close a nfnetlink handler
334 * @nfnlh: nfnetlink handler
336 * This function closes the nfnetlink handler. On success, 0 is returned.
337 * On error, -1 is returned and errno is set appropiately.
339 int nfnl_close(struct nfnl_handle *nfnlh)
341 int i, ret;
343 assert(nfnlh);
345 for (i = 0; i < NFNL_MAX_SUBSYS; i++)
346 nfnl_subsys_close(&nfnlh->subsys[i]);
348 ret = close(nfnlh->fd);
349 if (ret < 0)
350 return ret;
352 free(nfnlh);
354 return 0;
358 * nfnl_join - join a nfnetlink multicast group
359 * @nfnlh: nfnetlink handler
360 * @group: group we want to join
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.
366 * On success, 0 is returned. On error, -1 is returned and errno is set
367 * approapiately.
369 int nfnl_join(const struct nfnl_handle *nfnlh, unsigned int group)
371 assert(nfnlh);
372 return setsockopt(nfnlh->fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
373 &group, sizeof(group));
377 * nfnl_send - send a nfnetlink message through netlink socket
378 * @nfnlh: nfnetlink handler
379 * @n: netlink message
381 * On success, the number of bytes is returned. On error, -1 is returned
382 * and errno is set appropiately.
384 int nfnl_send(struct nfnl_handle *nfnlh, struct nlmsghdr *n)
386 assert(nfnlh);
387 assert(n);
389 nfnl_debug_dump_packet(n, n->nlmsg_len+sizeof(*n), "nfnl_send");
391 return sendto(nfnlh->fd, n, n->nlmsg_len, 0,
392 (struct sockaddr *)&nfnlh->peer, sizeof(nfnlh->peer));
395 int nfnl_sendmsg(const struct nfnl_handle *nfnlh, const struct msghdr *msg,
396 unsigned int flags)
398 assert(nfnlh);
399 assert(msg);
401 return sendmsg(nfnlh->fd, msg, flags);
404 int nfnl_sendiov(const struct nfnl_handle *nfnlh, const struct iovec *iov,
405 unsigned int num, unsigned int flags)
407 struct msghdr msg;
409 assert(nfnlh);
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;
419 return nfnl_sendmsg(nfnlh, &msg, flags);
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
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.
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)
443 assert(ssh);
444 assert(nlh);
446 struct nfgenmsg *nfg = (void *)nlh + sizeof(*nlh);
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;
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;
463 nfg->nfgen_family = family;
464 nfg->version = NFNETLINK_V0;
465 nfg->res_id = htons(res_id);
468 struct nfattr *
469 nfnl_parse_hdr(const struct nfnl_handle *nfnlh,
470 const struct nlmsghdr *nlh,
471 struct nfgenmsg **genmsg)
473 if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nfgenmsg)))
474 return NULL;
476 if (nlh->nlmsg_len == NLMSG_LENGTH(sizeof(struct nfgenmsg))) {
477 if (genmsg)
478 *genmsg = (void *)nlh + sizeof(*nlh);
479 return NULL;
482 if (genmsg)
483 *genmsg = (void *)nlh + sizeof(*nlh);
485 return (void *)nlh + NLMSG_LENGTH(sizeof(struct nfgenmsg));
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
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.
498 * On success, 0 is returned. On error, -1 is returned and errno is set
499 * appropiately.
501 * Note that ENOBUFS is returned in case that nfnetlink is exhausted. In
502 * that case is possible that the information requested is incomplete.
504 ssize_t
505 nfnl_recv(const struct nfnl_handle *h, unsigned char *buf, size_t len)
507 socklen_t addrlen;
508 int status;
509 struct sockaddr_nl peer;
511 assert(h);
512 assert(buf);
513 assert(len > 0);
515 if (len < sizeof(struct nlmsgerr)
516 || len < sizeof(struct nlmsghdr)) {
517 errno = EBADMSG;
518 return -1;
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;
527 if (addrlen != sizeof(peer)) {
528 errno = EINVAL;
529 return -1;
532 if (peer.nl_pid != 0) {
533 errno = ENOMSG;
534 return -1;
537 return status;
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
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().
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.
562 int nfnl_listen(struct nfnl_handle *nfnlh,
563 int (*handler)(struct sockaddr_nl *, struct nlmsghdr *n,
564 void *), void *jarg)
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;
574 struct msghdr msg = {
575 .msg_name = &nladdr,
576 .msg_namelen = sizeof(nladdr),
577 .msg_iov = &iov,
578 .msg_iovlen = 1,
581 memset(&nladdr, 0, sizeof(nladdr));
582 nladdr.nl_family = AF_NETLINK;
583 iov.iov_base = buf;
584 iov.iov_len = sizeof(buf);
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;
599 if (remain == 0) {
600 nfnl_error("EOF on netlink");
601 return -1;
603 if (msg.msg_namelen != sizeof(nladdr)) {
604 nfnl_error("Bad sender address len (%d)",
605 msg.msg_namelen);
606 return -1;
609 for (h = (struct nlmsghdr *)buf; remain >= sizeof(*h);) {
610 int err;
611 int len = h->nlmsg_len;
612 int l = len - sizeof(*h);
614 if (l < 0 || len > remain) {
615 if (msg.msg_flags & MSG_TRUNC) {
616 nfnl_error("MSG_TRUNC");
617 return -1;
619 nfnl_error("Malformed msg (len=%d)", len);
620 return -1;
623 /* end of messages reached, let's return */
624 if (h->nlmsg_type == NLMSG_DONE)
625 return 0;
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;
634 err = handler(&nladdr, h, jarg);
635 if (err < 0)
636 return err;
637 quit |= err;
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));
644 if (msg.msg_flags & MSG_TRUNC) {
645 nfnl_error("MSG_TRUNC");
646 continue;
648 if (remain) {
649 nfnl_error("remnant size %d", remain);
650 return -1;
654 return quit;
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
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.
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)
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
684 struct msghdr msg = {
685 .msg_name = &nladdr,
686 .msg_namelen = sizeof(nladdr),
687 .msg_iov = &iov,
688 .msg_iovlen = 1,
691 memset(&nladdr, 0, sizeof(nladdr));
692 nladdr.nl_family = AF_NETLINK;
693 nladdr.nl_pid = peer;
694 nladdr.nl_groups = groups;
696 n->nlmsg_seq = seq = ++nfnlh->seq;
697 /* FIXME: why ? */
698 if (!answer)
699 n->nlmsg_flags |= NLM_F_ACK;
701 status = sendmsg(nfnlh->fd, &msg, 0);
702 if (status < 0) {
703 nfnl_error("sendmsg(netlink) %s", strerror(errno));
704 return -1;
706 iov.iov_base = buf;
707 iov.iov_len = sizeof(buf);
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;
717 if (status == 0) {
718 nfnl_error("EOF on netlink");
719 return -1;
721 if (msg.msg_namelen != sizeof(nladdr)) {
722 nfnl_error("Bad sender address len %d",
723 msg.msg_namelen);
724 return -1;
727 for (h = (struct nlmsghdr *)buf; status >= sizeof(*h); ) {
728 int len = h->nlmsg_len;
729 int l = len - sizeof(*h);
730 int err;
732 if (l < 0 || len > status) {
733 if (msg.msg_flags & MSG_TRUNC) {
734 nfnl_error("Truncated message\n");
735 return -1;
737 nfnl_error("Malformed message: len=%d\n", len);
738 return -1; /* FIXME: libnetlink exits here */
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;
748 goto cont;
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;
762 perror("NFNETLINK answers");
764 return err->error;
766 if (answer) {
767 memcpy(answer, h, h->nlmsg_len);
768 return 0;
771 nfnl_error("Unexpected reply!\n");
772 cont:
773 status -= NLMSG_ALIGN(len);
774 h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len));
776 if (msg.msg_flags & MSG_TRUNC) {
777 nfnl_error("Messages truncated\n");
778 continue;
780 if (status)
781 nfnl_error("Remnant of size %d\n", status);
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
793 int nfnl_addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
794 int alen)
796 int len = NFA_LENGTH(alen);
797 struct nfattr *nfa;
799 assert(n);
800 assert(maxlen > 0);
801 assert(type >= 0);
803 if ((NLMSG_ALIGN(n->nlmsg_len) + len) > maxlen) {
804 errno = ENOSPC;
805 return -1;
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;
817 * nfnl_nfa_addattr_l - Add variable length attribute to struct nfattr
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
826 int nfnl_nfa_addattr_l(struct nfattr *nfa, int maxlen, int type,
827 const void *data, int alen)
829 struct nfattr *subnfa;
830 int len = NFA_LENGTH(alen);
832 assert(nfa);
833 assert(maxlen > 0);
834 assert(type >= 0);
836 if (NFA_ALIGN(nfa->nfa_len) + len > maxlen) {
837 errno = ENOSPC;
838 return -1;
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;
847 return 0;
851 * nfnl_addattr8 - Add u_int8_t attribute to nlmsghdr
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
858 int nfnl_addattr8(struct nlmsghdr *n, int maxlen, int type, u_int8_t data)
860 assert(n);
861 assert(maxlen > 0);
862 assert(type >= 0);
864 return nfnl_addattr_l(n, maxlen, type, &data, sizeof(data));
868 * nfnl_nfa_addattr16 - Add u_int16_t attribute to struct nfattr
870 * @nfa: struct nfattr
871 * @maxlen: maximal length of nfattr buffer
872 * @type: type for new attribute
873 * @data: content of new attribute
876 int nfnl_nfa_addattr16(struct nfattr *nfa, int maxlen, int type,
877 u_int16_t data)
879 assert(nfa);
880 assert(maxlen > 0);
881 assert(type >= 0);
883 return nfnl_nfa_addattr_l(nfa, maxlen, type, &data, sizeof(data));
887 * nfnl_addattr16 - Add u_int16_t attribute to nlmsghdr
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
895 int nfnl_addattr16(struct nlmsghdr *n, int maxlen, int type,
896 u_int16_t data)
898 assert(n);
899 assert(maxlen > 0);
900 assert(type >= 0);
902 return nfnl_addattr_l(n, maxlen, type, &data, sizeof(data));
906 * nfnl_nfa_addattr32 - Add u_int32_t attribute to struct nfattr
908 * @nfa: struct nfattr
909 * @maxlen: maximal length of nfattr buffer
910 * @type: type for new attribute
911 * @data: content of new attribute
914 int nfnl_nfa_addattr32(struct nfattr *nfa, int maxlen, int type,
915 u_int32_t data)
917 assert(nfa);
918 assert(maxlen > 0);
919 assert(type >= 0);
921 return nfnl_nfa_addattr_l(nfa, maxlen, type, &data, sizeof(data));
925 * nfnl_addattr32 - Add u_int32_t attribute to nlmsghdr
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
933 int nfnl_addattr32(struct nlmsghdr *n, int maxlen, int type,
934 u_int32_t data)
936 assert(n);
937 assert(maxlen > 0);
938 assert(type >= 0);
940 return nfnl_addattr_l(n, maxlen, type, &data, sizeof(data));
944 * nfnl_parse_attr - Parse a list of nfattrs into a pointer array
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'
951 * The returned value is equal to the number of remaining bytes of the netlink
952 * message that cannot be parsed.
954 int nfnl_parse_attr(struct nfattr *tb[], int max, struct nfattr *nfa, int len)
956 assert(tb);
957 assert(max > 0);
958 assert(nfa);
960 memset(tb, 0, sizeof(struct nfattr *) * max);
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);
968 return len;
972 * nfnl_build_nfa_iovec - Build two iovec's from tag, length and value
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'
981 void nfnl_build_nfa_iovec(struct iovec *iov, struct nfattr *nfa,
982 u_int16_t type, u_int32_t len, unsigned char *val)
984 assert(iov);
985 assert(nfa);
987 /* Set the attribut values */
988 nfa->nfa_len = sizeof(struct nfattr) + len;
989 nfa->nfa_type = type;
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);
997 #ifndef SO_RCVBUFFORCE
998 #define SO_RCVBUFFORCE (33)
999 #endif
1002 * nfnl_rcvbufsiz - set the socket buffer size
1003 * @h: nfnetlink handler
1004 * @size: size of the buffer we want to set
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.
1010 * This function returns the new size of the socket buffer.
1012 unsigned int nfnl_rcvbufsiz(const struct nfnl_handle *h, unsigned int size)
1014 int status;
1015 socklen_t socklen = sizeof(size);
1016 unsigned int read_size = 0;
1018 assert(h);
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);
1029 getsockopt(h->fd, SOL_SOCKET, SO_RCVBUF, &read_size, &socklen);
1031 return read_size;
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
1040 * This function returns a pointer to the first netlink message contained
1041 * in the chunk of data received from certain nfnetlink subsystem.
1043 * On success, a valid address that points to the netlink message is returned.
1044 * On error, NULL is returned.
1046 struct nlmsghdr *nfnl_get_msg_first(struct nfnl_handle *h,
1047 const unsigned char *buf,
1048 size_t len)
1050 struct nlmsghdr *nlh;
1052 assert(h);
1053 assert(buf);
1054 assert(len > 0);
1056 /* first message in buffer */
1057 nlh = (struct nlmsghdr *)buf;
1058 if (!NLMSG_OK(nlh, len))
1059 return NULL;
1060 h->last_nlhdr = nlh;
1062 return nlh;
1065 struct nlmsghdr *nfnl_get_msg_next(struct nfnl_handle *h,
1066 const unsigned char *buf,
1067 size_t len)
1069 struct nlmsghdr *nlh;
1070 size_t remain_len;
1072 assert(h);
1073 assert(buf);
1074 assert(len > 0);
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;
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;
1094 remain_len = (len - ((unsigned char *)h->last_nlhdr - buf));
1095 nlh = NLMSG_NEXT(h->last_nlhdr, remain_len);
1097 if (!NLMSG_OK(nlh, remain_len)) {
1098 h->last_nlhdr = NULL;
1099 return NULL;
1102 h->last_nlhdr = nlh;
1104 return nlh;
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
1113 * On success, 0 is returned. On error, -1 is returned and errno is set
1114 * appropiately.
1116 int nfnl_callback_register(struct nfnl_subsys_handle *ssh,
1117 u_int8_t type, struct nfnl_callback *cb)
1119 assert(ssh);
1120 assert(cb);
1122 if (type >= ssh->cb_count) {
1123 errno = EINVAL;
1124 return -1;
1127 memcpy(&ssh->cb[type], cb, sizeof(*cb));
1129 return 0;
1133 * nfnl_callback_unregister - unregister a certain callback
1134 * @ssh: nfnetlink subsys handler
1135 * @type: subsys call
1137 * On sucess, 0 is returned. On error, -1 is returned and errno is
1138 * set appropiately.
1140 int nfnl_callback_unregister(struct nfnl_subsys_handle *ssh, u_int8_t type)
1142 assert(ssh);
1144 if (type >= ssh->cb_count) {
1145 errno = EINVAL;
1146 return -1;
1149 ssh->cb[type].call = NULL;
1151 return 0;
1154 int nfnl_check_attributes(const struct nfnl_handle *h,
1155 const struct nlmsghdr *nlh,
1156 struct nfattr *nfa[])
1158 assert(h);
1159 assert(nlh);
1160 assert(nfa);
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;
1168 if (subsys_id > NFNL_MAX_SUBSYS)
1169 return -EINVAL;
1171 ssh = &h->subsys[subsys_id];
1172 cb = &ssh->cb[type];
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;
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);
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);
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;
1201 nfa[flavor - 1] = attr;
1203 attr = NFA_NEXT(attr, attrlen);
1207 return 0;
1210 static int __nfnl_handle_msg(struct nfnl_handle *h, struct nlmsghdr *nlh,
1211 int len)
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;
1218 if (subsys_id > NFNL_MAX_SUBSYS)
1219 return -1;
1221 ssh = &h->subsys[subsys_id];
1223 if (nlh->nlmsg_len < NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct nfgenmsg))))
1224 return -1;
1226 if (type >= ssh->cb_count)
1227 return -1;
1229 if (ssh->cb[type].attr_count) {
1230 struct nfattr *nfa[ssh->cb[type].attr_count];
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);
1238 return 0;
1241 int nfnl_handle_packet(struct nfnl_handle *h, char *buf, int len)
1244 while (len >= NLMSG_SPACE(0)) {
1245 u_int32_t rlen;
1246 struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
1248 if (nlh->nlmsg_len < sizeof(struct nlmsghdr)
1249 || len < nlh->nlmsg_len)
1250 return -1;
1252 rlen = NLMSG_ALIGN(nlh->nlmsg_len);
1253 if (rlen > len)
1254 rlen = len;
1256 if (__nfnl_handle_msg(h, nlh, rlen) < 0)
1257 return -1;
1259 len -= rlen;
1260 buf += rlen;
1262 return 0;
1265 static int nfnl_is_error(struct nfnl_handle *h, struct nlmsghdr *nlh)
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;
1275 errno = -(*((int *)NLMSG_DATA(nlh)));
1276 return 1;
1278 return 0;
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)
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);
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;
1299 /* nfnetlink sanity checks: check for nfgenmsg size */
1300 if (nlh->nlmsg_len < NLMSG_SPACE(sizeof(struct nfgenmsg))) {
1301 errno = ENOSPC;
1302 return -1;
1305 if (subsys_id > NFNL_MAX_SUBSYS) {
1306 errno = ENOENT;
1307 return -1;
1310 ssh = &h->subsys[subsys_id];
1311 if (!ssh) {
1312 errno = ENOENT;
1313 return -1;
1316 if (type >= ssh->cb_count) {
1317 errno = ENOENT;
1318 return -1;
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);
1328 err = nfnl_parse_attr(tb, ssh->cb[type].attr_count, attr, len);
1329 if (err == -1)
1330 return -1;
1332 if (ssh->cb[type].call) {
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.
1340 return ssh->cb[type].call(nlh,
1342 ssh->cb[type].data);
1345 /* no callback set, continue data processing */
1346 return 1;
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)
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().
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.
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.
1369 int nfnl_process(struct nfnl_handle *h, const unsigned char *buf, size_t len)
1371 int ret = 0;
1372 struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
1374 assert(h);
1375 assert(buf);
1376 assert(len > 0);
1378 /* check for out of sequence message */
1379 if (nlh->nlmsg_seq && nlh->nlmsg_seq != h->seq) {
1380 errno = EILSEQ;
1381 return -1;
1383 while (len >= NLMSG_SPACE(0) && NLMSG_OK(nlh, len)) {
1385 ret = nfnl_step(h, nlh);
1386 if (ret <= NFNL_CB_STOP)
1387 break;
1389 nlh = NLMSG_NEXT(nlh, len);
1391 return ret;
1395 * New parsing functions based on iterators
1398 struct nfnl_iterator {
1399 struct nlmsghdr *nlh;
1400 unsigned int len;
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)
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.
1413 * On success, a valid address is returned. On error, NULL is returned
1414 * and errno is set to the appropiate value.
1416 struct nfnl_iterator *
1417 nfnl_iterator_create(const struct nfnl_handle *h,
1418 const char *buf,
1419 size_t len)
1421 struct nlmsghdr *nlh;
1422 struct nfnl_iterator *it;
1424 assert(h);
1425 assert(buf);
1426 assert(len > 0);
1428 it = malloc(sizeof(struct nfnl_iterator));
1429 if (!it) {
1430 errno = ENOMEM;
1431 return NULL;
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;
1441 it->nlh = nlh;
1442 it->len = len;
1444 return it;
1448 * nfnl_iterator_destroy - destroy a nfnetlink iterator
1449 * @it: nfnetlink iterator
1451 * This function destroys a certain iterator. Nothing is returned.
1453 void nfnl_iterator_destroy(struct nfnl_iterator *it)
1455 assert(it);
1456 free(it);
1460 * nfnl_iterator_process - process a nfnetlink message
1461 * @h: nfnetlink handler
1462 * @it: nfnetlink iterator that contains the current message to be proccesed
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.
1468 int nfnl_iterator_process(struct nfnl_handle *h, struct nfnl_iterator *it)
1470 assert(h);
1471 assert(it->nlh);
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;
1478 if (it->len < NLMSG_SPACE(0) || !NLMSG_OK(it->nlh, it->len)) {
1479 errno = EBADMSG;
1480 return -1;
1482 return nfnl_step(h, it->nlh);
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
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.
1494 int nfnl_iterator_next(const struct nfnl_handle *h, struct nfnl_iterator *it)
1496 assert(h);
1497 assert(it);
1499 it->nlh = NLMSG_NEXT(it->nlh, it->len);
1500 if (!it->nlh)
1501 return 0;
1502 return 1;
1506 * nfnl_catch - get responses from the nfnetlink system and process them
1507 * @h: nfnetlink handler
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.
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.
1518 * Note that ENOBUFS is returned in case that nfnetlink is exhausted. In
1519 * that case is possible that the information requested is incomplete.
1521 int nfnl_catch(struct nfnl_handle *h)
1523 int ret;
1525 assert(h);
1527 while (1) {
1528 unsigned char buf[h->rcv_buffer_size]
1529 __attribute__ ((aligned));
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;
1539 ret = nfnl_process(h, buf, ret);
1540 if (ret <= NFNL_CB_STOP)
1541 break;
1544 return ret;
1548 * nfnl_query - request/response communication challenge
1549 * @h: nfnetlink handler
1550 * @nlh: nfnetlink message to be sent
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.
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.
1561 * Note that ENOBUFS is returned in case that nfnetlink is exhausted. In
1562 * that case is possible that the information requested is incomplete.
1564 int nfnl_query(struct nfnl_handle *h, struct nlmsghdr *nlh)
1566 assert(h);
1567 assert(nlh);
1569 if (nfnl_send(h, nlh) == -1)
1570 return -1;
1572 return nfnl_catch(h);