~ubuntu-branches/ubuntu/oneiric/ppp/oneiric

« back to all changes in this revision

Viewing changes to pppdump/bsd-comp.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2010-11-24 18:12:47 UTC
  • mfrom: (1.2.5 upstream) (2.1.6 sid)
  • Revision ID: james.westby@ubuntu.com-20101124181247-2fopr1k0ic1t6svs
Tags: 2.4.5-4ubuntu1
* Merge with Debian; remaining changes:
  - /etc/ppp/options: default is noauth instead of auth.
  - extra/pon: Perform ppp_on_boot migration from pppoe package.
  - debian/ppp.postinst: init script migration for version before
    2.4.5~git20081126t100229-0ubuntu2.
  - debian/ppp.pppd-dns: Update LSB header.
  - Provide pppoe_on_boot file.
  - Move pppd-dns script to S45.
  - debian/patches/load_ppp_generic_if_needed: load ppp_generic kernel
    module if needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Because this code is derived from the 4.3BSD compress source:
 
2
 *
 
3
 *
 
4
 * Copyright (c) 1985, 1986 The Regents of the University of California.
 
5
 * All rights reserved.
 
6
 *
 
7
 * This code is derived from software contributed to Berkeley by
 
8
 * James A. Woods, derived from original work by Spencer Thomas
 
9
 * and Joseph Orost.
 
10
 *
 
11
 * Redistribution and use in source and binary forms, with or without
 
12
 * modification, are permitted provided that the following conditions
 
13
 * are met:
 
14
 * 1. Redistributions of source code must retain the above copyright
 
15
 *    notice, this list of conditions and the following disclaimer.
 
16
 * 2. Redistributions in binary form must reproduce the above copyright
 
17
 *    notice, this list of conditions and the following disclaimer in the
 
18
 *    documentation and/or other materials provided with the distribution.
 
19
 * 3. All advertising materials mentioning features or use of this software
 
20
 *    must display the following acknowledgement:
 
21
 *      This product includes software developed by the University of
 
22
 *      California, Berkeley and its contributors.
 
23
 * 4. Neither the name of the University nor the names of its contributors
 
24
 *    may be used to endorse or promote products derived from this software
 
25
 *    without specific prior written permission.
 
26
 *
 
27
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 
28
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
29
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
30
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 
31
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
32
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
33
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
34
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
35
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
36
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
37
 * SUCH DAMAGE.
 
38
 */
 
39
 
 
40
/*
 
41
 * $Id: bsd-comp.c,v 1.4 2004/01/17 05:47:55 carlsonj Exp $
 
42
 */
 
43
 
 
44
#include <sys/types.h>
 
45
#include <stdio.h>
 
46
#include <stddef.h>
 
47
#include <stdlib.h>
 
48
#include <string.h>
 
49
#include "ppp_defs.h"
 
50
#include "ppp-comp.h"
 
51
 
 
52
#if DO_BSD_COMPRESS
 
53
 
 
54
/*
 
55
 * PPP "BSD compress" compression
 
56
 *  The differences between this compression and the classic BSD LZW
 
57
 *  source are obvious from the requirement that the classic code worked
 
58
 *  with files while this handles arbitrarily long streams that
 
59
 *  are broken into packets.  They are:
 
60
 *
 
61
 *      When the code size expands, a block of junk is not emitted by
 
62
 *          the compressor and not expected by the decompressor.
 
63
 *
 
64
 *      New codes are not necessarily assigned every time an old
 
65
 *          code is output by the compressor.  This is because a packet
 
66
 *          end forces a code to be emitted, but does not imply that a
 
67
 *          new sequence has been seen.
 
68
 *
 
69
 *      The compression ratio is checked at the first end of a packet
 
70
 *          after the appropriate gap.  Besides simplifying and speeding
 
71
 *          things up, this makes it more likely that the transmitter
 
72
 *          and receiver will agree when the dictionary is cleared when
 
73
 *          compression is not going well.
 
74
 */
 
75
 
 
76
/*
 
77
 * A dictionary for doing BSD compress.
 
78
 */
 
