diff options
Diffstat (limited to 'net/ipv4/tcp_minisocks.c')
-rw-r--r-- | net/ipv4/tcp_minisocks.c | 140 |
1 files changed, 69 insertions, 71 deletions
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 204c42162660..f976fc57892c 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -609,7 +609,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, | |||
609 | tcp_rsk(req)->rcv_isn + 1, tcp_rsk(req)->rcv_isn + 1 + req->rcv_wnd)) { | 609 | tcp_rsk(req)->rcv_isn + 1, tcp_rsk(req)->rcv_isn + 1 + req->rcv_wnd)) { |
610 | /* Out of window: send ACK and drop. */ | 610 | /* Out of window: send ACK and drop. */ |
611 | if (!(flg & TCP_FLAG_RST)) | 611 | if (!(flg & TCP_FLAG_RST)) |
612 | req->rsk_ops->send_ack(skb, req); | 612 | req->rsk_ops->send_ack(sk, skb, req); |
613 | if (paws_reject) | 613 | if (paws_reject) |
614 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED); | 614 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED); |
615 | return NULL; | 615 | return NULL; |
@@ -618,89 +618,87 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, | |||
618 | /* In sequence, PAWS is OK. */ | 618 | /* In sequence, PAWS is OK. */ |
619 | 619 | ||
620 | if (tmp_opt.saw_tstamp && !after(TCP_SKB_CB(skb)->seq, tcp_rsk(req)->rcv_isn + 1)) | 620 | if (tmp_opt.saw_tstamp && !after(TCP_SKB_CB(skb)->seq, tcp_rsk(req)->rcv_isn + 1)) |
621 | req->ts_recent = tmp_opt.rcv_tsval; | 621 | req->ts_recent = tmp_opt.rcv_tsval; |
622 | 622 | ||
623 | if (TCP_SKB_CB(skb)->seq == tcp_rsk(req)->rcv_isn) { | 623 | if (TCP_SKB_CB(skb)->seq == tcp_rsk(req)->rcv_isn) { |
624 | /* Truncate SYN, it is out of window starting | 624 | /* Truncate SYN, it is out of window starting |
625 | at tcp_rsk(req)->rcv_isn + 1. */ | 625 | at tcp_rsk(req)->rcv_isn + 1. */ |
626 | flg &= ~TCP_FLAG_SYN; | 626 | flg &= ~TCP_FLAG_SYN; |
627 | } | 627 | } |
628 | 628 | ||
629 | /* RFC793: "second check the RST bit" and | 629 | /* RFC793: "second check the RST bit" and |
630 | * "fourth, check the SYN bit" | 630 | * "fourth, check the SYN bit" |
631 | */ | 631 | */ |
632 | if (flg & (TCP_FLAG_RST|TCP_FLAG_SYN)) { | 632 | if (flg & (TCP_FLAG_RST|TCP_FLAG_SYN)) { |
633 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_ATTEMPTFAILS); | 633 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_ATTEMPTFAILS); |
634 | goto embryonic_reset; | 634 | goto embryonic_reset; |
635 | } | 635 | } |
636 | 636 | ||
637 | /* ACK sequence verified above, just make sure ACK is | 637 | /* ACK sequence verified above, just make sure ACK is |
638 | * set. If ACK not set, just silently drop the packet. | 638 | * set. If ACK not set, just silently drop the packet. |
639 | */ | 639 | */ |
640 | if (!(flg & TCP_FLAG_ACK)) | 640 | if (!(flg & TCP_FLAG_ACK)) |
641 | return NULL; | 641 | return NULL; |
642 | |||
643 | /* If TCP_DEFER_ACCEPT is set, drop bare ACK. */ | ||
644 | if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && | ||
645 | TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) { | ||
646 | inet_rsk(req)->acked = 1; | ||
647 | return NULL; | ||
648 | } | ||
649 | 642 | ||
650 | /* OK, ACK is valid, create big socket and | 643 | /* If TCP_DEFER_ACCEPT is set, drop bare ACK. */ |
651 | * feed this segment to it. It will repeat all | 644 | if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && |
652 | * the tests. THIS SEGMENT MUST MOVE SOCKET TO | 645 | TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) { |
653 | * ESTABLISHED STATE. If it will be dropped after | 646 | inet_rsk(req)->acked = 1; |
654 | * socket is created, wait for troubles. | 647 | return NULL; |
655 | */ | 648 | } |
656 | child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, | 649 | |
657 | req, NULL); | 650 | /* OK, ACK is valid, create big socket and |
658 | if (child == NULL) | 651 | * feed this segment to it. It will repeat all |
659 | goto listen_overflow; | 652 | * the tests. THIS SEGMENT MUST MOVE SOCKET TO |
653 | * ESTABLISHED STATE. If it will be dropped after | ||
654 | * socket is created, wait for troubles. | ||
655 | */ | ||
656 | child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL); | ||
657 | if (child == NULL) | ||
658 | goto listen_overflow; | ||
660 | #ifdef CONFIG_TCP_MD5SIG | 659 | #ifdef CONFIG_TCP_MD5SIG |
661 | else { | 660 | else { |
662 | /* Copy over the MD5 key from the original socket */ | 661 | /* Copy over the MD5 key from the original socket */ |
663 | struct tcp_md5sig_key *key; | 662 | struct tcp_md5sig_key *key; |
664 | struct tcp_sock *tp = tcp_sk(sk); | 663 | struct tcp_sock *tp = tcp_sk(sk); |
665 | key = tp->af_specific->md5_lookup(sk, child); | 664 | key = tp->af_specific->md5_lookup(sk, child); |
666 | if (key != NULL) { | 665 | if (key != NULL) { |
667 | /* | 666 | /* |
668 | * We're using one, so create a matching key on the | 667 | * We're using one, so create a matching key on the |
669 | * newsk structure. If we fail to get memory then we | 668 | * newsk structure. If we fail to get memory then we |
670 | * end up not copying the key across. Shucks. | 669 | * end up not copying the key across. Shucks. |
671 | */ | 670 | */ |
672 | char *newkey = kmemdup(key->key, key->keylen, | 671 | char *newkey = kmemdup(key->key, key->keylen, |
673 | GFP_ATOMIC); | 672 | GFP_ATOMIC); |
674 | if (newkey) { | 673 | if (newkey) { |
675 | if (!tcp_alloc_md5sig_pool()) | 674 | if (!tcp_alloc_md5sig_pool()) |
676 | BUG(); | 675 | BUG(); |
677 | tp->af_specific->md5_add(child, child, | 676 | tp->af_specific->md5_add(child, child, newkey, |
678 | newkey, | 677 | key->keylen); |
679 | key->keylen); | ||
680 | } | ||
681 | } | 678 | } |
682 | } | 679 | } |
680 | } | ||
683 | #endif | 681 | #endif |
684 | 682 | ||
685 | inet_csk_reqsk_queue_unlink(sk, req, prev); | 683 | inet_csk_reqsk_queue_unlink(sk, req, prev); |
686 | inet_csk_reqsk_queue_removed(sk, req); | 684 | inet_csk_reqsk_queue_removed(sk, req); |
687 | 685 | ||
688 | inet_csk_reqsk_queue_add(sk, req, child); | 686 | inet_csk_reqsk_queue_add(sk, req, child); |
689 | return child; | 687 | return child; |
690 | 688 | ||
691 | listen_overflow: | 689 | listen_overflow: |
692 | if (!sysctl_tcp_abort_on_overflow) { | 690 | if (!sysctl_tcp_abort_on_overflow) { |
693 | inet_rsk(req)->acked = 1; | 691 | inet_rsk(req)->acked = 1; |
694 | return NULL; | 692 | return NULL; |
695 | } | 693 | } |
696 | 694 | ||
697 | embryonic_reset: | 695 | embryonic_reset: |
698 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_EMBRYONICRSTS); | 696 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_EMBRYONICRSTS); |
699 | if (!(flg & TCP_FLAG_RST)) | 697 | if (!(flg & TCP_FLAG_RST)) |
700 | req->rsk_ops->send_reset(sk, skb); | 698 | req->rsk_ops->send_reset(sk, skb); |
701 | 699 | ||
702 | inet_csk_reqsk_queue_drop(sk, req, prev); | 700 | inet_csk_reqsk_queue_drop(sk, req, prev); |
703 | return NULL; | 701 | return NULL; |
704 | } | 702 | } |
705 | 703 | ||
706 | /* | 704 | /* |