diff options
Diffstat (limited to 'net/netfilter/nfnetlink_queue.c')
-rw-r--r-- | net/netfilter/nfnetlink_queue.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 556bc902af..5cf38fc0a3 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -228,19 +228,29 @@ find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id) static void nfqnl_reinject(struct nf_queue_entry *entry, unsigned int verdict) { const struct nf_ct_hook *ct_hook; - int err; if (verdict == NF_ACCEPT || verdict == NF_REPEAT || verdict == NF_STOP) { + unsigned int ct_verdict = verdict; + rcu_read_lock(); ct_hook = rcu_dereference(nf_ct_hook); - if (ct_hook) { - err = ct_hook->update(entry->state.net, entry->skb); - if (err < 0) - verdict = NF_DROP; - } + if (ct_hook) + ct_verdict = ct_hook->update(entry->state.net, entry->skb); rcu_read_unlock(); + + switch (ct_verdict & NF_VERDICT_MASK) { + case NF_ACCEPT: + /* follow userspace verdict, could be REPEAT */ + break; + case NF_STOLEN: + nf_queue_entry_free(entry); + return; + default: + verdict = ct_verdict & NF_VERDICT_MASK; + break; + } } nf_reinject(entry, verdict); } |