79
struct bsd_db {
 
80
    int     totlen;                     /* length of this structure */
 
81
    u_int   hsize;                      /* size of the hash table */
 
82
    u_char  hshift;                     /* used in hash function */
 
83
    u_char  n_bits;                     /* current bits/code */
 
84
    u_char  maxbits;
 
85
    u_char  debug;
 
86
    u_char  unit;
 
87
    u_short seqno;                      /* sequence number of next packet */
 
88
    u_int   hdrlen;                     /* header length to preallocate */
 
89
    u_int   mru;
 
90
    u_int   maxmaxcode;                 /* largest valid code */
 
91
    u_int   max_ent;                    /* largest code in use */
 
92
    u_int   in_count;                   /* uncompressed bytes, aged */
 
93
    u_int   bytes_out;                  /* compressed bytes, aged */
 
94
    u_int   ratio;                      /* recent compression ratio */
 
95
    u_int   checkpoint;                 /* when to next check the ratio */
 
96
    u_int   clear_count;                /* times dictionary cleared */
 
97
    u_int   incomp_count;               /* incompressible packets */
 
98
    u_int   incomp_bytes;               /* incompressible bytes */
 
99
    u_int   uncomp_count;               /* uncompressed packets */
 
100
    u_int   uncomp_bytes;               /* uncompressed bytes */
 
101
    u_int   comp_count;                 /* compressed packets */
 
102
    u_int   comp_bytes;                 /* compressed bytes */
 
103
    u_short *lens;                      /* array of lengths of codes */
 
104
    struct bsd_dict {
 
105
        union {                         /* hash value */
 
106
            u_int32_t   fcode;
 
107
            struct {
 
108
#ifdef BSD_LITTLE_ENDIAN
 
109
                u_short prefix;         /* preceding code */
 
110
                u_char  suffix;         /* last character of new code */
 
111
                u_char  pad;
 
112
#else
 
113
                u_char  pad;
 
114
                u_char  suffix;         /* last character of new code */
 
115
                u_short prefix;         /* preceding code */
 
116
#endif
 
117
            } hs;
 
118
        } f;
 
119
        u_short codem1;                 /* output of hash table -1 */
 
120
        u_short cptr;                   /* map code to hash table entry */
 
121
    } dict[1];
 
122
};
 
123
 
 
124
#define BSD_OVHD        2               /* BSD compress overhead/packet */
 
125
#define BSD_INIT_BITS   BSD_MIN_BITS
 
126
 
 
127
static void     *bsd_decomp_alloc __P((u_char *options, int opt_len));
 
128
static void     bsd_free __P((void *state));
 
129
static int      bsd_decomp_init __P((void *state, u_char *options, int opt_len,
 
130
                                     int unit, int hdrlen, int mru, int debug));
 
131
static void     bsd_incomp __P((void *state, u_char *dmsg, int len));
 
132
static int      bsd_decompress __P((void *state, u_char *cmp, int inlen,
 
133
                                    u_char *dmp, int *outlen));
 
134
static void     bsd_reset __P((void *state));
 
135
static void     bsd_comp_stats __P((void *state, struct compstat *stats));
 
136
 
 
137
/*
 
138
 * Exported procedures.
 
139
 */
 
140
struct compressor ppp_bsd_compress = {
 
141
    CI_BSD_COMPRESS,            /* compress_proto */
 
142
    bsd_decomp_alloc,           /* decomp_alloc */
 
143
    bsd_free,                   /* decomp_free */
 
144
    bsd_decomp_init,            /* decomp_init */
 
145
    bsd_reset,                  /* decomp_reset */
 
146
    bsd_decompress,             /* decompress */
 
147
    bsd_incomp,                 /* incomp */
 
148
    bsd_comp_stats,             /* decomp_stat */
 
149
};
 
150
 
 
151
/*
 
152
 * the next two codes should not be changed lightly, as they must not
 
153
 * lie within the contiguous general code space.
 
154
 */
 
155
#define CLEAR   256                     /* table clear output code */
 
156
#define FIRST   257                     /* first free entry */
 
