]> git.ozlabs.org Git - ppp.git/blobdiff - modules/bsd-comp.c
*** empty log message ***
[ppp.git] / modules / bsd-comp.c
index f2a688c4805b1b17be51355d3df98c437f8713be..dfa73aaa538346266f9f2a5d689200fbcab2a551 100644 (file)
 /*
  * This version is for use with STREAMS under SunOS 4.x.
  *
- * $Id: bsd-comp.c,v 1.4 1994/09/16 02:06:31 paulus Exp $
+ * $Id: bsd-comp.c,v 1.6 1994/10/24 04:28:14 paulus Exp $
  */
 
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/stream.h>
 #include <sys/kmem_alloc.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/ppp_defs.h>
 #include <net/ppp_str.h>
 
-#define PACKET mblk_t
+#define PACKETPTR      mblk_t *
 #include <net/ppp-comp.h>
 
 /*
@@ -94,16 +97,21 @@ struct bsd_db {
     u_char  maxbits;
     u_char  debug;
     u_char  unit;
-    u_short mru;
     u_short seqno;                     /* sequence number of next packet */
+    u_int   mru;
     u_int   maxmaxcode;                        /* largest valid code */
     u_int   max_ent;                   /* largest code in use */
-    u_int   in_count;                  /* uncompressed bytes */
-    u_int   bytes_out;                 /* compressed bytes */
+    u_int   in_count;                  /* uncompressed bytes, aged */
+    u_int   bytes_out;                 /* compressed bytes, aged */
     u_int   ratio;                     /* recent compression ratio */
-    u_int  checkpoint;                 /* when to next check the ratio */
-    int            clear_count;                /* times dictionary cleared */
-    int            incomp_count;               /* incompressible packets */
+    u_int   checkpoint;                        /* when to next check the ratio */
+    u_int   clear_count;               /* times dictionary cleared */
+    u_int   incomp_count;              /* incompressible packets */
+    u_int   incomp_bytes;              /* incompressible bytes */
+    u_int   uncomp_count;              /* uncompressed packets */
+    u_int   uncomp_bytes;              /* uncompressed bytes */
+    u_int   comp_count;                        /* compressed packets */
+    u_int   comp_bytes;                        /* compressed bytes */
     u_short *lens;                     /* array of lengths of codes */
     struct bsd_dict {
        union {                         /* hash value */
@@ -142,6 +150,7 @@ static int  bsd_compress __P((void *state, mblk_t **mret,
 static void    bsd_incomp __P((void *state, mblk_t *dmsg));
 static int     bsd_decompress __P((void *state, mblk_t *cmp, mblk_t **dmpp));
 static void    bsd_reset __P((void *state));
+static void    bsd_comp_stats __P((void *state, struct compstat *stats));
 
 /*
  * Procedures exported to ppp_comp.c.
@@ -153,12 +162,14 @@ struct compressor ppp_bsd_compress = {
     bsd_comp_init,             /* comp_init */
     bsd_reset,                 /* comp_reset */
     bsd_compress,              /* compress */
+    bsd_comp_stats,            /* comp_stat */
     bsd_decomp_alloc,          /* decomp_alloc */
     bsd_free,                  /* decomp_free */
     bsd_decomp_init,           /* decomp_init */
     bsd_reset,                 /* decomp_reset */
     bsd_decompress,            /* decompress */
     bsd_incomp,                        /* incomp */
+    bsd_comp_stats,            /* decomp_stat */
 };
 
 /*
@@ -253,6 +264,33 @@ bsd_check(db)
     return 0;
 }
 
+/*
+ * Return statistics.
+ */
+static void
+bsd_comp_stats(state, stats)
+    void *state;
+    struct compstat *stats;
+{
+    struct bsd_db *db = (struct bsd_db *) state;
+    u_int out;
+
+    stats->unc_bytes = db->uncomp_bytes;
+    stats->unc_packets = db->uncomp_count;
+    stats->comp_bytes = db->comp_bytes;
+    stats->comp_packets = db->comp_count;
+    stats->inc_bytes = db->incomp_bytes;
+    stats->inc_packets = db->incomp_count;
+    stats->ratio = db->in_count;
+    out = db->bytes_out;
+    if (stats->ratio <= 0x7fffff)
+       stats->ratio <<= 8;
+    else
+       out >>= 8;
+    if (out != 0)
+       stats->ratio /= out;
+}
+
 /*
  * Reset state, as on a CCP ResetReq.
  */
@@ -395,11 +433,10 @@ bsd_init(db, options, opt_len, unit, mru, debug, decomp)
 
     db->unit = unit;
     db->mru = mru;
-    db->clear_count = -1;
     if (debug)
        db->debug = 1;
 
-    bsd_clear(db);
+    bsd_reset(db);
 
     return 1;
 }
@@ -425,7 +462,6 @@ bsd_decomp_init(state, options, opt_len, unit, mru, debug)
 }
 
 
-
 /*
  * compress a packet
  *     One change from the BSD compress command is that when the
@@ -447,7 +483,7 @@ bsd_compress(state, mretp, mp, slen, maxolen)
     u_int32_t accm = 0, fcode;
     struct bsd_dict *dictp;
     u_char c;
-    int hval, disp, ent;
+    int hval, disp, ent, ilen;
     mblk_t *np, *mret;
     u_char *rptr, *wptr;
     u_char *cp_end;
@@ -541,7 +577,7 @@ bsd_compress(state, mretp, mp, slen, maxolen)
     rptr += PPP_HDRLEN;
 
     slen = mp->b_wptr - rptr;
-    db->in_count += slen + 1;
+    ilen = slen + 1;
     np = mp->b_cont;
     for (;;) {
        if (slen <= 0) {
@@ -552,7 +588,7 @@ bsd_compress(state, mretp, mp, slen, maxolen)
            np = np->b_cont;
            if (!slen)
                continue;   /* handle 0-length buffers */
-           db->in_count += slen;
+           ilen += slen;
        }
 
        slen--;
