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/ipv6/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/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 14 |
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 | ||
123 | static inline const void *choose_neigh_daddr(struct rt6_info *rt, const void *daddr) | 123 | static 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 | ||
132 | static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const void *daddr) | 136 | static 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); |