diff options
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 33 |
1 files changed, 22 insertions, 11 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 9e69eb0ec6dd..1250f9020670 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 | ||
@@ -252,6 +255,9 @@ static void ip6_dst_destroy(struct dst_entry *dst) | |||
252 | struct inet6_dev *idev = rt->rt6i_idev; | 255 | struct inet6_dev *idev = rt->rt6i_idev; |
253 | struct inet_peer *peer = rt->rt6i_peer; | 256 | struct inet_peer *peer = rt->rt6i_peer; |
254 | 257 | ||
258 | if (!(rt->dst.flags & DST_HOST)) | ||
259 | dst_destroy_metrics_generic(dst); | ||
260 | |||
255 | if (idev != NULL) { | 261 | if (idev != NULL) { |
256 | rt->rt6i_idev = NULL; | 262 | rt->rt6i_idev = NULL; |
257 | in6_dev_put(idev); | 263 | in6_dev_put(idev); |
@@ -723,9 +729,7 @@ static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort, | |||
723 | ipv6_addr_copy(&rt->rt6i_gateway, daddr); | 729 | ipv6_addr_copy(&rt->rt6i_gateway, daddr); |
724 | } | 730 | } |
725 | 731 | ||
726 | rt->rt6i_dst.plen = 128; | ||
727 | rt->rt6i_flags |= RTF_CACHE; | 732 | rt->rt6i_flags |= RTF_CACHE; |
728 | rt->dst.flags |= DST_HOST; | ||
729 | 733 | ||
730 | #ifdef CONFIG_IPV6_SUBTREES | 734 | #ifdef CONFIG_IPV6_SUBTREES |
731 | if (rt->rt6i_src.plen && saddr) { | 735 | if (rt->rt6i_src.plen && saddr) { |
@@ -775,9 +779,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, | |||
775 | struct rt6_info *rt = ip6_rt_copy(ort, daddr); | 779 | struct rt6_info *rt = ip6_rt_copy(ort, daddr); |
776 | 780 | ||
777 | if (rt) { | 781 | if (rt) { |
778 | rt->rt6i_dst.plen = 128; | ||
779 | rt->rt6i_flags |= RTF_CACHE; | 782 | 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))); | 783 | dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour_raw(&ort->dst))); |
782 | } | 784 | } |
783 | return rt; | 785 | return rt; |
@@ -1078,12 +1080,15 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
1078 | neigh = NULL; | 1080 | neigh = NULL; |
1079 | } | 1081 | } |
1080 | 1082 | ||
1081 | rt->rt6i_idev = idev; | 1083 | rt->dst.flags |= DST_HOST; |
1084 | rt->dst.output = ip6_output; | ||
1082 | dst_set_neighbour(&rt->dst, neigh); | 1085 | dst_set_neighbour(&rt->dst, neigh); |
1083 | atomic_set(&rt->dst.__refcnt, 1); | 1086 | atomic_set(&rt->dst.__refcnt, 1); |
1084 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); | ||
1085 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); | 1087 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); |
1086 | rt->dst.output = ip6_output; | 1088 | |
1089 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); | ||
1090 | rt->rt6i_dst.plen = 128; | ||
1091 | rt->rt6i_idev = idev; | ||
1087 | 1092 | ||
1088 | spin_lock_bh(&icmp6_dst_lock); | 1093 | spin_lock_bh(&icmp6_dst_lock); |
1089 | rt->dst.next = icmp6_dst_gc_list; | 1094 | rt->dst.next = icmp6_dst_gc_list; |
@@ -1261,6 +1266,14 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1261 | if (rt->rt6i_dst.plen == 128) | 1266 | if (rt->rt6i_dst.plen == 128) |
1262 | rt->dst.flags |= DST_HOST; | 1267 | rt->dst.flags |= DST_HOST; |
1263 | 1268 | ||
1269 | if (!(rt->dst.flags & DST_HOST) && cfg->fc_mx) { | ||
1270 | u32 *metrics = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL); | ||
1271 | if (!metrics) { | ||
1272 | err = -ENOMEM; | ||
1273 | goto out; | ||
1274 | } | ||
1275 | dst_init_metrics(&rt->dst, metrics, 0); | ||
1276 | } | ||
1264 | #ifdef CONFIG_IPV6_SUBTREES | 1277 | #ifdef CONFIG_IPV6_SUBTREES |
1265 | ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len); | 1278 | ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len); |
1266 | rt->rt6i_src.plen = cfg->fc_src_len; | 1279 | rt->rt6i_src.plen = cfg->fc_src_len; |
@@ -1607,9 +1620,6 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src, | |||
1607 | if (on_link) | 1620 | if (on_link) |
1608 | nrt->rt6i_flags &= ~RTF_GATEWAY; | 1621 | nrt->rt6i_flags &= ~RTF_GATEWAY; |
1609 | 1622 | ||
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); | 1623 | ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key); |
1614 | dst_set_neighbour(&nrt->dst, neigh_clone(neigh)); | 1624 | dst_set_neighbour(&nrt->dst, neigh_clone(neigh)); |
1615 | 1625 | ||
@@ -1754,9 +1764,10 @@ static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, | |||
1754 | if (rt) { | 1764 | if (rt) { |
1755 | rt->dst.input = ort->dst.input; | 1765 | rt->dst.input = ort->dst.input; |
1756 | rt->dst.output = ort->dst.output; | 1766 | rt->dst.output = ort->dst.output; |
1767 | rt->dst.flags |= DST_HOST; | ||
1757 | 1768 | ||
1758 | ipv6_addr_copy(&rt->rt6i_dst.addr, dest); | 1769 | ipv6_addr_copy(&rt->rt6i_dst.addr, dest); |
1759 | rt->rt6i_dst.plen = ort->rt6i_dst.plen; | 1770 | rt->rt6i_dst.plen = 128; |
1760 | dst_copy_metrics(&rt->dst, &ort->dst); | 1771 | dst_copy_metrics(&rt->dst, &ort->dst); |
1761 | rt->dst.error = ort->dst.error; | 1772 | rt->dst.error = ort->dst.error; |
1762 | rt->rt6i_idev = ort->rt6i_idev; | 1773 | rt->rt6i_idev = ort->rt6i_idev; |