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>
This commit is contained in:
Brian Somers 1999-10-13 07:49:13 +00:00
parent 6ed62da4d9
commit 71981dcfc1
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=52197

View File

@ -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;
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;
for (changes = 0; hlen > 0; hlen -= 2)
changes += *bp++;
changes = (changes & 0xffff) + (changes >> 16);
changes = (changes & 0xffff) + (changes >> 16);
/* And copy the result into our buffer */
memcpy(*bufp, &cs->cs_ip, cs->cs_hlen);
/* Watch out for alighment problems.... */
sum = ~changes;
bp = (u_short *)(cp + (int)&((struct ip *)0)->ip_sum);
memcpy(bp, &sum, sizeof *bp);
}
return (len);
bad:
comp->flags |= SLF_TOSS;