The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net/ppp_deflate.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: b3a6251a5a2748d731ae1d6f274c71dd


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.