X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=ultrix%2Fslcompress.c;h=1cbdd3f79f7d5c052e523f55534abc2252a9f5cd;hp=2d11faa2d5dbca7d27c6d99b24b2511c683853e5;hb=642b44a17f5b83cbfbbbca87d85ec0e4d83762cd;hpb=1799a5c14d883772c63fa1475a89f97309db3dc8 diff --git a/ultrix/slcompress.c b/ultrix/slcompress.c index 2d11faa..1cbdd3f 100644 --- a/ultrix/slcompress.c +++ b/ultrix/slcompress.c @@ -24,7 +24,7 @@ * so that the entire packet being decompressed doesn't have * to be in contiguous memory (just the compressed header). * - * $Id: slcompress.c,v 1.1 1994/11/22 00:27:52 paulus Exp $ + * $Id: slcompress.c,v 1.3 1996/05/24 07:04:55 paulus Exp $ */ #include "../h/types.h" @@ -35,6 +35,7 @@ #include "../net/netinet/ip.h" #include "../net/netinet/tcp.h" +#include "ppp_defs.h" #include "slcompress.h" #ifndef SL_NO_STATS @@ -151,8 +152,7 @@ sl_compress_setup(comp, max_state) } \ } - -u_char +u_int sl_compress_tcp(m, ip, comp, compress_cid) struct mbuf *m; register struct ip *ip; @@ -415,46 +415,89 @@ sl_uncompress_tcp(bufp, len, type, comp) u_int type; struct slcompress *comp; { - return sl_uncompress_tcp_part(bufp, len, len, type, comp); -} + u_char *hdr, *cp; + int hlen, vjlen; + + cp = bufp? *bufp: NULL; + vjlen = sl_uncompress_tcp_core(cp, len, len, type, comp, &hdr, &hlen); + if (vjlen < 0) + return (0); /* error */ + if (vjlen == 0) + return (len); /* was uncompressed already */ + cp += vjlen; + len -= vjlen; + + /* + * At this point, cp points to the first byte of data in the + * packet. If we're not aligned on a 4-byte boundary, copy the + * data down so the ip & tcp headers will be aligned. Then back up + * cp by the tcp/ip header length to make room for the reconstructed + * header (we assume the packet we were handed has enough space to + * prepend 128 bytes of header). + */ + if ((int)cp & 3) { + if (len > 0) + (void) ovbcopy(cp, (caddr_t)((int)cp &~ 3), len); + cp = (u_char *)((int)cp &~ 3); + } + cp -= hlen; + len += hlen; + BCOPY(hdr, cp, hlen); + + *bufp = cp; + return (len); +} /* * Uncompress a packet of total length total_len. The first buflen - * bytes are at *bufp; this must include the entire (compressed or - * uncompressed) TCP/IP header. In addition, there must be enough - * clear space before *bufp to build a full-length TCP/IP header. + * bytes are at buf; this must include the entire (compressed or + * uncompressed) TCP/IP header. This procedure returns the length + * of the VJ header, with a pointer to the uncompressed IP header + * in *hdrp and its length in *hlenp. */ int -sl_uncompress_tcp_part(bufp, buflen, total_len, type, comp) - u_char **bufp; +sl_uncompress_tcp_core(buf, buflen, total_len, type, comp, hdrp, hlenp) + u_char *buf; int buflen, total_len; u_int type; struct slcompress *comp; + u_char **hdrp; + u_int *hlenp; { register u_char *cp; register u_int hlen, changes; register struct tcphdr *th; register struct cstate *cs; register struct ip *ip; + register u_short *bp; + register u_int vjlen; switch (type) { case TYPE_UNCOMPRESSED_TCP: - ip = (struct ip *) *bufp; + ip = (struct ip *) buf; if (ip->ip_p >= MAX_STATES) goto bad; cs = &comp->rstate[comp->last_recv = ip->ip_p]; comp->flags &=~ SLF_TOSS; ip->ip_p = IPPROTO_TCP; - hlen = ip->ip_hl; - hlen += ((struct tcphdr *)&((int *)ip)[hlen])->th_off; - hlen <<= 2; + /* + * Calculate the size of the TCP/IP header and make sure that + * we don't overflow the space we have available for it. + */ + hlen = ip->ip_hl << 2; + if (hlen + sizeof(struct tcphdr) > buflen) + goto bad; + hlen += ((struct tcphdr *)&((char *)ip)[hlen])->th_off << 2; + if (hlen > MAX_HDR || hlen > buflen) + goto bad; BCOPY(ip, &cs->cs_ip, hlen); - cs->cs_ip.ip_sum = 0; cs->cs_hlen = hlen; INCR(sls_uncompressedin) - return (total_len); + *hdrp = (u_char *) &cs->cs_ip; + *hlenp = hlen; + return (0); default: goto bad; @@ -464,7 +507,7 @@ sl_uncompress_tcp_part(bufp, buflen, total_len, type, comp) } /* We've got a compressed packet. */ INCR(sls_compressedin) - cp = *bufp; + cp = buf; changes = *cp++; if (changes & NEW_C) { /* Make sure the state index is in range, then grab the state. @@ -480,7 +523,7 @@ sl_uncompress_tcp_part(bufp, buflen, total_len, type, comp) * explicit state index, we have to toss the packet. */ if (comp->flags & SLF_TOSS) { INCR(sls_tossed) - return (0); + return (-1); } } cs = &comp->rstate[comp->last_recv]; @@ -528,43 +571,34 @@ sl_uncompress_tcp_part(bufp, buflen, total_len, type, comp) /* * At this point, cp points to the first byte of data in the - * packet. If we're not aligned on a 4-byte boundary, copy the - * data down so the ip & tcp headers will be aligned. Then back up - * cp by the tcp/ip header length to make room for the reconstructed - * header (we assume the packet we were handed has enough space to - * prepend 128 bytes of header). Adjust the length to account for - * the new header & fill in the IP total length. + * packet. Fill in the IP total length and update the IP + * header checksum. */ - buflen -= (cp - *bufp); - total_len -= (cp - *bufp); + vjlen = cp - buf; + buflen -= vjlen; if (buflen < 0) /* we must have dropped some characters (crc should detect * this but the old slip framing won't) */ goto bad; - if ((int)cp & 3) { - if (buflen > 0) - (void) ovbcopy(cp, (caddr_t)((int)cp &~ 3), buflen); - cp = (u_char *)((int)cp &~ 3); - } - cp -= cs->cs_hlen; - total_len += cs->cs_hlen; + total_len += cs->cs_hlen - vjlen; cs->cs_ip.ip_len = htons(total_len); - BCOPY(&cs->cs_ip, cp, cs->cs_hlen); - *bufp = cp; /* recompute the ip header checksum */ - { - register u_short *bp = (u_short *)cp; - for (changes = 0; hlen > 0; hlen -= 2) - changes += *bp++; - changes = (changes & 0xffff) + (changes >> 16); - changes = (changes & 0xffff) + (changes >> 16); - ((struct ip *)cp)->ip_sum = ~ changes; - } - return (total_len); + bp = (u_short *) &cs->cs_ip; + cs->cs_ip.ip_sum = 0; + 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; + + *hdrp = (u_char *) &cs->cs_ip; + *hlenp = cs->cs_hlen; + return vjlen; + bad: comp->flags |= SLF_TOSS; INCR(sls_errorin) - return (0); + return (-1); }