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

Cache object: 17fae853de941488986aed0d116cf121


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