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

Cache object: 963da980845a16c840076b8dafeb6e53


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