diff options
author | brian <brian@FreeBSD.org> | 1999-10-13 07:49:13 +0000 |
---|---|---|
committer | brian <brian@FreeBSD.org> | 1999-10-13 07:49:13 +0000 |
commit | c1de2e69b94f0d98027eb56f83408c57ad570eb2 (patch) | |
tree | 8b3e7735282a5f1e7b18e950675101902537d815 /usr.sbin/ppp | |
parent | 1e09a99ada53a192649596eefdff0d435852ea59 (diff) | |
download | FreeBSD-src-c1de2e69b94f0d98027eb56f83408c57ad570eb2.zip FreeBSD-src-c1de2e69b94f0d98027eb56f83408c57ad570eb2.tar.gz |
When uncompressing VJ-compressed frames, fix the ip_sum directly
in struct cstate rather than copying the stored header slot into a
potentially mis-aligned buffer then trying to update the ip_sum
without causing an exception on non-i386 hardware.
I've never been able to reproduce this problem, but it has been
reported by many people... besides, the code is now a bit cleaner.
Testing & patience by: Anthony Solovjoff <asolovjoff@hotmail.com>
Diffstat (limited to 'usr.sbin/ppp')
-rw-r--r-- | usr.sbin/ppp/slcompress.c | 30 |
1 files changed, 13 insertions, 17 deletions
diff --git a/usr.sbin/ppp/slcompress.c b/usr.sbin/ppp/slcompress.c index 16912a6..19bbb4a 100644 --- a/usr.sbin/ppp/slcompress.c +++ b/usr.sbin/ppp/slcompress.c @@ -414,6 +414,7 @@ sl_uncompress_tcp(u_char ** bufp, int len, u_int type, struct slcompress *comp, register struct tcphdr *th; register struct cstate *cs; register struct ip *ip; + u_short *bp; switch (type) { @@ -437,7 +438,6 @@ sl_uncompress_tcp(u_char ** bufp, int len, u_int type, struct slcompress *comp, if (hlen > MAX_HDR) goto bad; memcpy(&cs->cs_ip, ip, hlen); - cs->cs_ip.ip_sum = 0; cs->cs_hlen = hlen; slstat->sls_uncompressedin++; return (len); @@ -541,26 +541,22 @@ sl_uncompress_tcp(u_char ** bufp, int len, u_int type, struct slcompress *comp, */ goto bad; - cp -= cs->cs_hlen; + *bufp = cp - cs->cs_hlen; len += cs->cs_hlen; cs->cs_ip.ip_len = htons(len); - memcpy(cp, &cs->cs_ip, cs->cs_hlen); - *bufp = cp; /* recompute the ip header checksum */ - { - u_short sum, *bp = (u_short *)&cs->cs_ip; - - for (changes = 0; hlen > 0; hlen -= 2) - changes += *bp++; - changes = (changes & 0xffff) + (changes >> 16); - changes = (changes & 0xffff) + (changes >> 16); - - /* Watch out for alighment problems.... */ - sum = ~changes; - bp = (u_short *)(cp + (int)&((struct ip *)0)->ip_sum); - memcpy(bp, &sum, sizeof *bp); - } + cs->cs_ip.ip_sum = 0; + bp = (u_short *)&cs->cs_ip; + for (changes = 0; hlen > 0; hlen -= 2) + changes += *bp++; + changes = (changes & 0xffff) + (changes >> 16); + changes = (changes & 0xffff) + (changes >> 16); + cs->cs_ip.ip_sum = ~changes; + + /* And copy the result into our buffer */ + memcpy(*bufp, &cs->cs_ip, cs->cs_hlen); + return (len); bad: comp->flags |= SLF_TOSS; |