157
#define LAST    255
 
158
 
 
159
#define MAXCODE(b)      ((1 << (b)) - 1)
 
160
#define BADCODEM1       MAXCODE(BSD_MAX_BITS)
 
161
 
 
162
#define BSD_HASH(prefix,suffix,hshift)  ((((u_int32_t)(suffix)) << (hshift)) \
 
163
                                         ^ (u_int32_t)(prefix))
 
164
#define BSD_KEY(prefix,suffix)          ((((u_int32_t)(suffix)) << 16) \
 
165
                                         + (u_int32_t)(prefix))
 
166
 
 
167
#define CHECK_GAP       10000           /* Ratio check interval */
 
168
 
 
169
#define RATIO_SCALE_LOG 8
 
170
#define RATIO_SCALE     (1<<RATIO_SCALE_LOG)
 
171
#define RATIO_MAX       (0x7fffffff>>RATIO_SCALE_LOG)
 
172
 
 
173
/*
 
174
 * clear the dictionary
 
175
 */
 
176
static void
 
177
bsd_clear(db)
 
178
    struct bsd_db *db;
 
179
{
 
180
    db->clear_count++;
 
181
    db->max_ent = FIRST-1;
 
182
    db->n_bits = BSD_INIT_BITS;
 
183
    db->ratio = 0;
 
184
    db->bytes_out = 0;
 
185
    db->in_count = 0;
 
186
    db->checkpoint = CHECK_GAP;
 
187
}
 
188
 
 
189
/*
 
190
 * If the dictionary is full, then see if it is time to reset it.
 
191
 *
 
192
 * Compute the compression ratio using fixed-point arithmetic
 
193
 * with 8 fractional bits.
 
194
 *
 
195
 * Since we have an infinite stream instead of a single file,
 
196
 * watch only the local compression ratio.
 
197
 *
 
198
 * Since both peers must reset the dictionary at the same time even in
 
199
 * the absence of CLEAR codes (while packets are incompressible), they
 
200
 * must compute the same ratio.
 
201
 */
 
202
static int                              /* 1=output CLEAR */
 
203
bsd_check(db)
 
204
    struct bsd_db *db;
 
205
{
 
206
    u_int new_ratio;
 
207
 
 
208
    if (db->in_count >= db->checkpoint) {
 
209
        /* age the ratio by limiting the size of the counts */
 
210
        if (db->in_count >= RATIO_MAX
 
211
            || db->bytes_out >= RATIO_MAX) {
 
212
            db->in_count -= db->in_count/4;
 
213
            db->bytes_out -= db->bytes_out/4;
 
214
        }
 
215
 
 
216
        db->checkpoint = db->in_count + CHECK_GAP;
 
217
 
 
218
        if (db->max_ent >= db->maxmaxcode) {
 
219
            /* Reset the dictionary only if the ratio is worse,
 
220
             * or if it looks as if it has been poisoned
 
221
             * by incompressible data.
 
222
             *
 
223
             * This does not overflow, because
 
224
             *  db->in_count <= RATIO_MAX.
 
225
             */
 
226
            new_ratio = db->in_count << RATIO_SCALE_LOG;
 
227
            if (db->bytes_out != 0)
 
228
                new_ratio /= db->bytes_out;
 
229
 
 
230
            if (new_ratio < db->ratio || new_ratio < 1 * RATIO_SCALE) {
 
231
                bsd_clear(db);
 
232
                return 1;
 
233
            }
 
234
            db->ratio = new_ratio;
 
235
        }
 
236
    }
 
237
    return 0;
 
238
}
 
239
 
 
240
/*
 
241
 * Return statistics.
 
242
 */
 
243
static void
 
244
bsd_comp_stats(state, stats)
 
245
    void *state;
 
246
    struct compstat *stats;
 
