Commit 39232973 authored by David S. Miller's avatar David S. Miller

ipv4/ipv6: Prepare for new route gateway semantics.

In the future the ipv4/ipv6 route gateway will take on two types
of values:

1) INADDR_ANY/IN6ADDR_ANY, for local network routes, and in this case
   the neighbour must be obtained using the destination address in
   ipv4/ipv6 header as the lookup key.

2) Everything else, the actual nexthop route address.

So if the gateway is not inaddr-any we use it, otherwise we must use
the packet's destination address.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 09e9b813
...@@ -1117,10 +1117,15 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const vo ...@@ -1117,10 +1117,15 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const vo
static const __be32 inaddr_any = 0; static const __be32 inaddr_any = 0;
struct net_device *dev = dst->dev; struct net_device *dev = dst->dev;
const __be32 *pkey = daddr; const __be32 *pkey = daddr;
const struct rtable *rt;
struct neighbour *n; struct neighbour *n;
rt = (const struct rtable *) dst;
if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
pkey = &inaddr_any; pkey = &inaddr_any;
else if (rt->rt_gateway)
pkey = (const __be32 *) &rt->rt_gateway;
n = __ipv4_neigh_lookup(&arp_tbl, dev, *(__force u32 *)pkey); n = __ipv4_neigh_lookup(&arp_tbl, dev, *(__force u32 *)pkey);
if (n) if (n)
......
...@@ -121,9 +121,23 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) ...@@ -121,9 +121,23 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
return p; 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) 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) if (n)
return n; return n;
return neigh_create(&nd_tbl, daddr, dst->dev); return neigh_create(&nd_tbl, daddr, dst->dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment