|
@@ -1683,6 +1683,41 @@ static int nf_conntrack_update(struct net *net, struct sk_buff *skb)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static bool nf_conntrack_get_tuple_skb(struct nf_conntrack_tuple *dst_tuple,
|
|
|
+ const struct sk_buff *skb)
|
|
|
+{
|
|
|
+ const struct nf_conntrack_tuple *src_tuple;
|
|
|
+ const struct nf_conntrack_tuple_hash *hash;
|
|
|
+ struct nf_conntrack_tuple srctuple;
|
|
|
+ enum ip_conntrack_info ctinfo;
|
|
|
+ struct nf_conn *ct;
|
|
|
+
|
|
|
+ ct = nf_ct_get(skb, &ctinfo);
|
|
|
+ if (ct) {
|
|
|
+ src_tuple = nf_ct_tuple(ct, CTINFO2DIR(ctinfo));
|
|
|
+ memcpy(dst_tuple, src_tuple, sizeof(*dst_tuple));
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb),
|
|
|
+ NFPROTO_IPV4, dev_net(skb->dev),
|
|
|
+ &srctuple))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ hash = nf_conntrack_find_get(dev_net(skb->dev),
|
|
|
+ &nf_ct_zone_dflt,
|
|
|
+ &srctuple);
|
|
|
+ if (!hash)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ ct = nf_ct_tuplehash_to_ctrack(hash);
|
|
|
+ src_tuple = nf_ct_tuple(ct, !hash->tuple.dst.dir);
|
|
|
+ memcpy(dst_tuple, src_tuple, sizeof(*dst_tuple));
|
|
|
+ nf_ct_put(ct);
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
/* Bring out ya dead! */
|
|
|
static struct nf_conn *
|
|
|
get_next_corpse(int (*iter)(struct nf_conn *i, void *data),
|
|
@@ -2204,6 +2239,7 @@ err_cachep:
|
|
|
static struct nf_ct_hook nf_conntrack_hook = {
|
|
|
.update = nf_conntrack_update,
|
|
|
.destroy = destroy_conntrack,
|
|
|
+ .get_tuple_skb = nf_conntrack_get_tuple_skb,
|
|
|
};
|
|
|
|
|
|
void nf_conntrack_init_end(void)
|