247
{
 
248
    struct bsd_db *db = (struct bsd_db *) state;
 
249
    u_int out;
 
250
 
 
251
    stats->unc_bytes = db->uncomp_bytes;
 
252
    stats->unc_packets = db->uncomp_count;
 
253
    stats->comp_bytes = db->comp_bytes;
 
254
    stats->comp_packets = db->comp_count;
 
255
    stats->inc_bytes = db->incomp_bytes;
 
256
    stats->inc_packets = db->incomp_count;
 
257
    stats->ratio = db->in_count;
 
258
    out = db->bytes_out;
 
259
    if (stats->ratio <= 0x7fffff)
 
260
        stats->ratio <<= 8;
 
261
    else
 
262
        out >>= 8;
 
263
    if (out != 0)
 
264
        stats->ratio /= out;
 
265
}
 
266
 
 
267
/*
 
268
 * Reset state, as on a CCP ResetReq.
 
269
 */
 
270
static void
 
271
bsd_reset(state)
 
272
    void *state;
 
273
{
 
274
    struct bsd_db *db = (struct bsd_db *) state;
 
275
 
 
276
    db->seqno = 0;
 
277
    bsd_clear(db);
 
278
    db->clear_count = 0;
 
279
}
 
280
 
 
281
/*
 
282
 * Allocate space for a (de) compressor.
 
283
 */
 
284
static void *
 
285
bsd_alloc(options, opt_len, decomp)
 
286
    u_char *options;
 
287
    int opt_len, decomp;
 
288
{
 
289
    int bits;
 
290
    u_int newlen, hsize, hshift, maxmaxcode;
 
291
    struct bsd_db *db;
 
292
 
 
293
    if (opt_len != 3 || options[0] != CI_BSD_COMPRESS || options[1] != 3
 
294
        || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION)
 
295
        return NULL;
 
296
 
 
297
    bits = BSD_NBITS(options[2]);
 
298
    switch (bits) {
 
299
    case 9:                     /* needs 82152 for both directions */
 
300
    case 10:                    /* needs 84144 */
 
301
    case 11:                    /* needs 88240 */
 
302
    case 12:                    /* needs 96432 */
 
303
        hsize = 5003;
 
304
        hshift = 4;
 
305
        break;
 
306
    case 13:                    /* needs 176784 */
 
307
        hsize = 9001;
 
308
        hshift = 5;
 
309
        break;
 
310
    case 14:                    /* needs 353744 */
 
311
        hsize = 18013;
 
312
        hshift = 6;
 
313
        break;
 
314
    case 15:                    /* needs 691440 */
 
315
        hsize = 35023;
 
316
        hshift = 7;
 
317
        break;
 
318
    case 16:                    /* needs 1366160--far too much, */
 
319
        /* hsize = 69001; */    /* and 69001 is too big for cptr */
 
320
        /* hshift = 8; */       /* in struct bsd_db */
 
321
        /* break; */
 
322
    default:
 
323
        return NULL;
 
324
    }
 
325
 
 
326
    maxmaxcode = MAXCODE(bits);
 
327
    newlen = sizeof(*db) + (hsize-1) * (sizeof(db->dict[0]));
 
328
    db = (struct bsd_db *) malloc(newlen);
 
329
    if (!db)
 
330
        return NULL;
 
331
    memset(db, 0, sizeof(*db) - sizeof(db->dict));
 
332
 
 
333
    if (!decomp) {
 
334
        db->lens = NULL;
 
335
    } else {
 
336
        db->lens = (u_short *) malloc((maxmaxcode+1) * sizeof(db->lens[0]));
 
337
        if (!db->lens) {
 
338
            free(db);
 
339
            return NULL;
 
340
        }
 
341
    }
 
342
 
 
343
    db->totlen = newlen;
 
344
    db->hsize = hsize;
 
345
    db->hshift = hshift;
 
346
    db->maxmaxcode = maxmaxcode;
 
347
    db->maxbits = bits;
 
348
 
 
349
    return (void *) db;
 
350
}
 
351
 
 
352
static void
 
353
bsd_free(state)
 
354
    void *state;
 
355
{
 
356
    struct bsd_db *db = (struct bsd_db *) state;
 
357
 
 
358
    if (db->lens)
 
359
        free(db->lens);
 
360
    free(db);
 
361
}
 
