Commit a8c28d05150f758625c5da38199b247887735e65

Authored by Patrick McHardy

Merge branch 'master' of git://dev.medozas.de/linux

Showing 19 changed files Side-by-side Diff

include/linux/netfilter/x_tables.h
... ... @@ -360,6 +360,7 @@
360 360 struct module *me;
361 361  
362 362 u_int8_t af; /* address/protocol family */
  363 + int priority; /* hook order */
363 364  
364 365 /* A unique name... */
365 366 const char name[XT_TABLE_MAXNAMELEN];
... ... @@ -520,6 +521,9 @@
520 521 BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long));
521 522 return ret;
522 523 }
  524 +
  525 +extern struct nf_hook_ops *xt_hook_link(const struct xt_table *, nf_hookfn *);
  526 +extern void xt_hook_unlink(const struct xt_table *, struct nf_hook_ops *);
523 527  
524 528 #ifdef CONFIG_COMPAT
525 529 #include <net/compat.h>
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");
12 13  
13 14  
14 15  
15 16  
16 17  
17 18  
18 19  
... ... @@ -15,93 +16,37 @@
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 .me = THIS_MODULE,
52 23 .af = NFPROTO_ARP,
  24 + .priority = NF_IP_PRI_FILTER,
53 25 };
54 26  
55 27 /* The work comes in here from netfilter.c */
56   -static unsigned int arpt_in_hook(unsigned int hook,
57   - struct sk_buff *skb,
58   - const struct net_device *in,
59   - const struct net_device *out,
60   - int (*okfn)(struct sk_buff *))
  28 +static unsigned int
  29 +arptable_filter_hook(unsigned int hook, struct sk_buff *skb,
  30 + const struct net_device *in, const struct net_device *out,
  31 + int (*okfn)(struct sk_buff *))
61 32 {
62   - return arpt_do_table(skb, hook, in, out,
63   - dev_net(in)->ipv4.arptable_filter);
64   -}
  33 + const struct net *net = dev_net((in != NULL) ? in : out);
65 34  
66   -static unsigned int arpt_out_hook(unsigned int hook,
67   - struct sk_buff *skb,
68   - const struct net_device *in,
69   - const struct net_device *out,
70   - int (*okfn)(struct sk_buff *))
71   -{
72   - return arpt_do_table(skb, hook, in, out,
73   - dev_net(out)->ipv4.arptable_filter);
  35 + return arpt_do_table(skb, hook, in, out, net->ipv4.arptable_filter);
74 36 }
75 37  
76   -static struct nf_hook_ops arpt_ops[] __read_mostly = {
77   - {
78   - .hook = arpt_in_hook,
79   - .owner = THIS_MODULE,
80   - .pf = NFPROTO_ARP,
81   - .hooknum = NF_ARP_IN,
82   - .priority = NF_IP_PRI_FILTER,
83   - },
84   - {
85   - .hook = arpt_out_hook,
86   - .owner = THIS_MODULE,
87   - .pf = NFPROTO_ARP,
88   - .hooknum = NF_ARP_OUT,
89   - .priority = NF_IP_PRI_FILTER,
90   - },
91   - {
92   - .hook = arpt_in_hook,
93   - .owner = THIS_MODULE,
94   - .pf = NFPROTO_ARP,
95   - .hooknum = NF_ARP_FORWARD,
96   - .priority = NF_IP_PRI_FILTER,
97   - },
98   -};
  38 +static struct nf_hook_ops *arpfilter_ops __read_mostly;
99 39  
100 40 static int __net_init arptable_filter_net_init(struct net *net)
101 41 {
102   - /* Register table */
  42 + struct arpt_replace *repl;
  43 +
  44 + repl = arpt_alloc_initial_table(&packet_filter);
  45 + if (repl == NULL)
  46 + return -ENOMEM;
103 47 net->ipv4.arptable_filter =
104   - arpt_register_table(net, &packet_filter, &initial_table.repl);
  48 + arpt_register_table(net, &packet_filter, repl);
  49 + kfree(repl);
105 50 if (IS_ERR(net->ipv4.arptable_filter))
106 51 return PTR_ERR(net->ipv4.arptable_filter);
107 52 return 0;
108 53  
... ... @@ -125,9 +70,11 @@
125 70 if (ret < 0)
126 71 return ret;
127 72  
128   - ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops));
129   - if (ret < 0)
  73 + arpfilter_ops = xt_hook_link(&packet_filter, arptable_filter_hook);
  74 + if (IS_ERR(arpfilter_ops)) {
  75 + ret = PTR_ERR(arpfilter_ops);
130 76 goto cleanup_table;
  77 + }
131 78 return ret;
132 79  
133 80 cleanup_table:
... ... @@ -137,7 +84,7 @@
137 84  
138 85 static void __exit arptable_filter_fini(void)
139 86 {
140   - nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops));
  87 + xt_hook_unlink(&packet_filter, arpfilter_ops);
141 88 unregister_pernet_subsys(&arptable_filter_net_ops);
142 89 }
143 90  
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,104 +23,32 @@
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 .me = THIS_MODULE,
60 30 .af = NFPROTO_IPV4,
  31 + .priority = NF_IP_PRI_FILTER,
61 32 };
62 33  
63   -/* The work comes in here from netfilter.c. */
64 34 static unsigned int
65   -ipt_local_in_hook(unsigned int hook,
66   - struct sk_buff *skb,
67   - const struct net_device *in,
68   - const struct net_device *out,
69   - int (*okfn)(struct sk_buff *))
  35 +iptable_filter_hook(unsigned int hook, struct sk_buff *skb,
  36 + const struct net_device *in, const struct net_device *out,
  37 + int (*okfn)(struct sk_buff *))
