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 | |
| 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>
| -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(); |
