Commit 2d59e5ca8c7113ad91452f0f9259a4b55ee90323

Authored by Yasuyuki Kozakai
Committed by David S. Miller
1 parent e54cbc1f91

[NETFILTER]: nf_nat: use extension infrastructure

Signed-off-by: Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 6 changed files with 73 additions and 36 deletions Side-by-side Diff

include/net/netfilter/nf_conntrack.h
... ... @@ -278,23 +278,6 @@
278 278 extern void
279 279 nf_conntrack_unregister_cache(u_int32_t features);
280 280  
281   -/* valid combinations:
282   - * basic: nf_conn, nf_conn .. nf_conn_help
283   - * nat: nf_conn .. nf_conn_nat, nf_conn .. nf_conn_nat .. nf_conn help
284   - */
285   -#ifdef CONFIG_NF_NAT_NEEDED
286   -#include <net/netfilter/nf_nat.h>
287   -static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct)
288   -{
289   - unsigned int offset = sizeof(struct nf_conn);
290   -
291   - if (!(ct->features & NF_CT_F_NAT))
292   - return NULL;
293   -
294   - offset = ALIGN(offset, __alignof__(struct nf_conn_nat));
295   - return (struct nf_conn_nat *) ((void *)ct + offset);
296   -}
297   -#endif /* CONFIG_NF_NAT_NEEDED */
298 281 #endif /* __KERNEL__ */
299 282 #endif /* _NF_CONNTRACK_H */
include/net/netfilter/nf_conntrack_extend.h
... ... @@ -6,10 +6,12 @@
6 6 enum nf_ct_ext_id
7 7 {
8 8 NF_CT_EXT_HELPER,
  9 + NF_CT_EXT_NAT,
9 10 NF_CT_EXT_NUM,
10 11 };
11 12  
12 13 #define NF_CT_EXT_HELPER_TYPE struct nf_conn_help
  14 +#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat
13 15  
14 16 /* Extensions: optional stuff which isn't permanently in struct. */
15 17 struct nf_ct_ext {
include/net/netfilter/nf_nat.h
... ... @@ -52,6 +52,7 @@
52 52 #ifdef __KERNEL__
53 53 #include <linux/list.h>
54 54 #include <linux/netfilter/nf_conntrack_pptp.h>
  55 +#include <net/netfilter/nf_conntrack_extend.h>
55 56  
56 57 struct nf_conn;
57 58  
... ... @@ -88,6 +89,11 @@
88 89 /* Is this tuple already taken? (not by us)*/
89 90 extern int nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
90 91 const struct nf_conn *ignored_conntrack);
  92 +
  93 +static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct)
  94 +{
  95 + return nf_ct_ext_find(ct, NF_CT_EXT_NAT);
  96 +}
91 97  
92 98 extern int nf_nat_module_is_loaded;
93 99  
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
... ... @@ -108,9 +108,6 @@
108 108  
109 109 static u_int32_t ipv4_get_features(const struct nf_conntrack_tuple *tuple)
110 110 {
111   - if (nf_nat_module_is_loaded)
112   - return NF_CT_F_NAT;
113   -
114 111 return NF_CT_F_BASIC;
115 112 }
116 113  
net/ipv4/netfilter/nf_nat_core.c
... ... @@ -297,11 +297,21 @@
297 297 unsigned int hooknum)
298 298 {
299 299 struct nf_conntrack_tuple curr_tuple, new_tuple;
300   - struct nf_conn_nat *nat = nfct_nat(ct);
301   - struct nf_nat_info *info = &nat->info;
  300 + struct nf_conn_nat *nat;
  301 + struct nf_nat_info *info;
302 302 int have_to_hash = !(ct->status & IPS_NAT_DONE_MASK);
303 303 enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum);
304 304  
  305 + /* nat helper or nfctnetlink also setup binding */
  306 + nat = nfct_nat(ct);
  307 + if (!nat) {
  308 + nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC);
  309 + if (nat == NULL) {
  310 + DEBUGP("failed to add NAT extension\n");
  311 + return NF_ACCEPT;
  312 + }
  313 + }
  314 +
305 315 NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING ||
306 316 hooknum == NF_IP_POST_ROUTING ||
307 317 hooknum == NF_IP_LOCAL_IN ||
... ... @@ -338,6 +348,8 @@
338 348  
339 349 srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
340 350 write_lock_bh(&nf_nat_lock);
  351 + /* nf_conntrack_alter_reply might re-allocate exntension aera */
  352 + info = &nfct_nat(ct)->info;
