aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/tcp_ipv6.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r--net/ipv6/tcp_ipv6.c41
1 files changed, 27 insertions, 14 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 4f43537197ef..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);
@@ -713,7 +720,8 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = {
713#endif 720#endif
714 721
715static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, 722static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
716 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)
717{ 725{
718 const struct tcphdr *th = tcp_hdr(skb); 726 const struct tcphdr *th = tcp_hdr(skb);
719 struct tcphdr *t1; 727 struct tcphdr *t1;
@@ -725,7 +733,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
725 struct dst_entry *dst; 733 struct dst_entry *dst;
726 __be32 *topt; 734 __be32 *topt;
727 735
728 if (ts) 736 if (tsecr)
729 tot_len += TCPOLEN_TSTAMP_ALIGNED; 737 tot_len += TCPOLEN_TSTAMP_ALIGNED;
730#ifdef CONFIG_TCP_MD5SIG 738#ifdef CONFIG_TCP_MD5SIG
731 if (key) 739 if (key)
@@ -755,11 +763,11 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
755 763
756 topt = (__be32 *)(t1 + 1); 764 topt = (__be32 *)(t1 + 1);
757 765
758 if (ts) { 766 if (tsecr) {
759 *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | 767 *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
760 (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); 768 (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
761 *topt++ = htonl(tcp_time_stamp); 769 *topt++ = htonl(tsval);
762 *topt++ = htonl(ts); 770 *topt++ = htonl(tsecr);
763 } 771 }
764 772
765#ifdef CONFIG_TCP_MD5SIG 773#ifdef CONFIG_TCP_MD5SIG
@@ -835,7 +843,8 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
835 * no RST generated if md5 hash doesn't match. 843 * no RST generated if md5 hash doesn't match.
836 */ 844 */
837 sk1 = inet6_lookup_listener(dev_net(skb_dst(skb)->dev), 845 sk1 = inet6_lookup_listener(dev_net(skb_dst(skb)->dev),
838 &tcp_hashinfo, &ipv6h->daddr, 846 &tcp_hashinfo, &ipv6h->saddr,
847 th->source, &ipv6h->daddr,
839 ntohs(th->source), inet6_iif(skb)); 848 ntohs(th->source), inet6_iif(skb));
840 if (!sk1) 849 if (!sk1)
841 return; 850 return;
@@ -859,7 +868,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
859 ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len - 868 ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len -
860 (th->doff << 2); 869 (th->doff << 2);
861 870
862 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);
863 872
864#ifdef CONFIG_TCP_MD5SIG 873#ifdef CONFIG_TCP_MD5SIG
865release_sk1: 874release_sk1:
@@ -870,10 +879,11 @@ release_sk1:
870#endif 879#endif
871} 880}
872 881
873static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts, 882static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
883 u32 win, u32 tsval, u32 tsecr,
874 struct tcp_md5sig_key *key, u8 tclass) 884 struct tcp_md5sig_key *key, u8 tclass)
875{ 885{
876 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);
877} 887}
878 888
879static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) 889static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
@@ -883,6 +893,7 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
883 893
884 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,
885 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,
886 tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw), 897 tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw),
887 tw->tw_tclass); 898 tw->tw_tclass);
888 899
@@ -892,7 +903,8 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
892static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, 903static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
893 struct request_sock *req) 904 struct request_sock *req)
894{ 905{
895 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,
896 tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), 0); 908 tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), 0);
897} 909}
898 910
@@ -1030,7 +1042,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
1030 treq->rmt_addr = ipv6_hdr(skb)->saddr; 1042 treq->rmt_addr = ipv6_hdr(skb)->saddr;
1031 treq->loc_addr = ipv6_hdr(skb)->daddr; 1043 treq->loc_addr = ipv6_hdr(skb)->daddr;
1032 if (!want_cookie || tmp_opt.tstamp_ok) 1044 if (!want_cookie || tmp_opt.tstamp_ok)
1033 TCP_ECN_create_request(req, skb); 1045 TCP_ECN_create_request(req, skb, sock_net(sk));
1034 1046
1035 treq->iif = sk->sk_bound_dev_if; 1047 treq->iif = sk->sk_bound_dev_if;
1036 1048
@@ -1167,7 +1179,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
1167 newnp->opt = NULL; 1179 newnp->opt = NULL;
1168 newnp->mcast_oif = inet6_iif(skb); 1180 newnp->mcast_oif = inet6_iif(skb);
1169 newnp->mcast_hops = ipv6_hdr(skb)->hop_limit; 1181 newnp->mcast_hops = ipv6_hdr(skb)->hop_limit;
1170 newnp->rcv_tclass = ipv6_tclass(ipv6_hdr(skb)); 1182 newnp->rcv_tclass = ipv6_get_dsfield(ipv6_hdr(skb));
1171 1183
1172 /* 1184 /*
1173 * 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
@@ -1247,7 +1259,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
1247 newnp->opt = NULL; 1259 newnp->opt = NULL;
1248 newnp->mcast_oif = inet6_iif(skb); 1260 newnp->mcast_oif = inet6_iif(skb);
1249 newnp->mcast_hops = ipv6_hdr(skb)->hop_limit; 1261 newnp->mcast_hops = ipv6_hdr(skb)->hop_limit;
1250 newnp->rcv_tclass = ipv6_tclass(ipv6_hdr(skb)); 1262 newnp->rcv_tclass = ipv6_get_dsfield(ipv6_hdr(skb));
1251 1263
1252 /* Clone native IPv6 options from listening socket (if any) 1264 /* Clone native IPv6 options from listening socket (if any)
1253 1265
@@ -1460,7 +1472,7 @@ ipv6_pktoptions:
1460 if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) 1472 if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim)
1461 np->mcast_hops = ipv6_hdr(opt_skb)->hop_limit; 1473 np->mcast_hops = ipv6_hdr(opt_skb)->hop_limit;
1462 if (np->rxopt.bits.rxtclass) 1474 if (np->rxopt.bits.rxtclass)
1463 np->rcv_tclass = ipv6_tclass(ipv6_hdr(skb)); 1475 np->rcv_tclass = ipv6_get_dsfield(ipv6_hdr(skb));
1464 if (ipv6_opt_accepted(sk, opt_skb)) { 1476 if (ipv6_opt_accepted(sk, opt_skb)) {
1465 skb_set_owner_r(opt_skb, sk); 1477 skb_set_owner_r(opt_skb, sk);
1466 opt_skb = xchg(&np->pktoptions, opt_skb); 1478 opt_skb = xchg(&np->pktoptions, opt_skb);
@@ -1602,6 +1614,7 @@ do_time_wait:
1602 struct sock *sk2; 1614 struct sock *sk2;
1603 1615
1604 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,
1605 &ipv6_hdr(skb)->daddr, 1618 &ipv6_hdr(skb)->daddr,
1606 ntohs(th->dest), inet6_iif(skb)); 1619 ntohs(th->dest), inet6_iif(skb));
1607 if (sk2 != NULL) { 1620 if (sk2 != NULL) {