add /etc/ppp/peers
[ppp.git] / ultrix / slcompress.c
index 2d11faa2d5dbca7d27c6d99b24b2511c683853e5..1cbdd3f79f7d5c052e523f55534abc2252a9f5cd 100644 (file)
@@ -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);
 }