aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-01-26 15:22:32 -0500
committerDavid S. Miller <davem@davemloft.net>2012-01-26 15:22:32 -0500
commit39232973b779ab0c02cb6dcd8f819b7cb0fcd09a (patch)
tree02713ba159c04960e7b158c70e994b56c11ae20b
parent09e9b813d34d9a09d64a64580a9959d8bae1f4f5 (diff)
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.c5
-rw-r--r--net/ipv6/route.c16
2 files changed, 20 insertions, 1 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index bcacf54e5418..4eeb8ce856e2 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
1117 static const __be32 inaddr_any = 0; 1117 static const __be32 inaddr_any = 0;
1118 struct net_device *dev = dst->dev; 1118 struct net_device *dev = dst->dev;
1119 const __be32 *pkey = daddr; 1119 const __be32 *pkey = daddr;
1120 const struct rtable *rt;
1120 struct neighbour *n; 1121 struct neighbour *n;
1121 1122
1123 rt = (const struct rtable *) dst;
1124
1122 if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) 1125 if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
1123 pkey = &inaddr_any; 1126 pkey = &inaddr_any;
1127 else if (rt->rt_gateway)
1128 pkey = (const __be32 *) &rt->rt_gateway;
1124 1129
1125 n = __ipv4_neigh_lookup(&arp_tbl, dev, *(__force u32 *)pkey); 1130 n = __ipv4_neigh_lookup(&arp_tbl, dev, *(__force u32 *)pkey);
1126 if (n) 1131 if (n)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 8c2e3ab58f2a..7d7f30697ead 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)
121 return p; 121 return p;
122} 122}
123 123
124static inline const void *choose_neigh_daddr(struct rt6_info *rt, const void *daddr)
125{
126 struct in6_addr *p = &rt->rt6i_gateway;
127
128 if (p->s6_addr32[0] | p->s6_addr32[1] |
129 p->s6_addr32[2] | p->s6_addr32[3])
130 return (const void *) p;
131 return daddr;
132}
133
124static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const void *daddr) 134static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const void *daddr)
125{ 135{
126 struct neighbour *n = __ipv6_neigh_lookup(&nd_tbl, dst->dev, daddr); 136 struct rt6_info *rt = (struct rt6_info *) dst;
137 struct neighbour *n;
138
139 daddr = choose_neigh_daddr(rt, daddr);
140 n = __ipv6_neigh_lookup(&nd_tbl, dst->dev, daddr);
127 if (n) 141 if (n)
128 return n; 142 return n;
129 return neigh_create(&nd_tbl, daddr, dst->dev); 143 return neigh_create(&nd_tbl, daddr, dst->dev);