Annotation of XNU/bsd/net/bsd_comp.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.