Skip to content

Commit b60a604

Browse files
tohojodavem330
authored andcommitted
netfilter: Add nf_ct_get_tuple_skb global lookup function
This adds a global netfilter function to extract a conntrack tuple from an skb. The function uses a new function added to nf_ct_hook, which will try to get the tuple from skb->_nfct, and do a full lookup if that fails. This makes it possible to use the lookup function before the skb has passed through the conntrack init hooks (e.g., in an ingress qdisc). The tuple is copied to the caller to avoid issues with reference counting. The function returns false if conntrack is not loaded, allowing it to be used without incurring a module dependency on conntrack. This is used by the NAT mode in sch_cake. Cc: [email protected] Signed-off-by: Toke Høiland-Jørgensen <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 8b71388 commit b60a604

File tree

3 files changed

+62
-0
lines changed

3 files changed

+62
-0
lines changed

include/linux/netfilter.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,8 +414,17 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family)
414414

415415
extern void (*ip_ct_attach)(struct sk_buff *, const struct sk_buff *) __rcu;
416416
void nf_ct_attach(struct sk_buff *, const struct sk_buff *);
417+
struct nf_conntrack_tuple;
418+
bool nf_ct_get_tuple_skb(struct nf_conntrack_tuple *dst_tuple,
419+
const struct sk_buff *skb);
417420
#else
418421
static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
422+
struct nf_conntrack_tuple;
423+
static inline bool nf_ct_get_tuple_skb(struct nf_conntrack_tuple *dst_tuple,
424+
const struct sk_buff *skb)
425+
{
426+
return false;
427+
}
419428
#endif
420429

421430
struct nf_conn;
@@ -424,6 +433,8 @@ enum ip_conntrack_info;
424433
struct nf_ct_hook {
425434
int (*update)(struct net *net, struct sk_buff *skb);
426435
void (*destroy)(struct nf_conntrack *);
436+
bool (*get_tuple_skb)(struct nf_conntrack_tuple *,
437+
const struct sk_buff *);
427438
};
428439
extern struct nf_ct_hook __rcu *nf_ct_hook;
429440

net/netfilter/core.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,21 @@ void nf_conntrack_destroy(struct nf_conntrack *nfct)
603603
}
604604
EXPORT_SYMBOL(nf_conntrack_destroy);
605605

606+
bool nf_ct_get_tuple_skb(struct nf_conntrack_tuple *dst_tuple,
607+
const struct sk_buff *skb)
608+
{
609+
struct nf_ct_hook *ct_hook;
610+
bool ret = false;
611+
612+
rcu_read_lock();
613+
ct_hook = rcu_dereference(nf_ct_hook);
614+
if (ct_hook)
615+
ret = ct_hook->get_tuple_skb(dst_tuple, skb);
616+
rcu_read_unlock();
617+
return ret;
618+
}
619+
EXPORT_SYMBOL(nf_ct_get_tuple_skb);
620+
606621
/* Built-in default zone used e.g. by modules. */
607622
const struct nf_conntrack_zone nf_ct_zone_dflt = {
608623
.id = NF_CT_DEFAULT_ZONE_ID,

net/netfilter/nf_conntrack_core.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1683,6 +1683,41 @@ static int nf_conntrack_update(struct net *net, struct sk_buff *skb)
16831683
return 0;
16841684
}
16851685

1686+
static bool nf_conntrack_get_tuple_skb(struct nf_conntrack_tuple *dst_tuple,
1687+
const struct sk_buff *skb)
1688+
{
1689+
const struct nf_conntrack_tuple *src_tuple;
1690+
const struct nf_conntrack_tuple_hash *hash;
1691+
struct nf_conntrack_tuple srctuple;
1692+
enum ip_conntrack_info ctinfo;
1693+
struct nf_conn *ct;
1694+
1695+
ct = nf_ct_get(skb, &ctinfo);
1696+
if (ct) {
1697+
src_tuple = nf_ct_tuple(ct, CTINFO2DIR(ctinfo));
1698+
memcpy(dst_tuple, src_tuple, sizeof(*dst_tuple));
1699+
return true;
1700+
}
1701+
1702+
if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb),
1703+
NFPROTO_IPV4, dev_net(skb->dev),
1704+
&srctuple))
1705+
return false;
1706+
1707+
hash = nf_conntrack_find_get(dev_net(skb->dev),
1708+
&nf_ct_zone_dflt,
1709+
&srctuple);
1710+
if (!hash)
1711+
return false;
1712+
1713+
ct = nf_ct_tuplehash_to_ctrack(hash);
1714+
src_tuple = nf_ct_tuple(ct, !hash->tuple.dst.dir);
1715+
memcpy(dst_tuple, src_tuple, sizeof(*dst_tuple));
1716+
nf_ct_put(ct);
1717+
1718+
return true;
1719+
}
1720+
16861721
/* Bring out ya dead! */
16871722
static struct nf_conn *
16881723
get_next_corpse(int (*iter)(struct nf_conn *i, void *data),
@@ -2204,6 +2239,7 @@ int nf_conntrack_init_start(void)
22042239
static struct nf_ct_hook nf_conntrack_hook = {
22052240
.update = nf_conntrack_update,
22062241
.destroy = destroy_conntrack,
2242+
.get_tuple_skb = nf_conntrack_get_tuple_skb,
22072243
};
22082244

22092245
void nf_conntrack_init_end(void)

0 commit comments

Comments
 (0)