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 | |
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')
-rw-r--r-- | net/bridge/br_netfilter.c | 4 | ||||
-rw-r--r-- | net/decnet/dn_route.c | 8 | ||||
-rw-r--r-- | net/ipv4/route.c | 14 | ||||
-rw-r--r-- | net/ipv6/route.c | 14 | ||||
-rw-r--r-- | net/xfrm/xfrm_policy.c | 6 |
5 files changed, 33 insertions, 13 deletions
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 | ||
123 | static struct neighbour *fake_neigh_lookup(const struct dst_entry *dst, const void *daddr) | 123 | static 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 *); | |||
117 | static struct dst_entry *dn_dst_negative_advice(struct dst_entry *); | 117 | static struct dst_entry *dn_dst_negative_advice(struct dst_entry *); |
118 | static void dn_dst_link_failure(struct sk_buff *); | 118 | static void dn_dst_link_failure(struct sk_buff *); |
119 | static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu); | 119 | static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu); |
120 | static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst, const void *daddr); | 120 | static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst, |
121 | struct sk_buff *skb, | ||
122 | const void *daddr); | ||
121 | static int dn_route_input(struct sk_buff *); | 123 | static int dn_route_input(struct sk_buff *); |
122 | static void dn_run_flush(unsigned long dummy); | 124 | static 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 | ||
831 | static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst, const void *daddr) | 833 | static 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 | ||
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; |
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); |
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 | ||
2407 | static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst, const void *daddr) | 2407 | static 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 | ||
2412 | int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) | 2414 | int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) |