diff options
-rw-r--r-- | include/net/netns/ipv6.h | 1 | ||||
-rw-r--r-- | net/ipv6/fib6_rules.c | 82 |
2 files changed, 47 insertions, 36 deletions
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h index 5279cd6a00ba..66bf9c0f745b 100644 --- a/include/net/netns/ipv6.h +++ b/include/net/netns/ipv6.h | |||
@@ -41,6 +41,7 @@ struct netns_ipv6 { | |||
41 | struct fib6_table *fib6_main_tbl; | 41 | struct fib6_table *fib6_main_tbl; |
42 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 42 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
43 | struct fib6_table *fib6_local_tbl; | 43 | struct fib6_table *fib6_local_tbl; |
44 | struct fib_rules_ops *fib6_rules_ops; | ||
44 | #endif | 45 | #endif |
45 | struct sock **icmp_sk; | 46 | struct sock **icmp_sk; |
46 | }; | 47 | }; |
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 60af08f12547..89cb092c9732 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
@@ -29,8 +29,6 @@ struct fib6_rule | |||
29 | u8 tclass; | 29 | u8 tclass; |
30 | }; | 30 | }; |
31 | 31 | ||
32 | static struct fib_rules_ops *fib6_rules_ops; | ||
33 | |||
34 | struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl, | 32 | struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl, |
35 | int flags, pol_lookup_t lookup) | 33 | int flags, pol_lookup_t lookup) |
36 | { | 34 | { |
@@ -38,7 +36,7 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl, | |||
38 | .lookup_ptr = lookup, | 36 | .lookup_ptr = lookup, |
39 | }; | 37 | }; |
40 | 38 | ||
41 | fib_rules_lookup(fib6_rules_ops, fl, flags, &arg); | 39 | fib_rules_lookup(net->ipv6.fib6_rules_ops, fl, flags, &arg); |
42 | if (arg.rule) | 40 | if (arg.rule) |
43 | fib_rule_put(arg.rule); | 41 | fib_rule_put(arg.rule); |
44 | 42 | ||
@@ -71,7 +69,7 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | |||
71 | goto discard_pkt; | 69 | goto discard_pkt; |
72 | } | 70 | } |
73 | 71 | ||
74 | table = fib6_get_table(&init_net, rule->table); | 72 | table = fib6_get_table(rule->fr_net, rule->table); |
75 | if (table) | 73 | if (table) |
76 | rt = lookup(table, flp, flags); | 74 | rt = lookup(table, flp, flags); |
77 | 75 | ||
@@ -145,13 +143,14 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | |||
145 | struct nlattr **tb) | 143 | struct nlattr **tb) |
146 | { | 144 | { |
147 | int err = -EINVAL; | 145 | int err = -EINVAL; |
146 | struct net *net = skb->sk->sk_net; | ||
148 | struct fib6_rule *rule6 = (struct fib6_rule *) rule; | 147 | struct fib6_rule *rule6 = (struct fib6_rule *) rule; |
149 | 148 | ||
150 | if (rule->action == FR_ACT_TO_TBL) { | 149 | if (rule->action == FR_ACT_TO_TBL) { |
151 | if (rule->table == RT6_TABLE_UNSPEC) | 150 | if (rule->table == RT6_TABLE_UNSPEC) |
152 | goto errout; | 151 | goto errout; |
153 | 152 | ||
154 | if (fib6_new_table(&init_net, rule->table) == NULL) { | 153 | if (fib6_new_table(net, rule->table) == NULL) { |
155 | err = -ENOBUFS; | 154 | err = -ENOBUFS; |
156 | goto errout; | 155 | goto errout; |
157 | } | 156 | } |
@@ -251,49 +250,60 @@ static struct fib_rules_ops fib6_rules_ops_template = { | |||
251 | .fro_net = &init_net, | 250 | .fro_net = &init_net, |
252 | }; | 251 | }; |
253 | 252 | ||
254 | static int __init fib6_default_rules_init(void) | 253 | static int fib6_rules_net_init(struct net *net) |
255 | { | 254 | { |
256 | int err; | 255 | int err = -ENOMEM; |
257 | 256 | ||
258 | fib6_rules_ops = kmemdup(&fib6_rules_ops_template, | 257 | net->ipv6.fib6_rules_ops = kmemdup(&fib6_rules_ops_template, |
259 | sizeof(*fib6_rules_ops), GFP_KERNEL); | 258 | sizeof(*net->ipv6.fib6_rules_ops), |
260 | if (!fib6_rules_ops) | 259 | GFP_KERNEL); |
261 | return -ENOMEM; | 260 | if (!net->ipv6.fib6_rules_ops) |
261 | goto out; | ||
262 | 262 | ||
263 | INIT_LIST_HEAD(&fib6_rules_ops->rules_list); | 263 | net->ipv6.fib6_rules_ops->fro_net = net; |
264 | INIT_LIST_HEAD(&net->ipv6.fib6_rules_ops->rules_list); | ||
264 | 265 | ||
265 | err = fib_default_rule_add(fib6_rules_ops, 0, | 266 | err = fib_default_rule_add(net->ipv6.fib6_rules_ops, 0, |
266 | RT6_TABLE_LOCAL, FIB_RULE_PERMANENT); | 267 | RT6_TABLE_LOCAL, FIB_RULE_PERMANENT); |
267 | if (err < 0) | 268 | if (err) |
268 | return err; | 269 | goto out_fib6_rules_ops; |
269 | err = fib_default_rule_add(fib6_rules_ops, 0x7FFE, RT6_TABLE_MAIN, 0); | ||
270 | if (err < 0) | ||
271 | return err; | ||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | int __init fib6_rules_init(void) | ||
276 | { | ||
277 | int ret; | ||
278 | 270 | ||
279 | ret = fib6_default_rules_init(); | 271 | err = fib_default_rule_add(net->ipv6.fib6_rules_ops, |
280 | if (ret) | 272 | 0x7FFE, RT6_TABLE_MAIN, 0); |
281 | goto out; | 273 | if (err) |
274 | goto out_fib6_default_rule_add; | ||
282 | 275 | ||
283 | ret = fib_rules_register(fib6_rules_ops); | 276 | err = fib_rules_register(net->ipv6.fib6_rules_ops); |
284 | if (ret) | 277 | if (err) |
285 | goto out_default_rules_init; | 278 | goto out_fib6_default_rule_add; |
286 | out: | 279 | out: |
287 | return ret; | 280 | return err; |
288 | 281 | ||
289 | out_default_rules_init: | 282 | out_fib6_default_rule_add: |
290 | fib_rules_cleanup_ops(fib6_rules_ops); | 283 | fib_rules_cleanup_ops(net->ipv6.fib6_rules_ops); |
291 | kfree(fib6_rules_ops); | 284 | out_fib6_rules_ops: |
285 | kfree(net->ipv6.fib6_rules_ops); | ||
292 | goto out; | 286 | goto out; |
293 | } | 287 | } |
294 | 288 | ||
289 | static void fib6_rules_net_exit(struct net *net) | ||
290 | { | ||
291 | fib_rules_unregister(net->ipv6.fib6_rules_ops); | ||
292 | kfree(net->ipv6.fib6_rules_ops); | ||
293 | } | ||
294 | |||
295 | static struct pernet_operations fib6_rules_net_ops = { | ||
296 | .init = fib6_rules_net_init, | ||
297 | .exit = fib6_rules_net_exit, | ||
298 | }; | ||
299 | |||
300 | int __init fib6_rules_init(void) | ||
301 | { | ||
302 | return register_pernet_subsys(&fib6_rules_net_ops); | ||
303 | } | ||
304 | |||
305 | |||
295 | void fib6_rules_cleanup(void) | 306 | void fib6_rules_cleanup(void) |
296 | { | 307 | { |
297 | fib_rules_unregister(fib6_rules_ops); | 308 | return unregister_pernet_subsys(&fib6_rules_net_ops); |
298 | kfree(fib6_rules_ops); | ||
299 | } | 309 | } |