diff options
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 47 |
1 files changed, 32 insertions, 15 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 93825dd3a7c0..f6d629fd6aee 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -389,6 +389,13 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
389 | } | 389 | } |
390 | 390 | ||
391 | if (type == ICMPV6_PKT_TOOBIG) { | 391 | if (type == ICMPV6_PKT_TOOBIG) { |
392 | /* We are not interested in TCP_LISTEN and open_requests | ||
393 | * (SYN-ACKs send out by Linux are always <576bytes so | ||
394 | * they should go through unfragmented). | ||
395 | */ | ||
396 | if (sk->sk_state == TCP_LISTEN) | ||
397 | goto out; | ||
398 | |||
392 | tp->mtu_info = ntohl(info); | 399 | tp->mtu_info = ntohl(info); |
393 | if (!sock_owned_by_user(sk)) | 400 | if (!sock_owned_by_user(sk)) |
394 | tcp_v6_mtu_reduced(sk); | 401 | tcp_v6_mtu_reduced(sk); |
@@ -423,6 +430,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
423 | } | 430 | } |
424 | 431 | ||
425 | inet_csk_reqsk_queue_drop(sk, req, prev); | 432 | inet_csk_reqsk_queue_drop(sk, req, prev); |
433 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | ||
426 | goto out; | 434 | goto out; |
427 | 435 | ||
428 | case TCP_SYN_SENT: | 436 | case TCP_SYN_SENT: |
@@ -712,7 +720,8 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { | |||
712 | #endif | 720 | #endif |
713 | 721 | ||
714 | static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | 722 | static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, |
715 | u32 ts, struct tcp_md5sig_key *key, int rst, u8 tclass) | 723 | u32 tsval, u32 tsecr, |
724 | struct tcp_md5sig_key *key, int rst, u8 tclass) | ||
716 | { | 725 | { |
717 | const struct tcphdr *th = tcp_hdr(skb); | 726 | const struct tcphdr *th = tcp_hdr(skb); |
718 | struct tcphdr *t1; | 727 | struct tcphdr *t1; |
@@ -724,7 +733,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | |||
724 | struct dst_entry *dst; | 733 | struct dst_entry *dst; |
725 | __be32 *topt; | 734 | __be32 *topt; |
726 | 735 | ||
727 | if (ts) | 736 | if (tsecr) |
728 | tot_len += TCPOLEN_TSTAMP_ALIGNED; | 737 | tot_len += TCPOLEN_TSTAMP_ALIGNED; |
729 | #ifdef CONFIG_TCP_MD5SIG | 738 | #ifdef CONFIG_TCP_MD5SIG |
730 | if (key) | 739 | if (key) |
@@ -754,11 +763,11 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | |||
754 | 763 | ||
755 | topt = (__be32 *)(t1 + 1); | 764 | topt = (__be32 *)(t1 + 1); |
756 | 765 | ||
757 | if (ts) { | 766 | if (tsecr) { |
758 | *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | | 767 | *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | |
759 | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); | 768 | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); |
760 | *topt++ = htonl(tcp_time_stamp); | 769 | *topt++ = htonl(tsval); |
761 | *topt++ = htonl(ts); | 770 | *topt++ = htonl(tsecr); |
762 | } | 771 | } |
763 | 772 | ||
764 | #ifdef CONFIG_TCP_MD5SIG | 773 | #ifdef CONFIG_TCP_MD5SIG |
@@ -834,7 +843,8 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
834 | * no RST generated if md5 hash doesn't match. | 843 | * no RST generated if md5 hash doesn't match. |
835 | */ | 844 | */ |
836 | sk1 = inet6_lookup_listener(dev_net(skb_dst(skb)->dev), | 845 | sk1 = inet6_lookup_listener(dev_net(skb_dst(skb)->dev), |
837 | &tcp_hashinfo, &ipv6h->daddr, | 846 | &tcp_hashinfo, &ipv6h->saddr, |
847 | th->source, &ipv6h->daddr, | ||
838 | ntohs(th->source), inet6_iif(skb)); | 848 | ntohs(th->source), inet6_iif(skb)); |
839 | if (!sk1) | 849 | if (!sk1) |
840 | return; | 850 | return; |
@@ -858,7 +868,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
858 | ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len - | 868 | ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len - |
859 | (th->doff << 2); | 869 | (th->doff << 2); |
860 | 870 | ||
861 | tcp_v6_send_response(skb, seq, ack_seq, 0, 0, key, 1, 0); | 871 | tcp_v6_send_response(skb, seq, ack_seq, 0, 0, 0, key, 1, 0); |
862 | 872 | ||
863 | #ifdef CONFIG_TCP_MD5SIG | 873 | #ifdef CONFIG_TCP_MD5SIG |
864 | release_sk1: | 874 | release_sk1: |
@@ -869,10 +879,11 @@ release_sk1: | |||
869 | #endif | 879 | #endif |
870 | } | 880 | } |
871 | 881 | ||
872 | static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts, | 882 | static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, |
883 | u32 win, u32 tsval, u32 tsecr, | ||
873 | struct tcp_md5sig_key *key, u8 tclass) | 884 | struct tcp_md5sig_key *key, u8 tclass) |
874 | { | 885 | { |
875 | tcp_v6_send_response(skb, seq, ack, win, ts, key, 0, tclass); | 886 | tcp_v6_send_response(skb, seq, ack, win, tsval, tsecr, key, 0, tclass); |
876 | } | 887 | } |
877 | 888 | ||
878 | static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) | 889 | static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) |
@@ -882,6 +893,7 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
882 | 893 | ||
883 | tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, | 894 | tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, |
884 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, | 895 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
896 | tcp_time_stamp + tcptw->tw_ts_offset, | ||
885 | tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw), | 897 | tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw), |
886 | tw->tw_tclass); | 898 | tw->tw_tclass); |
887 | 899 | ||
@@ -891,7 +903,8 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
891 | static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, | 903 | static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, |
892 | struct request_sock *req) | 904 | struct request_sock *req) |
893 | { | 905 | { |
894 | tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent, | 906 | tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, |
907 | req->rcv_wnd, tcp_time_stamp, req->ts_recent, | ||
895 | tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), 0); | 908 | tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), 0); |
896 | } | 909 | } |
897 | 910 | ||
@@ -958,8 +971,10 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
958 | goto drop; | 971 | goto drop; |
959 | } | 972 | } |
960 | 973 | ||
961 | if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) | 974 | if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) { |
975 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); | ||
962 | goto drop; | 976 | goto drop; |
977 | } | ||
963 | 978 | ||
964 | req = inet6_reqsk_alloc(&tcp6_request_sock_ops); | 979 | req = inet6_reqsk_alloc(&tcp6_request_sock_ops); |
965 | if (req == NULL) | 980 | if (req == NULL) |
@@ -1027,7 +1042,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1027 | treq->rmt_addr = ipv6_hdr(skb)->saddr; | 1042 | treq->rmt_addr = ipv6_hdr(skb)->saddr; |
1028 | treq->loc_addr = ipv6_hdr(skb)->daddr; | 1043 | treq->loc_addr = ipv6_hdr(skb)->daddr; |
1029 | if (!want_cookie || tmp_opt.tstamp_ok) | 1044 | if (!want_cookie || tmp_opt.tstamp_ok) |
1030 | TCP_ECN_create_request(req, skb); | 1045 | TCP_ECN_create_request(req, skb, sock_net(sk)); |
1031 | 1046 | ||
1032 | treq->iif = sk->sk_bound_dev_if; | 1047 | treq->iif = sk->sk_bound_dev_if; |
1033 | 1048 | ||
@@ -1108,6 +1123,7 @@ drop_and_release: | |||
1108 | drop_and_free: | 1123 | drop_and_free: |
1109 | reqsk_free(req); | 1124 | reqsk_free(req); |
1110 | drop: | 1125 | drop: |
1126 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | ||
1111 | return 0; /* don't send reset */ | 1127 | return 0; /* don't send reset */ |
1112 | } | 1128 | } |
1113 | 1129 | ||
@@ -1163,7 +1179,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1163 | newnp->opt = NULL; | 1179 | newnp->opt = NULL; |
1164 | newnp->mcast_oif = inet6_iif(skb); | 1180 | newnp->mcast_oif = inet6_iif(skb); |
1165 | newnp->mcast_hops = ipv6_hdr(skb)->hop_limit; | 1181 | newnp->mcast_hops = ipv6_hdr(skb)->hop_limit; |
1166 | newnp->rcv_tclass = ipv6_tclass(ipv6_hdr(skb)); | 1182 | newnp->rcv_tclass = ipv6_get_dsfield(ipv6_hdr(skb)); |
1167 | 1183 | ||
1168 | /* | 1184 | /* |
1169 | * No need to charge this sock to the relevant IPv6 refcnt debug socks count | 1185 | * No need to charge this sock to the relevant IPv6 refcnt debug socks count |
@@ -1243,7 +1259,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1243 | newnp->opt = NULL; | 1259 | newnp->opt = NULL; |
1244 | newnp->mcast_oif = inet6_iif(skb); | 1260 | newnp->mcast_oif = inet6_iif(skb); |
1245 | newnp->mcast_hops = ipv6_hdr(skb)->hop_limit; | 1261 | newnp->mcast_hops = ipv6_hdr(skb)->hop_limit; |
1246 | newnp->rcv_tclass = ipv6_tclass(ipv6_hdr(skb)); | 1262 | newnp->rcv_tclass = ipv6_get_dsfield(ipv6_hdr(skb)); |
1247 | 1263 | ||
1248 | /* Clone native IPv6 options from listening socket (if any) | 1264 | /* Clone native IPv6 options from listening socket (if any) |
1249 | 1265 | ||
@@ -1456,7 +1472,7 @@ ipv6_pktoptions: | |||
1456 | if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) | 1472 | if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) |
1457 | np->mcast_hops = ipv6_hdr(opt_skb)->hop_limit; | 1473 | np->mcast_hops = ipv6_hdr(opt_skb)->hop_limit; |
1458 | if (np->rxopt.bits.rxtclass) | 1474 | if (np->rxopt.bits.rxtclass) |
1459 | np->rcv_tclass = ipv6_tclass(ipv6_hdr(skb)); | 1475 | np->rcv_tclass = ipv6_get_dsfield(ipv6_hdr(skb)); |
1460 | if (ipv6_opt_accepted(sk, opt_skb)) { | 1476 | if (ipv6_opt_accepted(sk, opt_skb)) { |
1461 | skb_set_owner_r(opt_skb, sk); | 1477 | skb_set_owner_r(opt_skb, sk); |
1462 | opt_skb = xchg(&np->pktoptions, opt_skb); | 1478 | opt_skb = xchg(&np->pktoptions, opt_skb); |
@@ -1598,6 +1614,7 @@ do_time_wait: | |||
1598 | struct sock *sk2; | 1614 | struct sock *sk2; |
1599 | 1615 | ||
1600 | sk2 = inet6_lookup_listener(dev_net(skb->dev), &tcp_hashinfo, | 1616 | sk2 = inet6_lookup_listener(dev_net(skb->dev), &tcp_hashinfo, |
1617 | &ipv6_hdr(skb)->saddr, th->source, | ||
1601 | &ipv6_hdr(skb)->daddr, | 1618 | &ipv6_hdr(skb)->daddr, |
1602 | ntohs(th->dest), inet6_iif(skb)); | 1619 | ntohs(th->dest), inet6_iif(skb)); |
1603 | if (sk2 != NULL) { | 1620 | if (sk2 != NULL) { |