Subject: Re: ip_nat MSS clamping
To: Jun-ichiro itojun Hagino <itojun@iijlab.net>
From: Martin Husemann <martin@duskware.de>
List: tech-net
Date: 06/03/2002 13:16:49
--LwW0XdcUbUexiWVK
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

How about this version?

Martin

--LwW0XdcUbUexiWVK
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=patch

Index: ip_nat.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/ip_nat.c,v
retrieving revision 1.48
diff -c -u -r1.48 ip_nat.c
--- ip_nat.c	2002/05/02 17:13:29	1.48
+++ ip_nat.c	2002/06/03 11:09:38
@@ -1147,34 +1147,42 @@
 	fr_info_t *fin;
 	u_short *csump;
 {
-	uint8_t *cp;
+	uint8_t *cp, *ep;
 	uint32_t opt, mss, sumd;
 	int hlen;
+	int advance;
 
 	hlen = tcp->th_off << 2;
 	if (hlen > sizeof(*tcp)) {
 		cp = (uint8_t *)tcp + sizeof(*tcp);
+		ep = cp + hlen;
 
-		while (hlen > 0) {
-			opt = *cp++;
-			switch(opt) {
-			case TCPOPT_MAXSEG:
-				++cp;
-				mss = (uint32_t)ntohs(*(short *)cp);
+		while (cp < ep) {
+			opt = cp[0];
+			if (opt == TCPOPT_EOL)
+				break;
+			if (opt == TCPOPT_NOP) {
+				cp++;
+				continue;
+			}
+
+			if (&cp[1] > ep)
+				break;
+			advance = cp[1];
+			if (&cp[advance] > ep)
+				break;
+			if (opt == TCPOPT_MAXSEG) {
+				if (advance != 4)
+					break;
+				mss = (uint32_t)ntohs(*(short *)&cp[2]);
 				if (mss > maxmss) {
-					*(short *)cp = htons((short)(maxmss));
+					*(short *)&cp[2] = htons((short)(maxmss));
 					CALC_SUMD(mss, maxmss, sumd);
 					fix_outcksum(fin, csump, sumd);
 				}
-				hlen = 0;
 				break;
-			case TCPOPT_EOL:
-			case TCPOPT_NOP:
-				hlen--;
-			default:
-				hlen -= *cp;
-				cp += *cp - 2;
 			}
+			cp += advance;
 		}
 	}
 }

--LwW0XdcUbUexiWVK--