aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/route.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-07-03 00:52:24 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-05 04:04:01 -0400
commitf894cbf847c9bea1955095bf37aca6c050553167 (patch)
tree9cc63b36c2d299bba95ea90213f4a9ef0ae433d6 /net/ipv4/route.c
parent5110effee8fde2edfacac9cd12a9960ab2dc39ea (diff)
net: Add optional SKB arg to dst_ops->neigh_lookup().
Causes the handler to use the daddr in the ipv4/ipv6 header when the route gateway is unspecified (local subnet). Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r--net/ipv4/route.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index bae36386e722..7453dfcdb439 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -188,7 +188,9 @@ static u32 *ipv4_cow_metrics(struct dst_entry *dst, unsigned long old)
188 return p; 188 return p;
189} 189}
190 190
191static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr); 191static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
192 struct sk_buff *skb,
193 const void *daddr);
192 194
193static struct dst_ops ipv4_dst_ops = { 195static struct dst_ops ipv4_dst_ops = {
194 .family = AF_INET, 196 .family = AF_INET,
@@ -1088,7 +1090,9 @@ static int slow_chain_length(const struct rtable *head)
1088 return length >> FRACT_BITS; 1090 return length >> FRACT_BITS;
1089} 1091}
1090 1092
1091static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr) 1093static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
1094 struct sk_buff *skb,
1095 const void *daddr)
1092{ 1096{
1093 struct net_device *dev = dst->dev; 1097 struct net_device *dev = dst->dev;
1094 const __be32 *pkey = daddr; 1098 const __be32 *pkey = daddr;
@@ -1098,6 +1102,8 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const vo
1098 rt = (const struct rtable *) dst; 1102 rt = (const struct rtable *) dst;
1099 if (rt->rt_gateway) 1103 if (rt->rt_gateway)
1100 pkey = (const __be32 *) &rt->rt_gateway; 1104 pkey = (const __be32 *) &rt->rt_gateway;
1105 else if (skb)
1106 pkey = &ip_hdr(skb)->daddr;
1101 1107
1102 n = __ipv4_neigh_lookup(dev, *(__force u32 *)pkey); 1108 n = __ipv4_neigh_lookup(dev, *(__force u32 *)pkey);
1103 if (n) 1109 if (n)
@@ -1107,7 +1113,7 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const vo
1107 1113
1108static int rt_bind_neighbour(struct rtable *rt) 1114static int rt_bind_neighbour(struct rtable *rt)
1109{ 1115{
1110 struct neighbour *n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway); 1116 struct neighbour *n = ipv4_neigh_lookup(&rt->dst, NULL, &rt->rt_gateway);
1111 if (IS_ERR(n)) 1117 if (IS_ERR(n))
1112 return PTR_ERR(n); 1118 return PTR_ERR(n);
1113 dst_set_neighbour(&rt->dst, n); 1119 dst_set_neighbour(&rt->dst, n);
@@ -1388,7 +1394,7 @@ static void check_peer_redir(struct dst_entry *dst, struct inet_peer *peer)
1388 1394
1389 rt->rt_gateway = peer->redirect_learned.a4; 1395 rt->rt_gateway = peer->redirect_learned.a4;
1390 1396
1391 n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway); 1397 n = ipv4_neigh_lookup(&rt->dst, NULL, &rt->rt_gateway);
1392 if (IS_ERR(n)) { 1398 if (IS_ERR(n)) {
1393 rt->rt_gateway = orig_gw; 1399 rt->rt_gateway = orig_gw;
1394 return; 1400 return;