Commit a8c28d05150f758625c5da38199b247887735e65
Exists in
master
and in
39 other branches
Merge branch 'master' of git://dev.medozas.de/linux
Showing 19 changed files Side-by-side Diff
- include/linux/netfilter/x_tables.h
- include/linux/netfilter_arp/arp_tables.h
- include/linux/netfilter_ipv4/ip_tables.h
- include/linux/netfilter_ipv6/ip6_tables.h
- net/ipv4/netfilter/arp_tables.c
- net/ipv4/netfilter/arptable_filter.c
- net/ipv4/netfilter/ip_tables.c
- net/ipv4/netfilter/iptable_filter.c
- net/ipv4/netfilter/iptable_mangle.c
- net/ipv4/netfilter/iptable_raw.c
- net/ipv4/netfilter/iptable_security.c
- net/ipv4/netfilter/nf_nat_rule.c
- net/ipv6/netfilter/ip6_tables.c
- net/ipv6/netfilter/ip6table_filter.c
- net/ipv6/netfilter/ip6table_mangle.c
- net/ipv6/netfilter/ip6table_raw.c
- net/ipv6/netfilter/ip6table_security.c
- net/netfilter/x_tables.c
- net/netfilter/xt_repldata.h
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
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 | +}) |