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/netgraph/ng_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 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2006 Alexander Motin <mav@alkar.net>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice unmodified, this list of conditions, and the following
   12  *    disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  * $FreeBSD$
   30  */
   31 
   32 /*
   33  * Deflate PPP compression netgraph node type.
   34  */
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/kernel.h>
   39 #include <sys/mbuf.h>
   40 #include <sys/malloc.h>
   41 #include <sys/endian.h>
   42 #include <sys/errno.h>
   43 #include <sys/syslog.h>
   44 #include <contrib/zlib/zlib.h>
   45 
   46 #include <netgraph/ng_message.h>
   47 #include <netgraph/netgraph.h>
   48 #include <netgraph/ng_parse.h>
   49 #include <netgraph/ng_deflate.h>
   50 
   51 #include "opt_netgraph.h"
   52 
   53 static MALLOC_DEFINE(M_NETGRAPH_DEFLATE, "netgraph_deflate",
   54     "netgraph deflate node");
   55 
   56 /* DEFLATE header length */
   57 #define DEFLATE_HDRLEN          2
   58 
   59 #define PROT_COMPD              0x00fd
   60 
   61 #define DEFLATE_BUF_SIZE        4096
   62 
   63 /* Node private data */
   64 struct ng_deflate_private {
   65         struct ng_deflate_config cfg;           /* configuration */
   66         u_char          inbuf[DEFLATE_BUF_SIZE];        /* input buffer */
   67         u_char          outbuf[DEFLATE_BUF_SIZE];       /* output buffer */
   68         z_stream        cx;                     /* compression context */
   69         struct ng_deflate_stats stats;          /* statistics */
   70         ng_ID_t         ctrlnode;               /* path to controlling node */
   71         uint16_t        seqnum;                 /* sequence number */
   72         u_char          compress;               /* compress/decompress flag */
   73 };
   74 typedef struct ng_deflate_private *priv_p;
   75 
   76 /* Netgraph node methods */
   77 static ng_constructor_t ng_deflate_constructor;
   78 static ng_rcvmsg_t      ng_deflate_rcvmsg;
   79 static ng_shutdown_t    ng_deflate_shutdown;
   80 static ng_newhook_t     ng_deflate_newhook;
   81 static ng_rcvdata_t     ng_deflate_rcvdata;
   82 static ng_disconnect_t  ng_deflate_disconnect;
   83 
   84 /* Helper functions */
   85 static int      ng_deflate_compress(node_p, struct mbuf *, struct mbuf **);
   86 static int      ng_deflate_decompress(node_p, struct mbuf *, struct mbuf **);
   87 static void     ng_deflate_reset_req(node_p);
   88 
   89 /* Parse type for struct ng_deflate_config. */
   90 static const struct ng_parse_struct_field ng_deflate_config_type_fields[]
   91         = NG_DEFLATE_CONFIG_INFO;
   92 static const struct ng_parse_type ng_deflate_config_type = {
   93         &ng_parse_struct_type,
   94         ng_deflate_config_type_fields
   95 };
   96 
   97 /* Parse type for struct ng_deflate_stat. */
   98 static const struct ng_parse_struct_field ng_deflate_stats_type_fields[]
   99         = NG_DEFLATE_STATS_INFO;
  100 static const struct ng_parse_type ng_deflate_stat_type = {
  101         &ng_parse_struct_type,
  102         ng_deflate_stats_type_fields
  103 };
  104 
  105 /* List of commands and how to convert arguments to/from ASCII. */
  106 static const struct ng_cmdlist ng_deflate_cmds[] = {
  107         {
  108           NGM_DEFLATE_COOKIE,
  109           NGM_DEFLATE_CONFIG,
  110           "config",
  111           &ng_deflate_config_type,
  112           NULL
  113         },
  114         {
  115           NGM_DEFLATE_COOKIE,
  116           NGM_DEFLATE_RESETREQ,
  117           "resetreq",
  118           NULL,
  119           NULL
  120         },
  121         {
  122           NGM_DEFLATE_COOKIE,
  123           NGM_DEFLATE_GET_STATS,
  124           "getstats",
  125           NULL,
  126           &ng_deflate_stat_type
  127         },
  128         {
  129           NGM_DEFLATE_COOKIE,
  130           NGM_DEFLATE_CLR_STATS,
  131           "clrstats",
  132           NULL,
  133           NULL
  134         },
  135         {
  136           NGM_DEFLATE_COOKIE,
  137           NGM_DEFLATE_GETCLR_STATS,
  138           "getclrstats",
  139           NULL,
  140           &ng_deflate_stat_type
  141         },
  142         { 0 }
  143 };
  144 
  145 /* Node type descriptor */
  146 static struct ng_type ng_deflate_typestruct = {
  147         .version =      NG_ABI_VERSION,
  148         .name =         NG_DEFLATE_NODE_TYPE,
  149         .constructor =  ng_deflate_constructor,
  150         .rcvmsg =       ng_deflate_rcvmsg,
  151         .shutdown =     ng_deflate_shutdown,
  152         .newhook =      ng_deflate_newhook,
  153         .rcvdata =      ng_deflate_rcvdata,
  154         .disconnect =   ng_deflate_disconnect,
  155         .cmdlist =      ng_deflate_cmds,
  156 };
  157 NETGRAPH_INIT(deflate, &ng_deflate_typestruct);
  158 
  159 /* Depend on separate zlib module. */
  160 MODULE_DEPEND(ng_deflate, zlib, 1, 1, 1);
  161 
  162 #define ERROUT(x)       do { error = (x); goto done; } while (0)
  163 
  164 /************************************************************************
  165                         NETGRAPH NODE STUFF
  166  ************************************************************************/
  167 
  168 /*
  169  * Node type constructor
  170  */
  171 static int
  172 ng_deflate_constructor(node_p node)
  173 {
  174         priv_p priv;
  175 
  176         /* Allocate private structure. */
  177         priv = malloc(sizeof(*priv), M_NETGRAPH_DEFLATE, M_WAITOK | M_ZERO);
  178 
  179         NG_NODE_SET_PRIVATE(node, priv);
  180 
  181         /* This node is not thread safe. */
  182         NG_NODE_FORCE_WRITER(node);
  183 
  184         /* Done */
  185         return (0);
  186 }
  187 
  188 /*
  189  * Give our OK for a hook to be added.
  190  */
  191 static int
  192 ng_deflate_newhook(node_p node, hook_p hook, const char *name)
  193 {
  194         const priv_p priv = NG_NODE_PRIVATE(node);
  195 
  196         if (NG_NODE_NUMHOOKS(node) > 0)
  197                 return (EINVAL);
  198 
  199         if (strcmp(name, NG_DEFLATE_HOOK_COMP) == 0)
  200                 priv->compress = 1;
  201         else if (strcmp(name, NG_DEFLATE_HOOK_DECOMP) == 0)
  202                 priv->compress = 0;
  203         else
  204                 return (EINVAL);
  205 
  206         return (0);
  207 }
  208 
  209 /*
  210  * Receive a control message
  211  */
  212 static int
  213 ng_deflate_rcvmsg(node_p node, item_p item, hook_p lasthook)
  214 {
  215         const priv_p priv = NG_NODE_PRIVATE(node);
  216         struct ng_mesg *resp = NULL;
  217         int error = 0;
  218         struct ng_mesg *msg;
  219 
  220         NGI_GET_MSG(item, msg);
  221 
  222         if (msg->header.typecookie != NGM_DEFLATE_COOKIE)
  223                 ERROUT(EINVAL);
  224 
  225         switch (msg->header.cmd) {
  226         case NGM_DEFLATE_CONFIG:
  227             {
  228                 struct ng_deflate_config *const cfg
  229                     = (struct ng_deflate_config *)msg->data;
  230 
  231                 /* Check configuration. */
  232                 if (msg->header.arglen != sizeof(*cfg))
  233                         ERROUT(EINVAL);
  234                 if (cfg->enable) {
  235                     if (cfg->windowBits < 8 || cfg->windowBits > 15)
  236                         ERROUT(EINVAL);
  237                 } else
  238                     cfg->windowBits = 0;
  239 
  240                 /* Clear previous state. */
  241                 if (priv->cfg.enable) {
  242                         if (priv->compress)
  243                                 deflateEnd(&priv->cx);
  244                         else
  245                                 inflateEnd(&priv->cx);
  246                         priv->cfg.enable = 0;
  247                 }
  248 
  249                 /* Configuration is OK, reset to it. */
  250                 priv->cfg = *cfg;
  251 
  252                 if (priv->cfg.enable) {
  253                         priv->cx.next_in = NULL;
  254                         int res;
  255                         if (priv->compress) {
  256                                 if ((res = deflateInit2(&priv->cx,
  257                                     Z_DEFAULT_COMPRESSION, Z_DEFLATED,
  258                                     -cfg->windowBits, 8,
  259                                     Z_DEFAULT_STRATEGY)) != Z_OK) {
  260                                         log(LOG_NOTICE,
  261                                             "deflateInit2: error %d, %s\n",
  262                                             res, priv->cx.msg);
  263                                         priv->cfg.enable = 0;
  264                                         ERROUT(ENOMEM);
  265                                 }
  266                         } else {
  267                                 if ((res = inflateInit2(&priv->cx,
  268                                     -cfg->windowBits)) != Z_OK) {
  269                                         log(LOG_NOTICE,
  270                                             "inflateInit2: error %d, %s\n",
  271                                             res, priv->cx.msg);
  272                                         priv->cfg.enable = 0;
  273                                         ERROUT(ENOMEM);
  274                                 }
  275                         }
  276                 }
  277 
  278                 /* Initialize other state. */
  279                 priv->seqnum = 0;
  280 
  281                 /* Save return address so we can send reset-req's */
  282                 priv->ctrlnode = NGI_RETADDR(item);
  283                 break;
  284             }
  285 
  286         case NGM_DEFLATE_RESETREQ:
  287                 ng_deflate_reset_req(node);
  288                 break;
  289 
  290         case NGM_DEFLATE_GET_STATS:
  291         case NGM_DEFLATE_CLR_STATS:
  292         case NGM_DEFLATE_GETCLR_STATS:
  293                 /* Create response if requested. */
  294                 if (msg->header.cmd != NGM_DEFLATE_CLR_STATS) {
  295                         NG_MKRESPONSE(resp, msg,
  296                             sizeof(struct ng_deflate_stats), M_NOWAIT);
  297                         if (resp == NULL)
  298                                 ERROUT(ENOMEM);
  299                         bcopy(&priv->stats, resp->data,
  300                             sizeof(struct ng_deflate_stats));
  301                 }
  302 
  303                 /* Clear stats if requested. */
  304                 if (msg->header.cmd != NGM_DEFLATE_GET_STATS)
  305                         bzero(&priv->stats,
  306                             sizeof(struct ng_deflate_stats));
  307                 break;
  308 
  309         default:
  310                 error = EINVAL;
  311                 break;
  312         }
  313 done:
  314         NG_RESPOND_MSG(error, node, item, resp);
  315         NG_FREE_MSG(msg);
  316         return (error);
  317 }
  318 
  319 /*
  320  * Receive incoming data on our hook.
  321  */
  322 static int
  323 ng_deflate_rcvdata(hook_p hook, item_p item)
  324 {
  325         const node_p node = NG_HOOK_NODE(hook);
  326         const priv_p priv = NG_NODE_PRIVATE(node);
  327         struct mbuf *m, *out;
  328         int error;
  329 
  330         if (!priv->cfg.enable) {
  331                 NG_FREE_ITEM(item);
  332                 return (ENXIO);
  333         }
  334 
  335         NGI_GET_M(item, m);
  336         /* Compress */
  337         if (priv->compress) {
  338                 if ((error = ng_deflate_compress(node, m, &out)) != 0) {
  339                         NG_FREE_ITEM(item);
  340                         log(LOG_NOTICE, "%s: error: %d\n", __func__, error);
  341                         return (error);
  342                 }
  343         } else { /* Decompress */
  344                 if ((error = ng_deflate_decompress(node, m, &out)) != 0) {
  345                         NG_FREE_ITEM(item);
  346                         log(LOG_NOTICE, "%s: error: %d\n", __func__, error);
  347                         if (priv->ctrlnode != 0) {
  348                                 struct ng_mesg *msg;
  349 
  350                                 /* Need to send a reset-request. */
  351                                 NG_MKMESSAGE(msg, NGM_DEFLATE_COOKIE,
  352                                     NGM_DEFLATE_RESETREQ, 0, M_NOWAIT);
  353                                 if (msg == NULL)
  354                                         return (error);
  355                                 NG_SEND_MSG_ID(error, node, msg,
  356                                         priv->ctrlnode, 0);
  357                         }
  358                         return (error);
  359                 }
  360         }
  361 
  362         NG_FWD_NEW_DATA(error, item, hook, out);
  363         return (error);
  364 }
  365 
  366 /*
  367  * Destroy node.
  368  */
  369 static int
  370 ng_deflate_shutdown(node_p node)
  371 {
  372         const priv_p priv = NG_NODE_PRIVATE(node);
  373 
  374         /* Take down netgraph node. */
  375         if (priv->cfg.enable) {
  376             if (priv->compress)
  377                 deflateEnd(&priv->cx);
  378             else
  379                 inflateEnd(&priv->cx);
  380         }
  381 
  382         free(priv, M_NETGRAPH_DEFLATE);
  383         NG_NODE_SET_PRIVATE(node, NULL);
  384         NG_NODE_UNREF(node);            /* let the node escape */
  385         return (0);
  386 }
  387 
  388 /*
  389  * Hook disconnection
  390  */
  391 static int
  392 ng_deflate_disconnect(hook_p hook)
  393 {
  394         const node_p node = NG_HOOK_NODE(hook);
  395         const priv_p priv = NG_NODE_PRIVATE(node);
  396 
  397         if (priv->cfg.enable) {
  398             if (priv->compress)
  399                 deflateEnd(&priv->cx);
  400             else
  401                 inflateEnd(&priv->cx);
  402             priv->cfg.enable = 0;
  403         }
  404 
  405         /* Go away if no longer connected. */
  406         if ((NG_NODE_NUMHOOKS(node) == 0) && NG_NODE_IS_VALID(node))
  407                 ng_rmnode_self(node);
  408         return (0);
  409 }
  410 
  411 /************************************************************************
  412                         HELPER STUFF
  413  ************************************************************************/
  414 
  415 /*
  416  * Compress/encrypt a packet and put the result in a new mbuf at *resultp.
  417  * The original mbuf is not free'd.
  418  */
  419 static int
  420 ng_deflate_compress(node_p node, struct mbuf *m, struct mbuf **resultp)
  421 {
  422         const priv_p    priv = NG_NODE_PRIVATE(node);
  423         int             outlen, inlen;
  424         int             rtn;
  425 
  426         /* Initialize. */
  427         *resultp = NULL;
  428 
  429         inlen = m->m_pkthdr.len;
  430 
  431         priv->stats.FramesPlain++;
  432         priv->stats.InOctets+=inlen;
  433 
  434         if (inlen > DEFLATE_BUF_SIZE) {
  435                 priv->stats.Errors++;
  436                 NG_FREE_M(m);
  437                 return (ENOMEM);
  438         }
  439 
  440         /* We must own the mbuf chain exclusively to modify it. */
  441         m = m_unshare(m, M_NOWAIT);
  442         if (m == NULL) {
  443                 priv->stats.Errors++;
  444                 return (ENOMEM);
  445         }
  446 
  447         /* Work with contiguous regions of memory. */
  448         m_copydata(m, 0, inlen, (caddr_t)priv->inbuf);
  449         outlen = DEFLATE_BUF_SIZE;
  450 
  451         /* Compress "inbuf" into "outbuf". */
  452         /* Prepare to compress. */
  453         if (priv->inbuf[0] != 0) {
  454                 priv->cx.next_in = priv->inbuf;
  455                 priv->cx.avail_in = inlen;
  456         } else {
  457                 priv->cx.next_in = priv->inbuf + 1; /* compress protocol */
  458                 priv->cx.avail_in = inlen - 1;
  459         }
  460         priv->cx.next_out = priv->outbuf + 2 + DEFLATE_HDRLEN;
  461         priv->cx.avail_out = outlen - 2 - DEFLATE_HDRLEN;
  462 
  463         /* Compress. */
  464         rtn = deflate(&priv->cx, Z_SYNC_FLUSH);
  465 
  466         /* Check return value. */
  467         if (rtn != Z_OK) {
  468                 priv->stats.Errors++;
  469                 log(LOG_NOTICE, "ng_deflate: compression error: %d (%s)\n",
  470                     rtn, priv->cx.msg);
  471                 NG_FREE_M(m);
  472                 return (EINVAL);
  473         }
  474 
  475         /* Calculate resulting size. */
  476         outlen -= priv->cx.avail_out;
  477         /*
  478          * Z_SYNC_FLUSH completes the current deflate block and follows
  479          * it with an empty stored block that is three bits plus filler
  480          * bits to the next byte, followed by four bytes (00 00 ff ff).
  481          * RFC 1979 Section 2.1, "Data" requires the four bytes be
  482          * removed before transmission.
  483          */
  484         outlen -= 4;
  485         MPASS(outlen > 0);
  486         MPASS(priv->outbuf[outlen + 0] == 0x00);
  487         MPASS(priv->outbuf[outlen + 1] == 0x00);
  488         MPASS(priv->outbuf[outlen + 2] == 0xff);
  489         MPASS(priv->outbuf[outlen + 3] == 0xff);
  490 
  491         /* If we can't compress this packet, send it as-is. */
  492         if (outlen > inlen) {
  493                 /* Return original packet uncompressed. */
  494                 *resultp = m;
  495                 priv->stats.FramesUncomp++;
  496                 priv->stats.OutOctets+=inlen;
  497         } else {
  498                 /* Install header. */
  499                 be16enc(priv->outbuf, PROT_COMPD);
  500                 be16enc(priv->outbuf + 2, priv->seqnum);
  501 
  502                 /* Return packet in an mbuf. */
  503                 m_copyback(m, 0, outlen, (caddr_t)priv->outbuf);
  504                 if (m->m_pkthdr.len < outlen) {
  505                         m_freem(m);
  506                         priv->stats.Errors++;
  507                         return (ENOMEM);
  508                 } else if (outlen < m->m_pkthdr.len)
  509                         m_adj(m, outlen - m->m_pkthdr.len);
  510                 *resultp = m;
  511                 priv->stats.FramesComp++;
  512                 priv->stats.OutOctets+=outlen;
  513         }
  514 
  515         /* Update sequence number. */
  516         priv->seqnum++;
  517 
  518         return (0);
  519 }
  520 
  521 /*
  522  * Decompress/decrypt packet and put the result in a new mbuf at *resultp.
  523  * The original mbuf is not free'd.
  524  */
  525 static int
  526 ng_deflate_decompress(node_p node, struct mbuf *m, struct mbuf **resultp)
  527 {
  528         const priv_p    priv = NG_NODE_PRIVATE(node);
  529         int             outlen, inlen, datalen;
  530         int             rtn;
  531         uint16_t        proto;
  532         int             offset;
  533         uint16_t        rseqnum;
  534         u_char          headbuf[5];
  535         static u_char   EMPTY_BLOCK[4] = { 0x00, 0x00, 0xff, 0xff };
  536 
  537         /* Initialize. */
  538         *resultp = NULL;
  539 
  540         inlen = m->m_pkthdr.len;
  541 
  542         if (inlen > DEFLATE_BUF_SIZE) {
  543                 priv->stats.Errors++;
  544                 NG_FREE_M(m);
  545                 priv->seqnum = 0;
  546                 return (ENOMEM);
  547         }
  548 
  549         /* We must own the mbuf chain exclusively to modify it. */
  550         m = m_unshare(m, M_NOWAIT);
  551         if (m == NULL) {
  552                 priv->stats.Errors++;
  553                 return (ENOMEM);
  554         }
  555 
  556         /* Work with contiguous regions of memory. */
  557         m_copydata(m, 0, inlen, (caddr_t)priv->inbuf);
  558 
  559         /* Separate proto. */
  560         if ((priv->inbuf[0] & 0x01) != 0) {
  561                 proto = priv->inbuf[0];
  562                 offset = 1;
  563         } else {
  564                 proto = be16dec(priv->inbuf);
  565                 offset = 2;
  566         }
  567 
  568         priv->stats.InOctets += inlen;
  569 
  570         /* Packet is compressed, so decompress. */
  571         if (proto == PROT_COMPD) {
  572                 priv->stats.FramesComp++;
  573 
  574                 /* Check sequence number. */
  575                 rseqnum = be16dec(priv->inbuf + offset);
  576                 offset += 2;
  577                 if (rseqnum != priv->seqnum) {
  578                         priv->stats.Errors++;
  579                         log(LOG_NOTICE, "ng_deflate: wrong sequence: %u "
  580                             "instead of %u\n", rseqnum, priv->seqnum);
  581                         NG_FREE_M(m);
  582                         priv->seqnum = 0;
  583                         return (EPIPE);
  584                 }
  585 
  586                 outlen = DEFLATE_BUF_SIZE;
  587 
  588                 /* Decompress "inbuf" into "outbuf". */
  589                 /* Prepare to decompress. */
  590                 priv->cx.next_in = priv->inbuf + offset;
  591                 priv->cx.avail_in = inlen - offset;
  592                 /* Reserve space for protocol decompression. */
  593                 priv->cx.next_out = priv->outbuf + 1;
  594                 priv->cx.avail_out = outlen - 1;
  595 
  596                 /* Decompress. */
  597                 rtn = inflate(&priv->cx, Z_SYNC_FLUSH);
  598 
  599                 /* Check return value. */
  600                 if (rtn != Z_OK && rtn != Z_STREAM_END) {
  601                         priv->stats.Errors++;
  602                         NG_FREE_M(m);
  603                         priv->seqnum = 0;
  604                         log(LOG_NOTICE, "%s: decompression error: %d (%s)\n",
  605                             __func__, rtn, priv->cx.msg);
  606 
  607                         switch (rtn) {
  608                         case Z_MEM_ERROR:
  609                                 return (ENOMEM);
  610                         case Z_DATA_ERROR:
  611                                 return (EIO);
  612                         default:
  613                                 return (EINVAL);
  614                         }
  615                 }
  616 
  617                 /* Handle the EMPTY_BLOCK omitted by sender */
  618                 if (inflateSyncPoint(&priv->cx)) {
  619                         priv->cx.avail_in = 4;
  620                         priv->cx.next_in = EMPTY_BLOCK;
  621                         inflate(&priv->cx, Z_SYNC_FLUSH);
  622                 }
  623 
  624                 /* Calculate resulting size. */
  625                 outlen -= priv->cx.avail_out;
  626 
  627                 /* Decompress protocol. */
  628                 if ((priv->outbuf[1] & 0x01) != 0) {
  629                         priv->outbuf[0] = 0;
  630                         /* Return packet in an mbuf. */
  631                         m_copyback(m, 0, outlen, (caddr_t)priv->outbuf);
  632                 } else {
  633                         outlen--;
  634                         /* Return packet in an mbuf. */
  635                         m_copyback(m, 0, outlen, (caddr_t)(priv->outbuf + 1));
  636                 }
  637                 if (m->m_pkthdr.len < outlen) {
  638                         m_freem(m);
  639                         priv->stats.Errors++;
  640                         priv->seqnum = 0;
  641                         return (ENOMEM);
  642                 } else if (outlen < m->m_pkthdr.len)
  643                         m_adj(m, outlen - m->m_pkthdr.len);
  644                 *resultp = m;
  645                 priv->stats.FramesPlain++;
  646                 priv->stats.OutOctets+=outlen;
  647 
  648         } else {
  649                 /* Packet is not compressed, just update dictionary. */
  650                 priv->stats.FramesUncomp++;
  651 
  652                 /*
  653                  * Fake a header for uncompressed data block
  654                  */
  655                 datalen = inlen - offset + 1;
  656                 headbuf[0] = 0x80;
  657                 headbuf[1] = datalen & 0xff;
  658                 headbuf[2] = datalen >> 8;
  659                 headbuf[3] = (~datalen) & 0xff;
  660                 headbuf[4] = (~datalen) >> 8;
  661 
  662                 priv->cx.next_in = headbuf;
  663                 priv->cx.avail_in = sizeof(headbuf);
  664                 priv->cx.next_out = priv->outbuf;
  665                 priv->cx.avail_out = DEFLATE_BUF_SIZE;
  666 
  667                 rtn = inflate(&priv->cx, Z_NO_FLUSH);
  668 
  669                 if (priv->inbuf[0] == 0) {
  670                         priv->cx.next_in =
  671                             priv->inbuf + 1; /* compress protocol */
  672                         priv->cx.avail_in = inlen - 1;
  673                 } else {
  674                         priv->cx.next_in = priv->inbuf;
  675                         priv->cx.avail_in = inlen;
  676                 }
  677                 priv->cx.next_out = priv->outbuf;
  678                 priv->cx.avail_out = DEFLATE_BUF_SIZE;
  679 
  680                 rtn = inflate(&priv->cx, Z_SYNC_FLUSH);
  681 
  682                 /* Check return value */
  683                 if (rtn != Z_OK) {
  684                         priv->stats.Errors++;
  685                         log(LOG_NOTICE, "%s: inflate error: %d (%s)\n",
  686                             __func__, rtn, priv->cx.msg);
  687                         NG_FREE_M(m);
  688                         priv->seqnum = 0;
  689                         return (EINVAL);
  690                 }
  691 
  692                 *resultp = m;
  693                 priv->stats.FramesPlain++;
  694                 priv->stats.OutOctets += inlen;
  695         }
  696 
  697         /* Update sequence number. */
  698         priv->seqnum++;
  699 
  700         return (0);
  701 }
  702 
  703 /*
  704  * The peer has sent us a CCP ResetRequest, so reset our transmit state.
  705  */
  706 static void
  707 ng_deflate_reset_req(node_p node)
  708 {
  709         const priv_p priv = NG_NODE_PRIVATE(node);
  710 
  711         priv->seqnum = 0;
  712         if (priv->cfg.enable) {
  713             if (priv->compress)
  714                 deflateReset(&priv->cx);
  715             else
  716                 inflateReset(&priv->cx);
  717         }
  718 }
  719 

Cache object: ad313802f53487fe208d36d4696daa6b


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