diff options
-rw-r--r-- | net/ipv4/route.c | 35 |
1 files changed, 13 insertions, 22 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 588d971a3ba1..46af62363b8c 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -1310,7 +1310,7 @@ static void rt_del(unsigned hash, struct rtable *rt) | |||
1310 | spin_unlock_bh(rt_hash_lock_addr(hash)); | 1310 | spin_unlock_bh(rt_hash_lock_addr(hash)); |
1311 | } | 1311 | } |
1312 | 1312 | ||
1313 | static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer) | 1313 | static void check_peer_redir(struct dst_entry *dst, struct inet_peer *peer) |
1314 | { | 1314 | { |
1315 | struct rtable *rt = (struct rtable *) dst; | 1315 | struct rtable *rt = (struct rtable *) dst; |
1316 | __be32 orig_gw = rt->rt_gateway; | 1316 | __be32 orig_gw = rt->rt_gateway; |
@@ -1321,21 +1321,19 @@ static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer) | |||
1321 | rt->rt_gateway = peer->redirect_learned.a4; | 1321 | rt->rt_gateway = peer->redirect_learned.a4; |
1322 | 1322 | ||
1323 | n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway); | 1323 | n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway); |
1324 | if (IS_ERR(n)) | 1324 | if (IS_ERR(n)) { |
1325 | return PTR_ERR(n); | 1325 | rt->rt_gateway = orig_gw; |
1326 | return; | ||
1327 | } | ||
1326 | old_n = xchg(&rt->dst._neighbour, n); | 1328 | old_n = xchg(&rt->dst._neighbour, n); |
1327 | if (old_n) | 1329 | if (old_n) |
1328 | neigh_release(old_n); | 1330 | neigh_release(old_n); |
1329 | if (!n || !(n->nud_state & NUD_VALID)) { | 1331 | if (!(n->nud_state & NUD_VALID)) { |
1330 | if (n) | 1332 | neigh_event_send(n, NULL); |
1331 | neigh_event_send(n, NULL); | ||
1332 | rt->rt_gateway = orig_gw; | ||
1333 | return -EAGAIN; | ||
1334 | } else { | 1333 | } else { |
1335 | rt->rt_flags |= RTCF_REDIRECTED; | 1334 | rt->rt_flags |= RTCF_REDIRECTED; |
1336 | call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n); | 1335 | call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n); |
1337 | } | 1336 | } |
1338 | return 0; | ||
1339 | } | 1337 | } |
1340 | 1338 | ||
1341 | /* called in rcu_read_lock() section */ | 1339 | /* called in rcu_read_lock() section */ |
@@ -1693,7 +1691,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
1693 | } | 1691 | } |
1694 | 1692 | ||
1695 | 1693 | ||
1696 | static struct rtable *ipv4_validate_peer(struct rtable *rt) | 1694 | static void ipv4_validate_peer(struct rtable *rt) |
1697 | { | 1695 | { |
1698 | if (rt->rt_peer_genid != rt_peer_genid()) { | 1696 | if (rt->rt_peer_genid != rt_peer_genid()) { |
1699 | struct inet_peer *peer; | 1697 | struct inet_peer *peer; |
@@ -1708,15 +1706,12 @@ static struct rtable *ipv4_validate_peer(struct rtable *rt) | |||
1708 | if (peer->redirect_genid != redirect_genid) | 1706 | if (peer->redirect_genid != redirect_genid) |
1709 | peer->redirect_learned.a4 = 0; | 1707 | peer->redirect_learned.a4 = 0; |
1710 | if (peer->redirect_learned.a4 && | 1708 | if (peer->redirect_learned.a4 && |
1711 | peer->redirect_learned.a4 != rt->rt_gateway) { | 1709 | peer->redirect_learned.a4 != rt->rt_gateway) |
1712 | if (check_peer_redir(&rt->dst, peer)) | 1710 | check_peer_redir(&rt->dst, peer); |
1713 | return NULL; | ||
1714 | } | ||
1715 | } | 1711 | } |
1716 | 1712 | ||
1717 | rt->rt_peer_genid = rt_peer_genid(); | 1713 | rt->rt_peer_genid = rt_peer_genid(); |
1718 | } | 1714 | } |
1719 | return rt; | ||
1720 | } | 1715 | } |
1721 | 1716 | ||
1722 | static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) | 1717 | static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) |
@@ -1725,7 +1720,7 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) | |||
1725 | 1720 | ||
1726 | if (rt_is_expired(rt)) | 1721 | if (rt_is_expired(rt)) |
1727 | return NULL; | 1722 | return NULL; |
1728 | dst = (struct dst_entry *) ipv4_validate_peer(rt); | 1723 | ipv4_validate_peer(rt); |
1729 | return dst; | 1724 | return dst; |
1730 | } | 1725 | } |
1731 | 1726 | ||
@@ -2380,9 +2375,7 @@ int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
2380 | rth->rt_mark == skb->mark && | 2375 | rth->rt_mark == skb->mark && |
2381 | net_eq(dev_net(rth->dst.dev), net) && | 2376 | net_eq(dev_net(rth->dst.dev), net) && |
2382 | !rt_is_expired(rth)) { | 2377 | !rt_is_expired(rth)) { |
2383 | rth = ipv4_validate_peer(rth); | 2378 | ipv4_validate_peer(rth); |
2384 | if (!rth) | ||
2385 | continue; | ||
2386 | if (noref) { | 2379 | if (noref) { |
2387 | dst_use_noref(&rth->dst, jiffies); | 2380 | dst_use_noref(&rth->dst, jiffies); |
2388 | skb_dst_set_noref(skb, &rth->dst); | 2381 | skb_dst_set_noref(skb, &rth->dst); |
@@ -2758,9 +2751,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *flp4) | |||
2758 | (IPTOS_RT_MASK | RTO_ONLINK)) && | 2751 | (IPTOS_RT_MASK | RTO_ONLINK)) && |
2759 | net_eq(dev_net(rth->dst.dev), net) && | 2752 | net_eq(dev_net(rth->dst.dev), net) && |
2760 | !rt_is_expired(rth)) { | 2753 | !rt_is_expired(rth)) { |
2761 | rth = ipv4_validate_peer(rth); | 2754 | ipv4_validate_peer(rth); |
2762 | if (!rth) | ||
2763 | continue; | ||
2764 | dst_use(&rth->dst, jiffies); | 2755 | dst_use(&rth->dst, jiffies); |
2765 | RT_CACHE_STAT_INC(out_hit); | 2756 | RT_CACHE_STAT_INC(out_hit); |
2766 | rcu_read_unlock_bh(); | 2757 | rcu_read_unlock_bh(); |