diff options
author | David S. Miller <davem@davemloft.net> | 2011-12-01 13:38:59 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-12-01 13:38:59 -0500 |
commit | efbc368dcc6426d5430b9b8eeda944cf2cb74b8c (patch) | |
tree | b5b27a1d0df7fd5808b2c58c605bf9c563cc9056 /net | |
parent | 8f891489866ec62a87494eff3ed17c88152c32d4 (diff) |
ipv4: Perform peer validation on cached route lookup.
Otherwise we won't notice the peer GENID change.
Reported-by: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-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 57e01bc60947..ca5e237df029 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -1693,12 +1693,8 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
1693 | } | 1693 | } |
1694 | 1694 | ||
1695 | 1695 | ||
1696 | static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) | 1696 | static struct rtable *ipv4_validate_peer(struct rtable *rt) |
1697 | { | 1697 | { |
1698 | struct rtable *rt = (struct rtable *) dst; | ||
1699 | |||
1700 | if (rt_is_expired(rt)) | ||
1701 | return NULL; | ||
1702 | if (rt->rt_peer_genid != rt_peer_genid()) { | 1698 | if (rt->rt_peer_genid != rt_peer_genid()) { |
1703 | struct inet_peer *peer; | 1699 | struct inet_peer *peer; |
1704 | 1700 | ||
@@ -1707,19 +1703,29 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) | |||
1707 | 1703 | ||
1708 | peer = rt->peer; | 1704 | peer = rt->peer; |
1709 | if (peer) { | 1705 | if (peer) { |
1710 | check_peer_pmtu(dst, peer); | 1706 | check_peer_pmtu(&rt->dst, peer); |
1711 | 1707 | ||
1712 | if (peer->redirect_genid != redirect_genid) | 1708 | if (peer->redirect_genid != redirect_genid) |
1713 | peer->redirect_learned.a4 = 0; | 1709 | peer->redirect_learned.a4 = 0; |
1714 | if (peer->redirect_learned.a4 && | 1710 | if (peer->redirect_learned.a4 && |
1715 | peer->redirect_learned.a4 != rt->rt_gateway) { | 1711 | peer->redirect_learned.a4 != rt->rt_gateway) { |
1716 | if (check_peer_redir(dst, peer)) | 1712 | if (check_peer_redir(&rt->dst, peer)) |
1717 | return NULL; | 1713 | return NULL; |
1718 | } | 1714 | } |
1719 | } | 1715 | } |
1720 | 1716 | ||
1721 | rt->rt_peer_genid = rt_peer_genid(); | 1717 | rt->rt_peer_genid = rt_peer_genid(); |
1722 | } | 1718 | } |
1719 | return rt; | ||
1720 | } | ||
1721 | |||
1722 | static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) | ||
1723 | { | ||
1724 | struct rtable *rt = (struct rtable *) dst; | ||
1725 | |||
1726 | if (rt_is_expired(rt)) | ||
1727 | return NULL; | ||
1728 | dst = (struct dst_entry *) ipv4_validate_peer(rt); | ||
1723 | return dst; | 1729 | return dst; |
1724 | } | 1730 | } |
1725 | 1731 | ||
@@ -2374,6 +2380,9 @@ int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
2374 | rth->rt_mark == skb->mark && | 2380 | rth->rt_mark == skb->mark && |
2375 | net_eq(dev_net(rth->dst.dev), net) && | 2381 | net_eq(dev_net(rth->dst.dev), net) && |
2376 | !rt_is_expired(rth)) { | 2382 | !rt_is_expired(rth)) { |
2383 | rth = ipv4_validate_peer(rth); | ||
2384 | if (!rth) | ||
2385 | continue; | ||
2377 | if (noref) { | 2386 | if (noref) { |
2378 | dst_use_noref(&rth->dst, jiffies); | 2387 | dst_use_noref(&rth->dst, jiffies); |
2379 | skb_dst_set_noref(skb, &rth->dst); | 2388 | skb_dst_set_noref(skb, &rth->dst); |
@@ -2749,6 +2758,9 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *flp4) | |||
2749 | (IPTOS_RT_MASK | RTO_ONLINK)) && | 2758 | (IPTOS_RT_MASK | RTO_ONLINK)) && |
2750 | net_eq(dev_net(rth->dst.dev), net) && | 2759 | net_eq(dev_net(rth->dst.dev), net) && |
2751 | !rt_is_expired(rth)) { | 2760 | !rt_is_expired(rth)) { |
2761 | rth = ipv4_validate_peer(rth); | ||
2762 | if (!rth) | ||
2763 | continue; | ||
2752 | dst_use(&rth->dst, jiffies); | 2764 | dst_use(&rth->dst, jiffies); |
2753 | RT_CACHE_STAT_INC(out_hit); | 2765 | RT_CACHE_STAT_INC(out_hit); |
2754 | rcu_read_unlock_bh(); | 2766 | rcu_read_unlock_bh(); |