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

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            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.