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

Cache object: 8e9f8e22d2b4c9369adc5272544d31a9


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