diff options
author | Florian Westphal <fw@strlen.de> | 2011-01-18 16:08:30 +0100 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2011-01-18 16:08:30 +0100 |
commit | 94b27cc36123069966616670c3653cd6873babe9 (patch) | |
tree | b3a70cab28cbc021532d2a73cac6aae5e015d8ac /net/netfilter/nf_queue.c | |
parent | f615df76ed862b7d3927ec5f55b805ca19be29d9 (diff) | |
download | op-kernel-dev-94b27cc36123069966616670c3653cd6873babe9.zip op-kernel-dev-94b27cc36123069966616670c3653cd6873babe9.tar.gz |
netfilter: allow NFQUEUE bypass if no listener is available
If an skb is to be NF_QUEUE'd, but no program has opened the queue, the
packet is dropped.
This adds a v2 target revision of xt_NFQUEUE that allows packets to
continue through the ruleset instead.
Because the actual queueing happens outside of the target context, the
'bypass' flag has to be communicated back to the netfilter core.
Unfortunately the only choice to do this without adding a new function
argument is to use the target function return value (i.e. the verdict).
In the NF_QUEUE case, the upper 16bit already contain the queue number
to use. The previous patch reduced NF_VERDICT_MASK to 0xff, i.e.
we now have extra room for a new flag.
If a hook issued a NF_QUEUE verdict, then the netfilter core will
continue packet processing if the queueing hook
returns -ESRCH (== "this queue does not exist") and the new
NF_VERDICT_FLAG_QUEUE_BYPASS flag is set in the verdict value.
Note: If the queue exists, but userspace does not consume packets fast
enough, the skb will still be dropped.
Signed-off-by: Florian Westphal <fwestphal@astaro.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/netfilter/nf_queue.c')
-rw-r--r-- | net/netfilter/nf_queue.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index ce1150d4a..5ab22e2 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -138,8 +138,10 @@ static int __nf_queue(struct sk_buff *skb, rcu_read_lock(); qh = rcu_dereference(queue_handler[pf]); - if (!qh) + if (!qh) { + status = -ESRCH; goto err_unlock; + } afinfo = nf_get_afinfo(pf); if (!afinfo) @@ -303,6 +305,9 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) if (err < 0) { if (err == -ECANCELED) goto next_hook; + if (err == -ESRCH && + (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS)) + goto next_hook; kfree_skb(skb); } break; |