tcp: early_demux fixes
authorEric Dumazet <edumazet@google.com>
Tue, 24 Jul 2012 01:19:31 +0000 (01:19 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 24 Jul 2012 20:54:15 +0000 (13:54 -0700)
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>
net/ipv4/ip_input.c
net/ipv4/tcp_ipv4.c

index 4ebc6fe..93134b0 100644 (file)
@@ -326,8 +326,11 @@ static int ip_rcv_finish(struct sk_buff *skb)
 
                rcu_read_lock();
                ipprot = rcu_dereference(inet_protos[protocol]);
-               if (ipprot && ipprot->early_demux)
+               if (ipprot && ipprot->early_demux) {
                        ipprot->early_demux(skb);
+                       /* must reload iph, skb->head might have changed */
+                       iph = ip_hdr(skb);
+               }
                rcu_read_unlock();
        }
 
index 3e30548..b6b07c9 100644 (file)
@@ -1686,7 +1686,6 @@ void tcp_v4_early_demux(struct sk_buff *skb)
        struct net *net = dev_net(skb->dev);
        const struct iphdr *iph;
        const struct tcphdr *th;
-       struct net_device *dev;
        struct sock *sk;
 
        if (skb->pkt_type != PACKET_HOST)
@@ -1701,14 +1700,10 @@ void tcp_v4_early_demux(struct sk_buff *skb)
        if (th->doff < sizeof(struct tcphdr) / 4)
                return;
 
-       if (!pskb_may_pull(skb, ip_hdrlen(skb) + th->doff * 4))
-               return;
-
-       dev = skb->dev;
        sk = __inet_lookup_established(net, &tcp_hashinfo,
                                       iph->saddr, th->source,
                                       iph->daddr, ntohs(th->dest),
-                                      dev->ifindex);
+                                      skb->skb_iif);
        if (sk) {
                skb->sk = sk;
                skb->destructor = sock_edemux;
@@ -1718,7 +1713,7 @@ void tcp_v4_early_demux(struct sk_buff *skb)
                        if (dst)
                                dst = dst_check(dst, 0);
                        if (dst &&
-                           icsk->rx_dst_ifindex == dev->ifindex)
+                           icsk->rx_dst_ifindex == skb->skb_iif)
                                skb_dst_set_noref(skb, dst);
                }
        }