ipv4/ipv6: Prepare for new route gateway semantics.
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / ipv6 / route.c
index 07361dfa80852cbbe4db66027f8da5ef13ade4c1..7d7f30697eadee6773272c5e68ae006b21e38511 100644 (file)
@@ -121,9 +121,23 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
        return p;
 }
 
+static inline const void *choose_neigh_daddr(struct rt6_info *rt, const void *daddr)
+{
+       struct in6_addr *p = &rt->rt6i_gateway;
+
+       if (p->s6_addr32[0] | p->s6_addr32[1] |
+           p->s6_addr32[2] | p->s6_addr32[3])
+               return (const void *) p;
+       return daddr;
+}
+
 static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const void *daddr)
 {
-       struct neighbour *n = __ipv6_neigh_lookup(&nd_tbl, dst->dev, daddr);
+       struct rt6_info *rt = (struct rt6_info *) dst;
+       struct neighbour *n;
+
+       daddr = choose_neigh_daddr(rt, daddr);
+       n = __ipv6_neigh_lookup(&nd_tbl, dst->dev, daddr);
        if (n)
                return n;
        return neigh_create(&nd_tbl, daddr, dst->dev);
@@ -1091,6 +1105,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
        else {
                neigh = ip6_neigh_lookup(&rt->dst, &fl6->daddr);
                if (IS_ERR(neigh)) {
+                       in6_dev_put(idev);
                        dst_free(&rt->dst);
                        return ERR_CAST(neigh);
                }