diff options
author | Eric Dumazet <edumazet@google.com> | 2012-07-23 21:19:31 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-07-24 16:54:15 -0400 |
commit | 9cb429d692b341e972b12e6cd097364050ebbb26 (patch) | |
tree | 39450b1d5650322fc6cffca581f34edbc06233ee | |
parent | c20cd5d753a452807b080bbf390e2f844d7991b3 (diff) |
tcp: early_demux fixes
1) Remove a non needed pskb_may_pull() in tcp_v4_early_demux()
and fix a potential bug if skb->head was reallocated
(iph & th pointers were not reloaded)
TCP stack will pull/check headers anyway.
2) must reload iph in ip_rcv_finish() after early_demux()
call since skb->head might have changed.
3) skb->dev->ifindex can be now replaced by skb->skb_iif
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv4/ip_input.c | 5 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 9 |
2 files changed, 6 insertions, 8 deletions
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 4ebc6feee250..93134b0eab0c 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c | |||
@@ -326,8 +326,11 @@ static int ip_rcv_finish(struct sk_buff *skb) | |||
326 | 326 | ||
327 | rcu_read_lock(); | 327 | rcu_read_lock(); |
328 | ipprot = rcu_dereference(inet_protos[protocol]); | 328 | ipprot = rcu_dereference(inet_protos[protocol]); |
329 | if (ipprot && ipprot->early_demux) | 329 | if (ipprot && ipprot->early_demux) { |
330 | ipprot->early_demux(skb); | 330 | ipprot->early_demux(skb); |
331 | /* must reload iph, skb->head might have changed */ | ||
332 | iph = ip_hdr(skb); | ||
333 | } | ||
331 | rcu_read_unlock(); | 334 | rcu_read_unlock(); |
332 | } | 335 | } |
333 | 336 | ||
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 3e30548ac32a..b6b07c93924c 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1686,7 +1686,6 @@ void tcp_v4_early_demux(struct sk_buff *skb) | |||
1686 | struct net *net = dev_net(skb->dev); | 1686 | struct net *net = dev_net(skb->dev); |
1687 | const struct iphdr *iph; | 1687 | const struct iphdr *iph; |
1688 | const struct tcphdr *th; | 1688 | const struct tcphdr *th; |
1689 | struct net_device *dev; | ||
1690 | struct sock *sk; | 1689 | struct sock *sk; |
1691 | 1690 | ||
1692 | if (skb->pkt_type != PACKET_HOST) | 1691 | if (skb->pkt_type != PACKET_HOST) |
@@ -1701,14 +1700,10 @@ void tcp_v4_early_demux(struct sk_buff *skb) | |||
1701 | if (th->doff < sizeof(struct tcphdr) / 4) | 1700 | if (th->doff < sizeof(struct tcphdr) / 4) |
1702 | return; | 1701 | return; |
1703 | 1702 | ||
1704 | if (!pskb_may_pull(skb, ip_hdrlen(skb) + th->doff * 4)) | ||
1705 | return; | ||
1706 | |||
1707 | dev = skb->dev; | ||
1708 | sk = __inet_lookup_established(net, &tcp_hashinfo, | 1703 | sk = __inet_lookup_established(net, &tcp_hashinfo, |
1709 | iph->saddr, th->source, | 1704 | iph->saddr, th->source, |
1710 | iph->daddr, ntohs(th->dest), | 1705 | iph->daddr, ntohs(th->dest), |
1711 | dev->ifindex); | 1706 | skb->skb_iif); |
1712 | if (sk) { | 1707 | if (sk) { |
1713 | skb->sk = sk; | 1708 | skb->sk = sk; |
1714 | skb->destructor = sock_edemux; | 1709 | skb->destructor = sock_edemux; |
@@ -1718,7 +1713,7 @@ void tcp_v4_early_demux(struct sk_buff *skb) | |||
1718 | if (dst) | 1713 | if (dst) |
1719 | dst = dst_check(dst, 0); | 1714 | dst = dst_check(dst, 0); |
1720 | if (dst && | 1715 | if (dst && |
1721 | icsk->rx_dst_ifindex == dev->ifindex) | 1716 | icsk->rx_dst_ifindex == skb->skb_iif) |
1722 | skb_dst_set_noref(skb, dst); | 1717 | skb_dst_set_noref(skb, dst); |
1723 | } | 1718 | } |
1724 | } | 1719 | } |