70 38 {
71   - return ipt_do_table(skb, hook, in, out,
72   - dev_net(in)->ipv4.iptable_filter);
73   -}
  39 + const struct net *net;
74 40  
75   -static unsigned int
76   -ipt_hook(unsigned int hook,
77   - struct sk_buff *skb,
78   - const struct net_device *in,
79   - const struct net_device *out,
80   - int (*okfn)(struct sk_buff *))
81   -{
82   - return ipt_do_table(skb, hook, in, out,
83   - dev_net(in)->ipv4.iptable_filter);
84   -}
85   -
86   -static unsigned int
87   -ipt_local_out_hook(unsigned int hook,
88   - struct sk_buff *skb,
89   - const struct net_device *in,
90   - const struct net_device *out,
91   - int (*okfn)(struct sk_buff *))
92   -{
93   - /* root is playing with raw sockets. */
94   - if (skb->len < sizeof(struct iphdr) ||
95   - ip_hdrlen(skb) < sizeof(struct iphdr))
  41 + if (hook == NF_INET_LOCAL_OUT &&
  42 + (skb->len < sizeof(struct iphdr) ||
  43 + ip_hdrlen(skb) < sizeof(struct iphdr)))
  44 + /* root is playing with raw sockets. */
96 45 return NF_ACCEPT;
97   - return ipt_do_table(skb, hook, in, out,
98   - dev_net(out)->ipv4.iptable_filter);
  46 +
  47 + net = dev_net((in != NULL) ? in : out);
  48 + return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_filter);
99 49 }
100 50  
101   -static struct nf_hook_ops ipt_ops[] __read_mostly = {
102   - {
103   - .hook = ipt_local_in_hook,
104   - .owner = THIS_MODULE,
105   - .pf = NFPROTO_IPV4,
106   - .hooknum = NF_INET_LOCAL_IN,
107   - .priority = NF_IP_PRI_FILTER,
108   - },
109   - {
110   - .hook = ipt_hook,
111   - .owner = THIS_MODULE,
112   - .pf = NFPROTO_IPV4,
113   - .hooknum = NF_INET_FORWARD,
114   - .priority = NF_IP_PRI_FILTER,
115   - },
116   - {
117   - .hook = ipt_local_out_hook,
118   - .owner = THIS_MODULE,
119   - .pf = NFPROTO_IPV4,
120   - .hooknum = NF_INET_LOCAL_OUT,
121   - .priority = NF_IP_PRI_FILTER,
122   - },
123   -};
  51 +static struct nf_hook_ops *filter_ops __read_mostly;
124 52  
125 53 /* Default to forward because I got too much mail already. */
126 54 static int forward = NF_ACCEPT;
127 55  
... ... @@ -128,9 +56,18 @@
128 56  
129 57 static int __net_init iptable_filter_net_init(struct net *net)
130 58 {
131   - /* 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 +
132 68 net->ipv4.iptable_filter =
133   - ipt_register_table(net, &packet_filter, &initial_table.repl);
  69 + ipt_register_table(net, &packet_filter, repl);
  70 + kfree(repl);
134 71 if (IS_ERR(net->ipv4.iptable_filter))
135 72 return PTR_ERR(net->ipv4.iptable_filter);
136 73 return 0;
137 74  
138 75  
... ... @@ -155,17 +92,16 @@
155 92 return -EINVAL;
156 93 }
157 94  
158   - /* Entry 1 is the FORWARD hook */
159   - initial_table.entries[1].target.verdict = -forward - 1;
160   -
161 95 ret = register_pernet_subsys(&iptable_filter_net_ops);
162 96 if (ret < 0)
163 97 return ret;
164 98  
165 99 /* Register hooks */
166   - ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
167   - if (ret < 0)
  100 + filter_ops = xt_hook_link(&packet_filter, iptable_filter_hook);
  101 + if (IS_ERR(filter_ops)) {
  102 + ret = PTR_ERR(filter_ops);
168 103 goto cleanup_table;
  104 + }
169 105  
170 106 return ret;
171 107  
... ... @@ -176,7 +112,7 @@
176 112  
177 113 static void __exit iptable_filter_fini(void)
178 114 {
179   - nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
  115 + xt_hook_unlink(&packet_filter, filter_ops);
180 116 unregister_pernet_subsys(&iptable_filter_net_ops);
181 117 }
182 118  
net/ipv4/netfilter/iptable_mangle.c
... ... @@ -27,96 +27,15 @@
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 .me = THIS_MODULE,
71 34 .af = NFPROTO_IPV4,
  35 + .priority = NF_IP_PRI_MANGLE,
72 36 };
73 37  
74   -/* The work comes in here from netfilter.c. */
75 38 static unsigned int
76   -ipt_pre_routing_hook(unsigned int hook,
77   - struct sk_buff *skb,
78   - const struct net_device *in,
79   - const struct net_device *out,
80   - int (*okfn)(struct sk_buff *))
81   -{
82   - return ipt_do_table(skb, hook, in, out,
83   - dev_net(in)->ipv4.iptable_mangle);
84   -}
85   -
86   -static unsigned int
87   -ipt_post_routing_hook(unsigned int hook,
88   - struct sk_buff *skb,
89   - const struct net_device *in,
90   - const struct net_device *out,
91   - int (*okfn)(struct sk_buff *))
92   -{
93   - return ipt_do_table(skb, hook, in, out,
94   - dev_net(out)->ipv4.iptable_mangle);
95   -}
96   -
97   -static unsigned int
98   -ipt_local_in_hook(unsigned int hook,
99   - struct sk_buff *skb,
100   - const struct net_device *in,
101   - const struct net_device *out,
102   - int (*okfn)(struct sk_buff *))
103   -{
104   - return ipt_do_table(skb, hook, in, out,
105   - dev_net(in)->ipv4.iptable_mangle);
106   -}
107   -
108   -static unsigned int
109   -ipt_forward_hook(unsigned int hook,
110   - struct sk_buff *skb,
111   - const struct net_device *in,
112   - const struct net_device *out,
113   - int (*okfn)(struct sk_buff *))
114   -{
115   - return ipt_do_table(skb, hook, in, out,
116   - dev_net(in)->ipv4.iptable_mangle);
117   -}
118   -
119   -static unsigned int
120 39 ipt_local_hook(unsigned int hook,
121 40 struct sk_buff *skb,
122 41 const struct net_device *in,
123 42  
124 43  
125 44  
... ... @@ -158,49 +77,34 @@
158 77 return ret;
159 78 }
160 79  
161   -static struct nf_hook_ops ipt_ops[] __read_mostly = {
162   - {
163   - .hook = ipt_pre_routing_hook,
164   - .owner = THIS_MODULE,
165   - .pf = NFPROTO_IPV4,
166   - .hooknum = NF_INET_PRE_ROUTING,
167   - .priority = NF_IP_PRI_MANGLE,
168   - },
169   - {
170   - .hook = ipt_local_in_hook,
171   - .owner = THIS_MODULE,
172   - .pf = NFPROTO_IPV4,
173   - .hooknum = NF_INET_LOCAL_IN,
174   - .priority = NF_IP_PRI_MANGLE,
175   - },
176   - {
177   - .hook = ipt_forward_hook,
178   - .owner = THIS_MODULE,
179   - .pf = NFPROTO_IPV4,
180   - .hooknum = NF_INET_FORWARD,
181   - .priority = NF_IP_PRI_MANGLE,
182   - },
183   - {
184   - .hook = ipt_local_hook,
185   - .owner = THIS_MODULE,
186   - .pf = NFPROTO_IPV4,
187   - .hooknum = NF_INET_LOCAL_OUT,
188   - .priority = NF_IP_PRI_MANGLE,
189   - },
190   - {
191   - .hook = ipt_post_routing_hook,
192   - .owner = THIS_MODULE,
193   - .pf = NFPROTO_IPV4,
194   - .hooknum = NF_INET_POST_ROUTING,
195   - .priority = NF_IP_PRI_MANGLE,
196   - },
197   -};
  80 +/* The work comes in here from netfilter.c. */
  81 +static unsigned int
  82 +iptable_mangle_hook(unsigned int hook,
  83 + struct sk_buff *skb,
  84 + const struct net_device *in,
  85 + const struct net_device *out,
  86 + int (*okfn)(struct sk_buff *))
  87 +{
  88 + if (hook == NF_INET_LOCAL_OUT)
  89 + return ipt_local_hook(hook, skb, in, out, okfn);
198 90  
  91 + /* PREROUTING/INPUT/FORWARD: */
  92 + return ipt_do_table(skb, hook, in, out,
  93 + dev_net(in)->ipv4.iptable_mangle);
  94 +}
  95 +
  96 +static struct nf_hook_ops *mangle_ops __read_mostly;
  97 +
