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

[NETFILTER]: nf_nat: use extension infrastructure

Signed-off-by: default avatarYasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e54cbc1f
...@@ -278,22 +278,5 @@ nf_conntrack_register_cache(u_int32_t features, const char *name, size_t size); ...@@ -278,22 +278,5 @@ nf_conntrack_register_cache(u_int32_t features, const char *name, size_t size);
extern void extern void
nf_conntrack_unregister_cache(u_int32_t features); 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 /* __KERNEL__ */
#endif /* _NF_CONNTRACK_H */ #endif /* _NF_CONNTRACK_H */
...@@ -6,10 +6,12 @@ ...@@ -6,10 +6,12 @@
enum nf_ct_ext_id enum nf_ct_ext_id
{ {
NF_CT_EXT_HELPER, NF_CT_EXT_HELPER,
NF_CT_EXT_NAT,
NF_CT_EXT_NUM, NF_CT_EXT_NUM,
}; };
#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help #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. */ /* Extensions: optional stuff which isn't permanently in struct. */
struct nf_ct_ext { struct nf_ct_ext {
......
...@@ -52,6 +52,7 @@ struct nf_nat_multi_range_compat ...@@ -52,6 +52,7 @@ struct nf_nat_multi_range_compat
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/list.h> #include <linux/list.h>
#include <linux/netfilter/nf_conntrack_pptp.h> #include <linux/netfilter/nf_conntrack_pptp.h>
#include <net/netfilter/nf_conntrack_extend.h>
struct nf_conn; struct nf_conn;
...@@ -89,6 +90,11 @@ extern unsigned int nf_nat_setup_info(struct nf_conn *ct, ...@@ -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, extern int nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
const struct nf_conn *ignored_conntrack); 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; extern int nf_nat_module_is_loaded;
#else /* !__KERNEL__: iptables wants this to compile. */ #else /* !__KERNEL__: iptables wants this to compile. */
......
...@@ -108,9 +108,6 @@ EXPORT_SYMBOL_GPL(nf_nat_module_is_loaded); ...@@ -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) 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; return NF_CT_F_BASIC;
} }
......
...@@ -297,11 +297,21 @@ nf_nat_setup_info(struct nf_conn *ct, ...@@ -297,11 +297,21 @@ nf_nat_setup_info(struct nf_conn *ct,
unsigned int hooknum) unsigned int hooknum)
{ {
struct nf_conntrack_tuple curr_tuple, new_tuple; struct nf_conntrack_tuple curr_tuple, new_tuple;
struct nf_conn_nat *nat = nfct_nat(ct); struct nf_conn_nat *nat;
struct nf_nat_info *info = &nat->info; struct nf_nat_info *info;
int have_to_hash = !(ct->status & IPS_NAT_DONE_MASK); int have_to_hash = !(ct->status & IPS_NAT_DONE_MASK);
enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum); 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 || NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING ||
hooknum == NF_IP_POST_ROUTING || hooknum == NF_IP_POST_ROUTING ||
hooknum == NF_IP_LOCAL_IN || hooknum == NF_IP_LOCAL_IN ||
...@@ -338,6 +348,8 @@ nf_nat_setup_info(struct nf_conn *ct, ...@@ -338,6 +348,8 @@ nf_nat_setup_info(struct nf_conn *ct,
srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
write_lock_bh(&nf_nat_lock); write_lock_bh(&nf_nat_lock);
/* nf_conntrack_alter_reply might re-allocate exntension aera */
info = &nfct_nat(ct)->info;
info->ct = ct; info->ct = ct;
list_add(&info->bysource, &bysource[srchash]); list_add(&info->bysource, &bysource[srchash]);
write_unlock_bh(&nf_nat_lock); write_unlock_bh(&nf_nat_lock);
...@@ -592,17 +604,52 @@ nf_nat_port_nfattr_to_range(struct nfattr *tb[], struct nf_nat_range *range) ...@@ -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); EXPORT_SYMBOL_GPL(nf_nat_port_range_to_nfattr);
#endif #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) static int __init nf_nat_init(void)
{ {
size_t i; 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. */ /* Leave them the same for the moment. */
nf_nat_htable_size = nf_conntrack_htable_size; nf_nat_htable_size = nf_conntrack_htable_size;
/* One vmalloc for both hash tables */ /* One vmalloc for both hash tables */
bysource = vmalloc(sizeof(struct list_head) * nf_nat_htable_size); bysource = vmalloc(sizeof(struct list_head) * nf_nat_htable_size);
if (!bysource) if (!bysource) {
return -ENOMEM; ret = -ENOMEM;
goto cleanup_extend;
}
/* Sew in builtin protocols. */ /* Sew in builtin protocols. */
write_lock_bh(&nf_nat_lock); write_lock_bh(&nf_nat_lock);
...@@ -626,6 +673,10 @@ static int __init nf_nat_init(void) ...@@ -626,6 +673,10 @@ static int __init nf_nat_init(void)
l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET); l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET);
return 0; return 0;
cleanup_extend:
nf_ct_extend_unregister(&nat_extend);
return ret;
} }
/* Clear NAT section of all conntracks, in case we're loaded again. */ /* Clear NAT section of all conntracks, in case we're loaded again. */
...@@ -647,6 +698,7 @@ static void __exit nf_nat_cleanup(void) ...@@ -647,6 +698,7 @@ static void __exit nf_nat_cleanup(void)
synchronize_rcu(); synchronize_rcu();
vfree(bysource); vfree(bysource);
nf_ct_l3proto_put(l3proto); nf_ct_l3proto_put(l3proto);
nf_ct_extend_unregister(&nat_extend);
} }
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_extend.h>
#include <net/netfilter/nf_nat.h> #include <net/netfilter/nf_nat.h>
#include <net/netfilter/nf_nat_rule.h> #include <net/netfilter/nf_nat_rule.h>
#include <net/netfilter/nf_nat_protocol.h> #include <net/netfilter/nf_nat_protocol.h>
...@@ -113,8 +114,13 @@ nf_nat_fn(unsigned int hooknum, ...@@ -113,8 +114,13 @@ nf_nat_fn(unsigned int hooknum,
return NF_ACCEPT; return NF_ACCEPT;
nat = nfct_nat(ct); nat = nfct_nat(ct);
if (!nat) if (!nat) {
return NF_ACCEPT; 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;
}
}
switch (ctinfo) { switch (ctinfo) {
case IP_CT_RELATED: case IP_CT_RELATED:
...@@ -326,18 +332,10 @@ static struct nf_hook_ops nf_nat_ops[] = { ...@@ -326,18 +332,10 @@ static struct nf_hook_ops nf_nat_ops[] = {
static int __init nf_nat_standalone_init(void) static int __init nf_nat_standalone_init(void)
{ {
int size, ret = 0; int ret = 0;
need_conntrack(); need_conntrack();
size = ALIGN(sizeof(struct nf_conn), __alignof__(struct nf_conn_nat)) +
sizeof(struct nf_conn_nat);
ret = nf_conntrack_register_cache(NF_CT_F_NAT, "nf_nat:base", size);
if (ret < 0) {
printk(KERN_ERR "nf_nat_init: Unable to create slab cache\n");
return ret;
}
#ifdef CONFIG_XFRM #ifdef CONFIG_XFRM
BUG_ON(ip_nat_decode_session != NULL); BUG_ON(ip_nat_decode_session != NULL);
ip_nat_decode_session = nat_decode_session; ip_nat_decode_session = nat_decode_session;
...@@ -362,7 +360,6 @@ static int __init nf_nat_standalone_init(void) ...@@ -362,7 +360,6 @@ static int __init nf_nat_standalone_init(void)
ip_nat_decode_session = NULL; ip_nat_decode_session = NULL;
synchronize_net(); synchronize_net();
#endif #endif
nf_conntrack_unregister_cache(NF_CT_F_NAT);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment