diff --git a/configure.in b/configure.in index fbcbd61..6a71da3 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ AC_INIT AC_CANONICAL_SYSTEM -AM_INIT_AUTOMAKE(libnfnetlink, 0.0.30) +AM_INIT_AUTOMAKE(libnfnetlink, 0.0.33) AC_PROG_CC AC_EXEEXT diff --git a/include/libnfnetlink/libnfnetlink.h b/include/libnfnetlink/libnfnetlink.h index de77caa..37fa663 100644 --- a/include/libnfnetlink/libnfnetlink.h +++ b/include/libnfnetlink/libnfnetlink.h @@ -56,6 +56,9 @@ extern struct nfnl_subsys_handle *nfnl_subsys_open(struct nfnl_handle *, unsigned int); extern void nfnl_subsys_close(struct nfnl_subsys_handle *); +/* set receive buffer size (for nfnl_catch) */ +extern void nfnl_set_rcv_buffer_size(struct nfnl_handle *h, unsigned int size); + /* sending of data */ extern int nfnl_send(struct nfnl_handle *, struct nlmsghdr *); extern int nfnl_sendmsg(const struct nfnl_handle *, const struct msghdr *msg, @@ -170,7 +173,8 @@ extern int nfnl_parse_attr(struct nfattr **, int, struct nfattr *, int); extern void nfnl_build_nfa_iovec(struct iovec *iov, struct nfattr *nfa, u_int16_t type, u_int32_t len, unsigned char *val); -extern unsigned int nfnl_rcvbufsiz(struct nfnl_handle *h, unsigned int size); +extern unsigned int nfnl_rcvbufsiz(const struct nfnl_handle *h, + unsigned int size); extern void nfnl_dump_packet(struct nlmsghdr *, int, char *); diff --git a/src/libnfnetlink.c b/src/libnfnetlink.c index 6cbc43e..6b91631 100644 --- a/src/libnfnetlink.c +++ b/src/libnfnetlink.c @@ -85,6 +85,7 @@ struct nfnl_handle { u_int32_t subscriptions; u_int32_t seq; u_int32_t dump; + u_int32_t rcv_buffer_size; /* for nfnl_catch */ struct nlmsghdr *last_nlhdr; struct nfnl_subsys_handle subsys[NFNL_MAX_SUBSYS+1]; }; @@ -184,6 +185,7 @@ struct nfnl_handle *nfnl_open(void) goto err_close; } nfnlh->seq = time(NULL); + nfnlh->rcv_buffer_size = NFNL_BUFFSIZE; /* don't set pid here, only first socket of process has real pid !!! * binding to pid '0' will default */ @@ -211,6 +213,19 @@ err_free: } /** + * nfnl_set_rcv_buffer_size - set the size of the receive buffer + * @h: libnfnetlink handler + * @size: buffer size + * + * This function sets the size of the receive buffer size, i.e. the size + * of the buffer used by nfnl_recv. Default value is 4096 bytes. + */ +void nfnl_set_rcv_buffer_size(struct nfnl_handle *h, unsigned int size) +{ + h->rcv_buffer_size = size; +} + +/** * nfnl_subsys_open - open a netlink subsystem * @nfnlh: libnfnetlink handle * @subsys_id: which nfnetlink subsystem we are interested in @@ -943,7 +958,7 @@ void nfnl_build_nfa_iovec(struct iovec *iov, struct nfattr *nfa, * * This function returns the new size of the socket buffer. */ -unsigned int nfnl_rcvbufsiz(struct nfnl_handle *h, unsigned int size) +unsigned int nfnl_rcvbufsiz(const struct nfnl_handle *h, unsigned int size) { int status; socklen_t socklen = sizeof(size); @@ -1129,6 +1144,7 @@ int nfnl_check_attributes(const struct nfnl_handle *h, * the kernel which we don't understand * yet. We have to silently ignore this * for the sake of future compatibility */ + attr = NFA_NEXT(attr, attrlen); continue; } nfa[flavor - 1] = attr; @@ -1190,6 +1206,7 @@ int nfnl_handle_packet(struct nfnl_handle *h, char *buf, int len) return -1; len -= rlen; + buf += rlen; } return 0; } @@ -1453,52 +1470,11 @@ int nfnl_iterator_next(const struct nfnl_handle *h, struct nfnl_iterator *it) int nfnl_catch(struct nfnl_handle *h) { int ret; - unsigned int size = NFNL_BUFFSIZE; assert(h); - /* - * Since nfqueue can send big packets, we don't know how big - * must be the buffer that have to store the received data. - */ - { - unsigned char buf[size]; - struct sockaddr_nl peer; - struct iovec iov = { - .iov_len = size, - }; - struct msghdr msg = { - .msg_name = (void *) &peer, - .msg_namelen = sizeof(peer), - .msg_iov = &iov, - .msg_iovlen = 1, - .msg_control = NULL, - .msg_controllen = 0, - .msg_flags = 0 - }; - - memset(&peer, 0, sizeof(peer)); - peer.nl_family = AF_NETLINK; - iov.iov_base = buf; - iov.iov_len = size; - -retry: ret = recvmsg(h->fd, &msg, MSG_PEEK); - if (ret == -1) { - /* interrupted syscall must retry */ - if (errno == EINTR) - goto retry; - /* otherwise give up */ - return -1; - } - - if (msg.msg_flags & MSG_TRUNC) - /* maximum size of data received from netlink */ - size = 65535; - } - - /* now, receive data from netlink */ while (1) { - unsigned char buf[size]; + unsigned char buf[h->rcv_buffer_size]; ret = nfnl_recv(h, buf, sizeof(buf)); if (ret == -1) {