diff options
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 9e69eb0ec6dd..fb545edef6ea 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -104,6 +104,9 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) | |||
104 | struct inet_peer *peer; | 104 | struct inet_peer *peer; |
105 | u32 *p = NULL; | 105 | u32 *p = NULL; |
106 | 106 | ||
107 | if (!(rt->dst.flags & DST_HOST)) | ||
108 | return NULL; | ||
109 | |||
107 | if (!rt->rt6i_peer) | 110 | if (!rt->rt6i_peer) |
108 | rt6_bind_peer(rt, 1); | 111 | rt6_bind_peer(rt, 1); |
109 | 112 | ||
@@ -241,7 +244,9 @@ static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops, | |||
241 | { | 244 | { |
242 | struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, flags); | 245 | struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, flags); |
243 | 246 | ||
244 | memset(&rt->rt6i_table, 0, sizeof(*rt) - sizeof(struct dst_entry)); | 247 | if (rt != NULL) |
248 | memset(&rt->rt6i_table, 0, | ||
249 | sizeof(*rt) - sizeof(struct dst_entry)); | ||
245 | 250 | ||
246 | return rt; | 251 | return rt; |
247 | } | 252 | } |
@@ -252,6 +257,9 @@ static void ip6_dst_destroy(struct dst_entry *dst) | |||
252 | struct inet6_dev *idev = rt->rt6i_idev; | 257 | struct inet6_dev *idev = rt->rt6i_idev; |
253 | struct inet_peer *peer = rt->rt6i_peer; | 258 | struct inet_peer *peer = rt->rt6i_peer; |
254 | 259 | ||
260 | if (!(rt->dst.flags & DST_HOST)) | ||
261 | dst_destroy_metrics_generic(dst); | ||
262 | |||
255 | if (idev != NULL) { | 263 | if (idev != NULL) { |
256 | rt->rt6i_idev = NULL; | 264 | rt->rt6i_idev = NULL; |
257 | in6_dev_put(idev); | 265 | in6_dev_put(idev); |
@@ -723,9 +731,7 @@ static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort, | |||
723 | ipv6_addr_copy(&rt->rt6i_gateway, daddr); | 731 | ipv6_addr_copy(&rt->rt6i_gateway, daddr); |
724 | } | 732 | } |
725 | 733 | ||
726 | rt->rt6i_dst.plen = 128; | ||
727 | rt->rt6i_flags |= RTF_CACHE; | 734 | rt->rt6i_flags |= RTF_CACHE; |
728 | rt->dst.flags |= DST_HOST; | ||
729 | 735 | ||
730 | #ifdef CONFIG_IPV6_SUBTREES | 736 | #ifdef CONFIG_IPV6_SUBTREES |
731 | if (rt->rt6i_src.plen && saddr) { | 737 | if (rt->rt6i_src.plen && saddr) { |
@@ -775,9 +781,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, | |||
775 | struct rt6_info *rt = ip6_rt_copy(ort, daddr); | 781 | struct rt6_info *rt = ip6_rt_copy(ort, daddr); |
776 | 782 | ||
777 | if (rt) { | 783 | if (rt) { |
778 | rt->rt6i_dst.plen = 128; | ||
779 | rt->rt6i_flags |= RTF_CACHE; | 784 | rt->rt6i_flags |= RTF_CACHE; |
780 | rt->dst.flags |= DST_HOST; | ||
781 | dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour_raw(&ort->dst))); | 785 | dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour_raw(&ort->dst))); |
782 | } | 786 | } |
783 | return rt; | 787 | return rt; |
@@ -1078,12 +1082,15 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
1078 | neigh = NULL; | 1082 | neigh = NULL; |
1079 | } | 1083 | } |
1080 | 1084 | ||
1081 | rt->rt6i_idev = idev; | 1085 | rt->dst.flags |= DST_HOST; |
1086 | rt->dst.output = ip6_output; | ||
1082 | dst_set_neighbour(&rt->dst, neigh); | 1087 | dst_set_neighbour(&rt->dst, neigh); |
1083 | atomic_set(&rt->dst.__refcnt, 1); | 1088 | atomic_set(&rt->dst.__refcnt, 1); |
1084 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); | ||
1085 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); | 1089 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); |
1086 | rt->dst.output = ip6_output; | 1090 | |
1091 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); | ||
1092 | rt->rt6i_dst.plen = 128; | ||
1093 | rt->rt6i_idev = idev; | ||
1087 | 1094 | ||
1088 | spin_lock_bh(&icmp6_dst_lock); | 1095 | spin_lock_bh(&icmp6_dst_lock); |
1089 | rt->dst.next = icmp6_dst_gc_list; | 1096 | rt->dst.next = icmp6_dst_gc_list; |
@@ -1261,6 +1268,14 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1261 | if (rt->rt6i_dst.plen == 128) | 1268 | if (rt->rt6i_dst.plen == 128) |
1262 | rt->dst.flags |= DST_HOST; | 1269 | rt->dst.flags |= DST_HOST; |
1263 | 1270 | ||
1271 | if (!(rt->dst.flags & DST_HOST) && cfg->fc_mx) { | ||
1272 | u32 *metrics = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL); | ||
1273 | if (!metrics) { | ||
1274 | err = -ENOMEM; | ||
1275 | goto out; | ||
1276 | } | ||
1277 | dst_init_metrics(&rt->dst, metrics, 0); | ||
1278 | } | ||
1264 | #ifdef CONFIG_IPV6_SUBTREES | 1279 | #ifdef CONFIG_IPV6_SUBTREES |
1265 | ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len); | 1280 | ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len); |
1266 | rt->rt6i_src.plen = cfg->fc_src_len; | 1281 | rt->rt6i_src.plen = cfg->fc_src_len; |
@@ -1607,9 +1622,6 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src, | |||
1607 | if (on_link) | 1622 | if (on_link) |
1608 | nrt->rt6i_flags &= ~RTF_GATEWAY; | 1623 | nrt->rt6i_flags &= ~RTF_GATEWAY; |
1609 | 1624 | ||
1610 | nrt->rt6i_dst.plen = 128; | ||
1611 | nrt->dst.flags |= DST_HOST; | ||
1612 | |||
1613 | ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key); | 1625 | ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key); |
1614 | dst_set_neighbour(&nrt->dst, neigh_clone(neigh)); | 1626 | dst_set_neighbour(&nrt->dst, neigh_clone(neigh)); |
1615 | 1627 | ||
@@ -1754,9 +1766,10 @@ static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, | |||
1754 | if (rt) { | 1766 | if (rt) { |
1755 | rt->dst.input = ort->dst.input; | 1767 | rt->dst.input = ort->dst.input; |
1756 | rt->dst.output = ort->dst.output; | 1768 | rt->dst.output = ort->dst.output; |
1769 | rt->dst.flags |= DST_HOST; | ||
1757 | 1770 | ||
1758 | ipv6_addr_copy(&rt->rt6i_dst.addr, dest); | 1771 | ipv6_addr_copy(&rt->rt6i_dst.addr, dest); |
1759 | rt->rt6i_dst.plen = ort->rt6i_dst.plen; | 1772 | rt->rt6i_dst.plen = 128; |
1760 | dst_copy_metrics(&rt->dst, &ort->dst); | 1773 | dst_copy_metrics(&rt->dst, &ort->dst); |
1761 | rt->dst.error = ort->dst.error; | 1774 | rt->dst.error = ort->dst.error; |
1762 | rt->rt6i_idev = ort->rt6i_idev; | 1775 | rt->rt6i_idev = ort->rt6i_idev; |