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: releng/12.0/sys/netgraph/ng_deflate.c 328218 2018-01-21 15:42:36Z pfg $
   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 <sys/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 void     *z_alloc(void *, u_int items, u_int size);
   86 static void     z_free(void *, void *ptr);
   87 static int      ng_deflate_compress(node_p node,
   88                     struct mbuf *m, struct mbuf **resultp);
   89 static int      ng_deflate_decompress(node_p node,
   90                     struct mbuf *m, struct mbuf **resultp);
   91 static void     ng_deflate_reset_req(node_p node);
   92 
   93 /* Parse type for struct ng_deflate_config. */
   94 static const struct ng_parse_struct_field ng_deflate_config_type_fields[]
   95         = NG_DEFLATE_CONFIG_INFO;
   96 static const struct ng_parse_type ng_deflate_config_type = {
   97         &ng_parse_struct_type,
   98         ng_deflate_config_type_fields
   99 };
  100 
  101 /* Parse type for struct ng_deflate_stat. */
  102 static const struct ng_parse_struct_field ng_deflate_stats_type_fields[]
  103         = NG_DEFLATE_STATS_INFO;
  104 static const struct ng_parse_type ng_deflate_stat_type = {
  105         &ng_parse_struct_type,
  106         ng_deflate_stats_type_fields
  107 };
  108 
  109 /* List of commands and how to convert arguments to/from ASCII. */
  110 static const struct ng_cmdlist ng_deflate_cmds[] = {
  111         {
  112           NGM_DEFLATE_COOKIE,
  113           NGM_DEFLATE_CONFIG,
  114           "config",
  115           &ng_deflate_config_type,
  116           NULL
  117         },
  118         {
  119           NGM_DEFLATE_COOKIE,
  120           NGM_DEFLATE_RESETREQ,
  121           "resetreq",
  122           NULL,
  123           NULL
  124         },
  125         {
  126           NGM_DEFLATE_COOKIE,
  127           NGM_DEFLATE_GET_STATS,
  128           "getstats",
  129           NULL,
  130           &ng_deflate_stat_type
  131         },
  132         {
  133           NGM_DEFLATE_COOKIE,
  134           NGM_DEFLATE_CLR_STATS,
  135           "clrstats",
  136           NULL,
  137           NULL
  138         },
  139         {
  140           NGM_DEFLATE_COOKIE,
  141           NGM_DEFLATE_GETCLR_STATS,
  142           "getclrstats",
  143           NULL,
  144           &ng_deflate_stat_type
  145         },
  146         { 0 }
  147 };
  148 
  149 /* Node type descriptor */
  150 static struct ng_type ng_deflate_typestruct = {
  151         .version =      NG_ABI_VERSION,
  152         .name =         NG_DEFLATE_NODE_TYPE,
  153         .constructor =  ng_deflate_constructor,
  154         .rcvmsg =       ng_deflate_rcvmsg,
  155         .shutdown =     ng_deflate_shutdown,
  156         .newhook =      ng_deflate_newhook,
  157         .rcvdata =      ng_deflate_rcvdata,
  158         .disconnect =   ng_deflate_disconnect,
  159         .cmdlist =      ng_deflate_cmds,
  160 };
  161 NETGRAPH_INIT(deflate, &ng_deflate_typestruct);
  162 
  163 /* Depend on separate zlib module. */
  164 MODULE_DEPEND(ng_deflate, zlib, 1, 1, 1);
  165 
  166 #define ERROUT(x)       do { error = (x); goto done; } while (0)
  167 
  168 /************************************************************************
  169                         NETGRAPH NODE STUFF
  170  ************************************************************************/
  171 
  172 /*
  173  * Node type constructor
  174  */
  175 static int
  176 ng_deflate_constructor(node_p node)
  177 {
  178         priv_p priv;
  179 
  180         /* Allocate private structure. */
  181         priv = malloc(sizeof(*priv), M_NETGRAPH_DEFLATE, M_WAITOK | M_ZERO);
  182 
  183         NG_NODE_SET_PRIVATE(node, priv);
  184 
  185         /* This node is not thread safe. */
  186         NG_NODE_FORCE_WRITER(node);
  187 
  188         /* Done */
  189         return (0);
  190 }
  191 
  192 /*
  193  * Give our OK for a hook to be added.
  194  */
  195 static int
  196 ng_deflate_newhook(node_p node, hook_p hook, const char *name)
  197 {
  198         const priv_p priv = NG_NODE_PRIVATE(node);
  199 
  200         if (NG_NODE_NUMHOOKS(node) > 0)
  201                 return (EINVAL);
  202 
  203         if (strcmp(name, NG_DEFLATE_HOOK_COMP) == 0)
  204                 priv->compress = 1;
  205         else if (strcmp(name, NG_DEFLATE_HOOK_DECOMP) == 0)
  206                 priv->compress = 0;
  207         else
  208                 return (EINVAL);
  209 
  210         return (0);
  211 }
  212 
  213 /*
  214  * Receive a control message
  215  */
  216 static int
  217 ng_deflate_rcvmsg(node_p node, item_p item, hook_p lasthook)
  218 {
  219         const priv_p priv = NG_NODE_PRIVATE(node);
  220         struct ng_mesg *resp = NULL;
  221         int error = 0;
  222         struct ng_mesg *msg;
  223 
  224         NGI_GET_MSG(item, msg);
  225 
  226         if (msg->header.typecookie != NGM_DEFLATE_COOKIE)
  227                 ERROUT(EINVAL);
  228 
  229         switch (msg->header.cmd) {
  230         case NGM_DEFLATE_CONFIG:
  231             {
  232                 struct ng_deflate_config *const cfg
  233                     = (struct ng_deflate_config *)msg->data;
  234 
  235                 /* Check configuration. */
  236                 if (msg->header.arglen != sizeof(*cfg))
  237                         ERROUT(EINVAL);
  238                 if (cfg->enable) {
  239                     if (cfg->windowBits < 8 || cfg->windowBits > 15)
  240                         ERROUT(EINVAL);
  241                 } else
  242                     cfg->windowBits = 0;
  243 
  244                 /* Clear previous state. */
  245                 if (priv->cfg.enable) {
  246                         if (priv->compress)
  247                                 deflateEnd(&priv->cx);
  248                         else
  249                                 inflateEnd(&priv->cx);
  250                         priv->cfg.enable = 0;
  251                 }
  252 
  253                 /* Configuration is OK, reset to it. */
  254                 priv->cfg = *cfg;
  255 
  256                 if (priv->cfg.enable) {
  257                         priv->cx.next_in = NULL;
  258                         priv->cx.zalloc = z_alloc;
  259                         priv->cx.zfree = z_free;
  260                         int res;
  261                         if (priv->compress) {
  262                                 if ((res = deflateInit2(&priv->cx,
  263                                     Z_DEFAULT_COMPRESSION, Z_DEFLATED,
  264                                     -cfg->windowBits, 8,
  265                                     Z_DEFAULT_STRATEGY)) != Z_OK) {
  266                                         log(LOG_NOTICE,
  267                                             "deflateInit2: error %d, %s\n",
  268                                             res, priv->cx.msg);
  269                                         priv->cfg.enable = 0;
  270                                         ERROUT(ENOMEM);
  271                                 }
  272                         } else {
  273                                 if ((res = inflateInit2(&priv->cx,
  274                                     -cfg->windowBits)) != Z_OK) {
  275                                         log(LOG_NOTICE,
  276                                             "inflateInit2: error %d, %s\n",
  277                                             res, priv->cx.msg);
  278                                         priv->cfg.enable = 0;
  279                                         ERROUT(ENOMEM);
  280                                 }
  281                         }
  282                 }
  283 
  284                 /* Initialize other state. */
  285                 priv->seqnum = 0;
  286 
  287                 /* Save return address so we can send reset-req's */
  288                 priv->ctrlnode = NGI_RETADDR(item);
  289                 break;
  290             }
  291 
  292         case NGM_DEFLATE_RESETREQ:
  293                 ng_deflate_reset_req(node);
  294                 break;
  295 
  296         case NGM_DEFLATE_GET_STATS:
  297         case NGM_DEFLATE_CLR_STATS:
  298         case NGM_DEFLATE_GETCLR_STATS:
  299                 /* Create response if requested. */
  300                 if (msg->header.cmd != NGM_DEFLATE_CLR_STATS) {
  301                         NG_MKRESPONSE(resp, msg,
  302                             sizeof(struct ng_deflate_stats), M_NOWAIT);
  303                         if (resp == NULL)
  304                                 ERROUT(ENOMEM);
  305                         bcopy(&priv->stats, resp->data,
  306                             sizeof(struct ng_deflate_stats));
  307                 }
  308 
  309                 /* Clear stats if requested. */
  310                 if (msg->header.cmd != NGM_DEFLATE_GET_STATS)
  311                         bzero(&priv->stats,
  312                             sizeof(struct ng_deflate_stats));
  313                 break;
  314 
  315         default:
  316                 error = EINVAL;
  317                 break;
  318         }
  319 done:
  320         NG_RESPOND_MSG(error, node, item, resp);
  321         NG_FREE_MSG(msg);
  322         return (error);
  323 }
  324 
  325 /*
  326  * Receive incoming data on our hook.
  327  */
  328 static int
  329 ng_deflate_rcvdata(hook_p hook, item_p item)
  330 {
  331         const node_p node = NG_HOOK_NODE(hook);
  332         const priv_p priv = NG_NODE_PRIVATE(node);
  333         struct mbuf *m, *out;
  334         int error;
  335 
  336         if (!priv->cfg.enable) {
  337                 NG_FREE_ITEM(item);
  338                 return (ENXIO);
  339         }
  340 
  341         NGI_GET_M(item, m);
  342         /* Compress */
  343         if (priv->compress) {
  344                 if ((error = ng_deflate_compress(node, m, &out)) != 0) {
  345                         NG_FREE_ITEM(item);
  346                         log(LOG_NOTICE, "%s: error: %d\n", __func__, error);
  347                         return (error);
  348                 }
  349 
  350         } else { /* Decompress */
  351                 if ((error = ng_deflate_decompress(node, m, &out)) != 0) {
  352                         NG_FREE_ITEM(item);
  353                         log(LOG_NOTICE, "%s: error: %d\n", __func__, error);
  354                         if (priv->ctrlnode != 0) {
  355                                 struct ng_mesg *msg;
  356 
  357                                 /* Need to send a reset-request. */
  358                                 NG_MKMESSAGE(msg, NGM_DEFLATE_COOKIE,
  359                                     NGM_DEFLATE_RESETREQ, 0, M_NOWAIT);
  360                                 if (msg == NULL)
  361                                         return (error);
  362                                 NG_SEND_MSG_ID(error, node, msg,
  363                                         priv->ctrlnode, 0);
  364                         }
  365                         return (error);
  366                 }
  367         }
  368 
  369         NG_FWD_NEW_DATA(error, item, hook, out);
  370         return (error);
  371 }
  372 
  373 /*
  374  * Destroy node.
  375  */
  376 static int
  377 ng_deflate_shutdown(node_p node)
  378 {
  379         const priv_p priv = NG_NODE_PRIVATE(node);
  380 
  381         /* Take down netgraph node. */
  382         if (priv->cfg.enable) {
  383             if (priv->compress)
  384                 deflateEnd(&priv->cx);
  385             else
  386                 inflateEnd(&priv->cx);
  387         }
  388 
  389         free(priv, M_NETGRAPH_DEFLATE);
  390         NG_NODE_SET_PRIVATE(node, NULL);
  391         NG_NODE_UNREF(node);            /* let the node escape */
  392         return (0);
  393 }
  394 
  395 /*
  396  * Hook disconnection
  397  */
  398 static int
  399 ng_deflate_disconnect(hook_p hook)
  400 {
  401         const node_p node = NG_HOOK_NODE(hook);
  402         const priv_p priv = NG_NODE_PRIVATE(node);
  403 
  404         if (priv->cfg.enable) {
  405             if (priv->compress)
  406                 deflateEnd(&priv->cx);
  407             else
  408                 inflateEnd(&priv->cx);
  409             priv->cfg.enable = 0;
  410         }
  411 
  412         /* Go away if no longer connected. */
  413         if ((NG_NODE_NUMHOOKS(node) == 0) && NG_NODE_IS_VALID(node))
  414                 ng_rmnode_self(node);
  415         return (0);
  416 }
  417 
  418 /************************************************************************
  419                         HELPER STUFF
  420  ************************************************************************/
  421 
  422 /*
  423  * Space allocation and freeing routines for use by zlib routines.
  424  */
  425 
  426 static void *
  427 z_alloc(void *notused, u_int items, u_int size)
  428 {
  429 
  430         return (malloc(items * size, M_NETGRAPH_DEFLATE, M_NOWAIT));
  431 }
  432 
  433 static void
  434 z_free(void *notused, void *ptr)
  435 {
  436 
  437         free(ptr, M_NETGRAPH_DEFLATE);
  438 }
  439 
  440 /*
  441  * Compress/encrypt a packet and put the result in a new mbuf at *resultp.
  442  * The original mbuf is not free'd.
  443  */
  444 static int
  445 ng_deflate_compress(node_p node, struct mbuf *m, struct mbuf **resultp)
  446 {
  447         const priv_p    priv = NG_NODE_PRIVATE(node);
  448         int             outlen, inlen;
  449         int             rtn;
  450 
  451         /* Initialize. */
  452         *resultp = NULL;
  453 
  454         inlen = m->m_pkthdr.len;
  455 
  456         priv->stats.FramesPlain++;
  457         priv->stats.InOctets+=inlen;
  458 
  459         if (inlen > DEFLATE_BUF_SIZE) {
  460                 priv->stats.Errors++;
  461                 NG_FREE_M(m);
  462                 return (ENOMEM);
  463         }
  464 
  465         /* We must own the mbuf chain exclusively to modify it. */
  466         m = m_unshare(m, M_NOWAIT);
  467         if (m == NULL) {
  468                 priv->stats.Errors++;
  469                 return (ENOMEM);
  470         }
  471 
  472         /* Work with contiguous regions of memory. */
  473         m_copydata(m, 0, inlen, (caddr_t)priv->inbuf);
  474         outlen = DEFLATE_BUF_SIZE;
  475 
  476         /* Compress "inbuf" into "outbuf". */
  477         /* Prepare to compress. */
  478         if (priv->inbuf[0] != 0) {
  479                 priv->cx.next_in = priv->inbuf;
  480                 priv->cx.avail_in = inlen;
  481         } else {
  482                 priv->cx.next_in = priv->inbuf + 1; /* compress protocol */
  483                 priv->cx.avail_in = inlen - 1;
  484         }
  485         priv->cx.next_out = priv->outbuf + 2 + DEFLATE_HDRLEN;
  486         priv->cx.avail_out = outlen - 2 - DEFLATE_HDRLEN;
  487 
  488         /* Compress. */
  489         rtn = deflate(&priv->cx, Z_PACKET_FLUSH);
  490 
  491         /* Check return value. */
  492         if (rtn != Z_OK) {
  493                 priv->stats.Errors++;
  494                 log(LOG_NOTICE, "ng_deflate: compression error: %d (%s)\n",
  495                     rtn, priv->cx.msg);
  496                 NG_FREE_M(m);
  497                 return (EINVAL);
  498         }
  499 
  500         /* Calculate resulting size. */
  501         outlen -= priv->cx.avail_out;
  502 
  503         /* If we can't compress this packet, send it as-is. */
  504         if (outlen > inlen) {
  505                 /* Return original packet uncompressed. */
  506                 *resultp = m;
  507                 priv->stats.FramesUncomp++;
  508                 priv->stats.OutOctets+=inlen;
  509         } else {
  510                 /* Install header. */
  511                 be16enc(priv->outbuf, PROT_COMPD);
  512                 be16enc(priv->outbuf + 2, priv->seqnum);
  513 
  514                 /* Return packet in an mbuf. */
  515                 m_copyback(m, 0, outlen, (caddr_t)priv->outbuf);
  516                 if (m->m_pkthdr.len < outlen) {
  517                         m_freem(m);
  518                         priv->stats.Errors++;
  519                         return (ENOMEM);
  520                 } else if (outlen < m->m_pkthdr.len)
  521                         m_adj(m, outlen - m->m_pkthdr.len);
  522                 *resultp = m;
  523                 priv->stats.FramesComp++;
  524                 priv->stats.OutOctets+=outlen;
  525         }
  526 
  527         /* Update sequence number. */
  528         priv->seqnum++;
  529 
  530         return (0);
  531 }
  532 
  533 /*
  534  * Decompress/decrypt packet and put the result in a new mbuf at *resultp.
  535  * The original mbuf is not free'd.
  536  */
  537 static int
  538 ng_deflate_decompress(node_p node, struct mbuf *m, struct mbuf **resultp)
  539 {
  540         const priv_p    priv = NG_NODE_PRIVATE(node);
  541         int             outlen, inlen;
  542         int             rtn;
  543         uint16_t        proto;
  544         int             offset;
  545         uint16_t        rseqnum;
  546 
  547         /* Initialize. */
  548         *resultp = NULL;
  549 
  550         inlen = m->m_pkthdr.len;
  551 
  552         if (inlen > DEFLATE_BUF_SIZE) {
  553                 priv->stats.Errors++;
  554                 NG_FREE_M(m);
  555                 priv->seqnum = 0;
  556                 return (ENOMEM);
  557         }
  558 
  559         /* We must own the mbuf chain exclusively to modify it. */
  560         m = m_unshare(m, M_NOWAIT);
  561         if (m == NULL) {
  562                 priv->stats.Errors++;
  563                 return (ENOMEM);
  564         }
  565 
  566         /* Work with contiguous regions of memory. */
  567         m_copydata(m, 0, inlen, (caddr_t)priv->inbuf);
  568 
  569         /* Separate proto. */
  570         if ((priv->inbuf[0] & 0x01) != 0) {
  571                 proto = priv->inbuf[0];
  572                 offset = 1;
  573         } else {
  574                 proto = be16dec(priv->inbuf);
  575                 offset = 2;
  576         }
  577 
  578         priv->stats.InOctets += inlen;
  579 
  580         /* Packet is compressed, so decompress. */
  581         if (proto == PROT_COMPD) {
  582                 priv->stats.FramesComp++;
  583 
  584                 /* Check sequence number. */
  585                 rseqnum = be16dec(priv->inbuf + offset);
  586                 offset += 2;
  587                 if (rseqnum != priv->seqnum) {
  588                         priv->stats.Errors++;
  589                         log(LOG_NOTICE, "ng_deflate: wrong sequence: %u "
  590                             "instead of %u\n", rseqnum, priv->seqnum);
  591                         NG_FREE_M(m);
  592                         priv->seqnum = 0;
  593                         return (EPIPE);
  594                 }
  595 
  596                 outlen = DEFLATE_BUF_SIZE;
  597 
  598                 /* Decompress "inbuf" into "outbuf". */
  599                 /* Prepare to decompress. */
  600                 priv->cx.next_in = priv->inbuf + offset;
  601                 priv->cx.avail_in = inlen - offset;
  602                 /* Reserve space for protocol decompression. */
  603                 priv->cx.next_out = priv->outbuf + 1;
  604                 priv->cx.avail_out = outlen - 1;
  605 
  606                 /* Decompress. */
  607                 rtn = inflate(&priv->cx, Z_PACKET_FLUSH);
  608 
  609                 /* Check return value. */
  610                 if (rtn != Z_OK && rtn != Z_STREAM_END) {
  611                         priv->stats.Errors++;
  612                         NG_FREE_M(m);
  613                         priv->seqnum = 0;
  614                         log(LOG_NOTICE, "%s: decompression error: %d (%s)\n",
  615                             __func__, rtn, priv->cx.msg);
  616 
  617                         switch (rtn) {
  618                         case Z_MEM_ERROR:
  619                                 return (ENOMEM);
  620                         case Z_DATA_ERROR:
  621                                 return (EIO);
  622                         default:
  623                                 return (EINVAL);
  624                         }
  625                 }
  626 
  627                 /* Calculate resulting size. */
  628                 outlen -= priv->cx.avail_out;
  629 
  630                 /* Decompress protocol. */
  631                 if ((priv->outbuf[1] & 0x01) != 0) {
  632                         priv->outbuf[0] = 0;
  633                         /* Return packet in an mbuf. */
  634                         m_copyback(m, 0, outlen, (caddr_t)priv->outbuf);
  635                 } else {
  636                         outlen--;
  637                         /* Return packet in an mbuf. */
  638                         m_copyback(m, 0, outlen, (caddr_t)(priv->outbuf + 1));
  639                 }
  640                 if (m->m_pkthdr.len < outlen) {
  641                         m_freem(m);
  642                         priv->stats.Errors++;
  643                         priv->seqnum = 0;
  644                         return (ENOMEM);
  645                 } else if (outlen < m->m_pkthdr.len)
  646                         m_adj(m, outlen - m->m_pkthdr.len);
  647                 *resultp = m;
  648                 priv->stats.FramesPlain++;
  649                 priv->stats.OutOctets+=outlen;
  650 
  651         } else { /* Packet is not compressed, just update dictionary. */
  652                 priv->stats.FramesUncomp++;
  653                 if (priv->inbuf[0] == 0) {
  654                     priv->cx.next_in = priv->inbuf + 1; /* compress protocol */
  655                     priv->cx.avail_in = inlen - 1;
  656                 } else {
  657                     priv->cx.next_in = priv->inbuf;
  658                     priv->cx.avail_in = inlen;
  659                 }
  660 
  661                 rtn = inflateIncomp(&priv->cx);
  662 
  663                 /* Check return value */
  664                 if (rtn != Z_OK) {
  665                         priv->stats.Errors++;
  666                         log(LOG_NOTICE, "%s: inflateIncomp error: %d (%s)\n",
  667                             __func__, rtn, priv->cx.msg);
  668                         NG_FREE_M(m);
  669                         priv->seqnum = 0;
  670                         return (EINVAL);
  671                 }
  672 
  673                 *resultp = m;
  674                 priv->stats.FramesPlain++;
  675                 priv->stats.OutOctets += inlen;
  676         }
  677 
  678         /* Update sequence number. */
  679         priv->seqnum++;
  680 
  681         return (0);
  682 }
  683 
  684 /*
  685  * The peer has sent us a CCP ResetRequest, so reset our transmit state.
  686  */
  687 static void
  688 ng_deflate_reset_req(node_p node)
  689 {
  690         const priv_p priv = NG_NODE_PRIVATE(node);
  691 
  692         priv->seqnum = 0;
  693         if (priv->cfg.enable) {
  694             if (priv->compress)
  695                 deflateReset(&priv->cx);
  696             else
  697                 inflateReset(&priv->cx);
  698         }
  699 }
  700 

Cache object: 8bc7b3402115f154c073da15b9c564a3


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