summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2009-02-17 20:40:36 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2009-02-17 20:40:36 +0100
commitde8dafc90e335cbb06252a087d25a7589b607ad2 (patch)
treed11a6a4c82569a466245181cb5a06995eabd4b32 /src
parentb5194b353d27aa0c480691be44e2d4778759c9c0 (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.c37
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;