LCOV - code coverage report
Current view: top level - net - ppp-deflate.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 321 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 14 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13