diff options
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
| -rw-r--r-- | net/ipv4/tcp_ipv4.c | 42 |
1 files changed, 23 insertions, 19 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index eadb693eef55..d09203c63264 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
| @@ -274,13 +274,6 @@ static void tcp_v4_mtu_reduced(struct sock *sk) | |||
| 274 | struct inet_sock *inet = inet_sk(sk); | 274 | struct inet_sock *inet = inet_sk(sk); |
| 275 | u32 mtu = tcp_sk(sk)->mtu_info; | 275 | u32 mtu = tcp_sk(sk)->mtu_info; |
| 276 | 276 | ||
| 277 | /* We are not interested in TCP_LISTEN and open_requests (SYN-ACKs | ||
| 278 | * send out by Linux are always <576bytes so they should go through | ||
| 279 | * unfragmented). | ||
| 280 | */ | ||
| 281 | if (sk->sk_state == TCP_LISTEN) | ||
| 282 | return; | ||
| 283 | |||
| 284 | dst = inet_csk_update_pmtu(sk, mtu); | 277 | dst = inet_csk_update_pmtu(sk, mtu); |
| 285 | if (!dst) | 278 | if (!dst) |
| 286 | return; | 279 | return; |
| @@ -408,6 +401,13 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) | |||
| 408 | goto out; | 401 | goto out; |
| 409 | 402 | ||
| 410 | if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */ | 403 | if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */ |
| 404 | /* We are not interested in TCP_LISTEN and open_requests | ||
| 405 | * (SYN-ACKs send out by Linux are always <576bytes so | ||
| 406 | * they should go through unfragmented). | ||
| 407 | */ | ||
| 408 | if (sk->sk_state == TCP_LISTEN) | ||
| 409 | goto out; | ||
| 410 | |||
| 411 | tp->mtu_info = info; | 411 | tp->mtu_info = info; |
| 412 | if (!sock_owned_by_user(sk)) { | 412 | if (!sock_owned_by_user(sk)) { |
| 413 | tcp_v4_mtu_reduced(sk); | 413 | tcp_v4_mtu_reduced(sk); |
| @@ -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); |
| @@ -1570,7 +1572,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
| 1570 | goto drop_and_free; | 1572 | goto drop_and_free; |
| 1571 | 1573 | ||
| 1572 | if (!want_cookie || tmp_opt.tstamp_ok) | 1574 | if (!want_cookie || tmp_opt.tstamp_ok) |
| 1573 | TCP_ECN_create_request(req, skb); | 1575 | TCP_ECN_create_request(req, skb, sock_net(sk)); |
| 1574 | 1576 | ||
| 1575 | if (want_cookie) { | 1577 | if (want_cookie) { |
| 1576 | isn = cookie_v4_init_sequence(sk, skb, &req->mss); | 1578 | isn = cookie_v4_init_sequence(sk, skb, &req->mss); |
| @@ -2077,6 +2079,7 @@ do_time_wait: | |||
| 2077 | case TCP_TW_SYN: { | 2079 | case TCP_TW_SYN: { |
| 2078 | struct sock *sk2 = inet_lookup_listener(dev_net(skb->dev), | 2080 | struct sock *sk2 = inet_lookup_listener(dev_net(skb->dev), |
| 2079 | &tcp_hashinfo, | 2081 | &tcp_hashinfo, |
| 2082 | iph->saddr, th->source, | ||
| 2080 | iph->daddr, th->dest, | 2083 | iph->daddr, th->dest, |
| 2081 | inet_iif(skb)); | 2084 | inet_iif(skb)); |
| 2082 | if (sk2) { | 2085 | if (sk2) { |
| @@ -2612,7 +2615,7 @@ EXPORT_SYMBOL(tcp_proc_register); | |||
| 2612 | 2615 | ||
| 2613 | 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) |
| 2614 | { | 2617 | { |
| 2615 | proc_net_remove(net, afinfo->name); | 2618 | remove_proc_entry(afinfo->name, net->proc_net); |
| 2616 | } | 2619 | } |
| 2617 | EXPORT_SYMBOL(tcp_proc_unregister); | 2620 | EXPORT_SYMBOL(tcp_proc_unregister); |
| 2618 | 2621 | ||
| @@ -2891,6 +2894,7 @@ EXPORT_SYMBOL(tcp_prot); | |||
| 2891 | 2894 | ||
| 2892 | static int __net_init tcp_sk_init(struct net *net) | 2895 | static int __net_init tcp_sk_init(struct net *net) |
| 2893 | { | 2896 | { |
| 2897 | net->ipv4.sysctl_tcp_ecn = 2; | ||
| 2894 | return 0; | 2898 | return 0; |
| 2895 | } | 2899 | } |
| 2896 | 2900 | ||
