Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d59e5ca authored by Yasuyuki Kozakai's avatar Yasuyuki Kozakai Committed by David S. Miller
Browse files

[NETFILTER]: nf_nat: use extension infrastructure

parent e54cbc1f
Loading
Loading
Loading
Loading
+0 −17
Original line number Diff line number Diff line
@@ -278,22 +278,5 @@ nf_conntrack_register_cache(u_int32_t features, const char *name, size_t size);
extern void
nf_conntrack_unregister_cache(u_int32_t features);

/* valid combinations:
 * basic: nf_conn, nf_conn .. nf_conn_help
 * nat: nf_conn .. nf_conn_nat, nf_conn .. nf_conn_nat .. nf_conn help
 */
#ifdef CONFIG_NF_NAT_NEEDED
#include <net/netfilter/nf_nat.h>
static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct)
{
	unsigned int offset = sizeof(struct nf_conn);

	if (!(ct->features & NF_CT_F_NAT))
		return NULL;

	offset = ALIGN(offset, __alignof__(struct nf_conn_nat));
	return (struct nf_conn_nat *) ((void *)ct + offset);
}
#endif /* CONFIG_NF_NAT_NEEDED */
#endif /* __KERNEL__ */
#endif /* _NF_CONNTRACK_H */
+2 −0
Original line number Diff line number Diff line
@@ -6,10 +6,12 @@
enum nf_ct_ext_id
{
	NF_CT_EXT_HELPER,
	NF_CT_EXT_NAT,
	NF_CT_EXT_NUM,
};

#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help
#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat

/* Extensions: optional stuff which isn't permanently in struct. */
struct nf_ct_ext {
+6 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ struct nf_nat_multi_range_compat
#ifdef __KERNEL__
#include <linux/list.h>
#include <linux/netfilter/nf_conntrack_pptp.h>
#include <net/netfilter/nf_conntrack_extend.h>

struct nf_conn;

@@ -89,6 +90,11 @@ extern unsigned int nf_nat_setup_info(struct nf_conn *ct,
extern int nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
			     const struct nf_conn *ignored_conntrack);

static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct)
{
	return nf_ct_ext_find(ct, NF_CT_EXT_NAT);
}

extern int nf_nat_module_is_loaded;

#else  /* !__KERNEL__: iptables wants this to compile. */
+0 −3
Original line number Diff line number Diff line
@@ -108,9 +108,6 @@ EXPORT_SYMBOL_GPL(nf_nat_module_is_loaded);

static u_int32_t ipv4_get_features(const struct nf_conntrack_tuple *tuple)
{
	if (nf_nat_module_is_loaded)
		return NF_CT_F_NAT;

	return NF_CT_F_BASIC;
}

+56 −4
Original line number Diff line number Diff line
@@ -297,11 +297,21 @@ nf_nat_setup_info(struct nf_conn *ct,
		  unsigned int hooknum)
{
	struct nf_conntrack_tuple curr_tuple, new_tuple;
	struct nf_conn_nat *nat = nfct_nat(ct);
	struct nf_nat_info *info = &nat->info;
	struct nf_conn_nat *nat;
	struct nf_nat_info *info;
	int have_to_hash = !(ct->status & IPS_NAT_DONE_MASK);
	enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum);

	/* nat helper or nfctnetlink also setup binding */
	nat = nfct_nat(ct);
	if (!nat) {
		nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC);
		if (nat == NULL) {
			DEBUGP("failed to add NAT extension\n");
			return NF_ACCEPT;
		}
	}

	NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING ||
		     hooknum == NF_IP_POST_ROUTING ||
		     hooknum == NF_IP_LOCAL_IN ||
@@ -338,6 +348,8 @@ nf_nat_setup_info(struct nf_conn *ct,

		srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
		write_lock_bh(&nf_nat_lock);
		/* nf_conntrack_alter_reply might re-allocate exntension aera */
		info = &nfct_nat(ct)->info;
		info->ct = ct;
		list_add(&info->bysource, &bysource[srchash]);
		write_unlock_bh(&nf_nat_lock);
@@ -592,17 +604,52 @@ nf_nat_port_nfattr_to_range(struct nfattr *tb[], struct nf_nat_range *range)
EXPORT_SYMBOL_GPL(nf_nat_port_range_to_nfattr);
#endif

static void nf_nat_move_storage(struct nf_conn *conntrack, void *old)
{
	struct nf_conn_nat *new_nat = nf_ct_ext_find(conntrack, NF_CT_EXT_NAT);
	struct nf_conn_nat *old_nat = (struct nf_conn_nat *)old;
	struct nf_conn *ct = old_nat->info.ct;
	unsigned int srchash;

	if (!(ct->status & IPS_NAT_DONE_MASK))
		return;

	srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);

	write_lock_bh(&nf_nat_lock);
	list_replace(&old_nat->info.bysource, &new_nat->info.bysource);
	new_nat->info.ct = ct;
	write_unlock_bh(&nf_nat_lock);
}

struct nf_ct_ext_type nat_extend = {
	.len	= sizeof(struct nf_conn_nat),
	.align	= __alignof__(struct nf_conn_nat),
	.move	= nf_nat_move_storage,
	.id	= NF_CT_EXT_NAT,
	.flags	= NF_CT_EXT_F_PREALLOC,
};

static int __init nf_nat_init(void)
{
	size_t i;
	int ret;

	ret = nf_ct_extend_register(&nat_extend);
	if (ret < 0) {
		printk(KERN_ERR "nf_nat_core: Unable to register extension\n");
		return ret;
	}

	/* Leave them the same for the moment. */
	nf_nat_htable_size = nf_conntrack_htable_size;

	/* One vmalloc for both hash tables */
	bysource = vmalloc(sizeof(struct list_head) * nf_nat_htable_size);
	if (!bysource)
		return -ENOMEM;
	if (!bysource) {
		ret = -ENOMEM;
		goto cleanup_extend;
	}

	/* Sew in builtin protocols. */
	write_lock_bh(&nf_nat_lock);
@@ -626,6 +673,10 @@ static int __init nf_nat_init(void)

	l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET);
	return 0;

 cleanup_extend:
	nf_ct_extend_unregister(&nat_extend);
	return ret;
}

/* Clear NAT section of all conntracks, in case we're loaded again. */
@@ -647,6 +698,7 @@ static void __exit nf_nat_cleanup(void)
	synchronize_rcu();
	vfree(bysource);
	nf_ct_l3proto_put(l3proto);
	nf_ct_extend_unregister(&nat_extend);
}

MODULE_LICENSE("GPL");
Loading