@@ -579,7 +615,7 @@ bsd_compress(state, mretp, mp, slen, maxolen)
            if (dictp->codem1 >= max_ent)
                goto nomatch;
        } while (dictp->f.fcode != fcode);
-       ent = dictp->codem1+1;          /* finally found (prefix,suffix) */
+       ent = dictp->codem1 + 1;        /* finally found (prefix,suffix) */
        continue;
 
     nomatch:
@@ -607,11 +643,14 @@ bsd_compress(state, mretp, mp, slen, maxolen)
        ent = c;
     }
 
-    OUTPUT(ent);                       /* output the last code */
+    OUTPUT(ent);               /* output the last code */
     db->bytes_out += olen;
+    db->in_count += ilen;
+    if (bitno < 32)
+       ++db->bytes_out;        /* count complete bytes */
 
     if (bsd_check(db))
-       OUTPUT(CLEAR);                  /* do not count the CLEAR */
+       OUTPUT(CLEAR);          /* do not count the CLEAR */
 
     /*
      * Pad dribble bits of last code with ones.
@@ -627,16 +666,22 @@ bsd_compress(state, mretp, mp, slen, maxolen)
     if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode)
        db->n_bits++;
 
+    db->uncomp_bytes += ilen;
+    ++db->uncomp_count;
     if (olen + PPP_HDRLEN + BSD_OVHD > maxolen && mret != NULL) {
        /* throw away the compressed stuff if it is longer than uncompressed */
        freemsg(mret);
        mret = NULL;
+       ++db->incomp_count;
+       db->incomp_bytes += ilen;
     } else if (wptr != NULL) {
        m->b_wptr = wptr;
        if (m->b_cont) {
            freemsg(m->b_cont);
            m->b_cont = NULL;
        }
+       ++db->comp_count;
+       db->comp_bytes += olen + BSD_OVHD;
     }
 
     *mretp = mret;
@@ -663,7 +708,7 @@ bsd_incomp(state, dmsg)
     u_int32_t fcode;
     u_char c;
     long hval, disp;
-    int slen;
+    int slen, ilen;
     u_int bitno = 7;
     u_char *rptr;
     u_int ent;
@@ -680,7 +725,7 @@ bsd_incomp(state, dmsg)
 
     db->incomp_count++;
     db->seqno++;
-    db->in_count++;            /* count the protocol as 1 byte */
+    ilen = 1;          /* count the protocol as 1 byte */
     rptr += PPP_HDRLEN;
     for (;;) {
        slen = dmsg->b_wptr - rptr;
@@ -691,7 +736,7 @@ bsd_incomp(state, dmsg)
            rptr = dmsg->b_rptr;
            continue;           /* skip zero-length buffers */
        }