362
 
 
363
static void *
 
364
bsd_decomp_alloc(options, opt_len)
 
365
    u_char *options;
 
366
    int opt_len;
 
367
{
 
368
    return bsd_alloc(options, opt_len, 1);
 
369
}
 
370
 
 
371
/*
 
372
 * Initialize the database.
 
373
 */
 
374
static int
 
375
bsd_init(db, options, opt_len, unit, hdrlen, mru, debug, decomp)
 
376
    struct bsd_db *db;
 
377
    u_char *options;
 
378
    int opt_len, unit, hdrlen, mru, debug, decomp;
 
379
{
 
380
    int i;
 
381
 
 
382
    if (opt_len < CILEN_BSD_COMPRESS
 
383
        || options[0] != CI_BSD_COMPRESS || options[1] != CILEN_BSD_COMPRESS
 
384
        || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION
 
385
        || BSD_NBITS(options[2]) != db->maxbits
 
386
        || decomp && db->lens == NULL)
 
387
        return 0;
 
388
 
 
389
    if (decomp) {
 
390
        i = LAST+1;
 
391
        while (i != 0)
 
392
            db->lens[--i] = 1;
 
393
    }
 
394
    i = db->hsize;
 
395
    while (i != 0) {
 
396
        db->dict[--i].codem1 = BADCODEM1;
 
397
        db->dict[i].cptr = 0;
 
398
    }
 
399
 
 
400
    db->unit = unit;
 
401
    db->hdrlen = hdrlen;
 
402
    db->mru = mru;
 
403
    if (debug)
 
404
        db->debug = 1;
 
405
 
 
406
    bsd_reset(db);
 
407
 
 
408
    return 1;
 
409
}
 
410
 
 
411
static int
 
412
bsd_decomp_init(state, options, opt_len, unit, hdrlen, mru, debug)
 
413
    void *state;
 
414
    u_char *options;
 
415
    int opt_len, unit, hdrlen, mru, debug;
 
416
{
 
417
    return bsd_init((struct bsd_db *) state, options, opt_len,
 
418
                    unit, hdrlen, mru, debug, 1);
 
419
}
 
420
 
 
421
 
 
422
/*
 
423
 * Update the "BSD Compress" dictionary on the receiver for
 
424
 * incompressible data by pretending to compress the incoming data.
 
425
 */
 
426
static void
 
427
bsd_incomp(state, dmsg, mlen)
 
428
    void *state;
 
429
    u_char *dmsg;
 
430
    int mlen;
 
