diff options
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r-- | net/ipv4/route.c | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 1d4cd3b4fd69..33137307d52a 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -185,6 +185,8 @@ static u32 *ipv4_cow_metrics(struct dst_entry *dst, unsigned long old) | |||
185 | return p; | 185 | return p; |
186 | } | 186 | } |
187 | 187 | ||
188 | static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr); | ||
189 | |||
188 | static struct dst_ops ipv4_dst_ops = { | 190 | static struct dst_ops ipv4_dst_ops = { |
189 | .family = AF_INET, | 191 | .family = AF_INET, |
190 | .protocol = cpu_to_be16(ETH_P_IP), | 192 | .protocol = cpu_to_be16(ETH_P_IP), |
@@ -199,6 +201,7 @@ static struct dst_ops ipv4_dst_ops = { | |||
199 | .link_failure = ipv4_link_failure, | 201 | .link_failure = ipv4_link_failure, |
200 | .update_pmtu = ip_rt_update_pmtu, | 202 | .update_pmtu = ip_rt_update_pmtu, |
201 | .local_out = __ip_local_out, | 203 | .local_out = __ip_local_out, |
204 | .neigh_lookup = ipv4_neigh_lookup, | ||
202 | }; | 205 | }; |
203 | 206 | ||
204 | #define ECN_OR_COST(class) TC_PRIO_##class | 207 | #define ECN_OR_COST(class) TC_PRIO_##class |
@@ -1008,22 +1011,30 @@ static int slow_chain_length(const struct rtable *head) | |||
1008 | return length >> FRACT_BITS; | 1011 | return length >> FRACT_BITS; |
1009 | } | 1012 | } |
1010 | 1013 | ||
1011 | static int rt_bind_neighbour(struct rtable *rt) | 1014 | static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr) |
1012 | { | 1015 | { |
1013 | static const __be32 inaddr_any = 0; | ||
1014 | struct net_device *dev = rt->dst.dev; | ||
1015 | struct neigh_table *tbl = &arp_tbl; | 1016 | struct neigh_table *tbl = &arp_tbl; |
1016 | const __be32 *nexthop; | 1017 | static const __be32 inaddr_any = 0; |
1018 | struct net_device *dev = dst->dev; | ||
1019 | const __be32 *pkey = daddr; | ||
1017 | struct neighbour *n; | 1020 | struct neighbour *n; |
1018 | 1021 | ||
1019 | #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) | 1022 | #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) |
1020 | if (dev->type == ARPHRD_ATM) | 1023 | if (dev->type == ARPHRD_ATM) |
1021 | tbl = clip_tbl_hook; | 1024 | tbl = clip_tbl_hook; |
1022 | #endif | 1025 | #endif |
1023 | nexthop = &rt->rt_gateway; | ||
1024 | if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) | 1026 | if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) |
1025 | nexthop = &inaddr_any; | 1027 | pkey = &inaddr_any; |
1026 | n = ipv4_neigh_lookup(tbl, dev, nexthop); | 1028 | |
1029 | n = __ipv4_neigh_lookup(tbl, dev, *(__force u32 *)pkey); | ||
1030 | if (n) | ||
1031 | return n; | ||
1032 | return neigh_create(tbl, pkey, dev); | ||
1033 | } | ||
1034 | |||
1035 | static int rt_bind_neighbour(struct rtable *rt) | ||
1036 | { | ||
1037 | struct neighbour *n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway); | ||
1027 | if (IS_ERR(n)) | 1038 | if (IS_ERR(n)) |
1028 | return PTR_ERR(n); | 1039 | return PTR_ERR(n); |
1029 | dst_set_neighbour(&rt->dst, n); | 1040 | dst_set_neighbour(&rt->dst, n); |
@@ -2734,6 +2745,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = { | |||
2734 | .default_advmss = ipv4_default_advmss, | 2745 | .default_advmss = ipv4_default_advmss, |
2735 | .update_pmtu = ipv4_rt_blackhole_update_pmtu, | 2746 | .update_pmtu = ipv4_rt_blackhole_update_pmtu, |
2736 | .cow_metrics = ipv4_rt_blackhole_cow_metrics, | 2747 | .cow_metrics = ipv4_rt_blackhole_cow_metrics, |
2748 | .neigh_lookup = ipv4_neigh_lookup, | ||
2737 | }; | 2749 | }; |
2738 | 2750 | ||
2739 | struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig) | 2751 | struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig) |