-       db->in_count += slen;
+       ilen += slen;
 
        do {
            c = *rptr++;
@@ -748,8 +793,14 @@ bsd_incomp(state, dmsg)
     }
     bitno += n_bits;           /* output (count) the last code */
     db->bytes_out += bitno/8;
+    db->in_count += ilen;
     (void)bsd_check(db);
 
+    ++db->incomp_count;
+    db->incomp_bytes += ilen;
+    ++db->uncomp_count;
+    db->uncomp_bytes += ilen;
+
     /* Increase code size if we would have without the packet
      * boundary and as the decompressor will.
      */
@@ -760,6 +811,19 @@ bsd_incomp(state, dmsg)
 
 /*
  * Decompress "BSD Compress"
+ *
+ * Because of patent problems, we return DECOMP_ERROR for errors
+ * found by inspecting the input data and for system problems, but
+ * DECOMP_FATALERROR for any errors which could possibly be said to
+ * be being detected "after" decompression.  For DECOMP_ERROR,
+ * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
+ * infringing a patent of Motorola's if we do, so we take CCP down
+ * instead.
+ *
+ * Given that the frame has the correct sequence number and a good FCS,
+ * errors such as invalid codes in the input most likely indicate a
+ * bug, so we return DECOMP_FATALERROR for them in order to turn off
+ * compression, even though they are detected by inspecting the input.
  */
 static int
 bsd_decompress(state, cmsg, dmpp)
@@ -777,7 +841,7 @@ bsd_decompress(state, cmsg, dmpp)
     u_int incode, oldcode, finchar;
     u_char *p, *rptr, *wptr;
     mblk_t *dmsg, *mret;
-    int adrs, ctrl;
+    int adrs, ctrl, ilen;
     int dlen, space, codelen, extra;
 
     /*
@@ -802,7 +866,7 @@ bsd_decompress(state, cmsg, dmpp)
     rptr += PPP_HDRLEN;
     seq = (rptr[0] << 8) + rptr[1];
     rptr += BSD_OVHD;
-    len = cmsg->b_wptr - rptr;
+    ilen = len = cmsg->b_wptr - rptr;
 
     /*
      * Check the sequence number and give up if it is not what we expect.
@@ -830,7 +894,6 @@ bsd_decompress(state, cmsg, dmpp)
     wptr += PPP_HDRLEN - 1;
     space = dmsg->b_datap->db_lim - wptr;
 
-    db->bytes_out += len;
     oldcode = CLEAR;
     explen = 0;
     for (;;) {
@@ -840,7 +903,7 @@ bsd_decompress(state, cmsg, dmpp)
                break;
            rptr = cmsg->b_rptr;
            len = cmsg->b_wptr - rptr;
-           db->bytes_out += len;
+           ilen += len;
            continue;           /* handle 0-length buffers */
        }
 
@@ -875,11 +938,11 @@ bsd_decompress(state, cmsg, dmpp)
                }
            }
            bsd_clear(db);
-           explen = 0;
+           explen = ilen = 0;
            break;
        }
 
-       if (incode > max_ent+2 || incode > db->maxmaxcode
+       if (incode > max_ent + 2 || incode > db->maxmaxcode
            || incode > max_ent && oldcode == CLEAR) {
            freemsg(dmsg);
            if (db->debug) {
@@ -888,7 +951,7 @@ bsd_decompress(state, cmsg, dmpp)
                printf("max_ent=0x%x dlen=%d seqno=%d\n",
                       max_ent, dlen, db->seqno);
            }
-           return DECOMP_FATALERROR;
+           return DECOMP_FATALERROR;   /* probably a bug */
        }
 
        /* Special case for KwKwK string. */
@@ -1018,12 +1081,18 @@ bsd_decompress(state, cmsg, dmpp)
      * Keep the checkpoint right so that incompressible packets
      * clear the dictionary at the right times.
      */
+    db->bytes_out += ilen;
     db->in_count += explen;
     if (bsd_check(db) && db->debug) {
        printf("bsd_decomp%d: peer should have cleared dictionary\n",
               db->unit);
     }
 
+    ++db->comp_count;
+    db->comp_bytes += ilen + BSD_OVHD;
+    ++db->uncomp_count;
+    db->uncomp_bytes += explen;
+
     *dmpp = mret;
     return DECOMP_OK;
 }