431
{
 
432
    struct bsd_db *db = (struct bsd_db *) state;
 
433
    u_int hshift = db->hshift;
 
434
    u_int max_ent = db->max_ent;
 
435
    u_int n_bits = db->n_bits;
 
436
    struct bsd_dict *dictp;
 
437
    u_int32_t fcode;
 
438
    u_char c;
 
439
    long hval, disp;
 
440
    int slen, ilen;
 
441
    u_int bitno = 7;
 
442
    u_char *rptr;
 
443
    u_int ent;
 
444
 
 
445
    rptr = dmsg;
 
446
    ent = rptr[0];              /* get the protocol */
 
447
    if (ent == 0) {
 
448
        ++rptr;
 
449
        --mlen;
 
450
        ent = rptr[0];
 
451
    }
 
452
    if ((ent & 1) == 0 || ent < 0x21 || ent > 0xf9)
 
453
        return;
 
454
 
 
455
    db->seqno++;
 
456
    ilen = 1;           /* count the protocol as 1 byte */
 
457
    ++rptr;
 
458
    slen = dmsg + mlen - rptr;
 
459
    ilen += slen;
 
460
    for (; slen > 0; --slen) {
 
461
        c = *rptr++;
 
462
        fcode = BSD_KEY(ent, c);
 
463
        hval = BSD_HASH(ent, c, hshift);
 
464
        dictp = &db->dict[hval];
 
465
 
 
466
        /* validate and then check the entry */
 
467
        if (dictp->codem1 >= max_ent)
 
468
            goto nomatch;
 
469
        if (dictp->f.fcode == fcode) {
 
470
            ent = dictp->codem1+1;
 
471
            continue;   /* found (prefix,suffix) */
 
472
        }
 
473
 
 
474
        /* continue probing until a match or invalid entry */
 
475
        disp = (hval == 0) ? 1 : hval;
 
476
        do {
 
477
            hval += disp;
 
478
            if (hval >= db->hsize)
 
479
                hval -= db->hsize;
 
480
            dictp = &db->dict[hval];
 
481
            if (dictp->codem1 >= max_ent)
 
482
                goto nomatch;
 
483
        } while (dictp->f.fcode != fcode);
 
484
        ent = dictp->codem1+1;
 
485
        continue;       /* finally found (prefix,suffix) */
 
486
 
 
487
    nomatch:            /* output (count) the prefix */
 
488
        bitno += n_bits;
 
489
 
 
490
        /* code -> hashtable */
 
491
        if (max_ent < db->maxmaxcode) {
 
492
            struct bsd_dict *dictp2;
 
493
            /* expand code size if needed */
 
494
            if (max_ent >= MAXCODE(n_bits))
 
495
                db->n_bits = ++n_bits;
 
496
 
 
497
            /* Invalidate previous hash table entry
 
498
             * assigned this code, and then take it over.
 
499
             */
 
500
            dictp2 = &db->dict[max_ent+1];
 
501
            if (db->dict[dictp2->cptr].codem1 == max_ent)
 
502
                db->dict[dictp2->cptr].codem1 = BADCODEM1;
 
503
            dictp2->cptr = hval;
 
504
            dictp->codem1 = max_ent;
 
505
            dictp->f.fcode = fcode;
 
506
 
 
507
            db->max_ent = ++max_ent;
 
508
            db->lens[max_ent] = db->lens[ent]+1;
 
509
        }
 
510
        ent = c;
 
511
    }
 
512
    bitno += n_bits;            /* output (count) the last code */
 
513
    db->bytes_out += bitno/8;
 
514
    db->in_count += ilen;
 
515
    (void)bsd_check(db);
 
516
 
 
517
    ++db->incomp_count;
 
518
    db->incomp_bytes += ilen;
 
519
    ++db->uncomp_count;
 
520
    db->uncomp_bytes += ilen;
 
521
 
 
522
    /* Increase code size if we would have without the packet
 
523
     * boundary and as the decompressor will.
 
524
     */
 
525
    if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode)
 
526
        db->n_bits++;
 
527
}
 
528
 
 
529
 
 
530
/*
 
531
 * Decompress "BSD Compress"
 
532
 *
 
533
 * Because of patent problems, we return DECOMP_ERROR for errors
 
534
 * found by inspecting the input data and for system problems, but
 
535
 * DECOMP_FATALERROR for any errors which could possibly be said to
 
536
 * be being detected "after" decompression.  For DECOMP_ERROR,
 
537
 * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
 
538
 * infringing a patent of Motorola's if we do, so we take CCP down
 
539
 * instead.
 
540
 *
 
541
 * Given that the frame has the correct sequence number and a good FCS,
 
542
 * errors such as invalid codes in the input most likely indicate a
 
543
 * bug, so we return DECOMP_FATALERROR for them in order to turn off
 
544
 * compression, even though they are detected by inspecting the input.
 
545
 */
 
546
static int
 
547
bsd_decompress(state, cmsg, inlen, dmp, outlenp)
 
548
    void *state;
 
549
    u_char *cmsg, *dmp;
 
550
    int inlen, *outlenp;
 