341 353 info->ct = ct;
342 354 list_add(&info->bysource, &bysource[srchash]);
343 355 write_unlock_bh(&nf_nat_lock);
344 356  
345 357  
346 358  
... ... @@ -592,17 +604,52 @@
592 604 EXPORT_SYMBOL_GPL(nf_nat_port_range_to_nfattr);
593 605 #endif
594 606  
  607 +static void nf_nat_move_storage(struct nf_conn *conntrack, void *old)
  608 +{
  609 + struct nf_conn_nat *new_nat = nf_ct_ext_find(conntrack, NF_CT_EXT_NAT);
  610 + struct nf_conn_nat *old_nat = (struct nf_conn_nat *)old;
  611 + struct nf_conn *ct = old_nat->info.ct;
  612 + unsigned int srchash;
  613 +
  614 + if (!(ct->status & IPS_NAT_DONE_MASK))
  615 + return;
  616 +
  617 + srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
  618 +
  619 + write_lock_bh(&nf_nat_lock);
  620 + list_replace(&old_nat->info.bysource, &new_nat->info.bysource);
  621 + new_nat->info.ct = ct;
  622 + write_unlock_bh(&nf_nat_lock);
  623 +}
  624 +
  625 +struct nf_ct_ext_type nat_extend = {
  626 + .len = sizeof(struct nf_conn_nat),
  627 + .align = __alignof__(struct nf_conn_nat),
  628 + .move = nf_nat_move_storage,
  629 + .id = NF_CT_EXT_NAT,
  630 + .flags = NF_CT_EXT_F_PREALLOC,
  631 +};
  632 +
595 633 static int __init nf_nat_init(void)
596 634 {
597 635 size_t i;
  636 + int ret;
598 637  
  638 + ret = nf_ct_extend_register(&nat_extend);
  639 + if (ret < 0) {
  640 + printk(KERN_ERR "nf_nat_core: Unable to register extension\n");
  641 + return ret;
  642 + }
  643 +
599 644 /* Leave them the same for the moment. */
600 645 nf_nat_htable_size = nf_conntrack_htable_size;
601 646  
602 647 /* One vmalloc for both hash tables */
603 648 bysource = vmalloc(sizeof(struct list_head) * nf_nat_htable_size);
604   - if (!bysource)
605   - return -ENOMEM;
  649 + if (!bysource) {
  650 + ret = -ENOMEM;
  651 + goto cleanup_extend;
  652 + }
606 653  
607 654 /* Sew in builtin protocols. */
608 655 write_lock_bh(&nf_nat_lock);
... ... @@ -626,6 +673,10 @@
626 673  
627 674 l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET);
628 675 return 0;
  676 +
  677 + cleanup_extend:
  678 + nf_ct_extend_unregister(&nat_extend);
  679 + return ret;
629 680 }
630 681  
631 682 /* Clear NAT section of all conntracks, in case we're loaded again. */
... ... @@ -647,6 +698,7 @@
647 698 synchronize_rcu();
648 699 vfree(bysource);
649 700 nf_ct_l3proto_put(l3proto);
  701 + nf_ct_extend_unregister(&nat_extend);
650 702 }
651 703  
652 704 MODULE_LICENSE("GPL");
net/ipv4/netfilter/nf_nat_standalone.c
... ... @@ -19,6 +19,7 @@
19 19  
20 20 #include <net/netfilter/nf_conntrack.h>
21 21 #include <net/netfilter/nf_conntrack_core.h>
  22 +#include <net/netfilter/nf_conntrack_extend.h>
22 23 #include <net/netfilter/nf_nat.h>
23 24 #include <net/netfilter/nf_nat_rule.h>
24 25 #include <net/netfilter/nf_nat_protocol.h>
... ... @@ -113,8 +114,13 @@
113 114 return NF_ACCEPT;
114 115  
115 116 nat = nfct_nat(ct);
116   - if (!nat)
117   - return NF_ACCEPT;
  117 + if (!nat) {
  118 + nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC);
  119 + if (nat == NULL) {
  120 + DEBUGP("failed to add NAT extension\n");
  121 + return NF_ACCEPT;
  122 + }
  123 + }
118 124  
119 125 switch (ctinfo) {
120 126 case IP_CT_RELATED:
121 127  
... ... @@ -326,18 +332,10 @@
326 332  
327 333 static int __init nf_nat_standalone_init(void)
328 334 {
329   - int size, ret = 0;
  335 + int ret = 0;
330 336  
331 337 need_conntrack();
332 338  
333   - size = ALIGN(sizeof(struct nf_conn), __alignof__(struct nf_conn_nat)) +
334   - sizeof(struct nf_conn_nat);
335   - ret = nf_conntrack_register_cache(NF_CT_F_NAT, "nf_nat:base", size);
336   - if (ret < 0) {
337   - printk(KERN_ERR "nf_nat_init: Unable to create slab cache\n");
338   - return ret;
339   - }
340   -
341 339 #ifdef CONFIG_XFRM
342 340 BUG_ON(ip_nat_decode_session != NULL);
343 341 ip_nat_decode_session = nat_decode_session;
... ... @@ -362,7 +360,6 @@
362 360 ip_nat_decode_session = NULL;
363 361 synchronize_net();
364 362 #endif
365   - nf_conntrack_unregister_cache(NF_CT_F_NAT);
366 363 return ret;
367 364 }
368 365