199 98 static int __net_init iptable_mangle_net_init(struct net *net)
200 99 {
201   - /* Register table */
  100 + struct ipt_replace *repl;
  101 +
  102 + repl = ipt_alloc_initial_table(&packet_mangler);
  103 + if (repl == NULL)
  104 + return -ENOMEM;
202 105 net->ipv4.iptable_mangle =
203   - ipt_register_table(net, &packet_mangler, &initial_table.repl);
  106 + ipt_register_table(net, &packet_mangler, repl);
  107 + kfree(repl);
204 108 if (IS_ERR(net->ipv4.iptable_mangle))
205 109 return PTR_ERR(net->ipv4.iptable_mangle);
206 110 return 0;
207 111  
... ... @@ -225,9 +129,11 @@
225 129 return ret;
226 130  
227 131 /* Register hooks */
228   - ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
229   - if (ret < 0)
  132 + mangle_ops = xt_hook_link(&packet_mangler, iptable_mangle_hook);
  133 + if (IS_ERR(mangle_ops)) {
  134 + ret = PTR_ERR(mangle_ops);
230 135 goto cleanup_table;
  136 + }
231 137  
232 138 return ret;
233 139  
... ... @@ -238,7 +144,7 @@
238 144  
239 145 static void __exit iptable_mangle_fini(void)
240 146 {
241   - nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
  147 + xt_hook_unlink(&packet_mangler, mangle_ops);
242 148 unregister_pernet_subsys(&iptable_mangle_net_ops);
243 149 }
244 150  
net/ipv4/netfilter/iptable_raw.c
... ... @@ -9,90 +9,44 @@
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 .me = THIS_MODULE,
43 16 .af = NFPROTO_IPV4,
  17 + .priority = NF_IP_PRI_RAW,
44 18 };
45 19  
46 20 /* The work comes in here from netfilter.c. */
47 21 static unsigned int
48   -ipt_hook(unsigned int hook,
49   - struct sk_buff *skb,
50   - const struct net_device *in,
51   - const struct net_device *out,
52   - int (*okfn)(struct sk_buff *))
  22 +iptable_raw_hook(unsigned int hook, struct sk_buff *skb,
  23 + const struct net_device *in, const struct net_device *out,
  24 + int (*okfn)(struct sk_buff *))
53 25 {
54   - return ipt_do_table(skb, hook, in, out,
55   - dev_net(in)->ipv4.iptable_raw);
56   -}
  26 + const struct net *net;
