[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     ! 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