Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
[sfrench/cifs-2.6.git] / net / netfilter / nfnetlink_queue.c
index 494a9ab35cb67795c63d8f2ade18f76f23841f24..4ccd2988f9db637166358335d8e26299c7237bec 100644 (file)
@@ -227,6 +227,25 @@ find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id)
        return entry;
 }
 
+static void nfqnl_reinject(struct nf_queue_entry *entry, unsigned int verdict)
+{
+       struct nf_ct_hook *ct_hook;
+       int err;
+
+       if (verdict == NF_ACCEPT ||
+           verdict == NF_STOP) {
+               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;
+               }
+               rcu_read_unlock();
+       }
+       nf_reinject(entry, verdict);
+}
+
 static void
 nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data)
 {
@@ -237,7 +256,7 @@ nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data)
                if (!cmpfn || cmpfn(entry, data)) {
                        list_del(&entry->list);
                        queue->queue_total--;
-                       nf_reinject(entry, NF_DROP);
+                       nfqnl_reinject(entry, NF_DROP);
                }
        }
        spin_unlock_bh(&queue->lock);
@@ -686,7 +705,7 @@ err_out_free_nskb:
 err_out_unlock:
        spin_unlock_bh(&queue->lock);
        if (failopen)
-               nf_reinject(entry, NF_ACCEPT);
+               nfqnl_reinject(entry, NF_ACCEPT);
 err_out:
        return err;
 }
@@ -1085,7 +1104,8 @@ static int nfqnl_recv_verdict_batch(struct net *net, struct sock *ctnl,
        list_for_each_entry_safe(entry, tmp, &batch_list, list) {
                if (nfqa[NFQA_MARK])
                        entry->skb->mark = ntohl(nla_get_be32(nfqa[NFQA_MARK]));
-               nf_reinject(entry, verdict);
+
+               nfqnl_reinject(entry, verdict);
        }
        return 0;
 }
@@ -1208,7 +1228,7 @@ static int nfqnl_recv_verdict(struct net *net, struct sock *ctnl,
        if (nfqa[NFQA_MARK])
                entry->skb->mark = ntohl(nla_get_be32(nfqa[NFQA_MARK]));
 
-       nf_reinject(entry, verdict);
+       nfqnl_reinject(entry, verdict);
        return 0;
 }