diff options
author | Daniel Lezcano <dlezcano@fr.ibm.com> | 2008-03-04 16:48:30 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-03-04 16:48:30 -0500 |
commit | 8ed677896752fff056f6cf3d7ce462adc6c464f0 (patch) | |
tree | 8b0cc80f1d199760e484810b1abb9e3c95f64a05 /net/ipv6/route.c | |
parent | bdb3289f739e94bcae8b51972ae844ec66c2f4df (diff) |
[NETNS][IPV6] rt6_info - move rt6_info structure inside the namespace
The rt6_info structures are moved inside the network namespace
structure. All references to these structures are now relative to the
initial network namespace.
Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 202 |
1 files changed, 133 insertions, 69 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 8f954c1e961f..7ff66cebe77c 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -145,8 +145,6 @@ static struct rt6_info ip6_null_entry_template = { | |||
145 | .rt6i_ref = ATOMIC_INIT(1), | 145 | .rt6i_ref = ATOMIC_INIT(1), |
146 | }; | 146 | }; |
147 | 147 | ||
148 | struct rt6_info *ip6_null_entry; | ||
149 | |||
150 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 148 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
151 | 149 | ||
152 | static int ip6_pkt_prohibit(struct sk_buff *skb); | 150 | static int ip6_pkt_prohibit(struct sk_buff *skb); |
@@ -170,8 +168,6 @@ struct rt6_info ip6_prohibit_entry_template = { | |||
170 | .rt6i_ref = ATOMIC_INIT(1), | 168 | .rt6i_ref = ATOMIC_INIT(1), |
171 | }; | 169 | }; |
172 | 170 | ||
173 | struct rt6_info *ip6_prohibit_entry; | ||
174 | |||
175 | static struct rt6_info ip6_blk_hole_entry_template = { | 171 | static struct rt6_info ip6_blk_hole_entry_template = { |
176 | .u = { | 172 | .u = { |
177 | .dst = { | 173 | .dst = { |
@@ -190,8 +186,6 @@ static struct rt6_info ip6_blk_hole_entry_template = { | |||
190 | .rt6i_ref = ATOMIC_INIT(1), | 186 | .rt6i_ref = ATOMIC_INIT(1), |
191 | }; | 187 | }; |
192 | 188 | ||
193 | struct rt6_info *ip6_blk_hole_entry; | ||
194 | |||
195 | #endif | 189 | #endif |
196 | 190 | ||
197 | /* allocate dst with ip6_dst_ops */ | 191 | /* allocate dst with ip6_dst_ops */ |
@@ -245,7 +239,8 @@ static inline int rt6_need_strict(struct in6_addr *daddr) | |||
245 | * Route lookup. Any table->tb6_lock is implied. | 239 | * Route lookup. Any table->tb6_lock is implied. |
246 | */ | 240 | */ |
247 | 241 | ||
248 | static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt, | 242 | static inline struct rt6_info *rt6_device_match(struct net *net, |
243 | struct rt6_info *rt, | ||
249 | int oif, | 244 | int oif, |
250 | int strict) | 245 | int strict) |
251 | { | 246 | { |
@@ -274,7 +269,7 @@ static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt, | |||
274 | return local; | 269 | return local; |
275 | 270 | ||
276 | if (strict) | 271 | if (strict) |
277 | return ip6_null_entry; | 272 | return net->ipv6.ip6_null_entry; |
278 | } | 273 | } |
279 | return rt; | 274 | return rt; |
280 | } | 275 | } |
@@ -415,6 +410,7 @@ static struct rt6_info *find_rr_leaf(struct fib6_node *fn, | |||
415 | static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict) | 410 | static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict) |
416 | { | 411 | { |
417 | struct rt6_info *match, *rt0; | 412 | struct rt6_info *match, *rt0; |
413 | struct net *net; | ||
418 | 414 | ||
419 | RT6_TRACE("%s(fn->leaf=%p, oif=%d)\n", | 415 | RT6_TRACE("%s(fn->leaf=%p, oif=%d)\n", |
420 | __FUNCTION__, fn->leaf, oif); | 416 | __FUNCTION__, fn->leaf, oif); |
@@ -440,7 +436,8 @@ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict) | |||
440 | RT6_TRACE("%s() => %p\n", | 436 | RT6_TRACE("%s() => %p\n", |
441 | __FUNCTION__, match); | 437 | __FUNCTION__, match); |
442 | 438 | ||
443 | return (match ? match : ip6_null_entry); | 439 | net = rt0->rt6i_dev->nd_net; |
440 | return (match ? match : net->ipv6.ip6_null_entry); | ||
444 | } | 441 | } |
445 | 442 | ||
446 | #ifdef CONFIG_IPV6_ROUTE_INFO | 443 | #ifdef CONFIG_IPV6_ROUTE_INFO |
@@ -523,9 +520,9 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, | |||
523 | } | 520 | } |
524 | #endif | 521 | #endif |
525 | 522 | ||
526 | #define BACKTRACK(saddr) \ | 523 | #define BACKTRACK(__net, saddr) \ |
527 | do { \ | 524 | do { \ |
528 | if (rt == ip6_null_entry) { \ | 525 | if (rt == __net->ipv6.ip6_null_entry) { \ |
529 | struct fib6_node *pn; \ | 526 | struct fib6_node *pn; \ |
530 | while (1) { \ | 527 | while (1) { \ |
531 | if (fn->fn_flags & RTN_TL_ROOT) \ | 528 | if (fn->fn_flags & RTN_TL_ROOT) \ |
@@ -541,7 +538,8 @@ do { \ | |||
541 | } \ | 538 | } \ |
542 | } while(0) | 539 | } while(0) |
543 | 540 | ||
544 | static struct rt6_info *ip6_pol_route_lookup(struct fib6_table *table, | 541 | static struct rt6_info *ip6_pol_route_lookup(struct net *net, |
542 | struct fib6_table *table, | ||
545 | struct flowi *fl, int flags) | 543 | struct flowi *fl, int flags) |
546 | { | 544 | { |
547 | struct fib6_node *fn; | 545 | struct fib6_node *fn; |
@@ -551,8 +549,8 @@ static struct rt6_info *ip6_pol_route_lookup(struct fib6_table *table, | |||
551 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); | 549 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); |
552 | restart: | 550 | restart: |
553 | rt = fn->leaf; | 551 | rt = fn->leaf; |
554 | rt = rt6_device_match(rt, fl->oif, flags); | 552 | rt = rt6_device_match(net, rt, fl->oif, flags); |
555 | BACKTRACK(&fl->fl6_src); | 553 | BACKTRACK(net, &fl->fl6_src); |
556 | out: | 554 | out: |
557 | dst_use(&rt->u.dst, jiffies); | 555 | dst_use(&rt->u.dst, jiffies); |
558 | read_unlock_bh(&table->tb6_lock); | 556 | read_unlock_bh(&table->tb6_lock); |
@@ -668,8 +666,8 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d | |||
668 | return rt; | 666 | return rt; |
669 | } | 667 | } |
670 | 668 | ||
671 | static struct rt6_info *ip6_pol_route(struct fib6_table *table, int oif, | 669 | static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int oif, |
672 | struct flowi *fl, int flags) | 670 | struct flowi *fl, int flags) |
673 | { | 671 | { |
674 | struct fib6_node *fn; | 672 | struct fib6_node *fn; |
675 | struct rt6_info *rt, *nrt; | 673 | struct rt6_info *rt, *nrt; |
@@ -688,8 +686,9 @@ restart_2: | |||
688 | 686 | ||
689 | restart: | 687 | restart: |
690 | rt = rt6_select(fn, oif, strict | reachable); | 688 | rt = rt6_select(fn, oif, strict | reachable); |
691 | BACKTRACK(&fl->fl6_src); | 689 | |
692 | if (rt == ip6_null_entry || | 690 | BACKTRACK(net, &fl->fl6_src); |
691 | if (rt == net->ipv6.ip6_null_entry || | ||
693 | rt->rt6i_flags & RTF_CACHE) | 692 | rt->rt6i_flags & RTF_CACHE) |
694 | goto out; | 693 | goto out; |
695 | 694 | ||
@@ -707,7 +706,7 @@ restart: | |||
707 | } | 706 | } |
708 | 707 | ||
709 | dst_release(&rt->u.dst); | 708 | dst_release(&rt->u.dst); |
710 | rt = nrt ? : ip6_null_entry; | 709 | rt = nrt ? : net->ipv6.ip6_null_entry; |
711 | 710 | ||
712 | dst_hold(&rt->u.dst); | 711 | dst_hold(&rt->u.dst); |
713 | if (nrt) { | 712 | if (nrt) { |
@@ -740,10 +739,10 @@ out2: | |||
740 | return rt; | 739 | return rt; |
741 | } | 740 | } |
742 | 741 | ||
743 | static struct rt6_info *ip6_pol_route_input(struct fib6_table *table, | 742 | static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table, |
744 | struct flowi *fl, int flags) | 743 | struct flowi *fl, int flags) |
745 | { | 744 | { |
746 | return ip6_pol_route(table, fl->iif, fl, flags); | 745 | return ip6_pol_route(net, table, fl->iif, fl, flags); |
747 | } | 746 | } |
748 | 747 | ||
749 | void ip6_route_input(struct sk_buff *skb) | 748 | void ip6_route_input(struct sk_buff *skb) |
@@ -770,10 +769,10 @@ void ip6_route_input(struct sk_buff *skb) | |||
770 | skb->dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input); | 769 | skb->dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input); |
771 | } | 770 | } |
772 | 771 | ||
773 | static struct rt6_info *ip6_pol_route_output(struct fib6_table *table, | 772 | static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table, |
774 | struct flowi *fl, int flags) | 773 | struct flowi *fl, int flags) |
775 | { | 774 | { |
776 | return ip6_pol_route(table, fl->oif, fl, flags); | 775 | return ip6_pol_route(net, table, fl->oif, fl, flags); |
777 | } | 776 | } |
778 | 777 | ||
779 | struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) | 778 | struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) |
@@ -1259,8 +1258,9 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) | |||
1259 | { | 1258 | { |
1260 | int err; | 1259 | int err; |
1261 | struct fib6_table *table; | 1260 | struct fib6_table *table; |
1261 | struct net *net = rt->rt6i_dev->nd_net; | ||
1262 | 1262 | ||
1263 | if (rt == ip6_null_entry) | 1263 | if (rt == net->ipv6.ip6_null_entry) |
1264 | return -ENOENT; | 1264 | return -ENOENT; |
1265 | 1265 | ||
1266 | table = rt->rt6i_table; | 1266 | table = rt->rt6i_table; |
@@ -1329,7 +1329,8 @@ struct ip6rd_flowi { | |||
1329 | struct in6_addr gateway; | 1329 | struct in6_addr gateway; |
1330 | }; | 1330 | }; |
1331 | 1331 | ||
1332 | static struct rt6_info *__ip6_route_redirect(struct fib6_table *table, | 1332 | static struct rt6_info *__ip6_route_redirect(struct net *net, |
1333 | struct fib6_table *table, | ||
1333 | struct flowi *fl, | 1334 | struct flowi *fl, |
1334 | int flags) | 1335 | int flags) |
1335 | { | 1336 | { |
@@ -1372,8 +1373,8 @@ restart: | |||
1372 | } | 1373 | } |
1373 | 1374 | ||
1374 | if (!rt) | 1375 | if (!rt) |
1375 | rt = ip6_null_entry; | 1376 | rt = net->ipv6.ip6_null_entry; |
1376 | BACKTRACK(&fl->fl6_src); | 1377 | BACKTRACK(net, &fl->fl6_src); |
1377 | out: | 1378 | out: |
1378 | dst_hold(&rt->u.dst); | 1379 | dst_hold(&rt->u.dst); |
1379 | 1380 | ||
@@ -1415,10 +1416,11 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | |||
1415 | { | 1416 | { |
1416 | struct rt6_info *rt, *nrt = NULL; | 1417 | struct rt6_info *rt, *nrt = NULL; |
1417 | struct netevent_redirect netevent; | 1418 | struct netevent_redirect netevent; |
1419 | struct net *net = neigh->dev->nd_net; | ||
1418 | 1420 | ||
1419 | rt = ip6_route_redirect(dest, src, saddr, neigh->dev); | 1421 | rt = ip6_route_redirect(dest, src, saddr, neigh->dev); |
1420 | 1422 | ||
1421 | if (rt == ip6_null_entry) { | 1423 | if (rt == net->ipv6.ip6_null_entry) { |
1422 | if (net_ratelimit()) | 1424 | if (net_ratelimit()) |
1423 | printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop " | 1425 | printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop " |
1424 | "for redirect target\n"); | 1426 | "for redirect target\n"); |
@@ -1886,10 +1888,18 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
1886 | return rt; | 1888 | return rt; |
1887 | } | 1889 | } |
1888 | 1890 | ||
1891 | struct arg_dev_net { | ||
1892 | struct net_device *dev; | ||
1893 | struct net *net; | ||
1894 | }; | ||
1895 | |||
1889 | static int fib6_ifdown(struct rt6_info *rt, void *arg) | 1896 | static int fib6_ifdown(struct rt6_info *rt, void *arg) |
1890 | { | 1897 | { |
1891 | if (((void*)rt->rt6i_dev == arg || arg == NULL) && | 1898 | struct net_device *dev = ((struct arg_dev_net *)arg)->dev; |
1892 | rt != ip6_null_entry) { | 1899 | struct net *net = ((struct arg_dev_net *)arg)->net; |
1900 | |||
1901 | if (((void *)rt->rt6i_dev == dev || dev == NULL) && | ||
1902 | rt != net->ipv6.ip6_null_entry) { | ||
1893 | RT6_TRACE("deleted by ifdown %p\n", rt); | 1903 | RT6_TRACE("deleted by ifdown %p\n", rt); |
1894 | return -1; | 1904 | return -1; |
1895 | } | 1905 | } |
@@ -1898,7 +1908,12 @@ static int fib6_ifdown(struct rt6_info *rt, void *arg) | |||
1898 | 1908 | ||
1899 | void rt6_ifdown(struct net *net, struct net_device *dev) | 1909 | void rt6_ifdown(struct net *net, struct net_device *dev) |
1900 | { | 1910 | { |
1901 | fib6_clean_all(net, fib6_ifdown, 0, dev); | 1911 | struct arg_dev_net adn = { |
1912 | .dev = dev, | ||
1913 | .net = net, | ||
1914 | }; | ||
1915 | |||
1916 | fib6_clean_all(net, fib6_ifdown, 0, &adn); | ||
1902 | } | 1917 | } |
1903 | 1918 | ||
1904 | struct rt6_mtu_change_arg | 1919 | struct rt6_mtu_change_arg |
@@ -2289,6 +2304,26 @@ errout: | |||
2289 | rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err); | 2304 | rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err); |
2290 | } | 2305 | } |
2291 | 2306 | ||
2307 | static int ip6_route_dev_notify(struct notifier_block *this, | ||
2308 | unsigned long event, void *data) | ||
2309 | { | ||
2310 | struct net_device *dev = (struct net_device *)data; | ||
2311 | struct net *net = dev->nd_net; | ||
2312 | |||
2313 | if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) { | ||
2314 | net->ipv6.ip6_null_entry->u.dst.dev = dev; | ||
2315 | net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev); | ||
2316 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
2317 | net->ipv6.ip6_prohibit_entry->u.dst.dev = dev; | ||
2318 | net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); | ||
2319 | net->ipv6.ip6_blk_hole_entry->u.dst.dev = dev; | ||
2320 | net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); | ||
2321 | #endif | ||
2322 | } | ||
2323 | |||
2324 | return NOTIFY_OK; | ||
2325 | } | ||
2326 | |||
2292 | /* | 2327 | /* |
2293 | * /proc | 2328 | * /proc |
2294 | */ | 2329 | */ |
@@ -2535,11 +2570,47 @@ struct ctl_table *ipv6_route_sysctl_init(struct net *net) | |||
2535 | 2570 | ||
2536 | static int ip6_route_net_init(struct net *net) | 2571 | static int ip6_route_net_init(struct net *net) |
2537 | { | 2572 | { |
2573 | int ret = 0; | ||
2574 | |||
2575 | ret = -ENOMEM; | ||
2576 | net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template, | ||
2577 | sizeof(*net->ipv6.ip6_null_entry), | ||
2578 | GFP_KERNEL); | ||
2579 | if (!net->ipv6.ip6_null_entry) | ||
2580 | goto out; | ||
2581 | net->ipv6.ip6_null_entry->u.dst.path = | ||
2582 | (struct dst_entry *)net->ipv6.ip6_null_entry; | ||
2583 | |||
2584 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
2585 | net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, | ||
2586 | sizeof(*net->ipv6.ip6_prohibit_entry), | ||
2587 | GFP_KERNEL); | ||
2588 | if (!net->ipv6.ip6_prohibit_entry) { | ||
2589 | kfree(net->ipv6.ip6_null_entry); | ||
2590 | goto out; | ||
2591 | } | ||
2592 | net->ipv6.ip6_prohibit_entry->u.dst.path = | ||
2593 | (struct dst_entry *)net->ipv6.ip6_prohibit_entry; | ||
2594 | |||
2595 | net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, | ||
2596 | sizeof(*net->ipv6.ip6_blk_hole_entry), | ||
2597 | GFP_KERNEL); | ||
2598 | if (!net->ipv6.ip6_blk_hole_entry) { | ||
2599 | kfree(net->ipv6.ip6_null_entry); | ||
2600 | kfree(net->ipv6.ip6_prohibit_entry); | ||
2601 | goto out; | ||
2602 | } | ||
2603 | net->ipv6.ip6_blk_hole_entry->u.dst.path = | ||
2604 | (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; | ||
2605 | #endif | ||
2606 | |||
2538 | #ifdef CONFIG_PROC_FS | 2607 | #ifdef CONFIG_PROC_FS |
2539 | proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops); | 2608 | proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops); |
2540 | proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops); | 2609 | proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops); |
2541 | #endif | 2610 | #endif |
2542 | return 0; | 2611 | ret = 0; |
2612 | out: | ||
2613 | return ret; | ||
2543 | } | 2614 | } |
2544 | 2615 | ||
2545 | static void ip6_route_net_exit(struct net *net) | 2616 | static void ip6_route_net_exit(struct net *net) |
@@ -2548,7 +2619,11 @@ static void ip6_route_net_exit(struct net *net) | |||
2548 | proc_net_remove(net, "ipv6_route"); | 2619 | proc_net_remove(net, "ipv6_route"); |
2549 | proc_net_remove(net, "rt6_stats"); | 2620 | proc_net_remove(net, "rt6_stats"); |
2550 | #endif | 2621 | #endif |
2551 | rt6_ifdown(net, NULL); | 2622 | kfree(net->ipv6.ip6_null_entry); |
2623 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
2624 | kfree(net->ipv6.ip6_prohibit_entry); | ||
2625 | kfree(net->ipv6.ip6_blk_hole_entry); | ||
2626 | #endif | ||
2552 | } | 2627 | } |
2553 | 2628 | ||
2554 | static struct pernet_operations ip6_route_net_ops = { | 2629 | static struct pernet_operations ip6_route_net_ops = { |
@@ -2556,6 +2631,11 @@ static struct pernet_operations ip6_route_net_ops = { | |||
2556 | .exit = ip6_route_net_exit, | 2631 | .exit = ip6_route_net_exit, |
2557 | }; | 2632 | }; |
2558 | 2633 | ||
2634 | static struct notifier_block ip6_route_dev_notifier = { | ||
2635 | .notifier_call = ip6_route_dev_notify, | ||
2636 | .priority = 0, | ||
2637 | }; | ||
2638 | |||
2559 | int __init ip6_route_init(void) | 2639 | int __init ip6_route_init(void) |
2560 | { | 2640 | { |
2561 | int ret; | 2641 | int ret; |
@@ -2568,30 +2648,24 @@ int __init ip6_route_init(void) | |||
2568 | 2648 | ||
2569 | ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep; | 2649 | ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep; |
2570 | 2650 | ||
2571 | ret = -ENOMEM; | 2651 | ret = register_pernet_subsys(&ip6_route_net_ops); |
2572 | ip6_null_entry = kmemdup(&ip6_null_entry_template, | 2652 | if (ret) |
2573 | sizeof(*ip6_null_entry), GFP_KERNEL); | ||
2574 | if (!ip6_null_entry) | ||
2575 | goto out_kmem_cache; | 2653 | goto out_kmem_cache; |
2576 | ip6_null_entry->u.dst.path = (struct dst_entry *)ip6_null_entry; | ||
2577 | |||
2578 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
2579 | ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, | ||
2580 | sizeof(*ip6_prohibit_entry), GFP_KERNEL); | ||
2581 | if (!ip6_prohibit_entry) | ||
2582 | goto out_ip6_null_entry; | ||
2583 | ip6_prohibit_entry->u.dst.path = (struct dst_entry *)ip6_prohibit_entry; | ||
2584 | |||
2585 | ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, | ||
2586 | sizeof(*ip6_blk_hole_entry), GFP_KERNEL); | ||
2587 | if (!ip6_blk_hole_entry) | ||
2588 | goto out_ip6_prohibit_entry; | ||
2589 | ip6_blk_hole_entry->u.dst.path = (struct dst_entry *)ip6_blk_hole_entry; | ||
2590 | #endif | ||
2591 | 2654 | ||
2655 | /* Registering of the loopback is done before this portion of code, | ||
2656 | * the loopback reference in rt6_info will not be taken, do it | ||
2657 | * manually for init_net */ | ||
2658 | init_net.ipv6.ip6_null_entry->u.dst.dev = init_net.loopback_dev; | ||
2659 | init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
2660 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
2661 | init_net.ipv6.ip6_prohibit_entry->u.dst.dev = init_net.loopback_dev; | ||
2662 | init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
2663 | init_net.ipv6.ip6_blk_hole_entry->u.dst.dev = init_net.loopback_dev; | ||
2664 | init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
2665 | #endif | ||
2592 | ret = fib6_init(); | 2666 | ret = fib6_init(); |
2593 | if (ret) | 2667 | if (ret) |
2594 | goto out_ip6_blk_hole_entry; | 2668 | goto out_register_subsys; |
2595 | 2669 | ||
2596 | ret = xfrm6_init(); | 2670 | ret = xfrm6_init(); |
2597 | if (ret) | 2671 | if (ret) |
@@ -2607,9 +2681,10 @@ int __init ip6_route_init(void) | |||
2607 | __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL)) | 2681 | __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL)) |
2608 | goto fib6_rules_init; | 2682 | goto fib6_rules_init; |
2609 | 2683 | ||
2610 | ret = register_pernet_subsys(&ip6_route_net_ops); | 2684 | ret = register_netdevice_notifier(&ip6_route_dev_notifier); |
2611 | if (ret) | 2685 | if (ret) |
2612 | goto fib6_rules_init; | 2686 | goto fib6_rules_init; |
2687 | |||
2613 | out: | 2688 | out: |
2614 | return ret; | 2689 | return ret; |
2615 | 2690 | ||
@@ -2619,14 +2694,8 @@ xfrm6_init: | |||
2619 | xfrm6_fini(); | 2694 | xfrm6_fini(); |
2620 | out_fib6_init: | 2695 | out_fib6_init: |
2621 | fib6_gc_cleanup(); | 2696 | fib6_gc_cleanup(); |
2622 | out_ip6_blk_hole_entry: | 2697 | out_register_subsys: |
2623 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 2698 | unregister_pernet_subsys(&ip6_route_net_ops); |
2624 | kfree(ip6_blk_hole_entry); | ||
2625 | out_ip6_prohibit_entry: | ||
2626 | kfree(ip6_prohibit_entry); | ||
2627 | out_ip6_null_entry: | ||
2628 | #endif | ||
2629 | kfree(ip6_null_entry); | ||
2630 | out_kmem_cache: | 2699 | out_kmem_cache: |
2631 | kmem_cache_destroy(ip6_dst_ops.kmem_cachep); | 2700 | kmem_cache_destroy(ip6_dst_ops.kmem_cachep); |
2632 | goto out; | 2701 | goto out; |
@@ -2634,15 +2703,10 @@ out_kmem_cache: | |||
2634 | 2703 | ||
2635 | void ip6_route_cleanup(void) | 2704 | void ip6_route_cleanup(void) |
2636 | { | 2705 | { |
2637 | unregister_pernet_subsys(&ip6_route_net_ops); | 2706 | unregister_netdevice_notifier(&ip6_route_dev_notifier); |
2638 | fib6_rules_cleanup(); | 2707 | fib6_rules_cleanup(); |
2639 | xfrm6_fini(); | 2708 | xfrm6_fini(); |
2640 | fib6_gc_cleanup(); | 2709 | fib6_gc_cleanup(); |
2710 | unregister_pernet_subsys(&ip6_route_net_ops); | ||
2641 | kmem_cache_destroy(ip6_dst_ops.kmem_cachep); | 2711 | kmem_cache_destroy(ip6_dst_ops.kmem_cachep); |
2642 | |||
2643 | kfree(ip6_null_entry); | ||
2644 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
2645 | kfree(ip6_prohibit_entry); | ||
2646 | kfree(ip6_blk_hole_entry); | ||
2647 | #endif | ||
2648 | } | 2712 | } |