diff options
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
| -rw-r--r-- | net/ipv4/tcp_ipv4.c | 43 |
1 files changed, 25 insertions, 18 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 54139fa514e6..4a8ec457310f 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
| @@ -369,11 +369,10 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) | |||
| 369 | * We do take care of PMTU discovery (RFC1191) special case : | 369 | * We do take care of PMTU discovery (RFC1191) special case : |
| 370 | * we can receive locally generated ICMP messages while socket is held. | 370 | * we can receive locally generated ICMP messages while socket is held. |
| 371 | */ | 371 | */ |
| 372 | if (sock_owned_by_user(sk) && | 372 | if (sock_owned_by_user(sk)) { |
| 373 | type != ICMP_DEST_UNREACH && | 373 | if (!(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)) |
| 374 | code != ICMP_FRAG_NEEDED) | 374 | NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS); |
| 375 | NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS); | 375 | } |
| 376 | |||
| 377 | if (sk->sk_state == TCP_CLOSE) | 376 | if (sk->sk_state == TCP_CLOSE) |
| 378 | goto out; | 377 | goto out; |
| 379 | 378 | ||
| @@ -497,6 +496,7 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) | |||
| 497 | * errors returned from accept(). | 496 | * errors returned from accept(). |
| 498 | */ | 497 | */ |
| 499 | inet_csk_reqsk_queue_drop(sk, req, prev); | 498 | inet_csk_reqsk_queue_drop(sk, req, prev); |
| 499 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | ||
| 500 | goto out; | 500 | goto out; |
| 501 | 501 | ||
| 502 | case TCP_SYN_SENT: | 502 | case TCP_SYN_SENT: |
| @@ -657,7 +657,8 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) | |||
| 657 | * no RST generated if md5 hash doesn't match. | 657 | * no RST generated if md5 hash doesn't match. |
| 658 | */ | 658 | */ |
| 659 | sk1 = __inet_lookup_listener(dev_net(skb_dst(skb)->dev), | 659 | sk1 = __inet_lookup_listener(dev_net(skb_dst(skb)->dev), |
| 660 | &tcp_hashinfo, ip_hdr(skb)->daddr, | 660 | &tcp_hashinfo, ip_hdr(skb)->saddr, |
| 661 | th->source, ip_hdr(skb)->daddr, | ||
| 661 | ntohs(th->source), inet_iif(skb)); | 662 | ntohs(th->source), inet_iif(skb)); |
| 662 | /* don't send rst if it can't find key */ | 663 | /* don't send rst if it can't find key */ |
| 663 | if (!sk1) | 664 | if (!sk1) |
| @@ -725,7 +726,7 @@ release_sk1: | |||
| 725 | */ | 726 | */ |
| 726 | 727 | ||
| 727 | static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | 728 | static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, |
| 728 | u32 win, u32 ts, int oif, | 729 | u32 win, u32 tsval, u32 tsecr, int oif, |
| 729 | struct tcp_md5sig_key *key, | 730 | struct tcp_md5sig_key *key, |
| 730 | int reply_flags, u8 tos) | 731 | int reply_flags, u8 tos) |
| 731 | { | 732 | { |
| @@ -746,12 +747,12 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | |||
| 746 | 747 | ||
| 747 | arg.iov[0].iov_base = (unsigned char *)&rep; | 748 | arg.iov[0].iov_base = (unsigned char *)&rep; |
| 748 | arg.iov[0].iov_len = sizeof(rep.th); | 749 | arg.iov[0].iov_len = sizeof(rep.th); |
| 749 | if (ts) { | 750 | if (tsecr) { |
| 750 | rep.opt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | | 751 | rep.opt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | |
| 751 | (TCPOPT_TIMESTAMP << 8) | | 752 | (TCPOPT_TIMESTAMP << 8) | |
| 752 | TCPOLEN_TIMESTAMP); | 753 | TCPOLEN_TIMESTAMP); |
| 753 | rep.opt[1] = htonl(tcp_time_stamp); | 754 | rep.opt[1] = htonl(tsval); |
| 754 | rep.opt[2] = htonl(ts); | 755 | rep.opt[2] = htonl(tsecr); |
| 755 | arg.iov[0].iov_len += TCPOLEN_TSTAMP_ALIGNED; | 756 | arg.iov[0].iov_len += TCPOLEN_TSTAMP_ALIGNED; |
| 756 | } | 757 | } |
| 757 | 758 | ||
| @@ -766,7 +767,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | |||
| 766 | 767 | ||
| 767 | #ifdef CONFIG_TCP_MD5SIG | 768 | #ifdef CONFIG_TCP_MD5SIG |
| 768 | if (key) { | 769 | if (key) { |
| 769 | int offset = (ts) ? 3 : 0; | 770 | int offset = (tsecr) ? 3 : 0; |
| 770 | 771 | ||
| 771 | rep.opt[offset++] = htonl((TCPOPT_NOP << 24) | | 772 | rep.opt[offset++] = htonl((TCPOPT_NOP << 24) | |
| 772 | (TCPOPT_NOP << 16) | | 773 | (TCPOPT_NOP << 16) | |
| @@ -801,6 +802,7 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
| 801 | 802 | ||
| 802 | tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, | 803 | tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, |
| 803 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, | 804 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
| 805 | tcp_time_stamp + tcptw->tw_ts_offset, | ||
| 804 | tcptw->tw_ts_recent, | 806 | tcptw->tw_ts_recent, |
| 805 | tw->tw_bound_dev_if, | 807 | tw->tw_bound_dev_if, |
| 806 | tcp_twsk_md5_key(tcptw), | 808 | tcp_twsk_md5_key(tcptw), |
| @@ -820,6 +822,7 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, | |||
| 820 | tcp_v4_send_ack(skb, (sk->sk_state == TCP_LISTEN) ? | 822 | tcp_v4_send_ack(skb, (sk->sk_state == TCP_LISTEN) ? |
| 821 | tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt, | 823 | tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt, |
| 822 | tcp_rsk(req)->rcv_nxt, req->rcv_wnd, | 824 | tcp_rsk(req)->rcv_nxt, req->rcv_wnd, |
| 825 | tcp_time_stamp, | ||
| 823 | req->ts_recent, | 826 | req->ts_recent, |
| 824 | 0, | 827 | 0, |
| 825 | tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&ip_hdr(skb)->daddr, | 828 | tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&ip_hdr(skb)->daddr, |
| @@ -951,7 +954,6 @@ struct tcp_md5sig_key *tcp_md5_do_lookup(struct sock *sk, | |||
| 951 | { | 954 | { |
| 952 | struct tcp_sock *tp = tcp_sk(sk); | 955 | struct tcp_sock *tp = tcp_sk(sk); |
| 953 | struct tcp_md5sig_key *key; | 956 | struct tcp_md5sig_key *key; |
| 954 | struct hlist_node *pos; | ||
| 955 | unsigned int size = sizeof(struct in_addr); | 957 | unsigned int size = sizeof(struct in_addr); |
| 956 | struct tcp_md5sig_info *md5sig; | 958 | struct tcp_md5sig_info *md5sig; |
| 957 | 959 | ||
| @@ -965,7 +967,7 @@ struct tcp_md5sig_key *tcp_md5_do_lookup(struct sock *sk, | |||
| 965 | if (family == AF_INET6) | 967 | if (family == AF_INET6) |
| 966 | size = sizeof(struct in6_addr); | 968 | size = sizeof(struct in6_addr); |
| 967 | #endif | 969 | #endif |
| 968 | hlist_for_each_entry_rcu(key, pos, &md5sig->head, node) { | 970 | hlist_for_each_entry_rcu(key, &md5sig->head, node) { |
| 969 | if (key->family != family) | 971 | if (key->family != family) |
| 970 | continue; | 972 | continue; |
| 971 | if (!memcmp(&key->addr, addr, size)) | 973 | if (!memcmp(&key->addr, addr, size)) |
| @@ -1066,14 +1068,14 @@ static void tcp_clear_md5_list(struct sock *sk) | |||
| 1066 | { | 1068 | { |
| 1067 | struct tcp_sock *tp = tcp_sk(sk); | 1069 | struct tcp_sock *tp = tcp_sk(sk); |
| 1068 | struct tcp_md5sig_key *key; | 1070 | struct tcp_md5sig_key *key; |
| 1069 | struct hlist_node *pos, *n; | 1071 | struct hlist_node *n; |
| 1070 | struct tcp_md5sig_info *md5sig; | 1072 | struct tcp_md5sig_info *md5sig; |
| 1071 | 1073 | ||
| 1072 | md5sig = rcu_dereference_protected(tp->md5sig_info, 1); | 1074 | md5sig = rcu_dereference_protected(tp->md5sig_info, 1); |
| 1073 | 1075 | ||
| 1074 | if (!hlist_empty(&md5sig->head)) | 1076 | if (!hlist_empty(&md5sig->head)) |
| 1075 | tcp_free_md5sig_pool(); | 1077 | tcp_free_md5sig_pool(); |
| 1076 | hlist_for_each_entry_safe(key, pos, n, &md5sig->head, node) { | 1078 | hlist_for_each_entry_safe(key, n, &md5sig->head, node) { |
| 1077 | hlist_del_rcu(&key->node); | 1079 | hlist_del_rcu(&key->node); |
| 1078 | atomic_sub(sizeof(*key), &sk->sk_omem_alloc); | 1080 | atomic_sub(sizeof(*key), &sk->sk_omem_alloc); |
| 1079 | kfree_rcu(key, rcu); | 1081 | kfree_rcu(key, rcu); |
| @@ -1501,8 +1503,10 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
| 1501 | * clogging syn queue with openreqs with exponentially increasing | 1503 | * clogging syn queue with openreqs with exponentially increasing |
| 1502 | * timeout. | 1504 | * timeout. |
| 1503 | */ | 1505 | */ |
| 1504 | if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) | 1506 | if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) { |
| 1507 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); | ||
| 1505 | goto drop; | 1508 | goto drop; |
| 1509 | } | ||
| 1506 | 1510 | ||
| 1507 | req = inet_reqsk_alloc(&tcp_request_sock_ops); | 1511 | req = inet_reqsk_alloc(&tcp_request_sock_ops); |
| 1508 | if (!req) | 1512 | if (!req) |
| @@ -1568,7 +1572,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
| 1568 | goto drop_and_free; | 1572 | goto drop_and_free; |
| 1569 | 1573 | ||
| 1570 | if (!want_cookie || tmp_opt.tstamp_ok) | 1574 | if (!want_cookie || tmp_opt.tstamp_ok) |
| 1571 | TCP_ECN_create_request(req, skb); | 1575 | TCP_ECN_create_request(req, skb, sock_net(sk)); |
| 1572 | 1576 | ||
| 1573 | if (want_cookie) { | 1577 | if (want_cookie) { |
| 1574 | isn = cookie_v4_init_sequence(sk, skb, &req->mss); | 1578 | isn = cookie_v4_init_sequence(sk, skb, &req->mss); |
| @@ -1667,6 +1671,7 @@ drop_and_release: | |||
| 1667 | drop_and_free: | 1671 | drop_and_free: |
| 1668 | reqsk_free(req); | 1672 | reqsk_free(req); |
| 1669 | drop: | 1673 | drop: |
| 1674 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | ||
| 1670 | return 0; | 1675 | return 0; |
| 1671 | } | 1676 | } |
| 1672 | EXPORT_SYMBOL(tcp_v4_conn_request); | 1677 | EXPORT_SYMBOL(tcp_v4_conn_request); |
| @@ -2074,6 +2079,7 @@ do_time_wait: | |||
| 2074 | case TCP_TW_SYN: { | 2079 | case TCP_TW_SYN: { |
| 2075 | struct sock *sk2 = inet_lookup_listener(dev_net(skb->dev), | 2080 | struct sock *sk2 = inet_lookup_listener(dev_net(skb->dev), |
| 2076 | &tcp_hashinfo, | 2081 | &tcp_hashinfo, |
| 2082 | iph->saddr, th->source, | ||
| 2077 | iph->daddr, th->dest, | 2083 | iph->daddr, th->dest, |
| 2078 | inet_iif(skb)); | 2084 | inet_iif(skb)); |
| 2079 | if (sk2) { | 2085 | if (sk2) { |
| @@ -2609,7 +2615,7 @@ EXPORT_SYMBOL(tcp_proc_register); | |||
| 2609 | 2615 | ||
| 2610 | void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo) | 2616 | void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo) |
| 2611 | { | 2617 | { |
| 2612 | proc_net_remove(net, afinfo->name); | 2618 | remove_proc_entry(afinfo->name, net->proc_net); |
| 2613 | } | 2619 | } |
| 2614 | EXPORT_SYMBOL(tcp_proc_unregister); | 2620 | EXPORT_SYMBOL(tcp_proc_unregister); |
| 2615 | 2621 | ||
| @@ -2888,6 +2894,7 @@ EXPORT_SYMBOL(tcp_prot); | |||
| 2888 | 2894 | ||
| 2889 | static int __net_init tcp_sk_init(struct net *net) | 2895 | static int __net_init tcp_sk_init(struct net *net) |
| 2890 | { | 2896 | { |
| 2897 | net->ipv4.sysctl_tcp_ecn = 2; | ||
| 2891 | return 0; | 2898 | return 0; |
| 2892 | } | 2899 | } |
| 2893 | 2900 | ||
