--- sys/netinet/tcp_input.c	27 Feb 2005 21:43:54 -0000	1.252.2.14
+++ sys/netinet/tcp_input.c	28 Jun 2005 20:53:10 -0000
@@ -1081,7 +1081,7 @@
 	 * XXX this is traditional behavior, may need to be cleaned up.
 	 */
 	tcp_dooptions(tp, &to, optp, optlen, thflags & TH_SYN, th);
-	if (thflags & TH_SYN) {
+	if (tp->t_state == TCPS_SYN_SENT && (thflags & TH_SYN)) {
 		if (to.to_flags & TOF_SCALE) {
 			tp->t_flags |= TF_RCVD_SCALE;
 			tp->requested_s_scale = to.to_requested_s_scale;
@@ -1816,11 +1816,25 @@
 	/*
 	 * If last ACK falls within this segment's sequence numbers,
 	 * record its timestamp.
-	 * NOTE that the test is modified according to the latest
-	 * proposal of the tcplw@cray.com list (Braden 1993/04/26).
+	 * NOTE: 
+	 * 1) That the test incorporates suggestions from the latest
+	 *    proposal of the tcplw@cray.com list (Braden 1993/04/26).
+	 * 2) That updating only on newer timestamps interferes with
+	 *    our earlier PAWS tests, so this check should be solely
+	 *    predicated on the sequence space of this segment.
+	 * 3) That we modify the segment boundary check to be 
+	 *        Last.ACK.Sent <= SEG.SEQ + SEG.Len  
+	 *    instead of RFC1323's
+	 *        Last.ACK.Sent < SEG.SEQ + SEG.Len,
+	 *    This modified check allows us to overcome RFC1323's
+	 *    limitations as described in Stevens TCP/IP Illustrated
+	 *    Vol. 2 p.869. In such cases, we can still calculate the
+	 *    RTT correctly when RCV.NXT == Last.ACK.Sent.
 	 */
 	if ((to.to_flags & TOF_TS) != 0 &&
-	    SEQ_LEQ(th->th_seq, tp->last_ack_sent)) {
+	    SEQ_LEQ(th->th_seq, tp->last_ack_sent) &&
+	    SEQ_LEQ(tp->last_ack_sent, th->th_seq + tlen +
+		((thflags & (TH_SYN|TH_FIN)) != 0))) {
 		tp->ts_recent_age = ticks;
 		tp->ts_recent = to.to_tsval;
 	}
@@ -2685,6 +2699,12 @@
 			bcopy((char *)cp + 6,
 			    (char *)&to->to_tsecr, sizeof(to->to_tsecr));
 			to->to_tsecr = ntohl(to->to_tsecr);
+			/*
+			 * If echoed timestamp is later than the current time,
+			 * fall back to non RFC1323 RTT calculation.
+			 */
+			if ((to->to_tsecr != 0) && TSTMP_GT(to->to_tsecr, ticks))
+				to->to_tsecr = 0;
 			break;
 		case TCPOPT_CC:
 			if (optlen != TCPOLEN_CC)
--- sys/netinet/tcp_seq.h	31 Jan 2005 23:26:36 -0000	1.22.2.1
+++ sys/netinet/tcp_seq.h	29 Jun 2005 08:59:23 -0000
@@ -47,6 +47,7 @@
 
 /* for modulo comparisons of timestamps */
 #define TSTMP_LT(a,b)	((int)((a)-(b)) < 0)
+#define TSTMP_GT(a,b)	((int)((a)-(b)) > 0)
 #define TSTMP_GEQ(a,b)	((int)((a)-(b)) >= 0)
 
 /*