551
{
 
552
    struct bsd_db *db = (struct bsd_db *) state;
 
553
    u_int max_ent = db->max_ent;
 
554
    u_int32_t accm = 0;
 
555
    u_int bitno = 32;           /* 1st valid bit in accm */
 
556
    u_int n_bits = db->n_bits;
 
557
    u_int tgtbitno = 32-n_bits; /* bitno when we have a code */
 
558
    struct bsd_dict *dictp;
 
559
    int explen, i, seq, len;
 
560
    u_int incode, oldcode, finchar;
 
561
    u_char *p, *rptr, *wptr;
 
562
    int ilen;
 
563
    int dlen, space, codelen, extra;
 
564
 
 
565
    rptr = cmsg;
 
566
    if (*rptr == 0)
 
567
        ++rptr;
 
568
    ++rptr;                     /* skip protocol (assumed 0xfd) */
 
569
    seq = (rptr[0] << 8) + rptr[1];
 
570
    rptr += BSD_OVHD;
 
571
    ilen = len = cmsg + inlen - rptr;
 
572
 
 
573
    /*
 
574
     * Check the sequence number and give up if it is not what we expect.
 
575
     */
 
576
    if (seq != db->seqno++) {
 
577
        if (db->debug)
 
578
            printf("bsd_decomp%d: bad sequence # %d, expected %d\n",
 
579
                   db->unit, seq, db->seqno - 1);
 
580
        return DECOMP_ERROR;
 
581
    }
 
582
 
 
583
    wptr = dmp + db->hdrlen;
 
584
 
 
585
    oldcode = CLEAR;
 
586
    explen = 0;
 
587
    while (len > 0) {
 
588
        /*
 
589
         * Accumulate bytes until we have a complete code.
 
590
         * Then get the next code, relying on the 32-bit,
 
591
         * unsigned accm to mask the result.
 
592
         */
 
593
        bitno -= 8;
 
594
        accm |= *rptr++ << bitno;
 
595
        --len;
 
596
        if (tgtbitno < bitno)
 
597
            continue;
 
598
        incode = accm >> tgtbitno;
 
599
        accm <<= n_bits;
 
600
        bitno += n_bits;
 
601
 
 
602
        if (incode == CLEAR) {
 
603
            /*
 
604
             * The dictionary must only be cleared at
 
605
             * the end of a packet.  But there could be an
 
606
             * empty message block at the end.
 
607
             */
 
608
            if (len > 0) {
 
609
                if (db->debug)
 
610
                    printf("bsd_decomp%d: bad CLEAR\n", db->unit);
 
611
                return DECOMP_FATALERROR;
 
612
            }
 
613
            bsd_clear(db);
 
614
            explen = ilen = 0;
 
615
            break;
 
616
        }
 
617
 
 
618
        if (incode > max_ent + 2 || incode > db->maxmaxcode
 
619
            || incode > max_ent && oldcode == CLEAR) {
 
620
            if (db->debug) {
 
621
                printf("bsd_decomp%d: bad code 0x%x oldcode=0x%x ",
 
622
                       db->unit, incode, oldcode);
 
623
                printf("max_ent=0x%x dlen=%d seqno=%d\n",
 
624
                       max_ent, dlen, db->seqno);
 
625
            }
 
626
            return DECOMP_FATALERROR;   /* probably a bug */
 
627
        }
 
628
 
 
629
        /* Special case for KwKwK string. */
 
630
        if (incode > max_ent) {
 
631
            finchar = oldcode;
 
632
            extra = 1;
 
633
        } else {
 
634
            finchar = incode;
 
635
            extra = 0;
 
636
        }
 
637
 
 
638
        codelen = db->lens[finchar];
 
639
        explen += codelen + extra;
 
640
        if (explen > db->mru + 1) {
 
641
            if (db->debug)
 
642
                printf("bsd_decomp%d: ran out of mru\n", db->unit);
 
643
            return DECOMP_FATALERROR;
 
644
        }
 
645
 
 
646
        /*
 
647
         * Decode this code and install it in the decompressed buffer.
 
648
         */
 
649
        p = (wptr += codelen);
 
650
        while (finchar > LAST) {
 
651
            dictp = &db->dict[db->dict[finchar].cptr];
 
652
#ifdef DEBUG
 
653
            --codelen;
 
654
            if (codelen <= 0) {
 
655
                printf("bsd_decomp%d: fell off end of chain ", db->unit);
 
656
                printf("0x%x at 0x%x by 0x%x, max_ent=0x%x\n",
 
657
                       incode, finchar, db->dict[finchar].cptr, max_ent);
 
658
                return DECOMP_FATALERROR;
 
659
            }
 
660
            if (dictp->codem1 != finchar-1) {
 
661
                printf("bsd_decomp%d: bad code chain 0x%x finchar=0x%x ",
 
662
                       db->unit, incode, finchar);
 
663
                printf("oldcode=0x%x cptr=0x%x codem1=0x%x\n", oldcode,
 
664
                       db->dict[finchar].cptr, dictp->codem1);
 
665
                return DECOMP_FATALERROR;
 
666
            }
 
667
#endif
 
668
            *--p = dictp->f.hs.suffix;
 
669
            finchar = dictp->f.hs.prefix;
 
670
        }
 
671
        *--p = finchar;
 
672
 
 
673
#ifdef DEBUG
 
674
        if (--codelen != 0)
 
675
            printf("bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n",
 
676
                   db->unit, codelen, incode, max_ent);
 
677
#endif
 
678
 
 
679
        if (extra)              /* the KwKwK case again */
 
680
            *wptr++ = finchar;
 
681
 
 
682
        /*
 
683
         * If not first code in a packet, and
 
684
         * if not out of code space, then allocate a new code.
 
685
         *
 
686
         * Keep the hash table correct so it can be used
 
687
         * with uncompressed packets.
 
688
         */
 
689
        if (oldcode != CLEAR && max_ent < db->maxmaxcode) {
 
690
            struct bsd_dict *dictp2;
 
691
            u_int32_t fcode;
 
692
            int hval, disp;
 
693
 
 
694
            fcode = BSD_KEY(oldcode,finchar);
 
695
            hval = BSD_HASH(oldcode,finchar,db->hshift);
 
696
            dictp = &db->dict[hval];
 
697
 
 
698
            /* look for a free hash table entry */
 
699
            if (dictp->codem1 < max_ent) {
 
700
                disp = (hval == 0) ? 1 : hval;
 
701
                do {
 
702
                    hval += disp;
 
703
                    if (hval >= db->hsize)
 
704
                        hval -= db->hsize;
 
705
                    dictp = &db->dict[hval];
 
706
                } while (dictp->codem1 < max_ent);
 
707
            }
 
708
 
 
709
            /*
 
710
             * Invalidate previous hash table entry
 
711
             * assigned this code, and then take it over
 
712
             */
 
713
            dictp2 = &db->dict[max_ent+1];
 
714
            if (db->dict[dictp2->cptr].codem1 == max_ent) {
 
715
                db->dict[dictp2->cptr].codem1 = BADCODEM1;
 
716
            }
 
717
            dictp2->cptr = hval;
 
718
            dictp->codem1 = max_ent;
 
719
            dictp->f.fcode = fcode;
 
720
 
 
721
            db->max_ent = ++max_ent;
 
722
            db->lens[max_ent] = db->lens[oldcode]+1;
 
723
 
 
724
            /* Expand code size if needed. */
 
725
            if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode) {
 
726
                db->n_bits = ++n_bits;
 
727
                tgtbitno = 32-n_bits;
 
728
            }
 
729
        }
 
730
        oldcode = incode;
 
731
    }
 
732
    *outlenp = wptr - (dmp + db->hdrlen);
 
733
 
 
734
    /*
 
735
     * Keep the checkpoint right so that incompressible packets
 
736
     * clear the dictionary at the right times.
 
737
     */
 
738
    db->bytes_out += ilen;
 
739
    db->in_count += explen;
 
740
    if (bsd_check(db) && db->debug) {
 
741
        printf("bsd_decomp%d: peer should have cleared dictionary\n",
 
742
               db->unit);
 
743
    }
 
744
 
 
745
    ++db->comp_count;
 
746
    db->comp_bytes += ilen + BSD_OVHD;
 
747
    ++db->uncomp_count;
 
748
    db->uncomp_bytes += explen;
 
749
 
 
750
    return DECOMP_OK;
 
751
}
 
752
#endif /* DO_BSD_COMPRESS */