diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2009-02-17 20:40:36 +0100 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2009-02-17 20:40:36 +0100 |
commit | de8dafc90e335cbb06252a087d25a7589b607ad2 (patch) | |
tree | d11a6a4c82569a466245181cb5a06995eabd4b32 /src | |
parent | b5194b353d27aa0c480691be44e2d4778759c9c0 (diff) |
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 <anton.vazir@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/libnfnetlink.c | 37 |
1 files changed, 33 insertions, 4 deletions
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; @@ -213,6 +219,24 @@ err_free: } /** + * 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 * @size: buffer size @@ -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; |