aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/netns/ipv6.h1
-rw-r--r--net/ipv6/fib6_rules.c82
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
32static struct fib_rules_ops *fib6_rules_ops;
33
34struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl, 32struct 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
254static int __init fib6_default_rules_init(void) 253static 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
275int __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;
286out: 279out:
287 return ret; 280 return err;
288 281
289out_default_rules_init: 282out_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); 284out_fib6_rules_ops:
285 kfree(net->ipv6.fib6_rules_ops);
292 goto out; 286 goto out;
293} 287}
294 288
289static 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
295static struct pernet_operations fib6_rules_net_ops = {
296 .init = fib6_rules_net_init,
297 .exit = fib6_rules_net_exit,
298};
299
300int __init fib6_rules_init(void)
301{
302 return register_pernet_subsys(&fib6_rules_net_ops);
303}
304
305
295void fib6_rules_cleanup(void) 306void 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}