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

Cache object: 95a2f1936e479549e6f40d42683e9334


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