Commit e3eaa9910b380530cfd2c0670fcd3f627674da8a

Authored by Jan Engelhardt
1 parent 2b95efe7f6

netfilter: xtables: generate initial table on-demand

The static initial tables are pretty large, and after the net
namespace has been instantiated, they just hang around for nothing.
This commit removes them and creates tables on-demand at runtime when
needed.

Size shrinks by 7735 bytes (x86_64).

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>

Showing 18 changed files with 141 additions and 334 deletions Side-by-side Diff

include/linux/netfilter_arp/arp_tables.h
... ... @@ -258,6 +258,7 @@
258 258 .target.errorname = "ERROR", \
259 259 }
260 260  
  261 +extern void *arpt_alloc_initial_table(const struct xt_table *);
261 262 extern struct xt_table *arpt_register_table(struct net *net,
262 263 const struct xt_table *table,
263 264 const struct arpt_replace *repl);
include/linux/netfilter_ipv4/ip_tables.h
... ... @@ -282,6 +282,7 @@
282 282 .target.errorname = "ERROR", \
283 283 }
284 284  
  285 +extern void *ipt_alloc_initial_table(const struct xt_table *);
285 286 extern unsigned int ipt_do_table(struct sk_buff *skb,
286 287 unsigned int hook,
287 288 const struct net_device *in,
include/linux/netfilter_ipv6/ip6_tables.h
... ... @@ -297,6 +297,7 @@
297 297 #include <linux/init.h>
298 298 extern void ip6t_init(void) __init;
299 299  
  300 +extern void *ip6t_alloc_initial_table(const struct xt_table *);
300 301 extern struct xt_table *ip6t_register_table(struct net *net,
301 302 const struct xt_table *table,
302 303 const struct ip6t_replace *repl);
net/ipv4/netfilter/arp_tables.c
... ... @@ -27,6 +27,7 @@
27 27  
28 28 #include <linux/netfilter/x_tables.h>
29 29 #include <linux/netfilter_arp/arp_tables.h>
  30 +#include "../../netfilter/xt_repldata.h"
30 31  
31 32 MODULE_LICENSE("GPL");
32 33 MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
... ... @@ -57,6 +58,12 @@
57 58 #else
58 59 #define ARP_NF_ASSERT(x)
59 60 #endif
  61 +
  62 +void *arpt_alloc_initial_table(const struct xt_table *info)
  63 +{
  64 + return xt_alloc_initial_table(arpt, ARPT);
  65 +}
  66 +EXPORT_SYMBOL_GPL(arpt_alloc_initial_table);
60 67  
61 68 static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap,
62 69 const char *hdr_addr, int len)
net/ipv4/netfilter/arptable_filter.c
... ... @@ -6,6 +6,7 @@
6 6 */
7 7  
8 8 #include <linux/module.h>
  9 +#include <linux/netfilter/x_tables.h>
