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

Annotation of sys/net/ppp-deflate.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: ppp-deflate.c,v 1.7 2002/09/13 00:12:07 deraadt Exp $ */
                      2: /*     $NetBSD: ppp-deflate.c,v 1.1 1996/03/15 02:28:09 paulus Exp $   */
                      3:
                      4: /*
                      5:  * ppp_deflate.c - interface the zlib procedures for Deflate compression
                      6:  * and decompression (as used by gzip) to the PPP code.
                      7:  * This version is for use with mbufs on BSD-derived systems.
                      8:  *
                      9:  * Copyright (c) 1989-2002 Paul Mackerras. All rights reserved.
                     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:  *
                     15:  * 1. Redistributions of source code must retain the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer.
                     17:  *
                     18:  * 2. Redistributions in binary form must reproduce the above copyright
                     19:  *    notice, this list of conditions and the following disclaimer in
                     20:  *    the documentation and/or other materials provided with the
                     21:  *    distribution.
                     22:  *
                     23:  * 3. The name(s) of the authors of this software must not be used to
                     24:  *    endorse or promote products derived from this software without
                     25:  *    prior written permission.
                     26:  *
                     27:  * 4. Redistributions of any form whatsoever must retain the following
                     28:  *    acknowledgment:
                     29:  *    "This product includes software developed by Paul Mackerras
                     30:  *     <paulus@samba.org>".
                     31:  *
                     32:  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
                     33:  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
                     34:  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
                     35:  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     36:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
                     37:  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
                     38:  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     39:  */
                     40:
                     41: #include <sys/param.h>
                     42: #include <sys/types.h>
                     43: #include <sys/systm.h>
                     44: #include <sys/mbuf.h>
                     45: #include <net/ppp_defs.h>
                     46: #include <net/zlib.h>
                     47:
                     48: #define PACKETPTR      struct mbuf *
                     49: #include <net/ppp-comp.h>
                     50:
                     51: #if DO_DEFLATE
                     52:
                     53: /*
                     54:  * State for a Deflate (de)compressor.
                     55:  */
                     56: struct deflate_state {
                     57:     int                seqno;
                     58:     int                w_size;
                     59:     int                unit;
                     60:     int                hdrlen;
                     61:     int                mru;
                     62:     int                debug;
                     63:     z_stream   strm;
                     64:     struct compstat stats;
                     65: };
                     66:
                     67: #define DEFLATE_OVHD   2               /* Deflate overhead/packet */
                     68:
                     69: static void    *zalloc(void *, u_int items, u_int size);
                     70: static void    zfree(void *, void *ptr, u_int nb);
                     71: static void    *z_comp_alloc(u_char *options, int opt_len);
                     72: static void    *z_decomp_alloc(u_char *options, int opt_len);
                     73: static void    z_comp_free(void *state);
                     74: static void    z_decomp_free(void *state);
                     75: static int     z_comp_init(void *state, u_char *options, int opt_len,
                     76:                                 int unit, int hdrlen, int debug);
                     77: static int     z_decomp_init(void *state, u_char *options, int opt_len,
                     78:                                     int unit, int hdrlen, int mru, int debug);
                     79: static int     z_compress(void *state, struct mbuf **mret,
                     80:                                  struct mbuf *mp, int slen, int maxolen);
                     81: static void    z_incomp(void *state, struct mbuf *dmsg);
                     82: static int     z_decompress(void *state, struct mbuf *cmp,
                     83:                                    struct mbuf **dmpp);
                     84: static void    z_comp_reset(void *state);
                     85: static void    z_decomp_reset(void *state);
                     86: static void    z_comp_stats(void *state, struct compstat *stats);
                     87:
                     88: /*
                     89:  * Procedures exported to if_ppp.c.
                     90:  */
                     91: struct compressor ppp_deflate = {
                     92:     CI_DEFLATE,                        /* compress_proto */
                     93:     z_comp_alloc,              /* comp_alloc */
                     94:     z_comp_free,               /* comp_free */
                     95:     z_comp_init,               /* comp_init */
                     96:     z_comp_reset,              /* comp_reset */
                     97:     z_compress,                        /* compress */
                     98:     z_comp_stats,              /* comp_stat */
                     99:     z_decomp_alloc,            /* decomp_alloc */
                    100:     z_decomp_free,             /* decomp_free */
                    101:     z_decomp_init,             /* decomp_init */
                    102:     z_decomp_reset,            /* decomp_reset */
                    103:     z_decompress,              /* decompress */
                    104:     z_incomp,                  /* incomp */
                    105:     z_comp_stats,              /* decomp_stat */
                    106: };
                    107:
                    108: struct compressor ppp_deflate_draft = {
                    109:     CI_DEFLATE_DRAFT,          /* compress_proto */
                    110:     z_comp_alloc,              /* comp_alloc */
                    111:     z_comp_free,               /* comp_free */
                    112:     z_comp_init,               /* comp_init */
                    113:     z_comp_reset,              /* comp_reset */
                    114:     z_compress,                        /* compress */
                    115:     z_comp_stats,              /* comp_stat */
                    116:     z_decomp_alloc,            /* decomp_alloc */
                    117:     z_decomp_free,             /* decomp_free */
                    118:     z_decomp_init,             /* decomp_init */
                    119:     z_decomp_reset,            /* decomp_reset */
                    120:     z_decompress,              /* decompress */
                    121:     z_incomp,                  /* incomp */
                    122:     z_comp_stats,              /* decomp_stat */
                    123: };
                    124: /*
                    125:  * Space allocation and freeing routines for use by zlib routines.
                    126:  */
                    127: void *
                    128: zalloc(notused, items, size)
                    129:     void *notused;
                    130:     u_int items, size;
                    131: {
                    132:     void *ptr;
                    133:
                    134:     MALLOC(ptr, void *, items * size, M_DEVBUF, M_NOWAIT);
                    135:     return ptr;
                    136: }
                    137:
                    138: void
                    139: zfree(notused, ptr, nbytes)
                    140:     void *notused;
                    141:     void *ptr;
                    142:     u_int nbytes;
                    143: {
                    144:     FREE(ptr, M_DEVBUF);
                    145: }
                    146:
                    147: /*
                    148:  * Allocate space for a compressor.
                    149:  */
                    150: static void *
                    151: z_comp_alloc(options, opt_len)
                    152:     u_char *options;
                    153:     int opt_len;
                    154: {
                    155:     struct deflate_state *state;
                    156:     int w_size;
                    157:
                    158:     if (opt_len != CILEN_DEFLATE
                    159:        || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
                    160:        || options[1] != CILEN_DEFLATE
                    161:        || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
                    162:        || options[3] != DEFLATE_CHK_SEQUENCE)
                    163:        return NULL;
                    164:     w_size = DEFLATE_SIZE(options[2]);
                    165:     if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
                    166:        return NULL;
                    167:
                    168:     MALLOC(state, struct deflate_state *, sizeof(struct deflate_state),
                    169:           M_DEVBUF, M_NOWAIT);
                    170:     if (state == NULL)
                    171:        return NULL;
                    172:
                    173:     state->strm.next_in = NULL;
                    174:     state->strm.zalloc = zalloc;
                    175:     state->strm.zfree = zfree;
                    176:     if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, DEFLATE_METHOD_VAL,
                    177:                     -w_size, 8, Z_DEFAULT_STRATEGY, DEFLATE_OVHD+2) != Z_OK) {
                    178:        FREE(state, M_DEVBUF);
                    179:        return NULL;
                    180:     }
                    181:
                    182:     state->w_size = w_size;
                    183:     bzero(&state->stats, sizeof(state->stats));
                    184:     return (void *) state;
                    185: }
                    186:
                    187: static void
                    188: z_comp_free(arg)
                    189:     void *arg;
                    190: {
                    191:     struct deflate_state *state = (struct deflate_state *) arg;
                    192:
                    193:     deflateEnd(&state->strm);
                    194:     FREE(state, M_DEVBUF);
                    195: }
                    196:
                    197: static int
                    198: z_comp_init(arg, options, opt_len, unit, hdrlen, debug)
                    199:     void *arg;
                    200:     u_char *options;
                    201:     int opt_len, unit, hdrlen, debug;
                    202: {
                    203:     struct deflate_state *state = (struct deflate_state *) arg;
                    204:
                    205:     if (opt_len < CILEN_DEFLATE
                    206:        || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
                    207:        || options[1] != CILEN_DEFLATE
                    208:        || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
                    209:        || DEFLATE_SIZE(options[2]) != state->w_size
                    210:        || options[3] != DEFLATE_CHK_SEQUENCE)
                    211:        return 0;
                    212:
                    213:     state->seqno = 0;
                    214:     state->unit = unit;
                    215:     state->hdrlen = hdrlen;
                    216:     state->debug = debug;
                    217:
                    218:     deflateReset(&state->strm);
                    219:
                    220:     return 1;
                    221: }
                    222:
                    223: static void
                    224: z_comp_reset(arg)
                    225:     void *arg;
                    226: {
                    227:     struct deflate_state *state = (struct deflate_state *) arg;
                    228:
                    229:     state->seqno = 0;
                    230:     deflateReset(&state->strm);
                    231: }
                    232:
                    233: int
                    234: z_compress(arg, mret, mp, orig_len, maxolen)
                    235:     void *arg;
                    236:     struct mbuf **mret;                /* compressed packet (out) */
                    237:     struct mbuf *mp;           /* uncompressed packet (in) */
                    238:     int orig_len, maxolen;
                    239: {
                    240:     struct deflate_state *state = (struct deflate_state *) arg;
                    241:     u_char *rptr, *wptr;
                    242:     int proto, olen, wspace, r, flush;
                    243:     struct mbuf *m;
                    244:
                    245:     /*
                    246:      * Check that the protocol is in the range we handle.
                    247:      */
                    248:     rptr = mtod(mp, u_char *);
                    249:     proto = PPP_PROTOCOL(rptr);
                    250:     if (proto > 0x3fff || proto == 0xfd || proto == 0xfb) {
                    251:        *mret = NULL;
                    252:        return orig_len;
                    253:     }
                    254:
                    255:     /* Allocate one mbuf initially. */
                    256:     if (maxolen > orig_len)
                    257:        maxolen = orig_len;
                    258:     MGET(m, M_DONTWAIT, MT_DATA);
                    259:     *mret = m;
                    260:     if (m != NULL) {
                    261:        m->m_len = 0;
                    262:        if (maxolen + state->hdrlen > MLEN)
                    263:            MCLGET(m, M_DONTWAIT);
                    264:        wspace = M_TRAILINGSPACE(m);
                    265:        if (state->hdrlen + PPP_HDRLEN + 2 < wspace) {
                    266:            m->m_data += state->hdrlen;
                    267:            wspace -= state->hdrlen;
                    268:        }
                    269:        wptr = mtod(m, u_char *);
                    270:
                    271:        /*
                    272:         * Copy over the PPP header and store the 2-byte sequence number.
                    273:         */
                    274:        wptr[0] = PPP_ADDRESS(rptr);
                    275:        wptr[1] = PPP_CONTROL(rptr);
                    276:        wptr[2] = PPP_COMP >> 8;
                    277:        wptr[3] = PPP_COMP;
                    278:        wptr += PPP_HDRLEN;
                    279:        wptr[0] = state->seqno >> 8;
                    280:        wptr[1] = state->seqno;
                    281:        wptr += 2;
                    282:        state->strm.next_out = wptr;
                    283:        state->strm.avail_out = wspace - (PPP_HDRLEN + 2);
                    284:     } else {
                    285:        state->strm.next_out = NULL;
                    286:        state->strm.avail_out = 1000000;
                    287:        wptr = NULL;
                    288:        wspace = 0;
                    289:     }
                    290:     ++state->seqno;
                    291:
                    292:     rptr += (proto > 0xff)? 2: 3;      /* skip 1st proto byte if 0 */
                    293:     state->strm.next_in = rptr;
                    294:     state->strm.avail_in = mtod(mp, u_char *) + mp->m_len - rptr;
                    295:     mp = mp->m_next;
                    296:     flush = (mp == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
                    297:     olen = 0;
                    298:     for (;;) {
                    299:        r = deflate(&state->strm, flush);
                    300:        if (r != Z_OK) {
                    301:            printf("z_compress: deflate returned %d (%s)\n",
                    302:                   r, (state->strm.msg? state->strm.msg: ""));
                    303:            break;
                    304:        }
                    305:        if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
                    306:            break;              /* all done */
                    307:        if (state->strm.avail_in == 0 && mp != NULL) {
                    308:            state->strm.next_in = mtod(mp, u_char *);
                    309:            state->strm.avail_in = mp->m_len;
                    310:            mp = mp->m_next;
                    311:            if (mp == NULL)
                    312:                flush = Z_PACKET_FLUSH;
                    313:        }
                    314:        if (state->strm.avail_out == 0) {
                    315:            if (m != NULL) {
                    316:                m->m_len = wspace;
                    317:                olen += wspace;
                    318:                MGET(m->m_next, M_DONTWAIT, MT_DATA);
                    319:                m = m->m_next;
                    320:                if (m != NULL) {
                    321:                    m->m_len = 0;
                    322:                    if (maxolen - olen > MLEN)
                    323:                        MCLGET(m, M_DONTWAIT);
                    324:                    state->strm.next_out = mtod(m, u_char *);
                    325:                    state->strm.avail_out = wspace = M_TRAILINGSPACE(m);
                    326:                }
                    327:            }
                    328:            if (m == NULL) {
                    329:                state->strm.next_out = NULL;
                    330:                state->strm.avail_out = 1000000;
                    331:            }
                    332:        }
                    333:     }
                    334:     if (m != NULL)
                    335:        olen += (m->m_len = wspace - state->strm.avail_out);
                    336:
                    337:     /*
                    338:      * See if we managed to reduce the size of the packet.
                    339:      * If the compressor just gave us a single zero byte, it means
                    340:      * the packet was incompressible.
                    341:      */
                    342:     if (m != NULL && olen < orig_len
                    343:        && !(olen == PPP_HDRLEN + 3 && *wptr == 0)) {
                    344:        state->stats.comp_bytes += olen;
                    345:        state->stats.comp_packets++;
                    346:     } else {
                    347:        if (*mret != NULL) {
                    348:            m_freem(*mret);
                    349:            *mret = NULL;
                    350:        }
                    351:        state->stats.inc_bytes += orig_len;
                    352:        state->stats.inc_packets++;
                    353:        olen = orig_len;
                    354:     }
                    355:     state->stats.unc_bytes += orig_len;
                    356:     state->stats.unc_packets++;
                    357:
                    358:     return olen;
                    359: }
                    360:
                    361: static void
                    362: z_comp_stats(arg, stats)
                    363:     void *arg;
                    364:     struct compstat *stats;
                    365: {
                    366:     struct deflate_state *state = (struct deflate_state *) arg;
                    367:     u_int out;
                    368:
                    369:     *stats = state->stats;
                    370:     stats->ratio = stats->unc_bytes;
                    371:     out = stats->comp_bytes + stats->inc_bytes;
                    372:     if (stats->ratio <= 0x7ffffff)
                    373:        stats->ratio <<= 8;
                    374:     else
                    375:        out >>= 8;
                    376:     if (out != 0)
                    377:        stats->ratio /= out;
                    378: }
                    379:
                    380: /*
                    381:  * Allocate space for a decompressor.
                    382:  */
                    383: static void *
                    384: z_decomp_alloc(options, opt_len)
                    385:     u_char *options;
                    386:     int opt_len;
                    387: {
                    388:     struct deflate_state *state;
                    389:     int w_size;
                    390:
                    391:     if (opt_len != CILEN_DEFLATE
                    392:        || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
                    393:        || options[1] != CILEN_DEFLATE
                    394:        || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
                    395:        || options[3] != DEFLATE_CHK_SEQUENCE)
                    396:        return NULL;
                    397:     w_size = DEFLATE_SIZE(options[2]);
                    398:     if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
                    399:        return NULL;
                    400:
                    401:     MALLOC(state, struct deflate_state *, sizeof(struct deflate_state),
                    402:           M_DEVBUF, M_NOWAIT);
                    403:     if (state == NULL)
                    404:        return NULL;
                    405:
                    406:     state->strm.next_out = NULL;
                    407:     state->strm.zalloc = zalloc;
                    408:     state->strm.zfree = zfree;
                    409:     if (inflateInit2(&state->strm, -w_size) != Z_OK) {
                    410:        FREE(state, M_DEVBUF);
                    411:        return NULL;
                    412:     }
                    413:
                    414:     state->w_size = w_size;
                    415:     bzero(&state->stats, sizeof(state->stats));
                    416:     return (void *) state;
                    417: }
                    418:
                    419: static void
                    420: z_decomp_free(arg)
                    421:     void *arg;
                    422: {
                    423:     struct deflate_state *state = (struct deflate_state *) arg;
                    424:
                    425:     inflateEnd(&state->strm);
                    426:     FREE(state, M_DEVBUF);
                    427: }
                    428:
                    429: static int
                    430: z_decomp_init(arg, options, opt_len, unit, hdrlen, mru, debug)
                    431:     void *arg;
                    432:     u_char *options;
                    433:     int opt_len, unit, hdrlen, mru, debug;
                    434: {
                    435:     struct deflate_state *state = (struct deflate_state *) arg;
                    436:
                    437:     if (opt_len < CILEN_DEFLATE
                    438:        || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
                    439:        || options[1] != CILEN_DEFLATE
                    440:        || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
                    441:        || DEFLATE_SIZE(options[2]) != state->w_size
                    442:        || options[3] != DEFLATE_CHK_SEQUENCE)
                    443:        return 0;
                    444:
                    445:     state->seqno = 0;
                    446:     state->unit = unit;
                    447:     state->hdrlen = hdrlen;
                    448:     state->debug = debug;
                    449:     state->mru = mru;
                    450:
                    451:     inflateReset(&state->strm);
                    452:
                    453:     return 1;
                    454: }
                    455:
                    456: static void
                    457: z_decomp_reset(arg)
                    458:     void *arg;
                    459: {
                    460:     struct deflate_state *state = (struct deflate_state *) arg;
                    461:
                    462:     state->seqno = 0;
                    463:     inflateReset(&state->strm);
                    464: }
                    465:
                    466: /*
                    467:  * Decompress a Deflate-compressed packet.
                    468:  *
                    469:  * Because of patent problems, we return DECOMP_ERROR for errors
                    470:  * found by inspecting the input data and for system problems, but
                    471:  * DECOMP_FATALERROR for any errors which could possibly be said to
                    472:  * be being detected "after" decompression.  For DECOMP_ERROR,
                    473:  * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
                    474:  * infringing a patent of Motorola's if we do, so we take CCP down
                    475:  * instead.
                    476:  *
                    477:  * Given that the frame has the correct sequence number and a good FCS,
                    478:  * errors such as invalid codes in the input most likely indicate a
                    479:  * bug, so we return DECOMP_FATALERROR for them in order to turn off
                    480:  * compression, even though they are detected by inspecting the input.
                    481:  */
                    482: int
                    483: z_decompress(arg, mi, mop)
                    484:     void *arg;
                    485:     struct mbuf *mi, **mop;
                    486: {
                    487:     struct deflate_state *state = (struct deflate_state *) arg;
                    488:     struct mbuf *mo, *mo_head;
                    489:     u_char *rptr, *wptr;
                    490:     int rlen, olen, ospace;
                    491:     int seq, i, flush, r, decode_proto;
                    492:     u_char hdr[PPP_HDRLEN + DEFLATE_OVHD];
                    493:
                    494:     *mop = NULL;
                    495:     rptr = mtod(mi, u_char *);
                    496:     rlen = mi->m_len;
                    497:     for (i = 0; i < PPP_HDRLEN + DEFLATE_OVHD; ++i) {
                    498:        while (rlen <= 0) {
                    499:            mi = mi->m_next;
                    500:            if (mi == NULL)
                    501:                return DECOMP_ERROR;
                    502:            rptr = mtod(mi, u_char *);
                    503:            rlen = mi->m_len;
                    504:        }
                    505:        hdr[i] = *rptr++;
                    506:        --rlen;
                    507:     }
                    508:
                    509:     /* Check the sequence number. */
                    510:     seq = (hdr[PPP_HDRLEN] << 8) + hdr[PPP_HDRLEN+1];
                    511:     if (seq != state->seqno) {
                    512:        if (state->debug)
                    513:            printf("z_decompress%d: bad seq # %d, expected %d\n",
                    514:                   state->unit, seq, state->seqno);
                    515:        return DECOMP_ERROR;
                    516:     }
                    517:     ++state->seqno;
                    518:
                    519:     /* Allocate an output mbuf. */
                    520:     MGETHDR(mo, M_DONTWAIT, MT_DATA);
                    521:     if (mo == NULL)
                    522:        return DECOMP_ERROR;
                    523:     mo_head = mo;
                    524:     mo->m_len = 0;
                    525:     mo->m_next = NULL;
                    526:     MCLGET(mo, M_DONTWAIT);
                    527:     ospace = M_TRAILINGSPACE(mo);
                    528:     if (state->hdrlen + PPP_HDRLEN < ospace) {
                    529:        mo->m_data += state->hdrlen;
                    530:        ospace -= state->hdrlen;
                    531:     }
                    532:
                    533:     /*
                    534:      * Fill in the first part of the PPP header.  The protocol field
                    535:      * comes from the decompressed data.
                    536:      */
                    537:     wptr = mtod(mo, u_char *);
                    538:     wptr[0] = PPP_ADDRESS(hdr);
                    539:     wptr[1] = PPP_CONTROL(hdr);
                    540:     wptr[2] = 0;
                    541:
                    542:     /*
                    543:      * Set up to call inflate.  We set avail_out to 1 initially so we can
                    544:      * look at the first byte of the output and decide whether we have
                    545:      * a 1-byte or 2-byte protocol field.
                    546:      */
                    547:     state->strm.next_in = rptr;
                    548:     state->strm.avail_in = rlen;
                    549:     mi = mi->m_next;
                    550:     flush = (mi == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
                    551:     rlen += PPP_HDRLEN + DEFLATE_OVHD;
                    552:     state->strm.next_out = wptr + 3;
                    553:     state->strm.avail_out = 1;
                    554:     decode_proto = 1;
                    555:     olen = PPP_HDRLEN;
                    556:
                    557:     /*
                    558:      * Call inflate, supplying more input or output as needed.
                    559:      */
                    560:     for (;;) {
                    561:        r = inflate(&state->strm, flush);
                    562:        if (r != Z_OK) {
                    563: #ifndef DEFLATE_DEBUG
                    564:            if (state->debug)
                    565: #endif
                    566:                printf("z_decompress%d: inflate returned %d (%s)\n",
                    567:                       state->unit, r, (state->strm.msg? state->strm.msg: ""));
                    568:            m_freem(mo_head);
                    569:            return DECOMP_FATALERROR;
                    570:        }
                    571:        if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
                    572:            break;              /* all done */
                    573:        if (state->strm.avail_in == 0 && mi != NULL) {
                    574:            state->strm.next_in = mtod(mi, u_char *);
                    575:            state->strm.avail_in = mi->m_len;
                    576:            rlen += mi->m_len;
                    577:            mi = mi->m_next;
                    578:            if (mi == NULL)
                    579:                flush = Z_PACKET_FLUSH;
                    580:        }
                    581:        if (state->strm.avail_out == 0) {
                    582:            if (decode_proto) {
                    583:                state->strm.avail_out = ospace - PPP_HDRLEN;
                    584:                if ((wptr[3] & 1) == 0) {
                    585:                    /* 2-byte protocol field */
                    586:                    wptr[2] = wptr[3];
                    587:                    --state->strm.next_out;
                    588:                    ++state->strm.avail_out;
                    589:                    --olen;
                    590:                }
                    591:                decode_proto = 0;
                    592:            } else {
                    593:                mo->m_len = ospace;
                    594:                olen += ospace;
                    595:                MGET(mo->m_next, M_DONTWAIT, MT_DATA);
                    596:                mo = mo->m_next;
                    597:                if (mo == NULL) {
                    598:                    m_freem(mo_head);
                    599:                    return DECOMP_ERROR;
                    600:                }
                    601:                MCLGET(mo, M_DONTWAIT);
                    602:                state->strm.next_out = mtod(mo, u_char *);
                    603:                state->strm.avail_out = ospace = M_TRAILINGSPACE(mo);
                    604:            }
                    605:        }
                    606:     }
                    607:     if (decode_proto) {
                    608:        m_freem(mo_head);
                    609:        return DECOMP_ERROR;
                    610:     }
                    611:     olen += (mo->m_len = ospace - state->strm.avail_out);
                    612: #ifdef DEFLATE_DEBUG
                    613:     if (olen > state->mru + PPP_HDRLEN)
                    614:        printf("ppp_deflate%d: exceeded mru (%d > %d)\n",
                    615:               state->unit, olen, state->mru + PPP_HDRLEN);
                    616: #endif
                    617:
                    618:     state->stats.unc_bytes += olen;
                    619:     state->stats.unc_packets++;
                    620:     state->stats.comp_bytes += rlen;
                    621:     state->stats.comp_packets++;
                    622:
                    623:     *mop = mo_head;
                    624:     return DECOMP_OK;
                    625: }
                    626:
                    627: /*
                    628:  * Incompressible data has arrived - add it to the history.
                    629:  */
                    630: static void
                    631: z_incomp(arg, mi)
                    632:     void *arg;
                    633:     struct mbuf *mi;
                    634: {
                    635:     struct deflate_state *state = (struct deflate_state *) arg;
                    636:     u_char *rptr;
                    637:     int rlen, proto, r;
                    638:
                    639:     /*
                    640:      * Check that the protocol is one we handle.
                    641:      */
                    642:     rptr = mtod(mi, u_char *);
                    643:     proto = PPP_PROTOCOL(rptr);
                    644:     if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
                    645:        return;
                    646:
                    647:     ++state->seqno;
                    648:
                    649:     /*
                    650:      * Iterate through the mbufs, adding the characters in them
                    651:      * to the decompressor's history.  For the first mbuf, we start
                    652:      * at the either the 1st or 2nd byte of the protocol field,
                    653:      * depending on whether the protocol value is compressible.
                    654:      */
                    655:     rlen = mi->m_len;
                    656:     state->strm.next_in = rptr + 3;
                    657:     state->strm.avail_in = rlen - 3;
                    658:     if (proto > 0xff) {
                    659:        --state->strm.next_in;
                    660:        ++state->strm.avail_in;
                    661:     }
                    662:     for (;;) {
                    663:        r = inflateIncomp(&state->strm);
                    664:        if (r != Z_OK) {
                    665:            /* gak! */
                    666: #ifndef DEFLATE_DEBUG
                    667:            if (state->debug)
                    668: #endif
                    669:                printf("z_incomp%d: inflateIncomp returned %d (%s)\n",
                    670:                       state->unit, r, (state->strm.msg? state->strm.msg: ""));
                    671:            return;
                    672:        }
                    673:        mi = mi->m_next;
                    674:        if (mi == NULL)
                    675:            break;
                    676:        state->strm.next_in = mtod(mi, u_char *);
                    677:        state->strm.avail_in = mi->m_len;
                    678:        rlen += mi->m_len;
                    679:     }
                    680:
                    681:     /*
                    682:      * Update stats.
                    683:      */
                    684:     state->stats.inc_bytes += rlen;
                    685:     state->stats.inc_packets++;
                    686:     state->stats.unc_bytes += rlen;
                    687:     state->stats.unc_packets++;
                    688: }
                    689:
                    690: #endif /* DO_DEFLATE */

CVSweb