diff options
author | David S. Miller <davem@davemloft.net> | 2012-01-26 15:22:32 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-01-26 15:22:32 -0500 |
commit | 39232973b779ab0c02cb6dcd8f819b7cb0fcd09a (patch) | |
tree | 02713ba159c04960e7b158c70e994b56c11ae20b | |
parent | 09e9b813d34d9a09d64a64580a9959d8bae1f4f5 (diff) | |
download | linux-3.10-39232973b779ab0c02cb6dcd8f819b7cb0fcd09a.tar.gz linux-3.10-39232973b779ab0c02cb6dcd8f819b7cb0fcd09a.tar.bz2 linux-3.10-39232973b779ab0c02cb6dcd8f819b7cb0fcd09a.zip |
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: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv4/route.c | 5 | ||||
-rw-r--r-- | net/ipv6/route.c | 16 |
2 files changed, 20 insertions, 1 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index bcacf54e541..4eeb8ce856e 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1117,10 +1117,15 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const vo static const __be32 inaddr_any = 0; struct net_device *dev = dst->dev; const __be32 *pkey = daddr; + const struct rtable *rt; struct neighbour *n; + rt = (const struct rtable *) dst; + if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) pkey = &inaddr_any; + else if (rt->rt_gateway) + pkey = (const __be32 *) &rt->rt_gateway; n = __ipv4_neigh_lookup(&arp_tbl, dev, *(__force u32 *)pkey); if (n) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 8c2e3ab58f2..7d7f30697ea 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -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); |