57 27  
58   -static unsigned int
59   -ipt_local_hook(unsigned int hook,
60   - struct sk_buff *skb,
61   - const struct net_device *in,
62   - const struct net_device *out,
63   - int (*okfn)(struct sk_buff *))
64   -{
65   - /* root is playing with raw sockets. */
66   - if (skb->len < sizeof(struct iphdr) ||
67   - ip_hdrlen(skb) < sizeof(struct iphdr))
  28 + if (hook == NF_INET_LOCAL_OUT &&
  29 + (skb->len < sizeof(struct iphdr) ||
  30 + ip_hdrlen(skb) < sizeof(struct iphdr)))
  31 + /* root is playing with raw sockets. */
68 32 return NF_ACCEPT;
69   - return ipt_do_table(skb, hook, in, out,
70   - dev_net(out)->ipv4.iptable_raw);
  33 +
  34 + net = dev_net((in != NULL) ? in : out);
  35 + return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_raw);
71 36 }
72 37  
73   -/* 'raw' is the very first table. */
74   -static struct nf_hook_ops ipt_ops[] __read_mostly = {
75   - {
76   - .hook = ipt_hook,
77   - .pf = NFPROTO_IPV4,
78   - .hooknum = NF_INET_PRE_ROUTING,
79   - .priority = NF_IP_PRI_RAW,
80   - .owner = THIS_MODULE,
81   - },
82   - {
83   - .hook = ipt_local_hook,
84   - .pf = NFPROTO_IPV4,
85   - .hooknum = NF_INET_LOCAL_OUT,
86   - .priority = NF_IP_PRI_RAW,
87   - .owner = THIS_MODULE,
88   - },
89   -};
  38 +static struct nf_hook_ops *rawtable_ops __read_mostly;
90 39  
91 40 static int __net_init iptable_raw_net_init(struct net *net)
92 41 {
93   - /* Register table */
  42 + struct ipt_replace *repl;
  43 +
  44 + repl = ipt_alloc_initial_table(&packet_raw);
  45 + if (repl == NULL)
  46 + return -ENOMEM;
94 47 net->ipv4.iptable_raw =
95   - ipt_register_table(net, &packet_raw, &initial_table.repl);
  48 + ipt_register_table(net, &packet_raw, repl);
  49 + kfree(repl);
96 50 if (IS_ERR(net->ipv4.iptable_raw))
97 51 return PTR_ERR(net->ipv4.iptable_raw);
98 52 return 0;
99 53  
... ... @@ -117,9 +71,11 @@
117 71 return ret;
118 72  
119 73 /* Register hooks */
120   - ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
121   - if (ret < 0)
  74 + rawtable_ops = xt_hook_link(&packet_raw, iptable_raw_hook);
  75 + if (IS_ERR(rawtable_ops)) {
  76 + ret = PTR_ERR(rawtable_ops);
122 77 goto cleanup_table;
  78 + }
123 79  
124 80 return ret;
125 81  
... ... @@ -130,7 +86,7 @@
130 86  
131 87 static void __exit iptable_raw_fini(void)
132 88 {
133   - nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
  89 + xt_hook_unlink(&packet_raw, rawtable_ops);
134 90 unregister_pernet_subsys(&iptable_raw_net_ops);
135 91 }
136 92  
net/ipv4/netfilter/iptable_security.c
... ... @@ -27,109 +27,44 @@
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 .me = THIS_MODULE,
64 34 .af = NFPROTO_IPV4,
  35 + .priority = NF_IP_PRI_SECURITY,
65 36 };
66 37  
67 38 static unsigned int
68   -ipt_local_in_hook(unsigned int hook,
69   - struct sk_buff *skb,
70   - const struct net_device *in,
71   - const struct net_device *out,
72   - int (*okfn)(struct sk_buff *))
  39 +iptable_security_hook(unsigned int hook, struct sk_buff *skb,
  40 + const struct net_device *in,
  41 + const struct net_device *out,
  42 + int (*okfn)(struct sk_buff *))
73 43 {
74   - return ipt_do_table(skb, hook, in, out,
75   - dev_net(in)->ipv4.iptable_security);
76   -}
  44 + const struct net *net;
77 45  
78   -static unsigned int
79   -ipt_forward_hook(unsigned int hook,
80   - struct sk_buff *skb,
81   - const struct net_device *in,
82   - const struct net_device *out,
83   - int (*okfn)(struct sk_buff *))
84   -{
85   - return ipt_do_table(skb, hook, in, out,
86   - dev_net(in)->ipv4.iptable_security);
87   -}
88   -
89   -static unsigned int
90   -ipt_local_out_hook(unsigned int hook,
91   - struct sk_buff *skb,
92   - const struct net_device *in,
93   - const struct net_device *out,
94   - int (*okfn)(struct sk_buff *))
95   -{
96   - /* Somebody is playing with raw sockets. */
97   - if (skb->len < sizeof(struct iphdr) ||
98   - ip_hdrlen(skb) < sizeof(struct iphdr))
  46 + if (hook == NF_INET_LOCAL_OUT &&
  47 + (skb->len < sizeof(struct iphdr) ||
  48 + ip_hdrlen(skb) < sizeof(struct iphdr)))
  49 + /* Somebody is playing with raw sockets. */
99 50 return NF_ACCEPT;
100   - return ipt_do_table(skb, hook, in, out,
101   - dev_net(out)->ipv4.iptable_security);
  51 +
  52 + net = dev_net((in != NULL) ? in : out);
  53 + return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_security);
102 54 }
103 55  
104   -static struct nf_hook_ops ipt_ops[] __read_mostly = {
105   - {
106   - .hook = ipt_local_in_hook,
107   - .owner = THIS_MODULE,
108   - .pf = NFPROTO_IPV4,
109   - .hooknum = NF_INET_LOCAL_IN,
110   - .priority = NF_IP_PRI_SECURITY,
111   - },
112   - {
113   - .hook = ipt_forward_hook,
114   - .owner = THIS_MODULE,
115   - .pf = NFPROTO_IPV4,
116   - .hooknum = NF_INET_FORWARD,
117   - .priority = NF_IP_PRI_SECURITY,
118   - },
119   - {
120   - .hook = ipt_local_out_hook,
121   - .owner = THIS_MODULE,
122   - .pf = NFPROTO_IPV4,
123   - .hooknum = NF_INET_LOCAL_OUT,
124   - .priority = NF_IP_PRI_SECURITY,
125   - },
126   -};
  56 +static struct nf_hook_ops *sectbl_ops __read_mostly;
127 57  
128 58 static int __net_init iptable_security_net_init(struct net *net)
129 59 {
130   - net->ipv4.iptable_security =
131   - ipt_register_table(net, &security_table, &initial_table.repl);
  60 + struct ipt_replace *repl;
132 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);
133 68 if (IS_ERR(net->ipv4.iptable_security))
134 69 return PTR_ERR(net->ipv4.iptable_security);
135 70  
136 71  
... ... @@ -154,9 +89,11 @@
154 89 if (ret < 0)
155 90 return ret;
156 91  
157   - ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
158   - if (ret < 0)
  92 + sectbl_ops = xt_hook_link(&security_table, iptable_security_hook);
  93 + if (IS_ERR(sectbl_ops)) {
  94 + ret = PTR_ERR(sectbl_ops);
159 95 goto cleanup_table;
  96 + }
160 97  
161 98 return ret;
162 99  
... ... @@ -167,7 +104,7 @@
167 104  
168 105 static void __exit iptable_security_fini(void)
169 106 {
170   - nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
  107 + xt_hook_unlink(&security_table, sectbl_ops);
171 108 unregister_pernet_subsys(&iptable_security_net_ops);
172 109 }
173 110  
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,99 +21,26 @@
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 .me = THIS_MODULE,
58 28 .af = NFPROTO_IPV6,
  29 + .priority = NF_IP6_PRI_FILTER,
59 30 };
60 31  
61 32 /* The work comes in here from netfilter.c. */
62 33 static unsigned int
63   -ip6t_in_hook(unsigned int hook,
64   - struct sk_buff *skb,
65   - const struct net_device *in,
66   - const struct net_device *out,
67   - int (*okfn)(struct sk_buff *))
  34 +ip6table_filter_hook(unsigned int hook, struct sk_buff *skb,
  35 + const struct net_device *in, const struct net_device *out,
  36 + int (*okfn)(struct sk_buff *))
68 37 {
69   - return ip6t_do_table(skb, hook, in, out,
70   - dev_net(in)->ipv6.ip6table_filter);
71   -}
  38 + const struct net *net = dev_net((in != NULL) ? in : out);
72 39  
73   -static unsigned int
74   -ip6t_local_out_hook(unsigned int hook,
75   - struct sk_buff *skb,
76   - const struct net_device *in,
77   - const struct net_device *out,
78   - int (*okfn)(struct sk_buff *))
79   -{
80   -#if 0
81   - /* root is playing with raw sockets. */
82   - if (skb->len < sizeof(struct iphdr) ||
83   - ip_hdrlen(skb) < sizeof(struct iphdr)) {
84   - if (net_ratelimit())
85   - printk("ip6t_hook: happy cracking.\n");
86   - return NF_ACCEPT;
87   - }
88   -#endif
89   -
90   - return ip6t_do_table(skb, hook, in, out,
91   - dev_net(out)->ipv6.ip6table_filter);
  40 + return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_filter);
92 41 }
93 42  
94   -static struct nf_hook_ops ip6t_ops[] __read_mostly = {
95   - {
96   - .hook = ip6t_in_hook,
97   - .owner = THIS_MODULE,
98   - .pf = NFPROTO_IPV6,
99   - .hooknum = NF_INET_LOCAL_IN,
100   - .priority = NF_IP6_PRI_FILTER,
101   - },
102   - {
103   - .hook = ip6t_in_hook,
104   - .owner = THIS_MODULE,
105   - .pf = NFPROTO_IPV6,
106   - .hooknum = NF_INET_FORWARD,
107   - .priority = NF_IP6_PRI_FILTER,
108   - },
109   - {
110   - .hook = ip6t_local_out_hook,
111   - .owner = THIS_MODULE,
112   - .pf = NFPROTO_IPV6,
113   - .hooknum = NF_INET_LOCAL_OUT,
114   - .priority = NF_IP6_PRI_FILTER,
115   - },
116   -};
  43 +static struct nf_hook_ops *filter_ops __read_mostly;
