netfilter: handle NF_REPEAT from nf_conntrack_in()
authorPablo Neira Ayuso <pablo@netfilter.org>
Thu, 3 Nov 2016 09:56:43 +0000 (10:56 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 3 Nov 2016 10:53:00 +0000 (11:53 +0100)
NF_REPEAT is only needed from nf_conntrack_in() under a very specific
case required by the TCP protocol tracker, we can handle this case
without returning to the core hook path. Handling of NF_REPEAT from the
nf_reinject() is left untouched.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/netfilter/core.c
net/netfilter/nf_conntrack_core.c
net/openvswitch/conntrack.c

index bd9272eeccb5fe75a61df3a54973d5dbd901cfaf..de30e08d58f2fe848549e718757a403b0b8cf2ba 100644 (file)
@@ -322,8 +322,6 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state,
                        if (ret == 0)
                                ret = -EPERM;
                        return ret;
-               case NF_REPEAT:
-                       continue;
                case NF_QUEUE:
                        ret = nf_queue(skb, state, &entry, verdict);
                        if (ret == 1 && entry)
index df2f5a3901dfce580e051bf9a52d2e71da0f8e9b..de4b8a75f30b03ee0a91f3980c975af8cf1ea78f 100644 (file)
@@ -1305,7 +1305,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
                if (skb->nfct)
                        goto out;
        }
-
+repeat:
        ct = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum,
                               l3proto, l4proto, &set_reply, &ctinfo);
        if (!ct) {
@@ -1345,11 +1345,12 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
                nf_conntrack_event_cache(IPCT_REPLY, ct);
 out:
        if (tmpl) {
-               /* Special case: we have to repeat this hook, assign the
-                * template again to this packet. We assume that this packet
-                * has no conntrack assigned. This is used by nf_ct_tcp. */
+               /* Special case: TCP tracker reports an attempt to reopen a
+                * closed/aborted connection. We have to go back and create a
+                * fresh conntrack.
+                */
                if (ret == NF_REPEAT)
-                       skb->nfct = (struct nf_conntrack *)tmpl;
+                       goto repeat;
                else
                        nf_ct_put(tmpl);
        }
index 31045ef44a82b925e53ce34da2aca74448dd9c8d..9b8a028b7dad6b0c6175cebe9bb8c0b30f8c4149 100644 (file)
@@ -725,12 +725,8 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
                        skb->nfctinfo = IP_CT_NEW;
                }
 
-               /* Repeat if requested, see nf_iterate(). */
-               do {
-                       err = nf_conntrack_in(net, info->family,
-                                             NF_INET_PRE_ROUTING, skb);
-               } while (err == NF_REPEAT);
-
+               err = nf_conntrack_in(net, info->family,
+                                     NF_INET_PRE_ROUTING, skb);
                if (err != NF_ACCEPT)
                        return -ENOENT;