diff options
author | Alexey Dobriyan <adobriyan@sw.ru> | 2008-01-31 07:04:13 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-31 22:27:39 -0500 |
commit | 8280aa6182f03c4e27dc235ce0440bc94927dc28 (patch) | |
tree | aff3a05fabf07b8bb17d0e0867a48fdcf4921045 /net/ipv6 | |
parent | 336b517fdc0f92f54a3f77a2d0933f9556aa79ad (diff) |
[NETFILTER]: ip6_tables: per-netns IPv6 FILTER, MANGLE, RAW
Now it's possible to list and manipulate per-netns ip6tables rules.
Filtering decisions are based on init_net's table so far.
P.S.: remove init_net check in inet6_create() to see the effect
Signed-off-by: Alexey Dobriyan <adobriyan@sw.ru>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/netfilter/ip6table_filter.c | 40 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_mangle.c | 40 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_raw.c | 38 |
3 files changed, 86 insertions, 32 deletions
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index d0bf71d40cc5..2d9cd095a72c 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c | |||
@@ -26,7 +26,7 @@ static struct | |||
26 | struct ip6t_replace repl; | 26 | struct ip6t_replace repl; |
27 | struct ip6t_standard entries[3]; | 27 | struct ip6t_standard entries[3]; |
28 | struct ip6t_error term; | 28 | struct ip6t_error term; |
29 | } initial_table __initdata = { | 29 | } initial_table __net_initdata = { |
30 | .repl = { | 30 | .repl = { |
31 | .name = "filter", | 31 | .name = "filter", |
32 | .valid_hooks = FILTER_VALID_HOOKS, | 32 | .valid_hooks = FILTER_VALID_HOOKS, |
@@ -51,14 +51,13 @@ static struct | |||
51 | .term = IP6T_ERROR_INIT, /* ERROR */ | 51 | .term = IP6T_ERROR_INIT, /* ERROR */ |
52 | }; | 52 | }; |
53 | 53 | ||
54 | static struct xt_table __packet_filter = { | 54 | static struct xt_table packet_filter = { |
55 | .name = "filter", | 55 | .name = "filter", |
56 | .valid_hooks = FILTER_VALID_HOOKS, | 56 | .valid_hooks = FILTER_VALID_HOOKS, |
57 | .lock = RW_LOCK_UNLOCKED, | 57 | .lock = RW_LOCK_UNLOCKED, |
58 | .me = THIS_MODULE, | 58 | .me = THIS_MODULE, |
59 | .af = AF_INET6, | 59 | .af = AF_INET6, |
60 | }; | 60 | }; |
61 | static struct xt_table *packet_filter; | ||
62 | 61 | ||
63 | /* The work comes in here from netfilter.c. */ | 62 | /* The work comes in here from netfilter.c. */ |
64 | static unsigned int | 63 | static unsigned int |
@@ -68,7 +67,7 @@ ip6t_hook(unsigned int hook, | |||
68 | const struct net_device *out, | 67 | const struct net_device *out, |
69 | int (*okfn)(struct sk_buff *)) | 68 | int (*okfn)(struct sk_buff *)) |
70 | { | 69 | { |
71 | return ip6t_do_table(skb, hook, in, out, packet_filter); | 70 | return ip6t_do_table(skb, hook, in, out, init_net.ipv6.ip6table_filter); |
72 | } | 71 | } |
73 | 72 | ||
74 | static unsigned int | 73 | static unsigned int |
@@ -88,7 +87,7 @@ ip6t_local_out_hook(unsigned int hook, | |||
88 | } | 87 | } |
89 | #endif | 88 | #endif |
90 | 89 | ||
91 | return ip6t_do_table(skb, hook, in, out, packet_filter); | 90 | return ip6t_do_table(skb, hook, in, out, init_net.ipv6.ip6table_filter); |
92 | } | 91 | } |
93 | 92 | ||
94 | static struct nf_hook_ops ip6t_ops[] __read_mostly = { | 93 | static struct nf_hook_ops ip6t_ops[] __read_mostly = { |
@@ -119,6 +118,26 @@ static struct nf_hook_ops ip6t_ops[] __read_mostly = { | |||
119 | static int forward = NF_ACCEPT; | 118 | static int forward = NF_ACCEPT; |
120 | module_param(forward, bool, 0000); | 119 | module_param(forward, bool, 0000); |
121 | 120 | ||
121 | static int __net_init ip6table_filter_net_init(struct net *net) | ||
122 | { | ||
123 | /* Register table */ | ||
124 | net->ipv6.ip6table_filter = | ||
125 | ip6t_register_table(net, &packet_filter, &initial_table.repl); | ||
126 | if (IS_ERR(net->ipv6.ip6table_filter)) | ||
127 | return PTR_ERR(net->ipv6.ip6table_filter); | ||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static void __net_exit ip6table_filter_net_exit(struct net *net) | ||
132 | { | ||
133 | ip6t_unregister_table(net->ipv6.ip6table_filter); | ||
134 | } | ||
135 | |||
136 | static struct pernet_operations ip6table_filter_net_ops = { | ||
137 | .init = ip6table_filter_net_init, | ||
138 | .exit = ip6table_filter_net_exit, | ||
139 | }; | ||
140 | |||
122 | static int __init ip6table_filter_init(void) | 141 | static int __init ip6table_filter_init(void) |
123 | { | 142 | { |
124 | int ret; | 143 | int ret; |
@@ -131,10 +150,9 @@ static int __init ip6table_filter_init(void) | |||
131 | /* Entry 1 is the FORWARD hook */ | 150 | /* Entry 1 is the FORWARD hook */ |
132 | initial_table.entries[1].target.verdict = -forward - 1; | 151 | initial_table.entries[1].target.verdict = -forward - 1; |
133 | 152 | ||
134 | /* Register table */ | 153 | ret = register_pernet_subsys(&ip6table_filter_net_ops); |
135 | packet_filter = ip6t_register_table(&init_net, &__packet_filter, &initial_table.repl); | 154 | if (ret < 0) |
136 | if (IS_ERR(packet_filter)) | 155 | return ret; |
137 | return PTR_ERR(packet_filter); | ||
138 | 156 | ||
139 | /* Register hooks */ | 157 | /* Register hooks */ |
140 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 158 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); |
@@ -144,14 +162,14 @@ static int __init ip6table_filter_init(void) | |||
144 | return ret; | 162 | return ret; |
145 | 163 | ||
146 | cleanup_table: | 164 | cleanup_table: |
147 | ip6t_unregister_table(packet_filter); | 165 | unregister_pernet_subsys(&ip6table_filter_net_ops); |
148 | return ret; | 166 | return ret; |
149 | } | 167 | } |
150 | 168 | ||
151 | static void __exit ip6table_filter_fini(void) | 169 | static void __exit ip6table_filter_fini(void) |
152 | { | 170 | { |
153 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 171 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); |
154 | ip6t_unregister_table(packet_filter); | 172 | unregister_pernet_subsys(&ip6table_filter_net_ops); |
155 | } | 173 | } |
156 | 174 | ||
157 | module_init(ip6table_filter_init); | 175 | module_init(ip6table_filter_init); |
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index abdfece4ab82..035343a90ffe 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
@@ -26,7 +26,7 @@ static struct | |||
26 | struct ip6t_replace repl; | 26 | struct ip6t_replace repl; |
27 | struct ip6t_standard entries[5]; | 27 | struct ip6t_standard entries[5]; |
28 | struct ip6t_error term; | 28 | struct ip6t_error term; |
29 | } initial_table __initdata = { | 29 | } initial_table __net_initdata = { |
30 | .repl = { | 30 | .repl = { |
31 | .name = "mangle", | 31 | .name = "mangle", |
32 | .valid_hooks = MANGLE_VALID_HOOKS, | 32 | .valid_hooks = MANGLE_VALID_HOOKS, |
@@ -57,14 +57,13 @@ static struct | |||
57 | .term = IP6T_ERROR_INIT, /* ERROR */ | 57 | .term = IP6T_ERROR_INIT, /* ERROR */ |
58 | }; | 58 | }; |
59 | 59 | ||
60 | static struct xt_table __packet_mangler = { | 60 | static struct xt_table packet_mangler = { |
61 | .name = "mangle", | 61 | .name = "mangle", |
62 | .valid_hooks = MANGLE_VALID_HOOKS, | 62 | .valid_hooks = MANGLE_VALID_HOOKS, |
63 | .lock = RW_LOCK_UNLOCKED, | 63 | .lock = RW_LOCK_UNLOCKED, |
64 | .me = THIS_MODULE, | 64 | .me = THIS_MODULE, |
65 | .af = AF_INET6, | 65 | .af = AF_INET6, |
66 | }; | 66 | }; |
67 | static struct xt_table *packet_mangler; | ||
68 | 67 | ||
69 | /* The work comes in here from netfilter.c. */ | 68 | /* The work comes in here from netfilter.c. */ |
70 | static unsigned int | 69 | static unsigned int |
@@ -74,7 +73,7 @@ ip6t_route_hook(unsigned int hook, | |||
74 | const struct net_device *out, | 73 | const struct net_device *out, |
75 | int (*okfn)(struct sk_buff *)) | 74 | int (*okfn)(struct sk_buff *)) |
76 | { | 75 | { |
77 | return ip6t_do_table(skb, hook, in, out, packet_mangler); | 76 | return ip6t_do_table(skb, hook, in, out, init_net.ipv6.ip6table_mangle); |
78 | } | 77 | } |
79 | 78 | ||
80 | static unsigned int | 79 | static unsigned int |
@@ -109,7 +108,7 @@ ip6t_local_hook(unsigned int hook, | |||
109 | /* flowlabel and prio (includes version, which shouldn't change either */ | 108 | /* flowlabel and prio (includes version, which shouldn't change either */ |
110 | flowlabel = *((u_int32_t *)ipv6_hdr(skb)); | 109 | flowlabel = *((u_int32_t *)ipv6_hdr(skb)); |
111 | 110 | ||
112 | ret = ip6t_do_table(skb, hook, in, out, packet_mangler); | 111 | ret = ip6t_do_table(skb, hook, in, out, init_net.ipv6.ip6table_mangle); |
113 | 112 | ||
114 | if (ret != NF_DROP && ret != NF_STOLEN | 113 | if (ret != NF_DROP && ret != NF_STOLEN |
115 | && (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) | 114 | && (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) |
@@ -159,14 +158,33 @@ static struct nf_hook_ops ip6t_ops[] __read_mostly = { | |||
159 | }, | 158 | }, |
160 | }; | 159 | }; |
161 | 160 | ||
161 | static int __net_init ip6table_mangle_net_init(struct net *net) | ||
162 | { | ||
163 | /* Register table */ | ||
164 | net->ipv6.ip6table_mangle = | ||
165 | ip6t_register_table(net, &packet_mangler, &initial_table.repl); | ||
166 | if (IS_ERR(net->ipv6.ip6table_mangle)) | ||
167 | return PTR_ERR(net->ipv6.ip6table_mangle); | ||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | static void __net_exit ip6table_mangle_net_exit(struct net *net) | ||
172 | { | ||
173 | ip6t_unregister_table(net->ipv6.ip6table_mangle); | ||
174 | } | ||
175 | |||
176 | static struct pernet_operations ip6table_mangle_net_ops = { | ||
177 | .init = ip6table_mangle_net_init, | ||
178 | .exit = ip6table_mangle_net_exit, | ||
179 | }; | ||
180 | |||
162 | static int __init ip6table_mangle_init(void) | 181 | static int __init ip6table_mangle_init(void) |
163 | { | 182 | { |
164 | int ret; | 183 | int ret; |
165 | 184 | ||
166 | /* Register table */ | 185 | ret = register_pernet_subsys(&ip6table_mangle_net_ops); |
167 | packet_mangler = ip6t_register_table(&init_net, &__packet_mangler, &initial_table.repl); | 186 | if (ret < 0) |
168 | if (IS_ERR(packet_mangler)) | 187 | return ret; |
169 | return PTR_ERR(packet_mangler); | ||
170 | 188 | ||
171 | /* Register hooks */ | 189 | /* Register hooks */ |
172 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 190 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); |
@@ -176,14 +194,14 @@ static int __init ip6table_mangle_init(void) | |||
176 | return ret; | 194 | return ret; |
177 | 195 | ||
178 | cleanup_table: | 196 | cleanup_table: |
179 | ip6t_unregister_table(packet_mangler); | 197 | unregister_pernet_subsys(&ip6table_mangle_net_ops); |
180 | return ret; | 198 | return ret; |
181 | } | 199 | } |
182 | 200 | ||
183 | static void __exit ip6table_mangle_fini(void) | 201 | static void __exit ip6table_mangle_fini(void) |
184 | { | 202 | { |
185 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 203 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); |
186 | ip6t_unregister_table(packet_mangler); | 204 | unregister_pernet_subsys(&ip6table_mangle_net_ops); |
187 | } | 205 | } |
188 | 206 | ||
189 | module_init(ip6table_mangle_init); | 207 | module_init(ip6table_mangle_init); |
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index 12acd6300903..5cd84203abfe 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c | |||
@@ -13,7 +13,7 @@ static struct | |||
13 | struct ip6t_replace repl; | 13 | struct ip6t_replace repl; |
14 | struct ip6t_standard entries[2]; | 14 | struct ip6t_standard entries[2]; |
15 | struct ip6t_error term; | 15 | struct ip6t_error term; |
16 | } initial_table __initdata = { | 16 | } initial_table __net_initdata = { |
17 | .repl = { | 17 | .repl = { |
18 | .name = "raw", | 18 | .name = "raw", |
19 | .valid_hooks = RAW_VALID_HOOKS, | 19 | .valid_hooks = RAW_VALID_HOOKS, |
@@ -35,14 +35,13 @@ static struct | |||
35 | .term = IP6T_ERROR_INIT, /* ERROR */ | 35 | .term = IP6T_ERROR_INIT, /* ERROR */ |
36 | }; | 36 | }; |
37 | 37 | ||
38 | static struct xt_table __packet_raw = { | 38 | static struct xt_table packet_raw = { |
39 | .name = "raw", | 39 | .name = "raw", |
40 | .valid_hooks = RAW_VALID_HOOKS, | 40 | .valid_hooks = RAW_VALID_HOOKS, |
41 | .lock = RW_LOCK_UNLOCKED, | 41 | .lock = RW_LOCK_UNLOCKED, |
42 | .me = THIS_MODULE, | 42 | .me = THIS_MODULE, |
43 | .af = AF_INET6, | 43 | .af = AF_INET6, |
44 | }; | 44 | }; |
45 | static struct xt_table *packet_raw; | ||
46 | 45 | ||
47 | /* The work comes in here from netfilter.c. */ | 46 | /* The work comes in here from netfilter.c. */ |
48 | static unsigned int | 47 | static unsigned int |
@@ -52,7 +51,7 @@ ip6t_hook(unsigned int hook, | |||
52 | const struct net_device *out, | 51 | const struct net_device *out, |
53 | int (*okfn)(struct sk_buff *)) | 52 | int (*okfn)(struct sk_buff *)) |
54 | { | 53 | { |
55 | return ip6t_do_table(skb, hook, in, out, packet_raw); | 54 | return ip6t_do_table(skb, hook, in, out, init_net.ipv6.ip6table_raw); |
56 | } | 55 | } |
57 | 56 | ||
58 | static struct nf_hook_ops ip6t_ops[] __read_mostly = { | 57 | static struct nf_hook_ops ip6t_ops[] __read_mostly = { |
@@ -72,14 +71,33 @@ static struct nf_hook_ops ip6t_ops[] __read_mostly = { | |||
72 | }, | 71 | }, |
73 | }; | 72 | }; |
74 | 73 | ||
74 | static int __net_init ip6table_raw_net_init(struct net *net) | ||
75 | { | ||
76 | /* Register table */ | ||
77 | net->ipv6.ip6table_raw = | ||
78 | ip6t_register_table(net, &packet_raw, &initial_table.repl); | ||
79 | if (IS_ERR(net->ipv6.ip6table_raw)) | ||
80 | return PTR_ERR(net->ipv6.ip6table_raw); | ||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static void __net_exit ip6table_raw_net_exit(struct net *net) | ||
85 | { | ||
86 | ip6t_unregister_table(net->ipv6.ip6table_raw); | ||
87 | } | ||
88 | |||
89 | static struct pernet_operations ip6table_raw_net_ops = { | ||
90 | .init = ip6table_raw_net_init, | ||
91 | .exit = ip6table_raw_net_exit, | ||
92 | }; | ||
93 | |||
75 | static int __init ip6table_raw_init(void) | 94 | static int __init ip6table_raw_init(void) |
76 | { | 95 | { |
77 | int ret; | 96 | int ret; |
78 | 97 | ||
79 | /* Register table */ | 98 | ret = register_pernet_subsys(&ip6table_raw_net_ops); |
80 | packet_raw = ip6t_register_table(&init_net, &__packet_raw, &initial_table.repl); | 99 | if (ret < 0) |
81 | if (IS_ERR(packet_raw)) | 100 | return ret; |
82 | return PTR_ERR(packet_raw); | ||
83 | 101 | ||
84 | /* Register hooks */ | 102 | /* Register hooks */ |
85 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 103 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); |
@@ -89,14 +107,14 @@ static int __init ip6table_raw_init(void) | |||
89 | return ret; | 107 | return ret; |
90 | 108 | ||
91 | cleanup_table: | 109 | cleanup_table: |
92 | ip6t_unregister_table(packet_raw); | 110 | unregister_pernet_subsys(&ip6table_raw_net_ops); |
93 | return ret; | 111 | return ret; |
94 | } | 112 | } |
95 | 113 | ||
96 | static void __exit ip6table_raw_fini(void) | 114 | static void __exit ip6table_raw_fini(void) |
97 | { | 115 | { |
98 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 116 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); |
99 | ip6t_unregister_table(packet_raw); | 117 | unregister_pernet_subsys(&ip6table_raw_net_ops); |
100 | } | 118 | } |
101 | 119 | ||
102 | module_init(ip6table_raw_init); | 120 | module_init(ip6table_raw_init); |