[BACK]Return to bsd-comp.c CVS log [TXT][DIR] Up to [local] / sys / net

Annotation of sys/net/bsd-comp.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: bsd-comp.c,v 1.6 2003/06/02 23:28:11 millert Exp $    */
        !             2: /*     $NetBSD: bsd-comp.c,v 1.6 1996/10/13 02:10:58 christos Exp $    */
        !             3:
        !             4: /* Because this code is derived from the 4.3BSD compress source:
        !             5:  *
        !             6:  *
        !             7:  * Copyright (c) 1985, 1986 The Regents of the University of California.
        !             8:  * All rights reserved.
        !             9:  *
        !            10:  * This code is derived from software contributed to Berkeley by
        !            11:  * James A. Woods, derived from original work by Spencer Thomas
        !            12:  * and Joseph Orost.
        !            13:  *
        !            14:  * Redistribution and use in source and binary forms, with or without
        !            15:  * modification, are permitted provided that the following conditions
        !            16:  * are met:
        !            17:  * 1. Redistributions of source code must retain the above copyright
        !            18:  *    notice, this list of conditions and the following disclaimer.
        !            19:  * 2. Redistributions in binary form must reproduce the above copyright
        !            20:  *    notice, this list of conditions and the following disclaimer in the
        !            21:  *    documentation and/or other materials provided with the distribution.
        !            22:  * 3. Neither the name of the University nor the names of its contributors
        !            23:  *    may be used to endorse or promote products derived from this software
        !            24:  *    without specific prior written permission.
        !            25:  *
        !            26:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            28:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            29:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            30:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            31:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            32:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            36:  * SUCH DAMAGE.
        !            37:  */
        !            38:
        !            39: /*
        !            40:  * This version is for use with mbufs on BSD-derived systems.
        !            41:  */
        !            42:
        !            43: #include <sys/param.h>
        !            44: #include <sys/types.h>
        !            45: #include <sys/systm.h>
        !            46: #include <sys/mbuf.h>
        !            47: #include <sys/socket.h>
        !            48: #include <net/if.h>
        !            49: #include <net/if_types.h>
        !            50: #include <net/ppp_defs.h>
        !            51: #include <net/if_ppp.h>
        !            52:
        !            53: #define PACKETPTR      struct mbuf *
        !            54: #include <net/ppp-comp.h>
        !            55:
        !            56: #if DO_BSD_COMPRESS
        !            57: /*
        !            58:  * PPP "BSD compress" compression
        !            59:  *  The differences between this compression and the classic BSD LZW
        !            60:  *  source are obvious from the requirement that the classic code worked
        !            61:  *  with files while this handles arbitrarily long streams that
        !            62:  *  are broken into packets.  They are:
        !            63:  *
        !            64:  *     When the code size expands, a block of junk is not emitted by
        !            65:  *         the compressor and not expected by the decompressor.
        !            66:  *
        !            67:  *     New codes are not necessarily assigned every time an old
        !            68:  *         code is output by the compressor.  This is because a packet
        !            69:  *         end forces a code to be emitted, but does not imply that a
        !            70:  *         new sequence has been seen.
        !            71:  *
        !            72:  *     The compression ratio is checked at the first end of a packet
        !            73:  *         after the appropriate gap.  Besides simplifying and speeding
        !            74:  *         things up, this makes it more likely that the transmitter
        !            75:  *         and receiver will agree when the dictionary is cleared when
        !            76:  *         compression is not going well.
        !            77:  */
        !            78:
        !            79: /*
        !            80:  * A dictionary for doing BSD compress.
        !            81:  */
        !            82: struct bsd_db {
        !            83:     int            totlen;                     /* length of this structure */
        !            84:     u_int   hsize;                     /* size of the hash table */
        !            85:     u_char  hshift;                    /* used in hash function */
        !            86:     u_char  n_bits;                    /* current bits/code */
        !            87:     u_char  maxbits;
        !            88:     u_char  debug;
        !            89:     u_char  unit;
        !            90:     u_int16_t seqno;                   /* sequence # of next packet */
        !            91:     u_int   hdrlen;                    /* header length to preallocate */
        !            92:     u_int   mru;
        !            93:     u_int   maxmaxcode;                        /* largest valid code */
        !            94:     u_int   max_ent;                   /* largest code in use */
        !            95:     u_int   in_count;                  /* uncompressed bytes, aged */
        !            96:     u_int   bytes_out;                 /* compressed bytes, aged */
        !            97:     u_int   ratio;                     /* recent compression ratio */
        !            98:     u_int   checkpoint;                        /* when to next check the ratio */
        !            99:     u_int   clear_count;               /* times dictionary cleared */
        !           100:     u_int   incomp_count;              /* incompressible packets */
        !           101:     u_int   incomp_bytes;              /* incompressible bytes */
        !           102:     u_int   uncomp_count;              /* uncompressed packets */
        !           103:     u_int   uncomp_bytes;              /* uncompressed bytes */
        !           104:     u_int   comp_count;                        /* compressed packets */
        !           105:     u_int   comp_bytes;                        /* compressed bytes */
        !           106:     u_int16_t *lens;                   /* array of lengths of codes */
        !           107:     struct bsd_dict {
        !           108:        union {                         /* hash value */
        !           109:            u_int32_t   fcode;
        !           110:            struct {
        !           111: #if BYTE_ORDER == LITTLE_ENDIAN
        !           112:                u_int16_t prefix;       /* preceding code */
        !           113:                u_char  suffix;         /* last character of new code */
        !           114:                u_char  pad;
        !           115: #else
        !           116:                u_char  pad;
        !           117:                u_char  suffix;         /* last character of new code */
        !           118:                u_int16_t prefix;       /* preceding code */
        !           119: #endif
        !           120:            } hs;
        !           121:        } f;
        !           122:        u_int16_t codem1;               /* output of hash table -1 */
        !           123:        u_int16_t cptr;                 /* map code to hash table entry */
        !           124:     } dict[1];
        !           125: };
        !           126:
        !           127: #define BSD_OVHD       2               /* BSD compress overhead/packet */
        !           128: #define BSD_INIT_BITS  BSD_MIN_BITS
        !           129:
        !           130: static void    *bsd_comp_alloc(u_char *options, int opt_len);
        !           131: static void    *bsd_decomp_alloc(u_char *options, int opt_len);
        !           132: static void    bsd_free(void *state);
        !           133: static int     bsd_comp_init(void *state, u_char *options, int opt_len,
        !           134:                                   int unit, int hdrlen, int debug);
        !           135: static int     bsd_decomp_init(void *state, u_char *options, int opt_len,
        !           136:                                     int unit, int hdrlen, int mru, int debug);
        !           137: static int     bsd_compress(void *state, struct mbuf **mret,
        !           138:                                  struct mbuf *mp, int slen, int maxolen);
        !           139: static void    bsd_incomp(void *state, struct mbuf *dmsg);
        !           140: static int     bsd_decompress(void *state, struct mbuf *cmp,
        !           141:                                    struct mbuf **dmpp);
        !           142: static void    bsd_reset(void *state);
        !           143: static void    bsd_comp_stats(void *state, struct compstat *stats);
        !           144:
        !           145: /*
        !           146:  * Procedures exported to if_ppp.c.
        !           147:  */
        !           148: struct compressor ppp_bsd_compress = {
        !           149:     CI_BSD_COMPRESS,           /* compress_proto */
        !           150:     bsd_comp_alloc,            /* comp_alloc */
        !           151:     bsd_free,                  /* comp_free */
        !           152:     bsd_comp_init,             /* comp_init */
        !           153:     bsd_reset,                 /* comp_reset */
        !           154:     bsd_compress,              /* compress */
        !           155:     bsd_comp_stats,            /* comp_stat */
        !           156:     bsd_decomp_alloc,          /* decomp_alloc */
        !           157:     bsd_free,                  /* decomp_free */
        !           158:     bsd_decomp_init,           /* decomp_init */
        !           159:     bsd_reset,                 /* decomp_reset */
        !           160:     bsd_decompress,            /* decompress */
        !           161:     bsd_incomp,                        /* incomp */
        !           162:     bsd_comp_stats,            /* decomp_stat */
        !           163: };
        !           164:
        !           165: /*
        !           166:  * the next two codes should not be changed lightly, as they must not
        !           167:  * lie within the contiguous general code space.
        !           168:  */
        !           169: #define CLEAR  256                     /* table clear output code */
        !           170: #define FIRST  257                     /* first free entry */
        !           171: #define LAST   255
        !           172:
        !           173: #define MAXCODE(b)     ((1 << (b)) - 1)
        !           174: #define BADCODEM1      MAXCODE(BSD_MAX_BITS)
        !           175:
        !           176: #define BSD_HASH(prefix,suffix,hshift) ((((u_int32_t)(suffix)) << (hshift)) \
        !           177:                                         ^ (u_int32_t)(prefix))
        !           178: #define BSD_KEY(prefix,suffix)         ((((u_int32_t)(suffix)) << 16) \
        !           179:                                         + (u_int32_t)(prefix))
        !           180:
        !           181: #define CHECK_GAP      10000           /* Ratio check interval */
        !           182:
        !           183: #define RATIO_SCALE_LOG        8
        !           184: #define RATIO_SCALE    (1<<RATIO_SCALE_LOG)
        !           185: #define RATIO_MAX      (0x7fffffff>>RATIO_SCALE_LOG)
        !           186:
        !           187: static void bsd_clear(struct bsd_db *);
        !           188: static int bsd_check(struct bsd_db *);
        !           189: static void *bsd_alloc(u_char *, int, int);
        !           190: static int bsd_init(struct bsd_db *, u_char *, int, int, int, int,
        !           191:                         int, int);
        !           192:
        !           193: /*
        !           194:  * clear the dictionary
        !           195:  */
        !           196: static void
        !           197: bsd_clear(db)
        !           198:     struct bsd_db *db;
        !           199: {
        !           200:     db->clear_count++;
        !           201:     db->max_ent = FIRST-1;
        !           202:     db->n_bits = BSD_INIT_BITS;
        !           203:     db->ratio = 0;
        !           204:     db->bytes_out = 0;
        !           205:     db->in_count = 0;
        !           206:     db->incomp_count = 0;
        !           207:     db->checkpoint = CHECK_GAP;
        !           208: }
        !           209:
        !           210: /*
        !           211:  * If the dictionary is full, then see if it is time to reset it.
        !           212:  *
        !           213:  * Compute the compression ratio using fixed-point arithmetic
        !           214:  * with 8 fractional bits.
        !           215:  *
        !           216:  * Since we have an infinite stream instead of a single file,
        !           217:  * watch only the local compression ratio.
        !           218:  *
        !           219:  * Since both peers must reset the dictionary at the same time even in
        !           220:  * the absence of CLEAR codes (while packets are incompressible), they
        !           221:  * must compute the same ratio.
        !           222:  */
        !           223: static int                             /* 1=output CLEAR */
        !           224: bsd_check(db)
        !           225:     struct bsd_db *db;
        !           226: {
        !           227:     u_int new_ratio;
        !           228:
        !           229:     if (db->in_count >= db->checkpoint) {
        !           230:        /* age the ratio by limiting the size of the counts */
        !           231:        if (db->in_count >= RATIO_MAX
        !           232:            || db->bytes_out >= RATIO_MAX) {
        !           233:            db->in_count -= db->in_count/4;
        !           234:            db->bytes_out -= db->bytes_out/4;
        !           235:        }
        !           236:
        !           237:        db->checkpoint = db->in_count + CHECK_GAP;
        !           238:
        !           239:        if (db->max_ent >= db->maxmaxcode) {
        !           240:            /* Reset the dictionary only if the ratio is worse,
        !           241:             * or if it looks as if it has been poisoned
        !           242:             * by incompressible data.
        !           243:             *
        !           244:             * This does not overflow, because
        !           245:             *  db->in_count <= RATIO_MAX.
        !           246:             */
        !           247:            new_ratio = db->in_count << RATIO_SCALE_LOG;
        !           248:            if (db->bytes_out != 0)
        !           249:                new_ratio /= db->bytes_out;
        !           250:
        !           251:            if (new_ratio < db->ratio || new_ratio < 1 * RATIO_SCALE) {
        !           252:                bsd_clear(db);
        !           253:                return 1;
        !           254:            }
        !           255:            db->ratio = new_ratio;
        !           256:        }
        !           257:     }
        !           258:     return 0;
        !           259: }
        !           260:
        !           261: /*
        !           262:  * Return statistics.
        !           263:  */
        !           264: static void
        !           265: bsd_comp_stats(state, stats)
        !           266:     void *state;
        !           267:     struct compstat *stats;
        !           268: {
        !           269:     struct bsd_db *db = (struct bsd_db *) state;
        !           270:     u_int out;
        !           271:
        !           272:     stats->unc_bytes = db->uncomp_bytes;
        !           273:     stats->unc_packets = db->uncomp_count;
        !           274:     stats->comp_bytes = db->comp_bytes;
        !           275:     stats->comp_packets = db->comp_count;
        !           276:     stats->inc_bytes = db->incomp_bytes;
        !           277:     stats->inc_packets = db->incomp_count;
        !           278:     stats->ratio = db->in_count;
        !           279:     out = db->bytes_out;
        !           280:     if (stats->ratio <= 0x7fffff)
        !           281:        stats->ratio <<= 8;
        !           282:     else
        !           283:        out >>= 8;
        !           284:     if (out != 0)
        !           285:        stats->ratio /= out;
        !           286: }
        !           287:
        !           288: /*
        !           289:  * Reset state, as on a CCP ResetReq.
        !           290:  */
        !           291: static void
        !           292: bsd_reset(state)
        !           293:     void *state;
        !           294: {
        !           295:     struct bsd_db *db = (struct bsd_db *) state;
        !           296:
        !           297:     db->seqno = 0;
        !           298:     bsd_clear(db);
        !           299:     db->clear_count = 0;
        !           300: }
        !           301:
        !           302: /*
        !           303:  * Allocate space for a (de) compressor.
        !           304:  */
        !           305: static void *
        !           306: bsd_alloc(options, opt_len, decomp)
        !           307:     u_char *options;
        !           308:     int opt_len, decomp;
        !           309: {
        !           310:     int bits;
        !           311:     u_int newlen, hsize, hshift, maxmaxcode;
        !           312:     struct bsd_db *db;
        !           313:
        !           314:     if (opt_len < CILEN_BSD_COMPRESS || options[0] != CI_BSD_COMPRESS
        !           315:        || options[1] != CILEN_BSD_COMPRESS
        !           316:        || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION)
        !           317:        return NULL;
        !           318:     bits = BSD_NBITS(options[2]);
        !           319:     switch (bits) {
        !           320:     case 9:                    /* needs 82152 for both directions */
        !           321:     case 10:                   /* needs 84144 */
        !           322:     case 11:                   /* needs 88240 */
        !           323:     case 12:                   /* needs 96432 */
        !           324:        hsize = 5003;
        !           325:        hshift = 4;
        !           326:        break;
        !           327:     case 13:                   /* needs 176784 */
        !           328:        hsize = 9001;
        !           329:        hshift = 5;
        !           330:        break;
        !           331:     case 14:                   /* needs 353744 */
        !           332:        hsize = 18013;
        !           333:        hshift = 6;
        !           334:        break;
        !           335:     case 15:                   /* needs 691440 */
        !           336:        hsize = 35023;
        !           337:        hshift = 7;
        !           338:        break;
        !           339:     case 16:                   /* needs 1366160--far too much, */
        !           340:        /* hsize = 69001; */    /* and 69001 is too big for cptr */
        !           341:        /* hshift = 8; */       /* in struct bsd_db */
        !           342:        /* break; */
        !           343:     default:
        !           344:        return NULL;
        !           345:     }
        !           346:
        !           347:     maxmaxcode = MAXCODE(bits);
        !           348:     newlen = sizeof(*db) + (hsize-1) * (sizeof(db->dict[0]));
        !           349:     MALLOC(db, struct bsd_db *, newlen, M_DEVBUF, M_NOWAIT);
        !           350:     if (!db)
        !           351:        return NULL;
        !           352:     bzero(db, sizeof(*db) - sizeof(db->dict));
        !           353:
        !           354:     if (!decomp) {
        !           355:        db->lens = NULL;
        !           356:     } else {
        !           357:        MALLOC(db->lens, u_int16_t *, (maxmaxcode+1) * sizeof(db->lens[0]),
        !           358:               M_DEVBUF, M_NOWAIT);
        !           359:        if (!db->lens) {
        !           360:            FREE(db, M_DEVBUF);
        !           361:            return NULL;
        !           362:        }
        !           363:     }
        !           364:
        !           365:     db->totlen = newlen;
        !           366:     db->hsize = hsize;
        !           367:     db->hshift = hshift;
        !           368:     db->maxmaxcode = maxmaxcode;
        !           369:     db->maxbits = bits;
        !           370:
        !           371:     return (void *) db;
        !           372: }
        !           373:
        !           374: static void
        !           375: bsd_free(state)
        !           376:     void *state;
        !           377: {
        !           378:     struct bsd_db *db = (struct bsd_db *) state;
        !           379:
        !           380:     if (db->lens)
        !           381:        FREE(db->lens, M_DEVBUF);
        !           382:     FREE(db, M_DEVBUF);
        !           383: }
        !           384:
        !           385: static void *
        !           386: bsd_comp_alloc(options, opt_len)
        !           387:     u_char *options;
        !           388:     int opt_len;
        !           389: {
        !           390:     return bsd_alloc(options, opt_len, 0);
        !           391: }
        !           392:
        !           393: static void *
        !           394: bsd_decomp_alloc(options, opt_len)
        !           395:     u_char *options;
        !           396:     int opt_len;
        !           397: {
        !           398:     return bsd_alloc(options, opt_len, 1);
        !           399: }
        !           400:
        !           401: /*
        !           402:  * Initialize the database.
        !           403:  */
        !           404: static int
        !           405: bsd_init(db, options, opt_len, unit, hdrlen, mru, debug, decomp)
        !           406:     struct bsd_db *db;
        !           407:     u_char *options;
        !           408:     int opt_len, unit, hdrlen, mru, debug, decomp;
        !           409: {
        !           410:     int i;
        !           411:
        !           412:     if (opt_len < CILEN_BSD_COMPRESS || options[0] != CI_BSD_COMPRESS
        !           413:        || options[1] != CILEN_BSD_COMPRESS
        !           414:        || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION
        !           415:        || BSD_NBITS(options[2]) != db->maxbits
        !           416:        || (decomp && db->lens == NULL))
        !           417:        return 0;
        !           418:
        !           419:     if (decomp) {
        !           420:        i = LAST+1;
        !           421:        while (i != 0)
        !           422:            db->lens[--i] = 1;
        !           423:     }
        !           424:     i = db->hsize;
        !           425:     while (i != 0) {
        !           426:        db->dict[--i].codem1 = BADCODEM1;
        !           427:        db->dict[i].cptr = 0;
        !           428:     }
        !           429:
        !           430:     db->unit = unit;
        !           431:     db->hdrlen = hdrlen;
        !           432:     db->mru = mru;
        !           433: #ifndef DEBUG
        !           434:     if (debug)
        !           435: #endif
        !           436:        db->debug = 1;
        !           437:
        !           438:     bsd_reset(db);
        !           439:
        !           440:     return 1;
        !           441: }
        !           442:
        !           443: static int
        !           444: bsd_comp_init(state, options, opt_len, unit, hdrlen, debug)
        !           445:     void *state;
        !           446:     u_char *options;
        !           447:     int opt_len, unit, hdrlen, debug;
        !           448: {
        !           449:     return bsd_init((struct bsd_db *) state, options, opt_len,
        !           450:                    unit, hdrlen, 0, debug, 0);
        !           451: }
        !           452:
        !           453: static int
        !           454: bsd_decomp_init(state, options, opt_len, unit, hdrlen, mru, debug)
        !           455:     void *state;
        !           456:     u_char *options;
        !           457:     int opt_len, unit, hdrlen, mru, debug;
        !           458: {
        !           459:     return bsd_init((struct bsd_db *) state, options, opt_len,
        !           460:                    unit, hdrlen, mru, debug, 1);
        !           461: }
        !           462:
        !           463:
        !           464: /*
        !           465:  * compress a packet
        !           466:  *     One change from the BSD compress command is that when the
        !           467:  *     code size expands, we do not output a bunch of padding.
        !           468:  */
        !           469: int                                    /* new slen */
        !           470: bsd_compress(state, mret, mp, slen, maxolen)
        !           471:     void *state;
        !           472:     struct mbuf **mret;                /* return compressed mbuf chain here */
        !           473:     struct mbuf *mp;           /* from here */
        !           474:     int slen;                  /* uncompressed length */
        !           475:     int maxolen;               /* max compressed length */
        !           476: {
        !           477:     struct bsd_db *db = (struct bsd_db *) state;
        !           478:     int hshift = db->hshift;
        !           479:     u_int max_ent = db->max_ent;
        !           480:     u_int n_bits = db->n_bits;
        !           481:     u_int bitno = 32;
        !           482:     u_int32_t accm = 0, fcode;
        !           483:     struct bsd_dict *dictp;
        !           484:     u_char c;
        !           485:     int hval, disp, ent, ilen;
        !           486:     u_char *rptr, *wptr;
        !           487:     u_char *cp_end;
        !           488:     int olen;
        !           489:     struct mbuf *m;
        !           490:
        !           491: #define PUTBYTE(v) {                                   \
        !           492:     ++olen;                                            \
        !           493:     if (wptr) {                                                \
        !           494:        *wptr++ = (v);                                  \
        !           495:        if (wptr >= cp_end) {                           \
        !           496:            m->m_len = wptr - mtod(m, u_char *);        \
        !           497:            MGET(m->m_next, M_DONTWAIT, MT_DATA);       \
        !           498:            m = m->m_next;                              \
        !           499:            if (m) {                                    \
        !           500:                m->m_len = 0;                           \
        !           501:                if (maxolen - olen > MLEN)              \
        !           502:                    MCLGET(m, M_DONTWAIT);              \
        !           503:                wptr = mtod(m, u_char *);               \
        !           504:                cp_end = wptr + M_TRAILINGSPACE(m);     \
        !           505:            } else                                      \
        !           506:                wptr = NULL;                            \
        !           507:        }                                               \
        !           508:     }                                                  \
        !           509: }
        !           510:
        !           511: #define OUTPUT(ent) {                                  \
        !           512:     bitno -= n_bits;                                   \
        !           513:     accm |= ((ent) << bitno);                          \
        !           514:     do {                                               \
        !           515:        PUTBYTE(accm >> 24);                            \
        !           516:        accm <<= 8;                                     \
        !           517:        bitno += 8;                                     \
        !           518:     } while (bitno <= 24);                             \
        !           519: }
        !           520:
        !           521:     /*
        !           522:      * If the protocol is not in the range we're interested in,
        !           523:      * just return without compressing the packet.  If it is,
        !           524:      * the protocol becomes the first byte to compress.
        !           525:      */
        !           526:     rptr = mtod(mp, u_char *);
        !           527:     ent = PPP_PROTOCOL(rptr);
        !           528:     if (ent < 0x21 || ent > 0xf9) {
        !           529:        *mret = NULL;
        !           530:        return slen;
        !           531:     }
        !           532:
        !           533:     /* Don't generate compressed packets which are larger than
        !           534:        the uncompressed packet. */
        !           535:     if (maxolen > slen)
        !           536:        maxolen = slen;
        !           537:
        !           538:     /* Allocate one mbuf to start with. */
        !           539:     MGET(m, M_DONTWAIT, MT_DATA);
        !           540:     *mret = m;
        !           541:     if (m != NULL) {
        !           542:        m->m_len = 0;
        !           543:        if (maxolen + db->hdrlen > MLEN)
        !           544:            MCLGET(m, M_DONTWAIT);
        !           545:        m->m_data += db->hdrlen;
        !           546:        wptr = mtod(m, u_char *);
        !           547:        cp_end = wptr + M_TRAILINGSPACE(m);
        !           548:     } else
        !           549:        wptr = cp_end = NULL;
        !           550:
        !           551:     /*
        !           552:      * Copy the PPP header over, changing the protocol,
        !           553:      * and install the 2-byte packet sequence number.
        !           554:      */
        !           555:     if (wptr) {
        !           556:        *wptr++ = PPP_ADDRESS(rptr);    /* assumes the ppp header is */
        !           557:        *wptr++ = PPP_CONTROL(rptr);    /* all in one mbuf */
        !           558:        *wptr++ = 0;                    /* change the protocol */
        !           559:        *wptr++ = PPP_COMP;
        !           560:        *wptr++ = db->seqno >> 8;
        !           561:        *wptr++ = db->seqno;
        !           562:     }
        !           563:     ++db->seqno;
        !           564:
        !           565:     olen = 0;
        !           566:     rptr += PPP_HDRLEN;
        !           567:     slen = mp->m_len - PPP_HDRLEN;
        !           568:     ilen = slen + 1;
        !           569:     for (;;) {
        !           570:        if (slen <= 0) {
        !           571:            mp = mp->m_next;
        !           572:            if (!mp)
        !           573:                break;
        !           574:            rptr = mtod(mp, u_char *);
        !           575:            slen = mp->m_len;
        !           576:            if (!slen)
        !           577:                continue;   /* handle 0-length buffers */
        !           578:            ilen += slen;
        !           579:        }
        !           580:
        !           581:        slen--;
        !           582:        c = *rptr++;
        !           583:        fcode = BSD_KEY(ent, c);
        !           584:        hval = BSD_HASH(ent, c, hshift);
        !           585:        dictp = &db->dict[hval];
        !           586:
        !           587:        /* Validate and then check the entry. */
        !           588:        if (dictp->codem1 >= max_ent)
        !           589:            goto nomatch;
        !           590:        if (dictp->f.fcode == fcode) {
        !           591:            ent = dictp->codem1+1;
        !           592:            continue;   /* found (prefix,suffix) */
        !           593:        }
        !           594:
        !           595:        /* continue probing until a match or invalid entry */
        !           596:        disp = (hval == 0) ? 1 : hval;
        !           597:        do {
        !           598:            hval += disp;
        !           599:            if (hval >= db->hsize)
        !           600:                hval -= db->hsize;
        !           601:            dictp = &db->dict[hval];
        !           602:            if (dictp->codem1 >= max_ent)
        !           603:                goto nomatch;
        !           604:        } while (dictp->f.fcode != fcode);
        !           605:        ent = dictp->codem1 + 1;        /* finally found (prefix,suffix) */
        !           606:        continue;
        !           607:
        !           608:     nomatch:
        !           609:        OUTPUT(ent);            /* output the prefix */
        !           610:
        !           611:        /* code -> hashtable */
        !           612:        if (max_ent < db->maxmaxcode) {
        !           613:            struct bsd_dict *dictp2;
        !           614:            /* expand code size if needed */
        !           615:            if (max_ent >= MAXCODE(n_bits))
        !           616:                db->n_bits = ++n_bits;
        !           617:
        !           618:            /* Invalidate old hash table entry using
        !           619:             * this code, and then take it over.
        !           620:             */
        !           621:            dictp2 = &db->dict[max_ent+1];
        !           622:            if (db->dict[dictp2->cptr].codem1 == max_ent)
        !           623:                db->dict[dictp2->cptr].codem1 = BADCODEM1;
        !           624:            dictp2->cptr = hval;
        !           625:            dictp->codem1 = max_ent;
        !           626:            dictp->f.fcode = fcode;
        !           627:
        !           628:            db->max_ent = ++max_ent;
        !           629:        }
        !           630:        ent = c;
        !           631:     }
        !           632:
        !           633:     OUTPUT(ent);               /* output the last code */
        !           634:     db->bytes_out += olen;
        !           635:     db->in_count += ilen;
        !           636:     if (bitno < 32)
        !           637:        ++db->bytes_out;        /* count complete bytes */
        !           638:
        !           639:     if (bsd_check(db))
        !           640:        OUTPUT(CLEAR);          /* do not count the CLEAR */
        !           641:
        !           642:     /*
        !           643:      * Pad dribble bits of last code with ones.
        !           644:      * Do not emit a completely useless byte of ones.
        !           645:      */
        !           646:     if (bitno != 32)
        !           647:        PUTBYTE((accm | (0xff << (bitno-8))) >> 24);
        !           648:
        !           649:     if (m != NULL) {
        !           650:        m->m_len = wptr - mtod(m, u_char *);
        !           651:        m->m_next = NULL;
        !           652:     }
        !           653:
        !           654:     /*
        !           655:      * Increase code size if we would have without the packet
        !           656:      * boundary and as the decompressor will.
        !           657:      */
        !           658:     if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode)
        !           659:        db->n_bits++;
        !           660:
        !           661:     db->uncomp_bytes += ilen;
        !           662:     ++db->uncomp_count;
        !           663:     if (olen + PPP_HDRLEN + BSD_OVHD > maxolen) {
        !           664:        /* throw away the compressed stuff if it is longer than uncompressed */
        !           665:        if (*mret != NULL) {
        !           666:            m_freem(*mret);
        !           667:            *mret = NULL;
        !           668:        }
        !           669:        ++db->incomp_count;
        !           670:        db->incomp_bytes += ilen;
        !           671:     } else {
        !           672:        ++db->comp_count;
        !           673:        db->comp_bytes += olen + BSD_OVHD;
        !           674:     }
        !           675:
        !           676:     return olen + PPP_HDRLEN + BSD_OVHD;
        !           677: #undef OUTPUT
        !           678: #undef PUTBYTE
        !           679: }
        !           680:
        !           681:
        !           682: /*
        !           683:  * Update the "BSD Compress" dictionary on the receiver for
        !           684:  * incompressible data by pretending to compress the incoming data.
        !           685:  */
        !           686: static void
        !           687: bsd_incomp(state, dmsg)
        !           688:     void *state;
        !           689:     struct mbuf *dmsg;
        !           690: {
        !           691:     struct bsd_db *db = (struct bsd_db *) state;
        !           692:     u_int hshift = db->hshift;
        !           693:     u_int max_ent = db->max_ent;
        !           694:     u_int n_bits = db->n_bits;
        !           695:     struct bsd_dict *dictp;
        !           696:     u_int32_t fcode;
        !           697:     u_char c;
        !           698:     u_int32_t hval, disp;
        !           699:     int slen, ilen;
        !           700:     u_int bitno = 7;
        !           701:     u_char *rptr;
        !           702:     u_int ent;
        !           703:
        !           704:     /*
        !           705:      * If the protocol is not in the range we're interested in,
        !           706:      * just return without looking at the packet.  If it is,
        !           707:      * the protocol becomes the first byte to "compress".
        !           708:      */
        !           709:     rptr = mtod(dmsg, u_char *);
        !           710:     ent = PPP_PROTOCOL(rptr);
        !           711:     if (ent < 0x21 || ent > 0xf9)
        !           712:        return;
        !           713:
        !           714:     db->incomp_count++;
        !           715:     db->seqno++;
        !           716:     ilen = 1;          /* count the protocol as 1 byte */
        !           717:     rptr += PPP_HDRLEN;
        !           718:     slen = dmsg->m_len - PPP_HDRLEN;
        !           719:     for (;;) {
        !           720:        if (slen <= 0) {
        !           721:            dmsg = dmsg->m_next;
        !           722:            if (!dmsg)
        !           723:                break;
        !           724:            rptr = mtod(dmsg, u_char *);
        !           725:            slen = dmsg->m_len;
        !           726:            continue;
        !           727:        }
        !           728:        ilen += slen;
        !           729:
        !           730:        do {
        !           731:            c = *rptr++;
        !           732:            fcode = BSD_KEY(ent, c);
        !           733:            hval = BSD_HASH(ent, c, hshift);
        !           734:            dictp = &db->dict[hval];
        !           735:
        !           736:            /* validate and then check the entry */
        !           737:            if (dictp->codem1 >= max_ent)
        !           738:                goto nomatch;
        !           739:            if (dictp->f.fcode == fcode) {
        !           740:                ent = dictp->codem1+1;
        !           741:                continue;   /* found (prefix,suffix) */
        !           742:            }
        !           743:
        !           744:            /* continue probing until a match or invalid entry */
        !           745:            disp = (hval == 0) ? 1 : hval;
        !           746:            do {
        !           747:                hval += disp;
        !           748:                if (hval >= db->hsize)
        !           749:                    hval -= db->hsize;
        !           750:                dictp = &db->dict[hval];
        !           751:                if (dictp->codem1 >= max_ent)
        !           752:                    goto nomatch;
        !           753:            } while (dictp->f.fcode != fcode);
        !           754:            ent = dictp->codem1+1;
        !           755:            continue;   /* finally found (prefix,suffix) */
        !           756:
        !           757:        nomatch:                /* output (count) the prefix */
        !           758:            bitno += n_bits;
        !           759:
        !           760:            /* code -> hashtable */
        !           761:            if (max_ent < db->maxmaxcode) {
        !           762:                struct bsd_dict *dictp2;
        !           763:                /* expand code size if needed */
        !           764:                if (max_ent >= MAXCODE(n_bits))
        !           765:                    db->n_bits = ++n_bits;
        !           766:
        !           767:                /* Invalidate previous hash table entry
        !           768:                 * assigned this code, and then take it over.
        !           769:                 */
        !           770:                dictp2 = &db->dict[max_ent+1];
        !           771:                if (db->dict[dictp2->cptr].codem1 == max_ent)
        !           772:                    db->dict[dictp2->cptr].codem1 = BADCODEM1;
        !           773:                dictp2->cptr = hval;
        !           774:                dictp->codem1 = max_ent;
        !           775:                dictp->f.fcode = fcode;
        !           776:
        !           777:                db->max_ent = ++max_ent;
        !           778:                db->lens[max_ent] = db->lens[ent]+1;
        !           779:            }
        !           780:            ent = c;
        !           781:        } while (--slen != 0);
        !           782:     }
        !           783:     bitno += n_bits;           /* output (count) the last code */
        !           784:     db->bytes_out += bitno/8;
        !           785:     db->in_count += ilen;
        !           786:     (void)bsd_check(db);
        !           787:
        !           788:     ++db->incomp_count;
        !           789:     db->incomp_bytes += ilen;
        !           790:     ++db->uncomp_count;
        !           791:     db->uncomp_bytes += ilen;
        !           792:
        !           793:     /* Increase code size if we would have without the packet
        !           794:      * boundary and as the decompressor will.
        !           795:      */
        !           796:     if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode)
        !           797:        db->n_bits++;
        !           798: }
        !           799:
        !           800:
        !           801: /*
        !           802:  * Decompress "BSD Compress".
        !           803:  *
        !           804:  * Because of patent problems, we return DECOMP_ERROR for errors
        !           805:  * found by inspecting the input data and for system problems, but
        !           806:  * DECOMP_FATALERROR for any errors which could possibly be said to
        !           807:  * be being detected "after" decompression.  For DECOMP_ERROR,
        !           808:  * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
        !           809:  * infringing a patent of Motorola's if we do, so we take CCP down
        !           810:  * instead.
        !           811:  *
        !           812:  * Given that the frame has the correct sequence number and a good FCS,
        !           813:  * errors such as invalid codes in the input most likely indicate a
        !           814:  * bug, so we return DECOMP_FATALERROR for them in order to turn off
        !           815:  * compression, even though they are detected by inspecting the input.
        !           816:  */
        !           817: int
        !           818: bsd_decompress(state, cmp, dmpp)
        !           819:     void *state;
        !           820:     struct mbuf *cmp, **dmpp;
        !           821: {
        !           822:     struct bsd_db *db = (struct bsd_db *) state;
        !           823:     u_int max_ent = db->max_ent;
        !           824:     u_int32_t accm = 0;
        !           825:     u_int bitno = 32;          /* 1st valid bit in accm */
        !           826:     u_int n_bits = db->n_bits;
        !           827:     u_int tgtbitno = 32-n_bits;        /* bitno when we have a code */
        !           828:     struct bsd_dict *dictp;
        !           829:     int explen, i, seq, len;
        !           830:     u_int incode, oldcode, finchar;
        !           831:     u_char *p, *rptr, *wptr;
        !           832:     struct mbuf *m, *dmp, *mret;
        !           833:     int adrs, ctrl, ilen;
        !           834:     int space, codelen, extra;
        !           835:
        !           836:     /*
        !           837:      * Save the address/control from the PPP header
        !           838:      * and then get the sequence number.
        !           839:      */
        !           840:     *dmpp = NULL;
        !           841:     rptr = mtod(cmp, u_char *);
        !           842:     adrs = PPP_ADDRESS(rptr);
        !           843:     ctrl = PPP_CONTROL(rptr);
        !           844:     rptr += PPP_HDRLEN;
        !           845:     len = cmp->m_len - PPP_HDRLEN;
        !           846:     seq = 0;
        !           847:     for (i = 0; i < 2; ++i) {
        !           848:        while (len <= 0) {
        !           849:            cmp = cmp->m_next;
        !           850:            if (cmp == NULL)
        !           851:                return DECOMP_ERROR;
        !           852:            rptr = mtod(cmp, u_char *);
        !           853:            len = cmp->m_len;
        !           854:        }
        !           855:        seq = (seq << 8) + *rptr++;
        !           856:        --len;
        !           857:     }
        !           858:
        !           859:     /*
        !           860:      * Check the sequence number and give up if it differs from
        !           861:      * the value we're expecting.
        !           862:      */
        !           863:     if (seq != db->seqno) {
        !           864:        if (db->debug)
        !           865:            printf("bsd_decomp%d: bad sequence # %d, expected %d\n",
        !           866:                   db->unit, seq, db->seqno - 1);
        !           867:        return DECOMP_ERROR;
        !           868:     }
        !           869:     ++db->seqno;
        !           870:
        !           871:     /*
        !           872:      * Allocate one mbuf to start with.
        !           873:      */
        !           874:     MGETHDR(dmp, M_DONTWAIT, MT_DATA);
        !           875:     if (dmp == NULL)
        !           876:        return DECOMP_ERROR;
        !           877:     mret = dmp;
        !           878:     dmp->m_len = 0;
        !           879:     dmp->m_next = NULL;
        !           880:     MCLGET(dmp, M_DONTWAIT);
        !           881:     dmp->m_data += db->hdrlen;
        !           882:     wptr = mtod(dmp, u_char *);
        !           883:     space = M_TRAILINGSPACE(dmp) - PPP_HDRLEN + 1;
        !           884:
        !           885:     /*
        !           886:      * Fill in the ppp header, but not the last byte of the protocol
        !           887:      * (that comes from the decompressed data).
        !           888:      */
        !           889:     wptr[0] = adrs;
        !           890:     wptr[1] = ctrl;
        !           891:     wptr[2] = 0;
        !           892:     wptr += PPP_HDRLEN - 1;
        !           893:
        !           894:     ilen = len;
        !           895:     oldcode = CLEAR;
        !           896:     explen = 0;
        !           897:     for (;;) {
        !           898:        if (len == 0) {
        !           899:            cmp = cmp->m_next;
        !           900:            if (!cmp)           /* quit at end of message */
        !           901:                break;
        !           902:            rptr = mtod(cmp, u_char *);
        !           903:            len = cmp->m_len;
        !           904:            ilen += len;
        !           905:            continue;           /* handle 0-length buffers */
        !           906:        }
        !           907:
        !           908:        /*
        !           909:         * Accumulate bytes until we have a complete code.
        !           910:         * Then get the next code, relying on the 32-bit,
        !           911:         * unsigned accm to mask the result.
        !           912:         */
        !           913:        bitno -= 8;
        !           914:        accm |= *rptr++ << bitno;
        !           915:        --len;
        !           916:        if (tgtbitno < bitno)
        !           917:            continue;
        !           918:        incode = accm >> tgtbitno;
        !           919:        accm <<= n_bits;
        !           920:        bitno += n_bits;
        !           921:
        !           922:        if (incode == CLEAR) {
        !           923:            /*
        !           924:             * The dictionary must only be cleared at
        !           925:             * the end of a packet.  But there could be an
        !           926:             * empty mbuf at the end.
        !           927:             */
        !           928:            if (len > 0 || cmp->m_next != NULL) {
        !           929:                while ((cmp = cmp->m_next) != NULL)
        !           930:                    len += cmp->m_len;
        !           931:                if (len > 0) {
        !           932:                    m_freem(mret);
        !           933:                    if (db->debug)
        !           934:                        printf("bsd_decomp%d: bad CLEAR\n", db->unit);
        !           935:                    return DECOMP_FATALERROR;   /* probably a bug */
        !           936:                }
        !           937:            }
        !           938:            bsd_clear(db);
        !           939:            explen = ilen = 0;
        !           940:            break;
        !           941:        }
        !           942:
        !           943:        if (incode > max_ent + 2 || incode > db->maxmaxcode
        !           944:            || (incode > max_ent && oldcode == CLEAR)) {
        !           945:            m_freem(mret);
        !           946:            if (db->debug) {
        !           947:                printf("bsd_decomp%d: bad code 0x%x oldcode=0x%x ",
        !           948:                       db->unit, incode, oldcode);
        !           949:                printf("max_ent=0x%x explen=%d seqno=%d\n",
        !           950:                       max_ent, explen, db->seqno);
        !           951:            }
        !           952:            return DECOMP_FATALERROR;   /* probably a bug */
        !           953:        }
        !           954:
        !           955:        /* Special case for KwKwK string. */
        !           956:        if (incode > max_ent) {
        !           957:            finchar = oldcode;
        !           958:            extra = 1;
        !           959:        } else {
        !           960:            finchar = incode;
        !           961:            extra = 0;
        !           962:        }
        !           963:
        !           964:        codelen = db->lens[finchar];
        !           965:        explen += codelen + extra;
        !           966:        if (explen > db->mru + 1) {
        !           967:            m_freem(mret);
        !           968:            if (db->debug) {
        !           969:                printf("bsd_decomp%d: ran out of mru\n", db->unit);
        !           970: #ifdef DEBUG
        !           971:                while ((cmp = cmp->m_next) != NULL)
        !           972:                    len += cmp->m_len;
        !           973:                printf("  len=%d, finchar=0x%x, codelen=%d, explen=%d\n",
        !           974:                       len, finchar, codelen, explen);
        !           975: #endif
        !           976:            }
        !           977:            return DECOMP_FATALERROR;
        !           978:        }
        !           979:
        !           980:        /*
        !           981:         * For simplicity, the decoded characters go in a single mbuf,
        !           982:         * so we allocate a single extra cluster mbuf if necessary.
        !           983:         */
        !           984:        if ((space -= codelen + extra) < 0) {
        !           985:            dmp->m_len = wptr - mtod(dmp, u_char *);
        !           986:            MGET(m, M_DONTWAIT, MT_DATA);
        !           987:            if (m == NULL) {
        !           988:                m_freem(mret);
        !           989:                return DECOMP_ERROR;
        !           990:            }
        !           991:            m->m_len = 0;
        !           992:            m->m_next = NULL;
        !           993:            dmp->m_next = m;
        !           994:            MCLGET(m, M_DONTWAIT);
        !           995:            space = M_TRAILINGSPACE(m) - (codelen + extra);
        !           996:            if (space < 0) {
        !           997:                /* now that's what I call *compression*. */
        !           998:                m_freem(mret);
        !           999:                return DECOMP_ERROR;
        !          1000:            }
        !          1001:            dmp = m;
        !          1002:            wptr = mtod(dmp, u_char *);
        !          1003:        }
        !          1004:
        !          1005:        /*
        !          1006:         * Decode this code and install it in the decompressed buffer.
        !          1007:         */
        !          1008:        p = (wptr += codelen);
        !          1009:        while (finchar > LAST) {
        !          1010:            dictp = &db->dict[db->dict[finchar].cptr];
        !          1011: #ifdef DEBUG
        !          1012:            if (--codelen <= 0 || dictp->codem1 != finchar-1)
        !          1013:                goto bad;
        !          1014: #endif
        !          1015:            *--p = dictp->f.hs.suffix;
        !          1016:            finchar = dictp->f.hs.prefix;
        !          1017:        }
        !          1018:        *--p = finchar;
        !          1019:
        !          1020: #ifdef DEBUG
        !          1021:        if (--codelen != 0)
        !          1022:            printf("bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n",
        !          1023:                   db->unit, codelen, incode, max_ent);
        !          1024: #endif
        !          1025:
        !          1026:        if (extra)              /* the KwKwK case again */
        !          1027:            *wptr++ = finchar;
        !          1028:
        !          1029:        /*
        !          1030:         * If not first code in a packet, and
        !          1031:         * if not out of code space, then allocate a new code.
        !          1032:         *
        !          1033:         * Keep the hash table correct so it can be used
        !          1034:         * with uncompressed packets.
        !          1035:         */
        !          1036:        if (oldcode != CLEAR && max_ent < db->maxmaxcode) {
        !          1037:            struct bsd_dict *dictp2;
        !          1038:            u_int32_t fcode;
        !          1039:            u_int32_t hval, disp;
        !          1040:
        !          1041:            fcode = BSD_KEY(oldcode,finchar);
        !          1042:            hval = BSD_HASH(oldcode,finchar,db->hshift);
        !          1043:            dictp = &db->dict[hval];
        !          1044:
        !          1045:            /* look for a free hash table entry */
        !          1046:            if (dictp->codem1 < max_ent) {
        !          1047:                disp = (hval == 0) ? 1 : hval;
        !          1048:                do {
        !          1049:                    hval += disp;
        !          1050:                    if (hval >= db->hsize)
        !          1051:                        hval -= db->hsize;
        !          1052:                    dictp = &db->dict[hval];
        !          1053:                } while (dictp->codem1 < max_ent);
        !          1054:            }
        !          1055:
        !          1056:            /*
        !          1057:             * Invalidate previous hash table entry
        !          1058:             * assigned this code, and then take it over
        !          1059:             */
        !          1060:            dictp2 = &db->dict[max_ent+1];
        !          1061:            if (db->dict[dictp2->cptr].codem1 == max_ent) {
        !          1062:                db->dict[dictp2->cptr].codem1 = BADCODEM1;
        !          1063:            }
        !          1064:            dictp2->cptr = hval;
        !          1065:            dictp->codem1 = max_ent;
        !          1066:            dictp->f.fcode = fcode;
        !          1067:
        !          1068:            db->max_ent = ++max_ent;
        !          1069:            db->lens[max_ent] = db->lens[oldcode]+1;
        !          1070:
        !          1071:            /* Expand code size if needed. */
        !          1072:            if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode) {
        !          1073:                db->n_bits = ++n_bits;
        !          1074:                tgtbitno = 32-n_bits;
        !          1075:            }
        !          1076:        }
        !          1077:        oldcode = incode;
        !          1078:     }
        !          1079:     dmp->m_len = wptr - mtod(dmp, u_char *);
        !          1080:
        !          1081:     /*
        !          1082:      * Keep the checkpoint right so that incompressible packets
        !          1083:      * clear the dictionary at the right times.
        !          1084:      */
        !          1085:     db->bytes_out += ilen;
        !          1086:     db->in_count += explen;
        !          1087:     if (bsd_check(db) && db->debug) {
        !          1088:        printf("bsd_decomp%d: peer should have cleared dictionary\n",
        !          1089:               db->unit);
        !          1090:     }
        !          1091:
        !          1092:     ++db->comp_count;
        !          1093:     db->comp_bytes += ilen + BSD_OVHD;
        !          1094:     ++db->uncomp_count;
        !          1095:     db->uncomp_bytes += explen;
        !          1096:
        !          1097:     *dmpp = mret;
        !          1098:     return DECOMP_OK;
        !          1099:
        !          1100: #ifdef DEBUG
        !          1101:  bad:
        !          1102:     if (codelen <= 0) {
        !          1103:        printf("bsd_decomp%d: fell off end of chain ", db->unit);
        !          1104:        printf("0x%x at 0x%x by 0x%x, max_ent=0x%x\n",
        !          1105:               incode, finchar, db->dict[finchar].cptr, max_ent);
        !          1106:     } else if (dictp->codem1 != finchar-1) {
        !          1107:        printf("bsd_decomp%d: bad code chain 0x%x finchar=0x%x ",
        !          1108:               db->unit, incode, finchar);
        !          1109:        printf("oldcode=0x%x cptr=0x%x codem1=0x%x\n", oldcode,
        !          1110:               db->dict[finchar].cptr, dictp->codem1);
        !          1111:     }
        !          1112:     m_freem(mret);
        !          1113:     return DECOMP_FATALERROR;
        !          1114: #endif /* DEBUG */
        !          1115: }
        !          1116: #endif /* DO_BSD_COMPRESS */

CVSweb