diff options
author | David S. Miller <davem@davemloft.net> | 2012-07-03 00:52:24 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-07-05 04:04:01 -0400 |
commit | f894cbf847c9bea1955095bf37aca6c050553167 (patch) | |
tree | 9cc63b36c2d299bba95ea90213f4a9ef0ae433d6 /net/ipv4/route.c | |
parent | 5110effee8fde2edfacac9cd12a9960ab2dc39ea (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.c | 14 |
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 | ||
191 | static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr); | 191 | static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, |
192 | struct sk_buff *skb, | ||
193 | const void *daddr); | ||
192 | 194 | ||
193 | static struct dst_ops ipv4_dst_ops = { | 195 | static 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 | ||
1091 | static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr) | 1093 | static 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 | ||
1108 | static int rt_bind_neighbour(struct rtable *rt) | 1114 | static 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; |