diff options
-rw-r--r-- | include/net/ip6_route.h | 6 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 12 | ||||
-rw-r--r-- | net/ipv6/fib6_rules.c | 12 | ||||
-rw-r--r-- | net/ipv6/ip6_fib.c | 18 | ||||
-rw-r--r-- | net/ipv6/route.c | 70 |
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 | ||
37 | extern struct rt6_info ip6_null_entry; | 37 | extern struct rt6_info *ip6_null_entry; |
38 | 38 | ||
39 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 39 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
40 | extern struct rt6_info ip6_prohibit_entry; | 40 | extern struct rt6_info *ip6_prohibit_entry; |
41 | extern struct rt6_info ip6_blk_hole_entry; | 41 | extern struct rt6_info *ip6_blk_hole_entry; |
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | extern void ip6_route_input(struct sk_buff *skb); | 44 | extern 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 | ||
50 | static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | 50 | static 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, | |||
962 | static struct rt6_info * fib6_find_prefix(struct fib6_node *fn) | 962 | static 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 | ||
130 | struct rt6_info ip6_null_entry = { | 130 | static 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 | ||
148 | struct rt6_info *ip6_null_entry; | ||
149 | |||
149 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 150 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
150 | 151 | ||
151 | static int ip6_pkt_prohibit(struct sk_buff *skb); | 152 | static int ip6_pkt_prohibit(struct sk_buff *skb); |
152 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); | 153 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); |
153 | 154 | ||
154 | struct rt6_info ip6_prohibit_entry = { | 155 | struct 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 | ||
173 | struct rt6_info ip6_blk_hole_entry = { | 173 | struct rt6_info *ip6_prohibit_entry; |
174 | |||
175 | static 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 | ||
193 | struct 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) \ |
524 | do { \ | 527 | do { \ |
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: | |||
686 | restart: | 689 | restart: |
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); |
1374 | out: | 1377 | out: |
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, | |||
1886 | static int fib6_ifdown(struct rt6_info *rt, void *arg) | 1889 | static 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(); |
2596 | out_fib6_init: | 2620 | out_fib6_init: |
2597 | fib6_gc_cleanup(); | 2621 | fib6_gc_cleanup(); |
2622 | out_ip6_blk_hole_entry: | ||
2623 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
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); | ||
2598 | out_kmem_cache: | 2630 | out_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 | } |