Annotation of XNU/bsd/net/ppp_deflate.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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