117 44  
118 45 /* Default to forward because I got too much mail already. */
119 46 static int forward = NF_ACCEPT;
120 47  
... ... @@ -121,9 +48,18 @@
121 48  
122 49 static int __net_init ip6table_filter_net_init(struct net *net)
123 50 {
124   - /* 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 +
125 60 net->ipv6.ip6table_filter =
126   - ip6t_register_table(net, &packet_filter, &initial_table.repl);
  61 + ip6t_register_table(net, &packet_filter, repl);
  62 + kfree(repl);
127 63 if (IS_ERR(net->ipv6.ip6table_filter))
128 64 return PTR_ERR(net->ipv6.ip6table_filter);
129 65 return 0;
130 66  
131 67  
... ... @@ -148,17 +84,16 @@
148 84 return -EINVAL;
149 85 }
150 86  
151   - /* Entry 1 is the FORWARD hook */
152   - initial_table.entries[1].target.verdict = -forward - 1;
153   -
154 87 ret = register_pernet_subsys(&ip6table_filter_net_ops);
155 88 if (ret < 0)
156 89 return ret;
157 90  
158 91 /* Register hooks */
159   - ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
160   - if (ret < 0)
  92 + filter_ops = xt_hook_link(&packet_filter, ip6table_filter_hook);
  93 + if (IS_ERR(filter_ops)) {
  94 + ret = PTR_ERR(filter_ops);
161 95 goto cleanup_table;
  96 + }
162 97  
163 98 return ret;
164 99  
... ... @@ -169,7 +104,7 @@
169 104  
170 105 static void __exit ip6table_filter_fini(void)
171 106 {
172   - nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
  107 + xt_hook_unlink(&packet_filter, filter_ops);
173 108 unregister_pernet_subsys(&ip6table_filter_net_ops);
174 109 }
175 110  
net/ipv6/netfilter/ip6table_mangle.c
... ... @@ -21,76 +21,17 @@
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 .me = THIS_MODULE,
64 28 .af = NFPROTO_IPV6,
  29 + .priority = NF_IP6_PRI_MANGLE,
65 30 };
66 31  
67   -/* The work comes in here from netfilter.c. */
68 32 static unsigned int
69   -ip6t_in_hook(unsigned int hook,
70   - struct sk_buff *skb,
71   - const struct net_device *in,
72   - const struct net_device *out,
73   - int (*okfn)(struct sk_buff *))
74   -{
75   - return ip6t_do_table(skb, hook, in, out,
76   - dev_net(in)->ipv6.ip6table_mangle);
77   -}
78   -
79   -static unsigned int
80   -ip6t_post_routing_hook(unsigned int hook,
81   - struct sk_buff *skb,
82   - const struct net_device *in,
83   - const struct net_device *out,
84   - int (*okfn)(struct sk_buff *))
85   -{
86   - return ip6t_do_table(skb, hook, in, out,
87   - dev_net(out)->ipv6.ip6table_mangle);
88   -}
89   -
90   -static unsigned int
91 33 ip6t_local_out_hook(unsigned int hook,
92 34 struct sk_buff *skb,
93   - const struct net_device *in,
94 35 const struct net_device *out,
95 36 int (*okfn)(struct sk_buff *))
96 37 {
... ... @@ -119,7 +60,7 @@
119 60 /* flowlabel and prio (includes version, which shouldn't change either */
120 61 flowlabel = *((u_int32_t *)ipv6_hdr(skb));
121 62  
122   - ret = ip6t_do_table(skb, hook, in, out,
  63 + ret = ip6t_do_table(skb, hook, NULL, out,
123 64 dev_net(out)->ipv6.ip6table_mangle);
124 65  
125 66 if (ret != NF_DROP && ret != NF_STOLEN &&
126 67  
127 68  
128 69  
... ... @@ -132,49 +73,31 @@
132 73 return ret;
133 74 }
134 75  
135   -static struct nf_hook_ops ip6t_ops[] __read_mostly = {
136   - {
137   - .hook = ip6t_in_hook,
138   - .owner = THIS_MODULE,
139   - .pf = NFPROTO_IPV6,
140   - .hooknum = NF_INET_PRE_ROUTING,
141   - .priority = NF_IP6_PRI_MANGLE,
142   - },
143   - {
144   - .hook = ip6t_in_hook,
145   - .owner = THIS_MODULE,
146   - .pf = NFPROTO_IPV6,
147   - .hooknum = NF_INET_LOCAL_IN,
148   - .priority = NF_IP6_PRI_MANGLE,
149   - },
150   - {
151   - .hook = ip6t_in_hook,
152   - .owner = THIS_MODULE,
153   - .pf = NFPROTO_IPV6,
154   - .hooknum = NF_INET_FORWARD,
155   - .priority = NF_IP6_PRI_MANGLE,
156   - },
157   - {
158   - .hook = ip6t_local_out_hook,
159   - .owner = THIS_MODULE,
160   - .pf = NFPROTO_IPV6,
161   - .hooknum = NF_INET_LOCAL_OUT,
162   - .priority = NF_IP6_PRI_MANGLE,
163   - },
164   - {
165   - .hook = ip6t_post_routing_hook,
166   - .owner = THIS_MODULE,
167   - .pf = NFPROTO_IPV6,
168   - .hooknum = NF_INET_POST_ROUTING,
169   - .priority = NF_IP6_PRI_MANGLE,
170   - },
171   -};
  76 +/* The work comes in here from netfilter.c. */
  77 +static unsigned int
  78 +ip6table_mangle_hook(unsigned int hook, struct sk_buff *skb,
  79 + const struct net_device *in, const struct net_device *out,
  80 + int (*okfn)(struct sk_buff *))
  81 +{
  82 + if (hook == NF_INET_LOCAL_OUT)
  83 + return ip6t_local_out_hook(hook, skb, out, okfn);
172 84  
  85 + /* INPUT/FORWARD */
  86 + return ip6t_do_table(skb, hook, in, out,
  87 + dev_net(in)->ipv6.ip6table_mangle);
  88 +}
  89 +
  90 +static struct nf_hook_ops *mangle_ops __read_mostly;
173 91 static int __net_init ip6table_mangle_net_init(struct net *net)
174 92 {
175   - /* Register table */
  93 + struct ip6t_replace *repl;
  94 +
  95 + repl = ip6t_alloc_initial_table(&packet_mangler);
  96 + if (repl == NULL)
  97 + return -ENOMEM;
176 98 net->ipv6.ip6table_mangle =
177   - ip6t_register_table(net, &packet_mangler, &initial_table.repl);
  99 + ip6t_register_table(net, &packet_mangler, repl);
  100 + kfree(repl);
178 101 if (IS_ERR(net->ipv6.ip6table_mangle))
179 102 return PTR_ERR(net->ipv6.ip6table_mangle);
180 103 return 0;
181 104  
... ... @@ -199,9 +122,11 @@
199 122 return ret;
200 123  
201 124 /* Register hooks */
202   - ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
203   - if (ret < 0)
  125 + mangle_ops = xt_hook_link(&packet_mangler, ip6table_mangle_hook);
  126 + if (IS_ERR(mangle_ops)) {
  127 + ret = PTR_ERR(mangle_ops);
204 128 goto cleanup_table;
  129 + }
205 130  
206 131 return ret;
207 132  
... ... @@ -212,7 +137,7 @@
212 137  
213 138 static void __exit ip6table_mangle_fini(void)
214 139 {
215   - nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
  140 + xt_hook_unlink(&packet_mangler, mangle_ops);
216 141 unregister_pernet_subsys(&ip6table_mangle_net_ops);
217 142 }
218 143  
net/ipv6/netfilter/ip6table_raw.c
... ... @@ -8,85 +8,37 @@
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 .me = THIS_MODULE,
42 15 .af = NFPROTO_IPV6,
  16 + .priority = NF_IP6_PRI_FIRST,
43 17 };
44 18  
45 19 /* The work comes in here from netfilter.c. */
46 20 static unsigned int
47   -ip6t_pre_routing_hook(unsigned int hook,
48   - struct sk_buff *skb,
49   - const struct net_device *in,
50   - const struct net_device *out,
51   - int (*okfn)(struct sk_buff *))
  21 +ip6table_raw_hook(unsigned int hook, struct sk_buff *skb,
  22 + const struct net_device *in, const struct net_device *out,
  23 + int (*okfn)(struct sk_buff *))
52 24 {
53   - return ip6t_do_table(skb, hook, in, out,
54   - dev_net(in)->ipv6.ip6table_raw);
55   -}
  25 + const struct net *net = dev_net((in != NULL) ? in : out);
56 26  
57   -static unsigned int
58   -ip6t_local_out_hook(unsigned int hook,
59   - struct sk_buff *skb,
60   - const struct net_device *in,
61   - const struct net_device *out,
62   - int (*okfn)(struct sk_buff *))
63   -{
64   - return ip6t_do_table(skb, hook, in, out,
65   - dev_net(out)->ipv6.ip6table_raw);
  27 + return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_raw);
66 28 }
67 29  
68   -static struct nf_hook_ops ip6t_ops[] __read_mostly = {
69   - {
70   - .hook = ip6t_pre_routing_hook,
71   - .pf = NFPROTO_IPV6,
72   - .hooknum = NF_INET_PRE_ROUTING,
73   - .priority = NF_IP6_PRI_FIRST,
74   - .owner = THIS_MODULE,
75   - },
76   - {
77   - .hook = ip6t_local_out_hook,
78   - .pf = NFPROTO_IPV6,
79   - .hooknum = NF_INET_LOCAL_OUT,
80   - .priority = NF_IP6_PRI_FIRST,
81   - .owner = THIS_MODULE,
82   - },
83   -};
  30 +static struct nf_hook_ops *rawtable_ops __read_mostly;
84 31  
85 32 static int __net_init ip6table_raw_net_init(struct net *net)
86 33 {
87   - /* Register table */
  34 + struct ip6t_replace *repl;
  35 +
  36 + repl = ip6t_alloc_initial_table(&packet_raw);
  37 + if (repl == NULL)
  38 + return -ENOMEM;
88 39 net->ipv6.ip6table_raw =
89   - ip6t_register_table(net, &packet_raw, &initial_table.repl);
  40 + ip6t_register_table(net, &packet_raw, repl);
  41 + kfree(repl);
90 42 if (IS_ERR(net->ipv6.ip6table_raw))
91 43 return PTR_ERR(net->ipv6.ip6table_raw);
92 44 return 0;
93 45  
... ... @@ -111,9 +63,11 @@
111 63 return ret;
112 64  
113 65 /* Register hooks */
114   - ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
115   - if (ret < 0)
  66 + rawtable_ops = xt_hook_link(&packet_raw, ip6table_raw_hook);
  67 + if (IS_ERR(rawtable_ops)) {
  68 + ret = PTR_ERR(rawtable_ops);
116 69 goto cleanup_table;
  70 + }
117 71  
118 72 return ret;
119 73  
... ... @@ -124,7 +78,7 @@
124 78  
125 79 static void __exit ip6table_raw_fini(void)
126 80 {
127   - nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
  81 + xt_hook_unlink(&packet_raw, rawtable_ops);
128 82 unregister_pernet_subsys(&ip6table_raw_net_ops);
129 83 }
130 84  
net/ipv6/netfilter/ip6table_security.c
... ... @@ -26,106 +26,37 @@
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 .me = THIS_MODULE,
63 33 .af = NFPROTO_IPV6,
  34 + .priority = NF_IP6_PRI_SECURITY,
64 35 };
65 36  
66 37 static unsigned int
67   -ip6t_local_in_hook(unsigned int hook,
68   - struct sk_buff *skb,
69   - const struct net_device *in,
70   - const struct net_device *out,
71   - int (*okfn)(struct sk_buff *))
  38 +ip6table_security_hook(unsigned int hook, struct sk_buff *skb,
  39 + const struct net_device *in,
  40 + const struct net_device *out,
  41 + int (*okfn)(struct sk_buff *))
72 42 {
73   - return ip6t_do_table(skb, hook, in, out,
74   - dev_net(in)->ipv6.ip6table_security);
75   -}
  43 + const struct net *net = dev_net((in != NULL) ? in : out);
76 44  
77   -static unsigned int
78   -ip6t_forward_hook(unsigned int hook,
79   - struct sk_buff *skb,
80   - const struct net_device *in,
81   - const struct net_device *out,
82   - int (*okfn)(struct sk_buff *))
83   -{
84   - return ip6t_do_table(skb, hook, in, out,
85   - dev_net(in)->ipv6.ip6table_security);
  45 + return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_security);
86 46 }
87 47  
88   -static unsigned int
89   -ip6t_local_out_hook(unsigned int hook,
90   - struct sk_buff *skb,
91   - const struct net_device *in,
92   - const struct net_device *out,
93   - int (*okfn)(struct sk_buff *))
94   -{
95   - /* TBD: handle short packets via raw socket */
96   - return ip6t_do_table(skb, hook, in, out,
97   - dev_net(out)->ipv6.ip6table_security);
98   -}
  48 +static struct nf_hook_ops *sectbl_ops __read_mostly;
