aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/ip6_route.h6
-rw-r--r--net/ipv6/addrconf.c12
-rw-r--r--net/ipv6/fib6_rules.c12
-rw-r--r--net/ipv6/ip6_fib.c18
-rw-r--r--net/ipv6/route.c70
5 files changed, 78 insertions, 40 deletions
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 2bcbfb826530..e0caed25bfba 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -34,11 +34,11 @@ struct route_info {
34#define RT6_LOOKUP_F_REACHABLE 0x2 34#define RT6_LOOKUP_F_REACHABLE 0x2
35#define RT6_LOOKUP_F_HAS_SADDR 0x4 35#define RT6_LOOKUP_F_HAS_SADDR 0x4
36 36
37extern struct rt6_info ip6_null_entry; 37extern struct rt6_info *ip6_null_entry;
38 38
39#ifdef CONFIG_IPV6_MULTIPLE_TABLES 39#ifdef CONFIG_IPV6_MULTIPLE_TABLES
40extern struct rt6_info ip6_prohibit_entry; 40extern struct rt6_info *ip6_prohibit_entry;
41extern struct rt6_info ip6_blk_hole_entry; 41extern struct rt6_info *ip6_blk_hole_entry;
42#endif 42#endif
43 43
44extern void ip6_route_input(struct sk_buff *skb); 44extern void ip6_route_input(struct sk_buff *skb);
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index b37ae421b61b..3192a848a53a 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4301,13 +4301,13 @@ int __init addrconf_init(void)
4301 if (err) 4301 if (err)
4302 goto errlo; 4302 goto errlo;
4303 4303
4304 ip6_null_entry.u.dst.dev = init_net.loopback_dev; 4304 ip6_null_entry->u.dst.dev = init_net.loopback_dev;
4305 ip6_null_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev); 4305 ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
4306#ifdef CONFIG_IPV6_MULTIPLE_TABLES 4306#ifdef CONFIG_IPV6_MULTIPLE_TABLES
4307 ip6_prohibit_entry.u.dst.dev = init_net.loopback_dev; 4307 ip6_prohibit_entry->u.dst.dev = init_net.loopback_dev;
4308 ip6_prohibit_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev); 4308 ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
4309 ip6_blk_hole_entry.u.dst.dev = init_net.loopback_dev; 4309 ip6_blk_hole_entry->u.dst.dev = init_net.loopback_dev;
4310 ip6_blk_hole_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev); 4310 ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
4311#endif 4311#endif
4312 4312
4313 register_netdevice_notifier(&ipv6_dev_notf); 4313 register_netdevice_notifier(&ipv6_dev_notf);
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index 89cb092c9732..c00055f232c4 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -43,8 +43,8 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl,
43 if (arg.result) 43 if (arg.result)
44 return arg.result; 44 return arg.result;
45 45
46 dst_hold(&ip6_null_entry.u.dst); 46 dst_hold(&ip6_null_entry->u.dst);
47 return &ip6_null_entry.u.dst; 47 return &ip6_null_entry->u.dst;
48} 48}
49 49
50static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, 50static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
@@ -58,14 +58,14 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
58 case FR_ACT_TO_TBL: 58 case FR_ACT_TO_TBL:
59 break; 59 break;
60 case FR_ACT_UNREACHABLE: 60 case FR_ACT_UNREACHABLE:
61 rt = &ip6_null_entry; 61 rt = ip6_null_entry;
62 goto discard_pkt; 62 goto discard_pkt;
63 default: 63 default:
64 case FR_ACT_BLACKHOLE: 64 case FR_ACT_BLACKHOLE:
65 rt = &ip6_blk_hole_entry; 65 rt = ip6_blk_hole_entry;
66 goto discard_pkt; 66 goto discard_pkt;
67 case FR_ACT_PROHIBIT: 67 case FR_ACT_PROHIBIT:
68 rt = &ip6_prohibit_entry; 68 rt = ip6_prohibit_entry;
69 goto discard_pkt; 69 goto discard_pkt;
70 } 70 }
71 71
@@ -73,7 +73,7 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
73 if (table) 73 if (table)
74 rt = lookup(table, flp, flags); 74 rt = lookup(table, flp, flags);
75 75
76 if (rt != &ip6_null_entry) { 76 if (rt != ip6_null_entry) {
77 struct fib6_rule *r = (struct fib6_rule *)rule; 77 struct fib6_rule *r = (struct fib6_rule *)rule;
78 78
79 /* 79 /*
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 1c2566e3d392..f028f7a1a446 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -200,7 +200,7 @@ static struct fib6_table *fib6_alloc_table(u32 id)
200 table = kzalloc(sizeof(*table), GFP_ATOMIC); 200 table = kzalloc(sizeof(*table), GFP_ATOMIC);
201 if (table != NULL) { 201 if (table != NULL) {
202 table->tb6_id = id; 202 table->tb6_id = id;
203 table->tb6_root.leaf = &ip6_null_entry; 203 table->tb6_root.leaf = ip6_null_entry;
204 table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; 204 table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
205 } 205 }
206 206
@@ -717,8 +717,8 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
717 if (sfn == NULL) 717 if (sfn == NULL)
718 goto st_failure; 718 goto st_failure;
719 719
720 sfn->leaf = &ip6_null_entry; 720 sfn->leaf = ip6_null_entry;
721 atomic_inc(&ip6_null_entry.rt6i_ref); 721 atomic_inc(&ip6_null_entry->rt6i_ref);
722 sfn->fn_flags = RTN_ROOT; 722 sfn->fn_flags = RTN_ROOT;
723 sfn->fn_sernum = fib6_new_sernum(); 723 sfn->fn_sernum = fib6_new_sernum();
724 724
@@ -777,7 +777,7 @@ out:
777#if RT6_DEBUG >= 2 777#if RT6_DEBUG >= 2
778 if (!pn->leaf) { 778 if (!pn->leaf) {
779 BUG_TRAP(pn->leaf != NULL); 779 BUG_TRAP(pn->leaf != NULL);
780 pn->leaf = &ip6_null_entry; 780 pn->leaf = ip6_null_entry;
781 } 781 }
782#endif 782#endif
783 atomic_inc(&pn->leaf->rt6i_ref); 783 atomic_inc(&pn->leaf->rt6i_ref);
@@ -962,7 +962,7 @@ struct fib6_node * fib6_locate(struct fib6_node *root,
962static struct rt6_info * fib6_find_prefix(struct fib6_node *fn) 962static struct rt6_info * fib6_find_prefix(struct fib6_node *fn)
963{ 963{
964 if (fn->fn_flags&RTN_ROOT) 964 if (fn->fn_flags&RTN_ROOT)
965 return &ip6_null_entry; 965 return ip6_null_entry;
966 966
967 while(fn) { 967 while(fn) {
968 if(fn->left) 968 if(fn->left)
@@ -1012,7 +1012,7 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn)
1012#if RT6_DEBUG >= 2 1012#if RT6_DEBUG >= 2
1013 if (fn->leaf==NULL) { 1013 if (fn->leaf==NULL) {
1014 BUG_TRAP(fn->leaf); 1014 BUG_TRAP(fn->leaf);
1015 fn->leaf = &ip6_null_entry; 1015 fn->leaf = ip6_null_entry;
1016 } 1016 }
1017#endif 1017#endif
1018 atomic_inc(&fn->leaf->rt6i_ref); 1018 atomic_inc(&fn->leaf->rt6i_ref);
@@ -1154,7 +1154,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info)
1154 return -ENOENT; 1154 return -ENOENT;
1155 } 1155 }
1156#endif 1156#endif
1157 if (fn == NULL || rt == &ip6_null_entry) 1157 if (fn == NULL || rt == ip6_null_entry)
1158 return -ENOENT; 1158 return -ENOENT;
1159 1159
1160 BUG_TRAP(fn->fn_flags&RTN_RTINFO); 1160 BUG_TRAP(fn->fn_flags&RTN_RTINFO);
@@ -1501,7 +1501,7 @@ static int fib6_net_init(struct net *net)
1501 goto out_fib_table_hash; 1501 goto out_fib_table_hash;
1502 1502
1503 net->ipv6.fib6_main_tbl->tb6_id = RT6_TABLE_MAIN; 1503 net->ipv6.fib6_main_tbl->tb6_id = RT6_TABLE_MAIN;
1504 net->ipv6.fib6_main_tbl->tb6_root.leaf = &ip6_null_entry; 1504 net->ipv6.fib6_main_tbl->tb6_root.leaf = ip6_null_entry;
1505 net->ipv6.fib6_main_tbl->tb6_root.fn_flags = 1505 net->ipv6.fib6_main_tbl->tb6_root.fn_flags =
1506 RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; 1506 RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
1507 1507
@@ -1511,7 +1511,7 @@ static int fib6_net_init(struct net *net)
1511 if (!net->ipv6.fib6_local_tbl) 1511 if (!net->ipv6.fib6_local_tbl)
1512 goto out_fib6_main_tbl; 1512 goto out_fib6_main_tbl;
1513 net->ipv6.fib6_local_tbl->tb6_id = RT6_TABLE_LOCAL; 1513 net->ipv6.fib6_local_tbl->tb6_id = RT6_TABLE_LOCAL;
1514 net->ipv6.fib6_local_tbl->tb6_root.leaf = &ip6_null_entry; 1514 net->ipv6.fib6_local_tbl->tb6_root.leaf = ip6_null_entry;
1515 net->ipv6.fib6_local_tbl->tb6_root.fn_flags = 1515 net->ipv6.fib6_local_tbl->tb6_root.fn_flags =
1516 RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; 1516 RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
1517#endif 1517#endif
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index b3ac4901af86..8f954c1e961f 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -127,7 +127,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
127 .entries = ATOMIC_INIT(0), 127 .entries = ATOMIC_INIT(0),
128}; 128};
129 129
130struct rt6_info ip6_null_entry = { 130static struct rt6_info ip6_null_entry_template = {
131 .u = { 131 .u = {
132 .dst = { 132 .dst = {
133 .__refcnt = ATOMIC_INIT(1), 133 .__refcnt = ATOMIC_INIT(1),
@@ -138,7 +138,6 @@ struct rt6_info ip6_null_entry = {
138 .input = ip6_pkt_discard, 138 .input = ip6_pkt_discard,
139 .output = ip6_pkt_discard_out, 139 .output = ip6_pkt_discard_out,
140 .ops = &ip6_dst_ops, 140 .ops = &ip6_dst_ops,
141 .path = (struct dst_entry*)&ip6_null_entry,
142 } 141 }
143 }, 142 },
144 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), 143 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
@@ -146,12 +145,14 @@ struct rt6_info ip6_null_entry = {
146 .rt6i_ref = ATOMIC_INIT(1), 145 .rt6i_ref = ATOMIC_INIT(1),
147}; 146};
148 147
148struct rt6_info *ip6_null_entry;
149
149#ifdef CONFIG_IPV6_MULTIPLE_TABLES 150#ifdef CONFIG_IPV6_MULTIPLE_TABLES
150 151
151static int ip6_pkt_prohibit(struct sk_buff *skb); 152static int ip6_pkt_prohibit(struct sk_buff *skb);
152static int ip6_pkt_prohibit_out(struct sk_buff *skb); 153static int ip6_pkt_prohibit_out(struct sk_buff *skb);
153 154
154struct rt6_info ip6_prohibit_entry = { 155struct rt6_info ip6_prohibit_entry_template = {
155 .u = { 156 .u = {
156 .dst = { 157 .dst = {
157 .__refcnt = ATOMIC_INIT(1), 158 .__refcnt = ATOMIC_INIT(1),
@@ -162,7 +163,6 @@ struct rt6_info ip6_prohibit_entry = {
162 .input = ip6_pkt_prohibit, 163 .input = ip6_pkt_prohibit,
163 .output = ip6_pkt_prohibit_out, 164 .output = ip6_pkt_prohibit_out,
164 .ops = &ip6_dst_ops, 165 .ops = &ip6_dst_ops,
165 .path = (struct dst_entry*)&ip6_prohibit_entry,
166 } 166 }
167 }, 167 },
168 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), 168 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
@@ -170,7 +170,9 @@ struct rt6_info ip6_prohibit_entry = {
170 .rt6i_ref = ATOMIC_INIT(1), 170 .rt6i_ref = ATOMIC_INIT(1),
171}; 171};
172 172
173struct rt6_info ip6_blk_hole_entry = { 173struct rt6_info *ip6_prohibit_entry;
174
175static struct rt6_info ip6_blk_hole_entry_template = {
174 .u = { 176 .u = {
175 .dst = { 177 .dst = {
176 .__refcnt = ATOMIC_INIT(1), 178 .__refcnt = ATOMIC_INIT(1),
@@ -181,7 +183,6 @@ struct rt6_info ip6_blk_hole_entry = {
181 .input = dst_discard, 183 .input = dst_discard,
182 .output = dst_discard, 184 .output = dst_discard,
183 .ops = &ip6_dst_ops, 185 .ops = &ip6_dst_ops,
184 .path = (struct dst_entry*)&ip6_blk_hole_entry,
185 } 186 }
186 }, 187 },
187 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), 188 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
@@ -189,6 +190,8 @@ struct rt6_info ip6_blk_hole_entry = {
189 .rt6i_ref = ATOMIC_INIT(1), 190 .rt6i_ref = ATOMIC_INIT(1),
190}; 191};
191 192
193struct rt6_info *ip6_blk_hole_entry;
194
192#endif 195#endif
193 196
194/* allocate dst with ip6_dst_ops */ 197/* allocate dst with ip6_dst_ops */
@@ -271,7 +274,7 @@ static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt,
271 return local; 274 return local;
272 275
273 if (strict) 276 if (strict)
274 return &ip6_null_entry; 277 return ip6_null_entry;
275 } 278 }
276 return rt; 279 return rt;
277} 280}
@@ -437,7 +440,7 @@ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict)
437 RT6_TRACE("%s() => %p\n", 440 RT6_TRACE("%s() => %p\n",
438 __FUNCTION__, match); 441 __FUNCTION__, match);
439 442
440 return (match ? match : &ip6_null_entry); 443 return (match ? match : ip6_null_entry);
441} 444}
442 445
443#ifdef CONFIG_IPV6_ROUTE_INFO 446#ifdef CONFIG_IPV6_ROUTE_INFO
@@ -522,7 +525,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
522 525
523#define BACKTRACK(saddr) \ 526#define BACKTRACK(saddr) \
524do { \ 527do { \
525 if (rt == &ip6_null_entry) { \ 528 if (rt == ip6_null_entry) { \
526 struct fib6_node *pn; \ 529 struct fib6_node *pn; \
527 while (1) { \ 530 while (1) { \
528 if (fn->fn_flags & RTN_TL_ROOT) \ 531 if (fn->fn_flags & RTN_TL_ROOT) \
@@ -686,7 +689,7 @@ restart_2:
686restart: 689restart:
687 rt = rt6_select(fn, oif, strict | reachable); 690 rt = rt6_select(fn, oif, strict | reachable);
688 BACKTRACK(&fl->fl6_src); 691 BACKTRACK(&fl->fl6_src);
689 if (rt == &ip6_null_entry || 692 if (rt == ip6_null_entry ||
690 rt->rt6i_flags & RTF_CACHE) 693 rt->rt6i_flags & RTF_CACHE)
691 goto out; 694 goto out;
692 695
@@ -704,7 +707,7 @@ restart:
704 } 707 }
705 708
706 dst_release(&rt->u.dst); 709 dst_release(&rt->u.dst);
707 rt = nrt ? : &ip6_null_entry; 710 rt = nrt ? : ip6_null_entry;
708 711
709 dst_hold(&rt->u.dst); 712 dst_hold(&rt->u.dst);
710 if (nrt) { 713 if (nrt) {
@@ -1257,7 +1260,7 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info)
1257 int err; 1260 int err;
1258 struct fib6_table *table; 1261 struct fib6_table *table;
1259 1262
1260 if (rt == &ip6_null_entry) 1263 if (rt == ip6_null_entry)
1261 return -ENOENT; 1264 return -ENOENT;
1262 1265
1263 table = rt->rt6i_table; 1266 table = rt->rt6i_table;
@@ -1369,7 +1372,7 @@ restart:
1369 } 1372 }
1370 1373
1371 if (!rt) 1374 if (!rt)
1372 rt = &ip6_null_entry; 1375 rt = ip6_null_entry;
1373 BACKTRACK(&fl->fl6_src); 1376 BACKTRACK(&fl->fl6_src);
1374out: 1377out:
1375 dst_hold(&rt->u.dst); 1378 dst_hold(&rt->u.dst);
@@ -1415,7 +1418,7 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
1415 1418
1416 rt = ip6_route_redirect(dest, src, saddr, neigh->dev); 1419 rt = ip6_route_redirect(dest, src, saddr, neigh->dev);
1417 1420
1418 if (rt == &ip6_null_entry) { 1421 if (rt == ip6_null_entry) {
1419 if (net_ratelimit()) 1422 if (net_ratelimit())
1420 printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop " 1423 printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop "
1421 "for redirect target\n"); 1424 "for redirect target\n");
@@ -1886,7 +1889,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
1886static int fib6_ifdown(struct rt6_info *rt, void *arg) 1889static int fib6_ifdown(struct rt6_info *rt, void *arg)
1887{ 1890{
1888 if (((void*)rt->rt6i_dev == arg || arg == NULL) && 1891 if (((void*)rt->rt6i_dev == arg || arg == NULL) &&
1889 rt != &ip6_null_entry) { 1892 rt != ip6_null_entry) {
1890 RT6_TRACE("deleted by ifdown %p\n", rt); 1893 RT6_TRACE("deleted by ifdown %p\n", rt);
1891 return -1; 1894 return -1;
1892 } 1895 }
@@ -2565,9 +2568,30 @@ int __init ip6_route_init(void)
2565 2568
2566 ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep; 2569 ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep;
2567 2570
2571 ret = -ENOMEM;
2572 ip6_null_entry = kmemdup(&ip6_null_entry_template,
2573 sizeof(*ip6_null_entry), GFP_KERNEL);
2574 if (!ip6_null_entry)
2575 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
2568 ret = fib6_init(); 2592 ret = fib6_init();
2569 if (ret) 2593 if (ret)
2570 goto out_kmem_cache; 2594 goto out_ip6_blk_hole_entry;
2571 2595
2572 ret = xfrm6_init(); 2596 ret = xfrm6_init();
2573 if (ret) 2597 if (ret)
@@ -2595,6 +2619,14 @@ xfrm6_init:
2595 xfrm6_fini(); 2619 xfrm6_fini();
2596out_fib6_init: 2620out_fib6_init:
2597 fib6_gc_cleanup(); 2621 fib6_gc_cleanup();
2622out_ip6_blk_hole_entry:
2623#ifdef CONFIG_IPV6_MULTIPLE_TABLES
2624 kfree(ip6_blk_hole_entry);
2625out_ip6_prohibit_entry:
2626 kfree(ip6_prohibit_entry);
2627out_ip6_null_entry:
2628#endif
2629 kfree(ip6_null_entry);
2598out_kmem_cache: 2630out_kmem_cache:
2599 kmem_cache_destroy(ip6_dst_ops.kmem_cachep); 2631 kmem_cache_destroy(ip6_dst_ops.kmem_cachep);
2600 goto out; 2632 goto out;
@@ -2607,4 +2639,10 @@ void ip6_route_cleanup(void)
2607 xfrm6_fini(); 2639 xfrm6_fini();
2608 fib6_gc_cleanup(); 2640 fib6_gc_cleanup();
2609 kmem_cache_destroy(ip6_dst_ops.kmem_cachep); 2641 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
2610} 2648}