|
@@ -104,6 +104,9 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
|
|
struct inet_peer *peer;
|
|
struct inet_peer *peer;
|
|
u32 *p = NULL;
|
|
u32 *p = NULL;
|
|
|
|
|
|
|
|
+ if (!(rt->dst.flags & DST_HOST))
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
if (!rt->rt6i_peer)
|
|
if (!rt->rt6i_peer)
|
|
rt6_bind_peer(rt, 1);
|
|
rt6_bind_peer(rt, 1);
|
|
|
|
|
|
@@ -252,6 +255,9 @@ static void ip6_dst_destroy(struct dst_entry *dst)
|
|
struct inet6_dev *idev = rt->rt6i_idev;
|
|
struct inet6_dev *idev = rt->rt6i_idev;
|
|
struct inet_peer *peer = rt->rt6i_peer;
|
|
struct inet_peer *peer = rt->rt6i_peer;
|
|
|
|
|
|
|
|
+ if (!(rt->dst.flags & DST_HOST))
|
|
|
|
+ dst_destroy_metrics_generic(dst);
|
|
|
|
+
|
|
if (idev != NULL) {
|
|
if (idev != NULL) {
|
|
rt->rt6i_idev = NULL;
|
|
rt->rt6i_idev = NULL;
|
|
in6_dev_put(idev);
|
|
in6_dev_put(idev);
|
|
@@ -723,9 +729,7 @@ static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort,
|
|
ipv6_addr_copy(&rt->rt6i_gateway, daddr);
|
|
ipv6_addr_copy(&rt->rt6i_gateway, daddr);
|
|
}
|
|
}
|
|
|
|
|
|
- rt->rt6i_dst.plen = 128;
|
|
|
|
rt->rt6i_flags |= RTF_CACHE;
|
|
rt->rt6i_flags |= RTF_CACHE;
|
|
- rt->dst.flags |= DST_HOST;
|
|
|
|
|
|
|
|
#ifdef CONFIG_IPV6_SUBTREES
|
|
#ifdef CONFIG_IPV6_SUBTREES
|
|
if (rt->rt6i_src.plen && saddr) {
|
|
if (rt->rt6i_src.plen && saddr) {
|
|
@@ -775,9 +779,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort,
|
|
struct rt6_info *rt = ip6_rt_copy(ort, daddr);
|
|
struct rt6_info *rt = ip6_rt_copy(ort, daddr);
|
|
|
|
|
|
if (rt) {
|
|
if (rt) {
|
|
- rt->rt6i_dst.plen = 128;
|
|
|
|
rt->rt6i_flags |= RTF_CACHE;
|
|
rt->rt6i_flags |= RTF_CACHE;
|
|
- rt->dst.flags |= DST_HOST;
|
|
|
|
dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour_raw(&ort->dst)));
|
|
dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour_raw(&ort->dst)));
|
|
}
|
|
}
|
|
return rt;
|
|
return rt;
|
|
@@ -1078,12 +1080,15 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
|
|
neigh = NULL;
|
|
neigh = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
- rt->rt6i_idev = idev;
|
|
|
|
|
|
+ rt->dst.flags |= DST_HOST;
|
|
|
|
+ rt->dst.output = ip6_output;
|
|
dst_set_neighbour(&rt->dst, neigh);
|
|
dst_set_neighbour(&rt->dst, neigh);
|
|
atomic_set(&rt->dst.__refcnt, 1);
|
|
atomic_set(&rt->dst.__refcnt, 1);
|
|
- ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
|
|
|
|
dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255);
|
|
dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255);
|
|
- rt->dst.output = ip6_output;
|
|
|
|
|
|
+
|
|
|
|
+ ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
|
|
|
|
+ rt->rt6i_dst.plen = 128;
|
|
|
|
+ rt->rt6i_idev = idev;
|
|
|
|
|
|
spin_lock_bh(&icmp6_dst_lock);
|
|
spin_lock_bh(&icmp6_dst_lock);
|
|
rt->dst.next = icmp6_dst_gc_list;
|
|
rt->dst.next = icmp6_dst_gc_list;
|
|
@@ -1261,6 +1266,14 @@ int ip6_route_add(struct fib6_config *cfg)
|
|
if (rt->rt6i_dst.plen == 128)
|
|
if (rt->rt6i_dst.plen == 128)
|
|
rt->dst.flags |= DST_HOST;
|
|
rt->dst.flags |= DST_HOST;
|
|
|
|
|
|
|
|
+ if (!(rt->dst.flags & DST_HOST) && cfg->fc_mx) {
|
|
|
|
+ u32 *metrics = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL);
|
|
|
|
+ if (!metrics) {
|
|
|
|
+ err = -ENOMEM;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ dst_init_metrics(&rt->dst, metrics, 0);
|
|
|
|
+ }
|
|
#ifdef CONFIG_IPV6_SUBTREES
|
|
#ifdef CONFIG_IPV6_SUBTREES
|
|
ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len);
|
|
ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len);
|
|
rt->rt6i_src.plen = cfg->fc_src_len;
|
|
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,
|
|
if (on_link)
|
|
if (on_link)
|
|
nrt->rt6i_flags &= ~RTF_GATEWAY;
|
|
nrt->rt6i_flags &= ~RTF_GATEWAY;
|
|
|
|
|
|
- nrt->rt6i_dst.plen = 128;
|
|
|
|
- nrt->dst.flags |= DST_HOST;
|
|
|
|
-
|
|
|
|
ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key);
|
|
ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key);
|
|
dst_set_neighbour(&nrt->dst, neigh_clone(neigh));
|
|
dst_set_neighbour(&nrt->dst, neigh_clone(neigh));
|
|
|
|
|
|
@@ -1754,9 +1764,10 @@ static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort,
|
|
if (rt) {
|
|
if (rt) {
|
|
rt->dst.input = ort->dst.input;
|
|
rt->dst.input = ort->dst.input;
|
|
rt->dst.output = ort->dst.output;
|
|
rt->dst.output = ort->dst.output;
|
|
|
|
+ rt->dst.flags |= DST_HOST;
|
|
|
|
|
|
ipv6_addr_copy(&rt->rt6i_dst.addr, dest);
|
|
ipv6_addr_copy(&rt->rt6i_dst.addr, dest);
|
|
- rt->rt6i_dst.plen = ort->rt6i_dst.plen;
|
|
|
|
|
|
+ rt->rt6i_dst.plen = 128;
|
|
dst_copy_metrics(&rt->dst, &ort->dst);
|
|
dst_copy_metrics(&rt->dst, &ort->dst);
|
|
rt->dst.error = ort->dst.error;
|
|
rt->dst.error = ort->dst.error;
|
|
rt->rt6i_idev = ort->rt6i_idev;
|
|
rt->rt6i_idev = ort->rt6i_idev;
|