aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--include/net/dst.h8
-rw-r--r--include/net/dst_ops.h4
-rw-r--r--net/bridge/br_netfilter.c4
-rw-r--r--net/decnet/dn_route.c8
-rw-r--r--net/ipv4/route.c14
-rw-r--r--net/ipv6/route.c14
-rw-r--r--net/xfrm/xfrm_policy.c6
7 files changed, 43 insertions, 15 deletions
diff --git a/include/net/dst.h b/include/net/dst.h
index 84e7a3ff968d..295a70547e7d 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -420,7 +420,13 @@ static inline int dst_neigh_output(struct dst_entry *dst, struct neighbour *n,
420 420
421static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr) 421static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr)
422{ 422{
423 return dst->ops->neigh_lookup(dst, daddr); 423 return dst->ops->neigh_lookup(dst, NULL, daddr);
424}
425
426static inline struct neighbour *dst_neigh_lookup_skb(const struct dst_entry *dst,
427 struct sk_buff *skb)
428{
429 return dst->ops->neigh_lookup(dst, skb, NULL);
424} 430}
425 431
426static inline void dst_link_failure(struct sk_buff *skb) 432static inline void dst_link_failure(struct sk_buff *skb)
diff --git a/include/net/dst_ops.h b/include/net/dst_ops.h
index 3682a0a076c1..4badc86e45d1 100644
--- a/include/net/dst_ops.h
+++ b/include/net/dst_ops.h
@@ -26,7 +26,9 @@ struct dst_ops {
26 void (*link_failure)(struct sk_buff *); 26 void (*link_failure)(struct sk_buff *);
27 void (*update_pmtu)(struct dst_entry *dst, u32 mtu); 27 void (*update_pmtu)(struct dst_entry *dst, u32 mtu);
28 int (*local_out)(struct sk_buff *skb); 28 int (*local_out)(struct sk_buff *skb);
29 struct neighbour * (*neigh_lookup)(const struct dst_entry *dst, const void *daddr); 29 struct neighbour * (*neigh_lookup)(const struct dst_entry *dst,
30 struct sk_buff *skb,
31 const void *daddr);
30 32
31 struct kmem_cache *kmem_cachep; 33 struct kmem_cache *kmem_cachep;
32 34
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 20fa719889ee..4378775432b6 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -120,7 +120,9 @@ static u32 *fake_cow_metrics(struct dst_entry *dst, unsigned long old)
120 return NULL; 120 return NULL;
121} 121}
122 122
123static struct neighbour *fake_neigh_lookup(const struct dst_entry *dst, const void *daddr) 123static struct neighbour *fake_neigh_lookup(const struct dst_entry *dst,
124 struct sk_buff *skb,
125 const void *daddr)
124{ 126{
125 return NULL; 127 return NULL;
126} 128}
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 2493ed5bfecd..60e4c6e1bac0 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -117,7 +117,9 @@ static void dn_dst_destroy(struct dst_entry *);
117static struct dst_entry *dn_dst_negative_advice(struct dst_entry *); 117static struct dst_entry *dn_dst_negative_advice(struct dst_entry *);
118static void dn_dst_link_failure(struct sk_buff *); 118static void dn_dst_link_failure(struct sk_buff *);
119static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu); 119static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu);
120static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst, const void *daddr); 120static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst,
121 struct sk_buff *skb,
122 const void *daddr);
121static int dn_route_input(struct sk_buff *); 123static int dn_route_input(struct sk_buff *);
122static void dn_run_flush(unsigned long dummy); 124static void dn_run_flush(unsigned long dummy);
123 125
@@ -828,7 +830,9 @@ static unsigned int dn_dst_mtu(const struct dst_entry *dst)
828 return mtu ? : dst->dev->mtu; 830 return mtu ? : dst->dev->mtu;
829} 831}
830 832
831static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst, const void *daddr) 833static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst,
834 struct sk_buff *skb,
835 const void *daddr)
832{ 836{
833 return __neigh_lookup_errno(&dn_neigh_table, daddr, dst->dev); 837 return __neigh_lookup_errno(&dn_neigh_table, daddr, dst->dev);
834} 838}
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;
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);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index ccfbd328a69d..a28a3f972d5b 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -2404,9 +2404,11 @@ static unsigned int xfrm_mtu(const struct dst_entry *dst)
2404 return mtu ? : dst_mtu(dst->path); 2404 return mtu ? : dst_mtu(dst->path);
2405} 2405}
2406 2406
2407static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst, const void *daddr) 2407static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst,
2408 struct sk_buff *skb,
2409 const void *daddr)
2408{ 2410{
2409 return dst_neigh_lookup(dst->path, daddr); 2411 return dst->path->ops->neigh_lookup(dst, skb, daddr);
2410} 2412}
2411 2413
2412int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) 2414int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)