aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/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/ipv6/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/ipv6/route.c')
-rw-r--r--net/ipv6/route.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index c518e4ec0cea..4b581c675bb2 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -120,21 +120,27 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
120 return p; 120 return p;
121} 121}
122 122
123static inline const void *choose_neigh_daddr(struct rt6_info *rt, const void *daddr) 123static inline const void *choose_neigh_daddr(struct rt6_info *rt,
124 struct sk_buff *skb,
125 const void *daddr)
124{ 126{
125 struct in6_addr *p = &rt->rt6i_gateway; 127 struct in6_addr *p = &rt->rt6i_gateway;
126 128
127 if (!ipv6_addr_any(p)) 129 if (!ipv6_addr_any(p))
128 return (const void *) p; 130 return (const void *) p;
131 else if (skb)
132 return &ipv6_hdr(skb)->daddr;
129 return daddr; 133 return daddr;
130} 134}
131 135
132static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const void *daddr) 136static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst,
137 struct sk_buff *skb,
138 const void *daddr)
133{ 139{
134 struct rt6_info *rt = (struct rt6_info *) dst; 140 struct rt6_info *rt = (struct rt6_info *) dst;
135 struct neighbour *n; 141 struct neighbour *n;
136 142
137 daddr = choose_neigh_daddr(rt, daddr); 143 daddr = choose_neigh_daddr(rt, skb, daddr);
138 n = __ipv6_neigh_lookup(&nd_tbl, dst->dev, daddr); 144 n = __ipv6_neigh_lookup(&nd_tbl, dst->dev, daddr);
139 if (n) 145 if (n)
140 return n; 146 return n;
@@ -1162,7 +1168,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
1162 if (neigh) 1168 if (neigh)
1163 neigh_hold(neigh); 1169 neigh_hold(neigh);
1164 else { 1170 else {
1165 neigh = ip6_neigh_lookup(&rt->dst, &fl6->daddr); 1171 neigh = ip6_neigh_lookup(&rt->dst, NULL, &fl6->daddr);
1166 if (IS_ERR(neigh)) { 1172 if (IS_ERR(neigh)) {
1167 in6_dev_put(idev); 1173 in6_dev_put(idev);
1168 dst_free(&rt->dst); 1174 dst_free(&rt->dst);