Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[linux-2.6-block.git] / net / ipv6 / tcp_ipv6.c
index 1a5a70fb85512bb607cc8faefc6799e5340a4064..33f2820181f9512fc465a6af7559c3d33f539a57 100644 (file)
@@ -867,7 +867,8 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
                 * no RST generated if md5 hash doesn't match.
                 */
                sk1 = inet6_lookup_listener(dev_net(skb_dst(skb)->dev),
-                                          &tcp_hashinfo, &ipv6h->saddr,
+                                          &tcp_hashinfo, NULL, 0,
+                                          &ipv6h->saddr,
                                           th->source, &ipv6h->daddr,
                                           ntohs(th->source), tcp_v6_iif(skb));
                if (!sk1)
@@ -1376,8 +1377,8 @@ static int tcp_v6_rcv(struct sk_buff *skb)
        hdr = ipv6_hdr(skb);
 
 lookup:
-       sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest,
-                               inet6_iif(skb));
+       sk = __inet6_lookup_skb(&tcp_hashinfo, skb, __tcp_hdrlen(th),
+                               th->source, th->dest, inet6_iif(skb));
        if (!sk)
                goto no_tcp_socket;
 
@@ -1387,7 +1388,7 @@ process:
 
        if (sk->sk_state == TCP_NEW_SYN_RECV) {
                struct request_sock *req = inet_reqsk(sk);
-               struct sock *nsk = NULL;
+               struct sock *nsk;
 
                sk = req->rsk_listener;
                tcp_v6_fill_cb(skb, hdr, th);
@@ -1395,24 +1396,24 @@ process:
                        reqsk_put(req);
                        goto discard_it;
                }
-               if (likely(sk->sk_state == TCP_LISTEN)) {
-                       nsk = tcp_check_req(sk, skb, req, false);
-               } else {
+               if (unlikely(sk->sk_state != TCP_LISTEN)) {
                        inet_csk_reqsk_queue_drop_and_put(sk, req);
                        goto lookup;
                }
+               sock_hold(sk);
+               nsk = tcp_check_req(sk, skb, req, false);
                if (!nsk) {
                        reqsk_put(req);
-                       goto discard_it;
+                       goto discard_and_relse;
                }
                if (nsk == sk) {
-                       sock_hold(sk);
                        reqsk_put(req);
                        tcp_v6_restore_cb(skb);
                } else if (tcp_child_process(sk, nsk, skb)) {
                        tcp_v6_send_reset(nsk, skb);
-                       goto discard_it;
+                       goto discard_and_relse;
                } else {
+                       sock_put(sk);
                        return 0;
                }
        }
@@ -1501,6 +1502,7 @@ do_time_wait:
                struct sock *sk2;
 
                sk2 = inet6_lookup_listener(dev_net(skb->dev), &tcp_hashinfo,
+                                           skb, __tcp_hdrlen(th),
                                            &ipv6_hdr(skb)->saddr, th->source,
                                            &ipv6_hdr(skb)->daddr,
                                            ntohs(th->dest), tcp_v6_iif(skb));
@@ -1866,7 +1868,7 @@ struct proto tcpv6_prot = {
        .sendpage               = tcp_sendpage,
        .backlog_rcv            = tcp_v6_do_rcv,
        .release_cb             = tcp_release_cb,
-       .hash                   = inet_hash,
+       .hash                   = inet6_hash,
        .unhash                 = inet_unhash,
        .get_port               = inet_csk_get_port,
        .enter_memory_pressure  = tcp_enter_memory_pressure,