99 49  
100   -static struct nf_hook_ops ip6t_ops[] __read_mostly = {
101   - {
102   - .hook = ip6t_local_in_hook,
103   - .owner = THIS_MODULE,
104   - .pf = NFPROTO_IPV6,
105   - .hooknum = NF_INET_LOCAL_IN,
106   - .priority = NF_IP6_PRI_SECURITY,
107   - },
108   - {
109   - .hook = ip6t_forward_hook,
110   - .owner = THIS_MODULE,
111   - .pf = NFPROTO_IPV6,
112   - .hooknum = NF_INET_FORWARD,
113   - .priority = NF_IP6_PRI_SECURITY,
114   - },
115   - {
116   - .hook = ip6t_local_out_hook,
117   - .owner = THIS_MODULE,
118   - .pf = NFPROTO_IPV6,
119   - .hooknum = NF_INET_LOCAL_OUT,
120   - .priority = NF_IP6_PRI_SECURITY,
121   - },
122   -};
123   -
124 50 static int __net_init ip6table_security_net_init(struct net *net)
125 51 {
126   - net->ipv6.ip6table_security =
127   - ip6t_register_table(net, &security_table, &initial_table.repl);
  52 + struct ip6t_replace *repl;
128 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);
129 60 if (IS_ERR(net->ipv6.ip6table_security))
130 61 return PTR_ERR(net->ipv6.ip6table_security);
131 62  
132 63  
... ... @@ -150,9 +81,11 @@
150 81 if (ret < 0)
151 82 return ret;
152 83  
153   - ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
154   - if (ret < 0)
  84 + sectbl_ops = xt_hook_link(&security_table, ip6table_security_hook);
  85 + if (IS_ERR(sectbl_ops)) {
  86 + ret = PTR_ERR(sectbl_ops);
155 87 goto cleanup_table;
  88 + }
