changeset 11092:17a676e9520e

6902309 redzone violation due to tcp_ack_mp scribbling tcp_ts_recent past end of db_lim
author Erik Nordmark <Erik.Nordmark@Sun.COM>
date Wed, 18 Nov 2009 09:20:55 -0800
parents d25092d8295b
children 92e0bcf89283
files usr/src/uts/common/inet/tcp/tcp.c
diffstat 1 files changed, 27 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/inet/tcp/tcp.c	Wed Nov 18 09:28:52 2009 -0700
+++ b/usr/src/uts/common/inet/tcp/tcp.c	Wed Nov 18 09:20:55 2009 -0800
@@ -8527,15 +8527,30 @@
 {
 	tcp_stack_t	*tcps = tcp->tcp_tcps;
 	conn_t		*connp = tcp->tcp_connp;
+	char		buf[TCP_MAX_HDR_LENGTH];
+	uint_t		buflen;
+	uint_t		ulplen = TCP_MIN_HEADER_LENGTH;
+	uint_t		extralen = TCP_MAX_TCP_OPTIONS_LENGTH;
 	tcpha_t		*tcpha;
 	uint32_t	cksum;
 	int		error;
 
+	/*
+	 * We might be called after the connection is set up, and we might
+	 * have TS options already in the TCP header. Thus we  save any
+	 * existing tcp header.
+	 */
+	buflen = connp->conn_ht_ulp_len;
+	if (buflen != 0) {
+		bcopy(connp->conn_ht_ulp, buf, buflen);
+		extralen -= buflen - ulplen;
+		ulplen = buflen;
+	}
+
 	/* Grab lock to satisfy ASSERT; TCP is serialized using squeue */
 	mutex_enter(&connp->conn_lock);
-	error = conn_build_hdr_template(connp, TCP_MIN_HEADER_LENGTH,
-	    TCP_MAX_TCP_OPTIONS_LENGTH, &connp->conn_laddr_v6,
-	    &connp->conn_faddr_v6, connp->conn_flowinfo);
+	error = conn_build_hdr_template(connp, ulplen, extralen,
+	    &connp->conn_laddr_v6, &connp->conn_faddr_v6, connp->conn_flowinfo);
 	mutex_exit(&connp->conn_lock);
 	if (error != 0)
 		return (error);
@@ -8547,10 +8562,15 @@
 	tcpha = (tcpha_t *)connp->conn_ht_ulp;
 	tcp->tcp_tcpha = tcpha;
 
-	tcpha->tha_lport = connp->conn_lport;
-	tcpha->tha_fport = connp->conn_fport;
-	tcpha->tha_sum = 0;
-	tcpha->tha_offset_and_reserved = (5 << 4);
+	/* restore any old tcp header */
+	if (buflen != 0) {
+		bcopy(buf, connp->conn_ht_ulp, buflen);
+	} else {
+		tcpha->tha_lport = connp->conn_lport;
+		tcpha->tha_fport = connp->conn_fport;
+		tcpha->tha_sum = 0;
+		tcpha->tha_offset_and_reserved = (5 << 4);
+	}
 
 	/*
 	 * IP wants our header length in the checksum field to