9 10 #include <linux/netfilter_arp/arp_tables.h>
10 11  
11 12 MODULE_LICENSE("GPL");
... ... @@ -15,36 +16,6 @@
15 16 #define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \
16 17 (1 << NF_ARP_FORWARD))
17 18  
18   -static const struct
19   -{
20   - struct arpt_replace repl;
21   - struct arpt_standard entries[3];
22   - struct arpt_error term;
23   -} initial_table __net_initdata = {
24   - .repl = {
25   - .name = "filter",
26   - .valid_hooks = FILTER_VALID_HOOKS,
27   - .num_entries = 4,
28   - .size = sizeof(struct arpt_standard) * 3 + sizeof(struct arpt_error),
29   - .hook_entry = {
30   - [NF_ARP_IN] = 0,
31   - [NF_ARP_OUT] = sizeof(struct arpt_standard),
32   - [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard),
33   - },
34   - .underflow = {
35   - [NF_ARP_IN] = 0,
36   - [NF_ARP_OUT] = sizeof(struct arpt_standard),
37   - [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard),
38   - },
39   - },
40   - .entries = {
41   - ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_IN */
42   - ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_OUT */
43   - ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_FORWARD */
44   - },
45   - .term = ARPT_ERROR_INIT,
46   -};
47   -
48 19 static const struct xt_table packet_filter = {
49 20 .name = "filter",
50 21 .valid_hooks = FILTER_VALID_HOOKS,
51 22  
... ... @@ -68,9 +39,14 @@
68 39  
69 40 static int __net_init arptable_filter_net_init(struct net *net)
70 41 {
71   - /* Register table */
  42 + struct arpt_replace *repl;
  43 +
  44 + repl = arpt_alloc_initial_table(&packet_filter);
  45 + if (repl == NULL)
  46 + return -ENOMEM;
72 47 net->ipv4.arptable_filter =
73   - arpt_register_table(net, &packet_filter, &initial_table.repl);
  48 + arpt_register_table(net, &packet_filter, repl);
  49 + kfree(repl);
74 50 if (IS_ERR(net->ipv4.arptable_filter))
75 51 return PTR_ERR(net->ipv4.arptable_filter);
76 52 return 0;
net/ipv4/netfilter/ip_tables.c
... ... @@ -28,6 +28,7 @@
28 28 #include <linux/netfilter/x_tables.h>
29 29 #include <linux/netfilter_ipv4/ip_tables.h>
30 30 #include <net/netfilter/nf_log.h>
  31 +#include "../../netfilter/xt_repldata.h"
31 32  
32 33 MODULE_LICENSE("GPL");
33 34 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
... ... @@ -65,6 +66,12 @@
65 66 #define static
66 67 #define inline
67 68 #endif
  69 +
  70 +void *ipt_alloc_initial_table(const struct xt_table *info)
  71 +{
  72 + return xt_alloc_initial_table(ipt, IPT);
  73 +}
  74 +EXPORT_SYMBOL_GPL(ipt_alloc_initial_table);
68 75  
69 76 /*
70 77 We keep a set of rules for each CPU, so we can avoid write-locking
net/ipv4/netfilter/iptable_filter.c
... ... @@ -23,36 +23,6 @@
23 23 (1 << NF_INET_FORWARD) | \
24 24 (1 << NF_INET_LOCAL_OUT))
25 25  
26   -static struct
27   -{
28   - struct ipt_replace repl;
29   - struct ipt_standard entries[3];
30   - struct ipt_error term;
31   -} initial_table __net_initdata = {
32   - .repl = {
33   - .name = "filter",
34   - .valid_hooks = FILTER_VALID_HOOKS,
35   - .num_entries = 4,
36   - .size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
37   - .hook_entry = {
38   - [NF_INET_LOCAL_IN] = 0,
39   - [NF_INET_FORWARD] = sizeof(struct ipt_standard),
40   - [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
41   - },
42   - .underflow = {
43   - [NF_INET_LOCAL_IN] = 0,
44   - [NF_INET_FORWARD] = sizeof(struct ipt_standard),
45   - [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
46   - },
47   - },
48   - .entries = {
49   - IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
50   - IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
51   - IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
52   - },
53   - .term = IPT_ERROR_INIT, /* ERROR */
54   -};
55   -
56 26 static const struct xt_table packet_filter = {
57 27 .name = "filter",
58 28 .valid_hooks = FILTER_VALID_HOOKS,
59 29  
... ... @@ -86,9 +56,18 @@
86 56  
87 57 static int __net_init iptable_filter_net_init(struct net *net)
88 58 {
89   - /* Register table */
  59 + struct ipt_replace *repl;
  60 +
  61 + repl = ipt_alloc_initial_table(&packet_filter);
  62 + if (repl == NULL)
  63 + return -ENOMEM;
  64 + /* Entry 1 is the FORWARD hook */
  65 + ((struct ipt_standard *)repl->entries)[1].target.verdict =
  66 + -forward - 1;
  67 +
90 68 net->ipv4.iptable_filter =
91   - ipt_register_table(net, &packet_filter, &initial_table.repl);
  69 + ipt_register_table(net, &packet_filter, repl);
  70 + kfree(repl);
92 71 if (IS_ERR(net->ipv4.iptable_filter))
93 72 return PTR_ERR(net->ipv4.iptable_filter);
94 73 return 0;
... ... @@ -112,9 +91,6 @@
112 91 printk("iptables forward must be 0 or 1\n");
113 92 return -EINVAL;
114 93 }
115   -
116   - /* Entry 1 is the FORWARD hook */
117   - initial_table.entries[1].target.verdict = -forward - 1;
118 94  
119 95 ret = register_pernet_subsys(&iptable_filter_net_ops);
120 96 if (ret < 0)
net/ipv4/netfilter/iptable_mangle.c
... ... @@ -27,43 +27,6 @@
27 27 (1 << NF_INET_LOCAL_OUT) | \
28 28 (1 << NF_INET_POST_ROUTING))
29 29  
30   -/* Ouch - five different hooks? Maybe this should be a config option..... -- BC */
31   -static const struct
32   -{
33   - struct ipt_replace repl;
34   - struct ipt_standard entries[5];
35   - struct ipt_error term;
36   -} initial_table __net_initdata = {
37   - .repl = {
38   - .name = "mangle",
39   - .valid_hooks = MANGLE_VALID_HOOKS,
40   - .num_entries = 6,
41   - .size = sizeof(struct ipt_standard) * 5 + sizeof(struct ipt_error),
42   - .hook_entry = {
43   - [NF_INET_PRE_ROUTING] = 0,
44   - [NF_INET_LOCAL_IN] = sizeof(struct ipt_standard),
45   - [NF_INET_FORWARD] = sizeof(struct ipt_standard) * 2,
46   - [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 3,
47   - [NF_INET_POST_ROUTING] = sizeof(struct ipt_standard) * 4,
48   - },
49   - .underflow = {
50   - [NF_INET_PRE_ROUTING] = 0,
51   - [NF_INET_LOCAL_IN] = sizeof(struct ipt_standard),
52   - [NF_INET_FORWARD] = sizeof(struct ipt_standard) * 2,
53   - [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 3,
54   - [NF_INET_POST_ROUTING] = sizeof(struct ipt_standard) * 4,
55   - },
56   - },
57   - .entries = {
58   - IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
59   - IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
60   - IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
61   - IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
62   - IPT_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
63   - },
64   - .term = IPT_ERROR_INIT, /* ERROR */
65   -};
66   -
67 30 static const struct xt_table packet_mangler = {
68 31 .name = "mangle",
69 32 .valid_hooks = MANGLE_VALID_HOOKS,
70 33  
... ... @@ -134,9 +97,14 @@
134 97  
135 98 static int __net_init iptable_mangle_net_init(struct net *net)
136 99 {
137   - /* Register table */
  100 + struct ipt_replace *repl;
  101 +
  102 + repl = ipt_alloc_initial_table(&packet_mangler);
  103 + if (repl == NULL)
  104 + return -ENOMEM;
138 105 net->ipv4.iptable_mangle =
139   - ipt_register_table(net, &packet_mangler, &initial_table.repl);
  106 + ipt_register_table(net, &packet_mangler, repl);
  107 + kfree(repl);
140 108 if (IS_ERR(net->ipv4.iptable_mangle))
141 109 return PTR_ERR(net->ipv4.iptable_mangle);
142 110 return 0;
net/ipv4/netfilter/iptable_raw.c
... ... @@ -9,33 +9,6 @@
9 9  
10 10 #define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT))
11 11  
12   -static const struct
13   -{
14   - struct ipt_replace repl;
15   - struct ipt_standard entries[2];
16   - struct ipt_error term;
17   -} initial_table __net_initdata = {
18   - .repl = {
19   - .name = "raw",
20   - .valid_hooks = RAW_VALID_HOOKS,
21   - .num_entries = 3,
22   - .size = sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error),
23   - .hook_entry = {
24   - [NF_INET_PRE_ROUTING] = 0,
25   - [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard)
26   - },
27   - .underflow = {
28   - [NF_INET_PRE_ROUTING] = 0,
29   - [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard)
30   - },
31   - },
32   - .entries = {
33   - IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
34   - IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
35   - },
36   - .term = IPT_ERROR_INIT, /* ERROR */
37   -};
38   -
39 12 static const struct xt_table packet_raw = {
40 13 .name = "raw",
41 14 .valid_hooks = RAW_VALID_HOOKS,
42 15  
... ... @@ -66,9 +39,14 @@
66 39  
67 40 static int __net_init iptable_raw_net_init(struct net *net)
68 41 {
69   - /* Register table */
  42 + struct ipt_replace *repl;
  43 +
  44 + repl = ipt_alloc_initial_table(&packet_raw);
  45 + if (repl == NULL)
  46 + return -ENOMEM;
70 47 net->ipv4.iptable_raw =
71   - ipt_register_table(net, &packet_raw, &initial_table.repl);
  48 + ipt_register_table(net, &packet_raw, repl);
  49 + kfree(repl);
72 50 if (IS_ERR(net->ipv4.iptable_raw))
73 51 return PTR_ERR(net->ipv4.iptable_raw);
74 52 return 0;
net/ipv4/netfilter/iptable_security.c
... ... @@ -27,36 +27,6 @@
27 27 (1 << NF_INET_FORWARD) | \
28 28 (1 << NF_INET_LOCAL_OUT)
29 29  
30   -static const struct
31   -{
32   - struct ipt_replace repl;
33   - struct ipt_standard entries[3];
34   - struct ipt_error term;
35   -} initial_table __net_initdata = {
36   - .repl = {
37   - .name = "security",
38   - .valid_hooks = SECURITY_VALID_HOOKS,
39   - .num_entries = 4,
40   - .size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
41   - .hook_entry = {
42   - [NF_INET_LOCAL_IN] = 0,
43   - [NF_INET_FORWARD] = sizeof(struct ipt_standard),
44   - [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
45   - },
46   - .underflow = {
47   - [NF_INET_LOCAL_IN] = 0,
48   - [NF_INET_FORWARD] = sizeof(struct ipt_standard),
49   - [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
50   - },
51   - },
52   - .entries = {
53   - IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
54   - IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
55   - IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
56   - },
57   - .term = IPT_ERROR_INIT, /* ERROR */
58   -};
59   -
60 30 static const struct xt_table security_table = {
61 31 .name = "security",
62 32 .valid_hooks = SECURITY_VALID_HOOKS,
63 33  
... ... @@ -87,9 +57,14 @@
87 57  
88 58 static int __net_init iptable_security_net_init(struct net *net)
89 59 {
90   - net->ipv4.iptable_security =
91   - ipt_register_table(net, &security_table, &initial_table.repl);
  60 + struct ipt_replace *repl;
92 61  
  62 + repl = ipt_alloc_initial_table(&security_table);
  63 + if (repl == NULL)
  64 + return -ENOMEM;
  65 + net->ipv4.iptable_security =
  66 + ipt_register_table(net, &security_table, repl);
  67 + kfree(repl);
93 68 if (IS_ERR(net->ipv4.iptable_security))
94 69 return PTR_ERR(net->ipv4.iptable_security);
95 70  
net/ipv4/netfilter/nf_nat_rule.c
... ... @@ -28,36 +28,6 @@
28 28 (1 << NF_INET_POST_ROUTING) | \
29 29 (1 << NF_INET_LOCAL_OUT))
30 30  
31   -static const struct
32   -{
33   - struct ipt_replace repl;
34   - struct ipt_standard entries[3];
35   - struct ipt_error term;
36   -} nat_initial_table __net_initdata = {
37   - .repl = {
38   - .name = "nat",
39   - .valid_hooks = NAT_VALID_HOOKS,
40   - .num_entries = 4,
41   - .size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
42   - .hook_entry = {
43   - [NF_INET_PRE_ROUTING] = 0,
44   - [NF_INET_POST_ROUTING] = sizeof(struct ipt_standard),
45   - [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2
46   - },
47   - .underflow = {
48   - [NF_INET_PRE_ROUTING] = 0,
49   - [NF_INET_POST_ROUTING] = sizeof(struct ipt_standard),
50   - [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2
51   - },
52   - },
53   - .entries = {
54   - IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
55   - IPT_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
56   - IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
57   - },
58   - .term = IPT_ERROR_INIT, /* ERROR */
59   -};
60   -
61 31 static const struct xt_table nat_table = {
62 32 .name = "nat",
63 33 .valid_hooks = NAT_VALID_HOOKS,
... ... @@ -186,8 +156,13 @@
186 156  
187 157 static int __net_init nf_nat_rule_net_init(struct net *net)
188 158 {
189   - net->ipv4.nat_table = ipt_register_table(net, &nat_table,
190   - &nat_initial_table.repl);
  159 + struct ipt_replace *repl;
  160 +
  161 + repl = ipt_alloc_initial_table(&nat_table);
  162 + if (repl == NULL)
  163 + return -ENOMEM;
  164 + net->ipv4.nat_table = ipt_register_table(net, &nat_table, repl);
  165 + kfree(repl);
191 166 if (IS_ERR(net->ipv4.nat_table))
192 167 return PTR_ERR(net->ipv4.nat_table);
193 168 return 0;
net/ipv6/netfilter/ip6_tables.c
... ... @@ -29,6 +29,7 @@
29 29 #include <linux/netfilter_ipv6/ip6_tables.h>
30 30 #include <linux/netfilter/x_tables.h>
31 31 #include <net/netfilter/nf_log.h>
  32 +#include "../../netfilter/xt_repldata.h"
32 33  
33 34 MODULE_LICENSE("GPL");
34 35 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
... ... @@ -66,6 +67,12 @@
66 67 #define static
67 68 #define inline
68 69 #endif
  70 +
  71 +void *ip6t_alloc_initial_table(const struct xt_table *info)
  72 +{
  73 + return xt_alloc_initial_table(ip6t, IP6T);
  74 +}
  75 +EXPORT_SYMBOL_GPL(ip6t_alloc_initial_table);
69 76  
70 77 /*
71 78 We keep a set of rules for each CPU, so we can avoid write-locking
net/ipv6/netfilter/ip6table_filter.c
... ... @@ -21,36 +21,6 @@
21 21 (1 << NF_INET_FORWARD) | \
22 22 (1 << NF_INET_LOCAL_OUT))
23 23  
24   -static struct
25   -{
26   - struct ip6t_replace repl;
27   - struct ip6t_standard entries[3];
28   - struct ip6t_error term;
29   -} initial_table __net_initdata = {
30   - .repl = {
31   - .name = "filter",
32   - .valid_hooks = FILTER_VALID_HOOKS,
33   - .num_entries = 4,
34   - .size = sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error),
35   - .hook_entry = {
36   - [NF_INET_LOCAL_IN] = 0,
37   - [NF_INET_FORWARD] = sizeof(struct ip6t_standard),
38   - [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2
39   - },
40   - .underflow = {
41   - [NF_INET_LOCAL_IN] = 0,
42   - [NF_INET_FORWARD] = sizeof(struct ip6t_standard),
43   - [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2
44   - },
45   - },
46   - .entries = {
47   - IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
48   - IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
49   - IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
50   - },
51   - .term = IP6T_ERROR_INIT, /* ERROR */
52   -};
53   -
54 24 static const struct xt_table packet_filter = {
55 25 .name = "filter",
56 26 .valid_hooks = FILTER_VALID_HOOKS,
57 27  
... ... @@ -78,9 +48,18 @@
78 48  
79 49 static int __net_init ip6table_filter_net_init(struct net *net)
80 50 {
81   - /* Register table */
  51 + struct ip6t_replace *repl;
  52 +
  53 + repl = ip6t_alloc_initial_table(&packet_filter);
  54 + if (repl == NULL)
  55 + return -ENOMEM;
  56 + /* Entry 1 is the FORWARD hook */
  57 + ((struct ip6t_standard *)repl->entries)[1].target.verdict =
  58 + -forward - 1;
  59 +
82 60 net->ipv6.ip6table_filter =
83   - ip6t_register_table(net, &packet_filter, &initial_table.repl);
  61 + ip6t_register_table(net, &packet_filter, repl);
  62 + kfree(repl);
84 63 if (IS_ERR(net->ipv6.ip6table_filter))
85 64 return PTR_ERR(net->ipv6.ip6table_filter);
86 65 return 0;
... ... @@ -104,9 +83,6 @@
104 83 printk("iptables forward must be 0 or 1\n");
105 84 return -EINVAL;
106 85 }
107   -
108   - /* Entry 1 is the FORWARD hook */
109   - initial_table.entries[1].target.verdict = -forward - 1;
110 86  
111 87 ret = register_pernet_subsys(&ip6table_filter_net_ops);
112 88 if (ret < 0)
net/ipv6/netfilter/ip6table_mangle.c
... ... @@ -21,42 +21,6 @@
21 21 (1 << NF_INET_LOCAL_OUT) | \
22 22 (1 << NF_INET_POST_ROUTING))
23 23  
24   -static const struct
25   -{
26   - struct ip6t_replace repl;
27   - struct ip6t_standard entries[5];
28   - struct ip6t_error term;
29   -} initial_table __net_initdata = {
30   - .repl = {
31   - .name = "mangle",
32   - .valid_hooks = MANGLE_VALID_HOOKS,
33   - .num_entries = 6,
34   - .size = sizeof(struct ip6t_standard) * 5 + sizeof(struct ip6t_error),
35   - .hook_entry = {
36   - [NF_INET_PRE_ROUTING] = 0,
37   - [NF_INET_LOCAL_IN] = sizeof(struct ip6t_standard),
38   - [NF_INET_FORWARD] = sizeof(struct ip6t_standard) * 2,
39   - [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3,
40   - [NF_INET_POST_ROUTING] = sizeof(struct ip6t_standard) * 4,
41   - },
42   - .underflow = {
43   - [NF_INET_PRE_ROUTING] = 0,
44   - [NF_INET_LOCAL_IN] = sizeof(struct ip6t_standard),
45   - [NF_INET_FORWARD] = sizeof(struct ip6t_standard) * 2,
46   - [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3,
47   - [NF_INET_POST_ROUTING] = sizeof(struct ip6t_standard) * 4,
48   - },
49   - },
50   - .entries = {
51   - IP6T_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
52   - IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
53   - IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
54   - IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
55   - IP6T_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
56   - },
57   - .term = IP6T_ERROR_INIT, /* ERROR */
58   -};
59   -
60 24 static const struct xt_table packet_mangler = {
61 25 .name = "mangle",
62 26 .valid_hooks = MANGLE_VALID_HOOKS,
63 27  
... ... @@ -126,9 +90,14 @@
126 90 static struct nf_hook_ops *mangle_ops __read_mostly;
127 91 static int __net_init ip6table_mangle_net_init(struct net *net)
128 92 {
129   - /* Register table */
  93 + struct ip6t_replace *repl;
  94 +
  95 + repl = ip6t_alloc_initial_table(&packet_mangler);
  96 + if (repl == NULL)
  97 + return -ENOMEM;
130 98 net->ipv6.ip6table_mangle =
131   - ip6t_register_table(net, &packet_mangler, &initial_table.repl);
  99 + ip6t_register_table(net, &packet_mangler, repl);
  100 + kfree(repl);
132 101 if (IS_ERR(net->ipv6.ip6table_mangle))
133 102 return PTR_ERR(net->ipv6.ip6table_mangle);
134 103 return 0;
net/ipv6/netfilter/ip6table_raw.c
... ... @@ -8,33 +8,6 @@
8 8  
9 9 #define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT))
10 10  
11   -static const struct
12   -{
13   - struct ip6t_replace repl;
14   - struct ip6t_standard entries[2];
15   - struct ip6t_error term;
16   -} initial_table __net_initdata = {
17   - .repl = {
18   - .name = "raw",
19   - .valid_hooks = RAW_VALID_HOOKS,
20   - .num_entries = 3,
21   - .size = sizeof(struct ip6t_standard) * 2 + sizeof(struct ip6t_error),
22   - .hook_entry = {
23   - [NF_INET_PRE_ROUTING] = 0,
24   - [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard)
25   - },
26   - .underflow = {
27   - [NF_INET_PRE_ROUTING] = 0,
28   - [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard)
29   - },
30   - },
31   - .entries = {
32   - IP6T_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
33   - IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
34   - },
35   - .term = IP6T_ERROR_INIT, /* ERROR */
36   -};
37   -
38 11 static const struct xt_table packet_raw = {
39 12 .name = "raw",
40 13 .valid_hooks = RAW_VALID_HOOKS,
41 14  
... ... @@ -58,9 +31,14 @@
58 31  
59 32 static int __net_init ip6table_raw_net_init(struct net *net)
60 33 {
61   - /* Register table */
  34 + struct ip6t_replace *repl;
  35 +
  36 + repl = ip6t_alloc_initial_table(&packet_raw);
  37 + if (repl == NULL)
  38 + return -ENOMEM;
62 39 net->ipv6.ip6table_raw =
63   - ip6t_register_table(net, &packet_raw, &initial_table.repl);
  40 + ip6t_register_table(net, &packet_raw, repl);
  41 + kfree(repl);
64 42 if (IS_ERR(net->ipv6.ip6table_raw))
65 43 return PTR_ERR(net->ipv6.ip6table_raw);
66 44 return 0;
net/ipv6/netfilter/ip6table_security.c
... ... @@ -26,36 +26,6 @@
26 26 (1 << NF_INET_FORWARD) | \
27 27 (1 << NF_INET_LOCAL_OUT)
28 28  
29   -static const struct
30   -{
31   - struct ip6t_replace repl;
32   - struct ip6t_standard entries[3];
33   - struct ip6t_error term;
34   -} initial_table __net_initdata = {
35   - .repl = {
36   - .name = "security",
37   - .valid_hooks = SECURITY_VALID_HOOKS,
38   - .num_entries = 4,
39   - .size = sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error),
40   - .hook_entry = {
41   - [NF_INET_LOCAL_IN] = 0,
42   - [NF_INET_FORWARD] = sizeof(struct ip6t_standard),
43   - [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2,
44   - },
45   - .underflow = {
46   - [NF_INET_LOCAL_IN] = 0,
47   - [NF_INET_FORWARD] = sizeof(struct ip6t_standard),
48   - [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2,
49   - },
50   - },
51   - .entries = {
52   - IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
53   - IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
54   - IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
55   - },
56   - .term = IP6T_ERROR_INIT, /* ERROR */
57   -};
58   -
59 29 static const struct xt_table security_table = {
60 30 .name = "security",
61 31 .valid_hooks = SECURITY_VALID_HOOKS,
62 32  
... ... @@ -79,9 +49,14 @@
79 49  
80 50 static int __net_init ip6table_security_net_init(struct net *net)
81 51 {
82   - net->ipv6.ip6table_security =
83   - ip6t_register_table(net, &security_table, &initial_table.repl);
  52 + struct ip6t_replace *repl;
84 53  
  54 + repl = ip6t_alloc_initial_table(&security_table);
  55 + if (repl == NULL)
  56 + return -ENOMEM;
  57 + net->ipv6.ip6table_security =
  58 + ip6t_register_table(net, &security_table, repl);
  59 + kfree(repl);
85 60 if (IS_ERR(net->ipv6.ip6table_security))
86 61 return PTR_ERR(net->ipv6.ip6table_security);
87 62  
net/netfilter/x_tables.c
... ... @@ -26,7 +26,9 @@
26 26  
27 27 #include <linux/netfilter/x_tables.h>
28 28 #include <linux/netfilter_arp.h>
29   -
  29 +#include <linux/netfilter_ipv4/ip_tables.h>
  30 +#include <linux/netfilter_ipv6/ip6_tables.h>
  31 +#include <linux/netfilter_arp/arp_tables.h>
30 32  
31 33 MODULE_LICENSE("GPL");
32 34 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
net/netfilter/xt_repldata.h
  1 +/*
  2 + * Today's hack: quantum tunneling in structs
  3 + *
  4 + * 'entries' and 'term' are never anywhere referenced by word in code. In fact,
  5 + * they serve as the hanging-off data accessed through repl.data[].
  6 + */
  7 +
  8 +#define xt_alloc_initial_table(type, typ2) ({ \
  9 + unsigned int hook_mask = info->valid_hooks; \
  10 + unsigned int nhooks = hweight32(hook_mask); \
  11 + unsigned int bytes = 0, hooknum = 0, i = 0; \
  12 + struct { \
  13 + struct type##_replace repl; \
  14 + struct type##_standard entries[nhooks]; \
  15 + struct type##_error term; \
  16 + } *tbl = kzalloc(sizeof(*tbl), GFP_KERNEL); \
  17 + if (tbl == NULL) \
  18 + return NULL; \
  19 + strncpy(tbl->repl.name, info->name, sizeof(tbl->repl.name)); \
  20 + tbl->term = (struct type##_error)typ2##_ERROR_INIT; \
  21 + tbl->repl.valid_hooks = hook_mask; \
  22 + tbl->repl.num_entries = nhooks + 1; \
  23 + tbl->repl.size = nhooks * sizeof(struct type##_standard) + \
  24 + sizeof(struct type##_error); \
  25 + for (; hook_mask != 0; hook_mask >>= 1, ++hooknum) { \
  26 + if (!(hook_mask & 1)) \
  27 + continue; \
  28 + tbl->repl.hook_entry[hooknum] = bytes; \
  29 + tbl->repl.underflow[hooknum] = bytes; \
  30 + tbl->entries[i++] = (struct type##_standard) \
  31 + typ2##_STANDARD_INIT(NF_ACCEPT); \
  32 + bytes += sizeof(struct type##_standard); \
  33 + } \
  34 + tbl; \
  35 +})