|
@@ -1129,7 +1129,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_free);
|
|
|
|
|
|
/* Allocate a new conntrack: we return -ENOMEM if classification
|
|
/* Allocate a new conntrack: we return -ENOMEM if classification
|
|
failed due to stress. Otherwise it really is unclassifiable. */
|
|
failed due to stress. Otherwise it really is unclassifiable. */
|
|
-static struct nf_conntrack_tuple_hash *
|
|
|
|
|
|
+static noinline struct nf_conntrack_tuple_hash *
|
|
init_conntrack(struct net *net, struct nf_conn *tmpl,
|
|
init_conntrack(struct net *net, struct nf_conn *tmpl,
|
|
const struct nf_conntrack_tuple *tuple,
|
|
const struct nf_conntrack_tuple *tuple,
|
|
struct nf_conntrack_l3proto *l3proto,
|
|
struct nf_conntrack_l3proto *l3proto,
|
|
@@ -1237,21 +1237,20 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
|
|
return &ct->tuplehash[IP_CT_DIR_ORIGINAL];
|
|
return &ct->tuplehash[IP_CT_DIR_ORIGINAL];
|
|
}
|
|
}
|
|
|
|
|
|
-/* On success, returns conntrack ptr, sets skb->_nfct | ctinfo */
|
|
|
|
-static inline struct nf_conn *
|
|
|
|
|
|
+/* On success, returns 0, sets skb->_nfct | ctinfo */
|
|
|
|
+static int
|
|
resolve_normal_ct(struct net *net, struct nf_conn *tmpl,
|
|
resolve_normal_ct(struct net *net, struct nf_conn *tmpl,
|
|
struct sk_buff *skb,
|
|
struct sk_buff *skb,
|
|
unsigned int dataoff,
|
|
unsigned int dataoff,
|
|
u_int16_t l3num,
|
|
u_int16_t l3num,
|
|
u_int8_t protonum,
|
|
u_int8_t protonum,
|
|
struct nf_conntrack_l3proto *l3proto,
|
|
struct nf_conntrack_l3proto *l3proto,
|
|
- struct nf_conntrack_l4proto *l4proto,
|
|
|
|
- int *set_reply,
|
|
|
|
- enum ip_conntrack_info *ctinfo)
|
|
|
|
|
|
+ struct nf_conntrack_l4proto *l4proto)
|
|
{
|
|
{
|
|
const struct nf_conntrack_zone *zone;
|
|
const struct nf_conntrack_zone *zone;
|
|
struct nf_conntrack_tuple tuple;
|
|
struct nf_conntrack_tuple tuple;
|
|
struct nf_conntrack_tuple_hash *h;
|
|
struct nf_conntrack_tuple_hash *h;
|
|
|
|
+ enum ip_conntrack_info ctinfo;
|
|
struct nf_conntrack_zone tmp;
|
|
struct nf_conntrack_zone tmp;
|
|
struct nf_conn *ct;
|
|
struct nf_conn *ct;
|
|
u32 hash;
|
|
u32 hash;
|
|
@@ -1260,7 +1259,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl,
|
|
dataoff, l3num, protonum, net, &tuple, l3proto,
|
|
dataoff, l3num, protonum, net, &tuple, l3proto,
|
|
l4proto)) {
|
|
l4proto)) {
|
|
pr_debug("Can't get tuple\n");
|
|
pr_debug("Can't get tuple\n");
|
|
- return NULL;
|
|
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/* look for tuple match */
|
|
/* look for tuple match */
|
|
@@ -1271,33 +1270,30 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl,
|
|
h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto,
|
|
h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto,
|
|
skb, dataoff, hash);
|
|
skb, dataoff, hash);
|
|
if (!h)
|
|
if (!h)
|
|
- return NULL;
|
|
|
|
|
|
+ return 0;
|
|
if (IS_ERR(h))
|
|
if (IS_ERR(h))
|
|
- return (void *)h;
|
|
|
|
|
|
+ return PTR_ERR(h);
|
|
}
|
|
}
|
|
ct = nf_ct_tuplehash_to_ctrack(h);
|
|
ct = nf_ct_tuplehash_to_ctrack(h);
|
|
|
|
|
|
/* It exists; we have (non-exclusive) reference. */
|
|
/* It exists; we have (non-exclusive) reference. */
|
|
if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) {
|
|
if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) {
|
|
- *ctinfo = IP_CT_ESTABLISHED_REPLY;
|
|
|
|
- /* Please set reply bit if this packet OK */
|
|
|
|
- *set_reply = 1;
|
|
|
|
|
|
+ ctinfo = IP_CT_ESTABLISHED_REPLY;
|
|
} else {
|
|
} else {
|
|
/* Once we've had two way comms, always ESTABLISHED. */
|
|
/* Once we've had two way comms, always ESTABLISHED. */
|
|
if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
|
|
if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
|
|
pr_debug("normal packet for %p\n", ct);
|
|
pr_debug("normal packet for %p\n", ct);
|
|
- *ctinfo = IP_CT_ESTABLISHED;
|
|
|
|
|
|
+ ctinfo = IP_CT_ESTABLISHED;
|
|
} else if (test_bit(IPS_EXPECTED_BIT, &ct->status)) {
|
|
} else if (test_bit(IPS_EXPECTED_BIT, &ct->status)) {
|
|
pr_debug("related packet for %p\n", ct);
|
|
pr_debug("related packet for %p\n", ct);
|
|
- *ctinfo = IP_CT_RELATED;
|
|
|
|
|
|
+ ctinfo = IP_CT_RELATED;
|
|
} else {
|
|
} else {
|
|
pr_debug("new packet for %p\n", ct);
|
|
pr_debug("new packet for %p\n", ct);
|
|
- *ctinfo = IP_CT_NEW;
|
|
|
|
|
|
+ ctinfo = IP_CT_NEW;
|
|
}
|
|
}
|
|
- *set_reply = 0;
|
|
|
|
}
|
|
}
|
|
- nf_ct_set(skb, ct, *ctinfo);
|
|
|
|
- return ct;
|
|
|
|
|
|
+ nf_ct_set(skb, ct, ctinfo);
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
unsigned int
|
|
unsigned int
|
|
@@ -1311,7 +1307,6 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
|
|
unsigned int *timeouts;
|
|
unsigned int *timeouts;
|
|
unsigned int dataoff;
|
|
unsigned int dataoff;
|
|
u_int8_t protonum;
|
|
u_int8_t protonum;
|
|
- int set_reply = 0;
|
|
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
tmpl = nf_ct_get(skb, &ctinfo);
|
|
tmpl = nf_ct_get(skb, &ctinfo);
|
|
@@ -1354,23 +1349,22 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
repeat:
|
|
repeat:
|
|
- ct = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum,
|
|
|
|
- l3proto, l4proto, &set_reply, &ctinfo);
|
|
|
|
- if (!ct) {
|
|
|
|
- /* Not valid part of a connection */
|
|
|
|
- NF_CT_STAT_INC_ATOMIC(net, invalid);
|
|
|
|
- ret = NF_ACCEPT;
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (IS_ERR(ct)) {
|
|
|
|
|
|
+ ret = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum,
|
|
|
|
+ l3proto, l4proto);
|
|
|
|
+ if (ret < 0) {
|
|
/* Too stressed to deal. */
|
|
/* Too stressed to deal. */
|
|
NF_CT_STAT_INC_ATOMIC(net, drop);
|
|
NF_CT_STAT_INC_ATOMIC(net, drop);
|
|
ret = NF_DROP;
|
|
ret = NF_DROP;
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
- NF_CT_ASSERT(skb_nfct(skb));
|
|
|
|
|
|
+ ct = nf_ct_get(skb, &ctinfo);
|
|
|
|
+ if (!ct) {
|
|
|
|
+ /* Not valid part of a connection */
|
|
|
|
+ NF_CT_STAT_INC_ATOMIC(net, invalid);
|
|
|
|
+ ret = NF_ACCEPT;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
|
|
/* Decide what timeout policy we want to apply to this flow. */
|
|
/* Decide what timeout policy we want to apply to this flow. */
|
|
timeouts = nf_ct_timeout_lookup(net, ct, l4proto);
|
|
timeouts = nf_ct_timeout_lookup(net, ct, l4proto);
|
|
@@ -1395,7 +1389,8 @@ repeat:
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
- if (set_reply && !test_and_set_bit(IPS_SEEN_REPLY_BIT, &ct->status))
|
|
|
|
|
|
+ if (ctinfo == IP_CT_ESTABLISHED_REPLY &&
|
|
|
|
+ !test_and_set_bit(IPS_SEEN_REPLY_BIT, &ct->status))
|
|
nf_conntrack_event_cache(IPCT_REPLY, ct);
|
|
nf_conntrack_event_cache(IPCT_REPLY, ct);
|
|
out:
|
|
out:
|
|
if (tmpl)
|
|
if (tmpl)
|