From de8dafc90e335cbb06252a087d25a7589b607ad2 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 17 Feb 2009 20:40:36 +0100 Subject: nfnl: allow disabling and enabling sequence tracking This patch adds a couple of functions to enable and disable netlink sequence tracking. Since nfqueue goes over a unicast socket, the same channel to receive control messages and packets is used. This leads to race conditions that may trigger sporious out-of-sequence errors while creating queues and receiving high load of packets at the same time. Reported-by: Anton Vazir Signed-off-by: Pablo Neira Ayuso --- src/libnfnetlink.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) (limited to 'src/libnfnetlink.c') diff --git a/src/libnfnetlink.c b/src/libnfnetlink.c index d4212f9..a836de1 100644 --- a/src/libnfnetlink.c +++ b/src/libnfnetlink.c @@ -78,6 +78,9 @@ struct nfnl_subsys_handle { }; #define NFNL_MAX_SUBSYS 16 /* enough for now */ + +#define NFNL_F_SEQTRACK_ENABLED (1 << 0) + struct nfnl_handle { int fd; struct sockaddr_nl local; @@ -86,6 +89,7 @@ struct nfnl_handle { u_int32_t seq; u_int32_t dump; u_int32_t rcv_buffer_size; /* for nfnl_catch */ + u_int32_t flags; struct nlmsghdr *last_nlhdr; struct nfnl_subsys_handle subsys[NFNL_MAX_SUBSYS+1]; }; @@ -202,6 +206,8 @@ struct nfnl_handle *nfnl_open(void) errno = EINVAL; goto err_close; } + /* sequence tracking enabled by default */ + nfnlh->flags |= NFNL_F_SEQTRACK_ENABLED; return nfnlh; @@ -212,6 +218,24 @@ err_free: return NULL; } +/** + * nfnl_set_sequence_tracking - set netlink sequence tracking + * @h: nfnetlink handler + */ +void nfnl_set_sequence_tracking(struct nfnl_handle *h) +{ + h->flags |= NFNL_F_SEQTRACK_ENABLED; +} + +/** + * nfnl_unset_sequence_tracking - set netlink sequence tracking + * @h: nfnetlink handler + */ +void nfnl_unset_sequence_tracking(struct nfnl_handle *h) +{ + h->flags &= ~NFNL_F_SEQTRACK_ENABLED; +} + /** * nfnl_set_rcv_buffer_size - set the size of the receive buffer * @h: libnfnetlink handler @@ -418,11 +442,16 @@ void nfnl_fill_hdr(struct nfnl_subsys_handle *ssh, nlh->nlmsg_type = (ssh->subsys_id<<8)|msg_type; nlh->nlmsg_flags = msg_flags; nlh->nlmsg_pid = 0; - nlh->nlmsg_seq = ++ssh->nfnlh->seq; - /* check for wraparounds: assume that seqnum 0 is only used by events */ - if (!ssh->nfnlh->seq) - nlh->nlmsg_seq = ssh->nfnlh->seq = time(NULL); + if (ssh->nfnlh->flags & NFNL_F_SEQTRACK_ENABLED) { + nlh->nlmsg_seq = ++ssh->nfnlh->seq; + /* kernel uses sequence number zero for events */ + if (!ssh->nfnlh->seq) + nlh->nlmsg_seq = ssh->nfnlh->seq = time(NULL); + } else { + /* unset sequence number, ignore it */ + nlh->nlmsg_seq = 0; + } nfg->nfgen_family = family; nfg->version = NFNETLINK_V0; -- cgit v1.2.3