156 89  
157 90 return ret;
158 91  
... ... @@ -163,7 +96,7 @@
163 96  
164 97 static void __exit ip6table_security_fini(void)
165 98 {
166   - nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
  99 + xt_hook_unlink(&security_table, sectbl_ops);
167 100 unregister_pernet_subsys(&ip6table_security_net_ops);
168 101 }
169 102  
net/netfilter/x_tables.c
... ... @@ -26,8 +26,10 @@
26 26  
27 27 #include <linux/netfilter/x_tables.h>
28 28 #include <linux/netfilter_arp.h>
  29 +#include <linux/netfilter_ipv4/ip_tables.h>
  30 +#include <linux/netfilter_ipv6/ip6_tables.h>
  31 +#include <linux/netfilter_arp/arp_tables.h>
29 32  
30   -
31 33 MODULE_LICENSE("GPL");
32 34 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
33 35 MODULE_DESCRIPTION("{ip,ip6,arp,eb}_tables backend module");
... ... @@ -1090,6 +1092,60 @@
1090 1092 #define FORMAT_TARGETS "_tables_targets"
1091 1093  
1092 1094 #endif /* CONFIG_PROC_FS */
  1095 +
  1096 +/**
  1097 + * xt_hook_link - set up hooks for a new table
  1098 + * @table: table with metadata needed to set up hooks
  1099 + * @fn: Hook function
  1100 + *
  1101 + * This function will take care of creating and registering the necessary
  1102 + * Netfilter hooks for XT tables.
  1103 + */
  1104 +struct nf_hook_ops *xt_hook_link(const struct xt_table *table, nf_hookfn *fn)
  1105 +{
  1106 + unsigned int hook_mask = table->valid_hooks;
  1107 + uint8_t i, num_hooks = hweight32(hook_mask);
  1108 + uint8_t hooknum;
  1109 + struct nf_hook_ops *ops;
  1110 + int ret;
  1111 +
  1112 + ops = kmalloc(sizeof(*ops) * num_hooks, GFP_KERNEL);
  1113 + if (ops == NULL)
  1114 + return ERR_PTR(-ENOMEM);
  1115 +
  1116 + for (i = 0, hooknum = 0; i < num_hooks && hook_mask != 0;
  1117 + hook_mask >>= 1, ++hooknum) {
  1118 + if (!(hook_mask & 1))
  1119 + continue;
  1120 + ops[i].hook = fn;
  1121 + ops[i].owner = table->me;
  1122 + ops[i].pf = table->af;
  1123 + ops[i].hooknum = hooknum;
  1124 + ops[i].priority = table->priority;
  1125 + ++i;
  1126 + }
  1127 +
  1128 + ret = nf_register_hooks(ops, num_hooks);
  1129 + if (ret < 0) {
  1130 + kfree(ops);
  1131 + return ERR_PTR(ret);
  1132 + }
  1133 +
  1134 + return ops;
  1135 +}
  1136 +EXPORT_SYMBOL_GPL(xt_hook_link);
  1137 +
  1138 +/**
  1139 + * xt_hook_unlink - remove hooks for a table
  1140 + * @ops: nf_hook_ops array as returned by nf_hook_link
  1141 + * @hook_mask: the very same mask that was passed to nf_hook_link
  1142 + */
  1143 +void xt_hook_unlink(const struct xt_table *table, struct nf_hook_ops *ops)
  1144 +{
  1145 + nf_unregister_hooks(ops, hweight32(table->valid_hooks));
  1146 + kfree(ops);
  1147 +}
  1148 +EXPORT_SYMBOL_GPL(xt_hook_unlink);
1093 1149  
1094 1150 int xt_proto_init(struct net *net, u_int8_t af)
1095 1151 {
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 +})