Subject: ip_nat MSS clamping
To: Darren Reed <darrenr@reed.wattle.id.au>
From: Jun-ichiro itojun Hagino <itojun@iijlab.net>
List: tech-net
Date: 06/03/2002 08:24:07
sys/netinet/ip_nat.c has tcp option parsing bug in MSS clamping
handling.
- it does not stop at EOL
- it does incorrect processing of NOP
does the following look ok?
itojun
Index: ip_nat.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/ip_nat.c,v
retrieving revision 1.48
diff -u -r1.48 ip_nat.c
--- ip_nat.c 2002/05/02 17:13:29 1.48
+++ ip_nat.c 2002/06/02 23:23:27
@@ -1147,34 +1147,46 @@
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) {
+ 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;
+ switch (opt) {
case TCPOPT_MAXSEG:
- ++cp;
- mss = (uint32_t)ntohs(*(short *)cp);
+ if (advance != 4)
+ break;
+ mss = (uint32_t)ntohs(*(short *)&cp[2]);
if (mss > maxmss) {
*(short *)cp = 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;
+ break;
}
+
+ cp += advance;
}
}
}