xref: /freebsd/sys/netgraph/ng_deflate.c (revision eb1b1807afd1266445720b768b1bdbcdf7655a0a)
181ccbd95SGleb Smirnoff /*-
281ccbd95SGleb Smirnoff  * Copyright (c) 2006 Alexander Motin <mav@alkar.net>
381ccbd95SGleb Smirnoff  * All rights reserved.
481ccbd95SGleb Smirnoff  *
581ccbd95SGleb Smirnoff  * Redistribution and use in source and binary forms, with or without
681ccbd95SGleb Smirnoff  * modification, are permitted provided that the following conditions
781ccbd95SGleb Smirnoff  * are met:
881ccbd95SGleb Smirnoff  * 1. Redistributions of source code must retain the above copyright
981ccbd95SGleb Smirnoff  *    notice unmodified, this list of conditions, and the following
1081ccbd95SGleb Smirnoff  *    disclaimer.
1181ccbd95SGleb Smirnoff  * 2. Redistributions in binary form must reproduce the above copyright
1281ccbd95SGleb Smirnoff  *    notice, this list of conditions and the following disclaimer in the
1381ccbd95SGleb Smirnoff  *    documentation and/or other materials provided with the distribution.
1481ccbd95SGleb Smirnoff  *
1581ccbd95SGleb Smirnoff  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1681ccbd95SGleb Smirnoff  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1781ccbd95SGleb Smirnoff  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1881ccbd95SGleb Smirnoff  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1981ccbd95SGleb Smirnoff  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2081ccbd95SGleb Smirnoff  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2181ccbd95SGleb Smirnoff  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2281ccbd95SGleb Smirnoff  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2381ccbd95SGleb Smirnoff  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2481ccbd95SGleb Smirnoff  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2581ccbd95SGleb Smirnoff  * SUCH DAMAGE.
2681ccbd95SGleb Smirnoff  *
2781ccbd95SGleb Smirnoff  * $FreeBSD$
2881ccbd95SGleb Smirnoff  */
2981ccbd95SGleb Smirnoff 
3081ccbd95SGleb Smirnoff /*
3181ccbd95SGleb Smirnoff  * Deflate PPP compression netgraph node type.
3281ccbd95SGleb Smirnoff  */
3381ccbd95SGleb Smirnoff 
3481ccbd95SGleb Smirnoff #include <sys/param.h>
3581ccbd95SGleb Smirnoff #include <sys/systm.h>
3681ccbd95SGleb Smirnoff #include <sys/kernel.h>
3781ccbd95SGleb Smirnoff #include <sys/mbuf.h>
3881ccbd95SGleb Smirnoff #include <sys/malloc.h>
39b652a5faSAlexander Motin #include <sys/endian.h>
4081ccbd95SGleb Smirnoff #include <sys/errno.h>
4181ccbd95SGleb Smirnoff #include <sys/syslog.h>
4281ccbd95SGleb Smirnoff 
4381ccbd95SGleb Smirnoff #include <net/zlib.h>
4481ccbd95SGleb Smirnoff 
4581ccbd95SGleb Smirnoff #include <netgraph/ng_message.h>
4681ccbd95SGleb Smirnoff #include <netgraph/netgraph.h>
4781ccbd95SGleb Smirnoff #include <netgraph/ng_parse.h>
4881ccbd95SGleb Smirnoff #include <netgraph/ng_deflate.h>
4981ccbd95SGleb Smirnoff 
5081ccbd95SGleb Smirnoff #include "opt_netgraph.h"
5181ccbd95SGleb Smirnoff 
52d745c852SEd Schouten static MALLOC_DEFINE(M_NETGRAPH_DEFLATE, "netgraph_deflate",
53d745c852SEd Schouten     "netgraph deflate node");
5481ccbd95SGleb Smirnoff 
5581ccbd95SGleb Smirnoff /* DEFLATE header length */
5681ccbd95SGleb Smirnoff #define DEFLATE_HDRLEN		2
5781ccbd95SGleb Smirnoff 
5881ccbd95SGleb Smirnoff #define PROT_COMPD		0x00fd
5981ccbd95SGleb Smirnoff 
6081ccbd95SGleb Smirnoff #define DEFLATE_BUF_SIZE	4096
6181ccbd95SGleb Smirnoff 
6281ccbd95SGleb Smirnoff /* Node private data */
6381ccbd95SGleb Smirnoff struct ng_deflate_private {
6481ccbd95SGleb Smirnoff 	struct ng_deflate_config cfg;		/* configuration */
6581ccbd95SGleb Smirnoff 	u_char		inbuf[DEFLATE_BUF_SIZE];	/* input buffer */
6681ccbd95SGleb Smirnoff 	u_char		outbuf[DEFLATE_BUF_SIZE];	/* output buffer */
6781ccbd95SGleb Smirnoff 	z_stream 	cx;			/* compression context */
6881ccbd95SGleb Smirnoff 	struct ng_deflate_stats stats;		/* statistics */
6981ccbd95SGleb Smirnoff 	ng_ID_t		ctrlnode;		/* path to controlling node */
7081ccbd95SGleb Smirnoff 	uint16_t	seqnum;			/* sequence number */
7181ccbd95SGleb Smirnoff 	u_char		compress;		/* compress/decompress flag */
7281ccbd95SGleb Smirnoff };
7381ccbd95SGleb Smirnoff typedef struct ng_deflate_private *priv_p;
7481ccbd95SGleb Smirnoff 
7581ccbd95SGleb Smirnoff /* Netgraph node methods */
7681ccbd95SGleb Smirnoff static ng_constructor_t	ng_deflate_constructor;
7781ccbd95SGleb Smirnoff static ng_rcvmsg_t	ng_deflate_rcvmsg;
7881ccbd95SGleb Smirnoff static ng_shutdown_t	ng_deflate_shutdown;
7981ccbd95SGleb Smirnoff static ng_newhook_t	ng_deflate_newhook;
8081ccbd95SGleb Smirnoff static ng_rcvdata_t	ng_deflate_rcvdata;
8181ccbd95SGleb Smirnoff static ng_disconnect_t	ng_deflate_disconnect;
8281ccbd95SGleb Smirnoff 
8381ccbd95SGleb Smirnoff /* Helper functions */
8481ccbd95SGleb Smirnoff static void	*z_alloc(void *, u_int items, u_int size);
8581ccbd95SGleb Smirnoff static void	z_free(void *, void *ptr);
8681ccbd95SGleb Smirnoff static int	ng_deflate_compress(node_p node,
8781ccbd95SGleb Smirnoff 		    struct mbuf *m, struct mbuf **resultp);
8881ccbd95SGleb Smirnoff static int	ng_deflate_decompress(node_p node,
8981ccbd95SGleb Smirnoff 		    struct mbuf *m, struct mbuf **resultp);
9081ccbd95SGleb Smirnoff static void	ng_deflate_reset_req(node_p node);
9181ccbd95SGleb Smirnoff 
9281ccbd95SGleb Smirnoff /* Parse type for struct ng_deflate_config. */
9381ccbd95SGleb Smirnoff static const struct ng_parse_struct_field ng_deflate_config_type_fields[]
9481ccbd95SGleb Smirnoff 	= NG_DEFLATE_CONFIG_INFO;
9581ccbd95SGleb Smirnoff static const struct ng_parse_type ng_deflate_config_type = {
9681ccbd95SGleb Smirnoff 	&ng_parse_struct_type,
9781ccbd95SGleb Smirnoff 	ng_deflate_config_type_fields
9881ccbd95SGleb Smirnoff };
9981ccbd95SGleb Smirnoff 
10081ccbd95SGleb Smirnoff /* Parse type for struct ng_deflate_stat. */
10181ccbd95SGleb Smirnoff static const struct ng_parse_struct_field ng_deflate_stats_type_fields[]
10281ccbd95SGleb Smirnoff 	= NG_DEFLATE_STATS_INFO;
10381ccbd95SGleb Smirnoff static const struct ng_parse_type ng_deflate_stat_type = {
10481ccbd95SGleb Smirnoff 	&ng_parse_struct_type,
10581ccbd95SGleb Smirnoff 	ng_deflate_stats_type_fields
10681ccbd95SGleb Smirnoff };
10781ccbd95SGleb Smirnoff 
10881ccbd95SGleb Smirnoff /* List of commands and how to convert arguments to/from ASCII. */
10981ccbd95SGleb Smirnoff static const struct ng_cmdlist ng_deflate_cmds[] = {
11081ccbd95SGleb Smirnoff 	{
11181ccbd95SGleb Smirnoff 	  NGM_DEFLATE_COOKIE,
11281ccbd95SGleb Smirnoff 	  NGM_DEFLATE_CONFIG,
11381ccbd95SGleb Smirnoff 	  "config",
11481ccbd95SGleb Smirnoff 	  &ng_deflate_config_type,
11581ccbd95SGleb Smirnoff 	  NULL
11681ccbd95SGleb Smirnoff 	},
11781ccbd95SGleb Smirnoff 	{
11881ccbd95SGleb Smirnoff 	  NGM_DEFLATE_COOKIE,
11981ccbd95SGleb Smirnoff 	  NGM_DEFLATE_RESETREQ,
12081ccbd95SGleb Smirnoff 	  "resetreq",
12181ccbd95SGleb Smirnoff 	  NULL,
12281ccbd95SGleb Smirnoff 	  NULL
12381ccbd95SGleb Smirnoff 	},
12481ccbd95SGleb Smirnoff 	{
12581ccbd95SGleb Smirnoff 	  NGM_DEFLATE_COOKIE,
12681ccbd95SGleb Smirnoff 	  NGM_DEFLATE_GET_STATS,
12781ccbd95SGleb Smirnoff 	  "getstats",
12881ccbd95SGleb Smirnoff 	  NULL,
12981ccbd95SGleb Smirnoff 	  &ng_deflate_stat_type
13081ccbd95SGleb Smirnoff 	},
13181ccbd95SGleb Smirnoff 	{
13281ccbd95SGleb Smirnoff 	  NGM_DEFLATE_COOKIE,
13381ccbd95SGleb Smirnoff 	  NGM_DEFLATE_CLR_STATS,
13481ccbd95SGleb Smirnoff 	  "clrstats",
13581ccbd95SGleb Smirnoff 	  NULL,
13681ccbd95SGleb Smirnoff 	  NULL
13781ccbd95SGleb Smirnoff 	},
13881ccbd95SGleb Smirnoff 	{
13981ccbd95SGleb Smirnoff 	  NGM_DEFLATE_COOKIE,
14081ccbd95SGleb Smirnoff 	  NGM_DEFLATE_GETCLR_STATS,
14181ccbd95SGleb Smirnoff 	  "getclrstats",
14281ccbd95SGleb Smirnoff 	  NULL,
14381ccbd95SGleb Smirnoff 	  &ng_deflate_stat_type
14481ccbd95SGleb Smirnoff 	},
14581ccbd95SGleb Smirnoff 	{ 0 }
14681ccbd95SGleb Smirnoff };
14781ccbd95SGleb Smirnoff 
14881ccbd95SGleb Smirnoff /* Node type descriptor */
14981ccbd95SGleb Smirnoff static struct ng_type ng_deflate_typestruct = {
15081ccbd95SGleb Smirnoff 	.version =	NG_ABI_VERSION,
15181ccbd95SGleb Smirnoff 	.name =		NG_DEFLATE_NODE_TYPE,
15281ccbd95SGleb Smirnoff 	.constructor =	ng_deflate_constructor,
15381ccbd95SGleb Smirnoff 	.rcvmsg =	ng_deflate_rcvmsg,
15481ccbd95SGleb Smirnoff 	.shutdown =	ng_deflate_shutdown,
15581ccbd95SGleb Smirnoff 	.newhook =	ng_deflate_newhook,
15681ccbd95SGleb Smirnoff 	.rcvdata =	ng_deflate_rcvdata,
15781ccbd95SGleb Smirnoff 	.disconnect =	ng_deflate_disconnect,
15881ccbd95SGleb Smirnoff 	.cmdlist =	ng_deflate_cmds,
15981ccbd95SGleb Smirnoff };
16081ccbd95SGleb Smirnoff NETGRAPH_INIT(deflate, &ng_deflate_typestruct);
16181ccbd95SGleb Smirnoff 
16281ccbd95SGleb Smirnoff /* Depend on separate zlib module. */
16381ccbd95SGleb Smirnoff MODULE_DEPEND(ng_deflate, zlib, 1, 1, 1);
16481ccbd95SGleb Smirnoff 
16581ccbd95SGleb Smirnoff #define ERROUT(x)	do { error = (x); goto done; } while (0)
16681ccbd95SGleb Smirnoff 
16781ccbd95SGleb Smirnoff /************************************************************************
16881ccbd95SGleb Smirnoff 			NETGRAPH NODE STUFF
16981ccbd95SGleb Smirnoff  ************************************************************************/
17081ccbd95SGleb Smirnoff 
17181ccbd95SGleb Smirnoff /*
17281ccbd95SGleb Smirnoff  * Node type constructor
17381ccbd95SGleb Smirnoff  */
17481ccbd95SGleb Smirnoff static int
17581ccbd95SGleb Smirnoff ng_deflate_constructor(node_p node)
17681ccbd95SGleb Smirnoff {
17781ccbd95SGleb Smirnoff 	priv_p priv;
17881ccbd95SGleb Smirnoff 
17981ccbd95SGleb Smirnoff 	/* Allocate private structure. */
18081ccbd95SGleb Smirnoff 	priv = malloc(sizeof(*priv), M_NETGRAPH_DEFLATE, M_WAITOK | M_ZERO);
18181ccbd95SGleb Smirnoff 
18281ccbd95SGleb Smirnoff 	NG_NODE_SET_PRIVATE(node, priv);
18381ccbd95SGleb Smirnoff 
18481ccbd95SGleb Smirnoff 	/* This node is not thread safe. */
18581ccbd95SGleb Smirnoff 	NG_NODE_FORCE_WRITER(node);
18681ccbd95SGleb Smirnoff 
18781ccbd95SGleb Smirnoff 	/* Done */
18881ccbd95SGleb Smirnoff 	return (0);
18981ccbd95SGleb Smirnoff }
19081ccbd95SGleb Smirnoff 
19181ccbd95SGleb Smirnoff /*
19281ccbd95SGleb Smirnoff  * Give our OK for a hook to be added.
19381ccbd95SGleb Smirnoff  */
19481ccbd95SGleb Smirnoff static int
19581ccbd95SGleb Smirnoff ng_deflate_newhook(node_p node, hook_p hook, const char *name)
19681ccbd95SGleb Smirnoff {
19781ccbd95SGleb Smirnoff 	const priv_p priv = NG_NODE_PRIVATE(node);
19881ccbd95SGleb Smirnoff 
19981ccbd95SGleb Smirnoff 	if (NG_NODE_NUMHOOKS(node) > 0)
20081ccbd95SGleb Smirnoff 		return (EINVAL);
20181ccbd95SGleb Smirnoff 
20281ccbd95SGleb Smirnoff 	if (strcmp(name, NG_DEFLATE_HOOK_COMP) == 0)
20381ccbd95SGleb Smirnoff 		priv->compress = 1;
20481ccbd95SGleb Smirnoff 	else if (strcmp(name, NG_DEFLATE_HOOK_DECOMP) == 0)
20581ccbd95SGleb Smirnoff 		priv->compress = 0;
20681ccbd95SGleb Smirnoff 	else
20781ccbd95SGleb Smirnoff 		return (EINVAL);
20881ccbd95SGleb Smirnoff 
20981ccbd95SGleb Smirnoff 	return (0);
21081ccbd95SGleb Smirnoff }
21181ccbd95SGleb Smirnoff 
21281ccbd95SGleb Smirnoff /*
21381ccbd95SGleb Smirnoff  * Receive a control message
21481ccbd95SGleb Smirnoff  */
21581ccbd95SGleb Smirnoff static int
21681ccbd95SGleb Smirnoff ng_deflate_rcvmsg(node_p node, item_p item, hook_p lasthook)
21781ccbd95SGleb Smirnoff {
21881ccbd95SGleb Smirnoff 	const priv_p priv = NG_NODE_PRIVATE(node);
21981ccbd95SGleb Smirnoff 	struct ng_mesg *resp = NULL;
22081ccbd95SGleb Smirnoff 	int error = 0;
22181ccbd95SGleb Smirnoff 	struct ng_mesg *msg;
22281ccbd95SGleb Smirnoff 
22381ccbd95SGleb Smirnoff 	NGI_GET_MSG(item, msg);
22481ccbd95SGleb Smirnoff 
22581ccbd95SGleb Smirnoff 	if (msg->header.typecookie != NGM_DEFLATE_COOKIE)
22681ccbd95SGleb Smirnoff 		ERROUT(EINVAL);
22781ccbd95SGleb Smirnoff 
22881ccbd95SGleb Smirnoff 	switch (msg->header.cmd) {
22981ccbd95SGleb Smirnoff 	case NGM_DEFLATE_CONFIG:
23081ccbd95SGleb Smirnoff 	    {
23181ccbd95SGleb Smirnoff 		struct ng_deflate_config *const cfg
23281ccbd95SGleb Smirnoff 		    = (struct ng_deflate_config *)msg->data;
23381ccbd95SGleb Smirnoff 
23481ccbd95SGleb Smirnoff 		/* Check configuration. */
23581ccbd95SGleb Smirnoff 		if (msg->header.arglen != sizeof(*cfg))
23681ccbd95SGleb Smirnoff 			ERROUT(EINVAL);
23781ccbd95SGleb Smirnoff 		if (cfg->enable) {
23881ccbd95SGleb Smirnoff 		    if (cfg->windowBits < 8 || cfg->windowBits > 15)
23981ccbd95SGleb Smirnoff 			ERROUT(EINVAL);
24081ccbd95SGleb Smirnoff 		} else
24181ccbd95SGleb Smirnoff 		    cfg->windowBits = 0;
24281ccbd95SGleb Smirnoff 
24381ccbd95SGleb Smirnoff 		/* Clear previous state. */
24481ccbd95SGleb Smirnoff 		if (priv->cfg.enable) {
24581ccbd95SGleb Smirnoff 			if (priv->compress)
24681ccbd95SGleb Smirnoff 				deflateEnd(&priv->cx);
24781ccbd95SGleb Smirnoff 			else
24881ccbd95SGleb Smirnoff 				inflateEnd(&priv->cx);
24981ccbd95SGleb Smirnoff 			priv->cfg.enable = 0;
25081ccbd95SGleb Smirnoff 		}
25181ccbd95SGleb Smirnoff 
25281ccbd95SGleb Smirnoff 		/* Configuration is OK, reset to it. */
25381ccbd95SGleb Smirnoff 		priv->cfg = *cfg;
25481ccbd95SGleb Smirnoff 
25581ccbd95SGleb Smirnoff 		if (priv->cfg.enable) {
25681ccbd95SGleb Smirnoff 			priv->cx.next_in = NULL;
25781ccbd95SGleb Smirnoff 			priv->cx.zalloc = z_alloc;
25881ccbd95SGleb Smirnoff 			priv->cx.zfree = z_free;
25981ccbd95SGleb Smirnoff 			int res;
26081ccbd95SGleb Smirnoff 			if (priv->compress) {
26181ccbd95SGleb Smirnoff 				if ((res = deflateInit2(&priv->cx,
26281ccbd95SGleb Smirnoff 				    Z_DEFAULT_COMPRESSION, Z_DEFLATED,
26381ccbd95SGleb Smirnoff 				    -cfg->windowBits, 8,
26481ccbd95SGleb Smirnoff 				    Z_DEFAULT_STRATEGY)) != Z_OK) {
26581ccbd95SGleb Smirnoff 					log(LOG_NOTICE,
26681ccbd95SGleb Smirnoff 					    "deflateInit2: error %d, %s\n",
26781ccbd95SGleb Smirnoff 					    res, priv->cx.msg);
26881ccbd95SGleb Smirnoff 					priv->cfg.enable = 0;
26981ccbd95SGleb Smirnoff 					ERROUT(ENOMEM);
27081ccbd95SGleb Smirnoff 				}
27181ccbd95SGleb Smirnoff 			} else {
27281ccbd95SGleb Smirnoff 				if ((res = inflateInit2(&priv->cx,
27381ccbd95SGleb Smirnoff 				    -cfg->windowBits)) != Z_OK) {
27481ccbd95SGleb Smirnoff 					log(LOG_NOTICE,
27581ccbd95SGleb Smirnoff 					    "inflateInit2: error %d, %s\n",
27681ccbd95SGleb Smirnoff 					    res, priv->cx.msg);
27781ccbd95SGleb Smirnoff 					priv->cfg.enable = 0;
27881ccbd95SGleb Smirnoff 					ERROUT(ENOMEM);
27981ccbd95SGleb Smirnoff 				}
28081ccbd95SGleb Smirnoff 			}
28181ccbd95SGleb Smirnoff 		}
28281ccbd95SGleb Smirnoff 
28381ccbd95SGleb Smirnoff 		/* Initialize other state. */
28481ccbd95SGleb Smirnoff 		priv->seqnum = 0;
28581ccbd95SGleb Smirnoff 
28681ccbd95SGleb Smirnoff 		/* Save return address so we can send reset-req's */
28781ccbd95SGleb Smirnoff 		priv->ctrlnode = NGI_RETADDR(item);
28881ccbd95SGleb Smirnoff 		break;
28981ccbd95SGleb Smirnoff 	    }
29081ccbd95SGleb Smirnoff 
29181ccbd95SGleb Smirnoff 	case NGM_DEFLATE_RESETREQ:
29281ccbd95SGleb Smirnoff 		ng_deflate_reset_req(node);
29381ccbd95SGleb Smirnoff 		break;
29481ccbd95SGleb Smirnoff 
29581ccbd95SGleb Smirnoff 	case NGM_DEFLATE_GET_STATS:
29681ccbd95SGleb Smirnoff 	case NGM_DEFLATE_CLR_STATS:
29781ccbd95SGleb Smirnoff 	case NGM_DEFLATE_GETCLR_STATS:
29881ccbd95SGleb Smirnoff 		/* Create response if requested. */
29981ccbd95SGleb Smirnoff 		if (msg->header.cmd != NGM_DEFLATE_CLR_STATS) {
30081ccbd95SGleb Smirnoff 			NG_MKRESPONSE(resp, msg,
30181ccbd95SGleb Smirnoff 			    sizeof(struct ng_deflate_stats), M_NOWAIT);
30281ccbd95SGleb Smirnoff 			if (resp == NULL)
30381ccbd95SGleb Smirnoff 				ERROUT(ENOMEM);
30481ccbd95SGleb Smirnoff 			bcopy(&priv->stats, resp->data,
30581ccbd95SGleb Smirnoff 			    sizeof(struct ng_deflate_stats));
30681ccbd95SGleb Smirnoff 		}
30781ccbd95SGleb Smirnoff 
30881ccbd95SGleb Smirnoff 		/* Clear stats if requested. */
30981ccbd95SGleb Smirnoff 		if (msg->header.cmd != NGM_DEFLATE_GET_STATS)
31081ccbd95SGleb Smirnoff 			bzero(&priv->stats,
31181ccbd95SGleb Smirnoff 			    sizeof(struct ng_deflate_stats));
31281ccbd95SGleb Smirnoff 		break;
31381ccbd95SGleb Smirnoff 
31481ccbd95SGleb Smirnoff 	default:
31581ccbd95SGleb Smirnoff 		error = EINVAL;
31681ccbd95SGleb Smirnoff 		break;
31781ccbd95SGleb Smirnoff 	}
31881ccbd95SGleb Smirnoff done:
31981ccbd95SGleb Smirnoff 	NG_RESPOND_MSG(error, node, item, resp);
32081ccbd95SGleb Smirnoff 	NG_FREE_MSG(msg);
32181ccbd95SGleb Smirnoff 	return (error);
32281ccbd95SGleb Smirnoff }
32381ccbd95SGleb Smirnoff 
32481ccbd95SGleb Smirnoff /*
32581ccbd95SGleb Smirnoff  * Receive incoming data on our hook.
32681ccbd95SGleb Smirnoff  */
32781ccbd95SGleb Smirnoff static int
32881ccbd95SGleb Smirnoff ng_deflate_rcvdata(hook_p hook, item_p item)
32981ccbd95SGleb Smirnoff {
33081ccbd95SGleb Smirnoff 	const node_p node = NG_HOOK_NODE(hook);
33181ccbd95SGleb Smirnoff 	const priv_p priv = NG_NODE_PRIVATE(node);
33281ccbd95SGleb Smirnoff 	struct mbuf *m, *out;
33381ccbd95SGleb Smirnoff 	int error;
33481ccbd95SGleb Smirnoff 
33581ccbd95SGleb Smirnoff 	if (!priv->cfg.enable) {
33681ccbd95SGleb Smirnoff 		NG_FREE_ITEM(item);
33781ccbd95SGleb Smirnoff 		return (ENXIO);
33881ccbd95SGleb Smirnoff 	}
33981ccbd95SGleb Smirnoff 
34081ccbd95SGleb Smirnoff 	NGI_GET_M(item, m);
34181ccbd95SGleb Smirnoff 	/* Compress */
34281ccbd95SGleb Smirnoff 	if (priv->compress) {
34381ccbd95SGleb Smirnoff 		if ((error = ng_deflate_compress(node, m, &out)) != 0) {
34481ccbd95SGleb Smirnoff 			NG_FREE_ITEM(item);
34581ccbd95SGleb Smirnoff 			log(LOG_NOTICE, "%s: error: %d\n", __func__, error);
34681ccbd95SGleb Smirnoff 			return (error);
34781ccbd95SGleb Smirnoff 		}
34881ccbd95SGleb Smirnoff 
34981ccbd95SGleb Smirnoff 	} else { /* Decompress */
35081ccbd95SGleb Smirnoff 		if ((error = ng_deflate_decompress(node, m, &out)) != 0) {
35181ccbd95SGleb Smirnoff 			NG_FREE_ITEM(item);
35281ccbd95SGleb Smirnoff 			log(LOG_NOTICE, "%s: error: %d\n", __func__, error);
35381ccbd95SGleb Smirnoff 			if (priv->ctrlnode != 0) {
35481ccbd95SGleb Smirnoff 				struct ng_mesg *msg;
35581ccbd95SGleb Smirnoff 
35681ccbd95SGleb Smirnoff 				/* Need to send a reset-request. */
35781ccbd95SGleb Smirnoff 				NG_MKMESSAGE(msg, NGM_DEFLATE_COOKIE,
35881ccbd95SGleb Smirnoff 				    NGM_DEFLATE_RESETREQ, 0, M_NOWAIT);
35981ccbd95SGleb Smirnoff 				if (msg == NULL)
36081ccbd95SGleb Smirnoff 					return (error);
36181ccbd95SGleb Smirnoff 				NG_SEND_MSG_ID(error, node, msg,
36281ccbd95SGleb Smirnoff 					priv->ctrlnode, 0);
36381ccbd95SGleb Smirnoff 			}
36481ccbd95SGleb Smirnoff 			return (error);
36581ccbd95SGleb Smirnoff 		}
36681ccbd95SGleb Smirnoff 	}
36781ccbd95SGleb Smirnoff 
36881ccbd95SGleb Smirnoff 	NG_FWD_NEW_DATA(error, item, hook, out);
36981ccbd95SGleb Smirnoff 	return (error);
37081ccbd95SGleb Smirnoff }
37181ccbd95SGleb Smirnoff 
37281ccbd95SGleb Smirnoff /*
37381ccbd95SGleb Smirnoff  * Destroy node.
37481ccbd95SGleb Smirnoff  */
37581ccbd95SGleb Smirnoff static int
37681ccbd95SGleb Smirnoff ng_deflate_shutdown(node_p node)
37781ccbd95SGleb Smirnoff {
37881ccbd95SGleb Smirnoff 	const priv_p priv = NG_NODE_PRIVATE(node);
37981ccbd95SGleb Smirnoff 
38081ccbd95SGleb Smirnoff 	/* Take down netgraph node. */
38181ccbd95SGleb Smirnoff 	if (priv->cfg.enable) {
38281ccbd95SGleb Smirnoff 	    if (priv->compress)
38381ccbd95SGleb Smirnoff 		deflateEnd(&priv->cx);
38481ccbd95SGleb Smirnoff 	    else
38581ccbd95SGleb Smirnoff 		inflateEnd(&priv->cx);
38681ccbd95SGleb Smirnoff 	}
38781ccbd95SGleb Smirnoff 
38881ccbd95SGleb Smirnoff 	free(priv, M_NETGRAPH_DEFLATE);
38981ccbd95SGleb Smirnoff 	NG_NODE_SET_PRIVATE(node, NULL);
39081ccbd95SGleb Smirnoff 	NG_NODE_UNREF(node);		/* let the node escape */
39181ccbd95SGleb Smirnoff 	return (0);
39281ccbd95SGleb Smirnoff }
39381ccbd95SGleb Smirnoff 
39481ccbd95SGleb Smirnoff /*
39581ccbd95SGleb Smirnoff  * Hook disconnection
39681ccbd95SGleb Smirnoff  */
39781ccbd95SGleb Smirnoff static int
39881ccbd95SGleb Smirnoff ng_deflate_disconnect(hook_p hook)
39981ccbd95SGleb Smirnoff {
40081ccbd95SGleb Smirnoff 	const node_p node = NG_HOOK_NODE(hook);
40181ccbd95SGleb Smirnoff 	const priv_p priv = NG_NODE_PRIVATE(node);
40281ccbd95SGleb Smirnoff 
40381ccbd95SGleb Smirnoff 	if (priv->cfg.enable) {
40481ccbd95SGleb Smirnoff 	    if (priv->compress)
40581ccbd95SGleb Smirnoff 		deflateEnd(&priv->cx);
40681ccbd95SGleb Smirnoff 	    else
40781ccbd95SGleb Smirnoff 		inflateEnd(&priv->cx);
40881ccbd95SGleb Smirnoff 	    priv->cfg.enable = 0;
40981ccbd95SGleb Smirnoff 	}
41081ccbd95SGleb Smirnoff 
41181ccbd95SGleb Smirnoff 	/* Go away if no longer connected. */
41281ccbd95SGleb Smirnoff 	if ((NG_NODE_NUMHOOKS(node) == 0) && NG_NODE_IS_VALID(node))
41381ccbd95SGleb Smirnoff 		ng_rmnode_self(node);
41481ccbd95SGleb Smirnoff 	return (0);
41581ccbd95SGleb Smirnoff }
41681ccbd95SGleb Smirnoff 
41781ccbd95SGleb Smirnoff /************************************************************************
41881ccbd95SGleb Smirnoff 			HELPER STUFF
41981ccbd95SGleb Smirnoff  ************************************************************************/
42081ccbd95SGleb Smirnoff 
42181ccbd95SGleb Smirnoff /*
42281ccbd95SGleb Smirnoff  * Space allocation and freeing routines for use by zlib routines.
42381ccbd95SGleb Smirnoff  */
42481ccbd95SGleb Smirnoff 
42581ccbd95SGleb Smirnoff static void *
42681ccbd95SGleb Smirnoff z_alloc(void *notused, u_int items, u_int size)
42781ccbd95SGleb Smirnoff {
42881ccbd95SGleb Smirnoff 
42981ccbd95SGleb Smirnoff 	return (malloc(items * size, M_NETGRAPH_DEFLATE, M_NOWAIT));
43081ccbd95SGleb Smirnoff }
43181ccbd95SGleb Smirnoff 
43281ccbd95SGleb Smirnoff static void
43381ccbd95SGleb Smirnoff z_free(void *notused, void *ptr)
43481ccbd95SGleb Smirnoff {
43581ccbd95SGleb Smirnoff 
43681ccbd95SGleb Smirnoff 	free(ptr, M_NETGRAPH_DEFLATE);
43781ccbd95SGleb Smirnoff }
43881ccbd95SGleb Smirnoff 
43981ccbd95SGleb Smirnoff /*
44081ccbd95SGleb Smirnoff  * Compress/encrypt a packet and put the result in a new mbuf at *resultp.
44181ccbd95SGleb Smirnoff  * The original mbuf is not free'd.
44281ccbd95SGleb Smirnoff  */
44381ccbd95SGleb Smirnoff static int
44481ccbd95SGleb Smirnoff ng_deflate_compress(node_p node, struct mbuf *m, struct mbuf **resultp)
44581ccbd95SGleb Smirnoff {
44681ccbd95SGleb Smirnoff 	const priv_p 	priv = NG_NODE_PRIVATE(node);
44781ccbd95SGleb Smirnoff 	int 		outlen, inlen;
44881ccbd95SGleb Smirnoff 	int 		rtn;
44981ccbd95SGleb Smirnoff 
45081ccbd95SGleb Smirnoff 	/* Initialize. */
45181ccbd95SGleb Smirnoff 	*resultp = NULL;
45281ccbd95SGleb Smirnoff 
45381ccbd95SGleb Smirnoff 	inlen = m->m_pkthdr.len;
45481ccbd95SGleb Smirnoff 
45581ccbd95SGleb Smirnoff 	priv->stats.FramesPlain++;
45681ccbd95SGleb Smirnoff 	priv->stats.InOctets+=inlen;
45781ccbd95SGleb Smirnoff 
45881ccbd95SGleb Smirnoff 	if (inlen > DEFLATE_BUF_SIZE) {
45981ccbd95SGleb Smirnoff 		priv->stats.Errors++;
46081ccbd95SGleb Smirnoff 		NG_FREE_M(m);
46181ccbd95SGleb Smirnoff 		return (ENOMEM);
46281ccbd95SGleb Smirnoff 	}
46381ccbd95SGleb Smirnoff 
464e4651e05SAlexander Motin 	/* We must own the mbuf chain exclusively to modify it. */
465*eb1b1807SGleb Smirnoff 	m = m_unshare(m, M_NOWAIT);
466e4651e05SAlexander Motin 	if (m == NULL) {
467e4651e05SAlexander Motin 		priv->stats.Errors++;
468e4651e05SAlexander Motin 		return (ENOMEM);
469e4651e05SAlexander Motin 	}
470e4651e05SAlexander Motin 
47181ccbd95SGleb Smirnoff 	/* Work with contiguous regions of memory. */
47281ccbd95SGleb Smirnoff 	m_copydata(m, 0, inlen, (caddr_t)priv->inbuf);
47381ccbd95SGleb Smirnoff 	outlen = DEFLATE_BUF_SIZE;
47481ccbd95SGleb Smirnoff 
47581ccbd95SGleb Smirnoff 	/* Compress "inbuf" into "outbuf". */
47681ccbd95SGleb Smirnoff 	/* Prepare to compress. */
47781ccbd95SGleb Smirnoff 	if (priv->inbuf[0] != 0) {
47881ccbd95SGleb Smirnoff 		priv->cx.next_in = priv->inbuf;
47981ccbd95SGleb Smirnoff 		priv->cx.avail_in = inlen;
48081ccbd95SGleb Smirnoff 	} else {
48181ccbd95SGleb Smirnoff 		priv->cx.next_in = priv->inbuf + 1; /* compress protocol */
48281ccbd95SGleb Smirnoff 		priv->cx.avail_in = inlen - 1;
48381ccbd95SGleb Smirnoff 	}
48481ccbd95SGleb Smirnoff 	priv->cx.next_out = priv->outbuf + 2 + DEFLATE_HDRLEN;
48581ccbd95SGleb Smirnoff 	priv->cx.avail_out = outlen - 2 - DEFLATE_HDRLEN;
48681ccbd95SGleb Smirnoff 
48781ccbd95SGleb Smirnoff 	/* Compress. */
48881ccbd95SGleb Smirnoff 	rtn = deflate(&priv->cx, Z_PACKET_FLUSH);
48981ccbd95SGleb Smirnoff 
49081ccbd95SGleb Smirnoff 	/* Check return value. */
49181ccbd95SGleb Smirnoff 	if (rtn != Z_OK) {
49281ccbd95SGleb Smirnoff 		priv->stats.Errors++;
49381ccbd95SGleb Smirnoff 		log(LOG_NOTICE, "ng_deflate: compression error: %d (%s)\n",
49481ccbd95SGleb Smirnoff 		    rtn, priv->cx.msg);
49581ccbd95SGleb Smirnoff 		NG_FREE_M(m);
49681ccbd95SGleb Smirnoff 		return (EINVAL);
49781ccbd95SGleb Smirnoff 	}
49881ccbd95SGleb Smirnoff 
49981ccbd95SGleb Smirnoff 	/* Calculate resulting size. */
50081ccbd95SGleb Smirnoff 	outlen -= priv->cx.avail_out;
50181ccbd95SGleb Smirnoff 
50281ccbd95SGleb Smirnoff 	/* If we can't compress this packet, send it as-is. */
50381ccbd95SGleb Smirnoff 	if (outlen > inlen) {
50481ccbd95SGleb Smirnoff 		/* Return original packet uncompressed. */
50581ccbd95SGleb Smirnoff 		*resultp = m;
50681ccbd95SGleb Smirnoff 		priv->stats.FramesUncomp++;
50781ccbd95SGleb Smirnoff 		priv->stats.OutOctets+=inlen;
50881ccbd95SGleb Smirnoff 	} else {
50981ccbd95SGleb Smirnoff 		/* Install header. */
510b652a5faSAlexander Motin 		be16enc(priv->outbuf, PROT_COMPD);
511b652a5faSAlexander Motin 		be16enc(priv->outbuf + 2, priv->seqnum);
51281ccbd95SGleb Smirnoff 
51381ccbd95SGleb Smirnoff 		/* Return packet in an mbuf. */
514e4651e05SAlexander Motin 		m_copyback(m, 0, outlen, (caddr_t)priv->outbuf);
515e4651e05SAlexander Motin 		if (m->m_pkthdr.len < outlen) {
516e4651e05SAlexander Motin 			m_freem(m);
51781ccbd95SGleb Smirnoff 			priv->stats.Errors++;
51881ccbd95SGleb Smirnoff 			return (ENOMEM);
519e4651e05SAlexander Motin 		} else if (outlen < m->m_pkthdr.len)
520e4651e05SAlexander Motin 			m_adj(m, outlen - m->m_pkthdr.len);
521e4651e05SAlexander Motin 		*resultp = m;
52281ccbd95SGleb Smirnoff 		priv->stats.FramesComp++;
52381ccbd95SGleb Smirnoff 		priv->stats.OutOctets+=outlen;
52481ccbd95SGleb Smirnoff 	}
52581ccbd95SGleb Smirnoff 
52681ccbd95SGleb Smirnoff 	/* Update sequence number. */
52781ccbd95SGleb Smirnoff 	priv->seqnum++;
52881ccbd95SGleb Smirnoff 
52981ccbd95SGleb Smirnoff 	return (0);
53081ccbd95SGleb Smirnoff }
53181ccbd95SGleb Smirnoff 
53281ccbd95SGleb Smirnoff /*
53381ccbd95SGleb Smirnoff  * Decompress/decrypt packet and put the result in a new mbuf at *resultp.
53481ccbd95SGleb Smirnoff  * The original mbuf is not free'd.
53581ccbd95SGleb Smirnoff  */
53681ccbd95SGleb Smirnoff static int
53781ccbd95SGleb Smirnoff ng_deflate_decompress(node_p node, struct mbuf *m, struct mbuf **resultp)
53881ccbd95SGleb Smirnoff {
53981ccbd95SGleb Smirnoff 	const priv_p 	priv = NG_NODE_PRIVATE(node);
54081ccbd95SGleb Smirnoff 	int 		outlen, inlen;
54181ccbd95SGleb Smirnoff 	int 		rtn;
54281ccbd95SGleb Smirnoff 	uint16_t	proto;
54381ccbd95SGleb Smirnoff 	int		offset;
54481ccbd95SGleb Smirnoff 	uint16_t	rseqnum;
54581ccbd95SGleb Smirnoff 
54681ccbd95SGleb Smirnoff 	/* Initialize. */
54781ccbd95SGleb Smirnoff 	*resultp = NULL;
54881ccbd95SGleb Smirnoff 
54981ccbd95SGleb Smirnoff 	inlen = m->m_pkthdr.len;
55081ccbd95SGleb Smirnoff 
55181ccbd95SGleb Smirnoff 	if (inlen > DEFLATE_BUF_SIZE) {
55281ccbd95SGleb Smirnoff 		priv->stats.Errors++;
55381ccbd95SGleb Smirnoff 		NG_FREE_M(m);
55481ccbd95SGleb Smirnoff 		priv->seqnum = 0;
55581ccbd95SGleb Smirnoff 		return (ENOMEM);
55681ccbd95SGleb Smirnoff 	}
55781ccbd95SGleb Smirnoff 
558e4651e05SAlexander Motin 	/* We must own the mbuf chain exclusively to modify it. */
559*eb1b1807SGleb Smirnoff 	m = m_unshare(m, M_NOWAIT);
560e4651e05SAlexander Motin 	if (m == NULL) {
561e4651e05SAlexander Motin 		priv->stats.Errors++;
562e4651e05SAlexander Motin 		return (ENOMEM);
563e4651e05SAlexander Motin 	}
564e4651e05SAlexander Motin 
56581ccbd95SGleb Smirnoff 	/* Work with contiguous regions of memory. */
56681ccbd95SGleb Smirnoff 	m_copydata(m, 0, inlen, (caddr_t)priv->inbuf);
56781ccbd95SGleb Smirnoff 
56881ccbd95SGleb Smirnoff 	/* Separate proto. */
56981ccbd95SGleb Smirnoff 	if ((priv->inbuf[0] & 0x01) != 0) {
57081ccbd95SGleb Smirnoff 		proto = priv->inbuf[0];
57181ccbd95SGleb Smirnoff 		offset = 1;
57281ccbd95SGleb Smirnoff 	} else {
573b652a5faSAlexander Motin 		proto = be16dec(priv->inbuf);
57481ccbd95SGleb Smirnoff 		offset = 2;
57581ccbd95SGleb Smirnoff 	}
57681ccbd95SGleb Smirnoff 
577833c4a01SGleb Smirnoff 	priv->stats.InOctets += inlen;
578833c4a01SGleb Smirnoff 
57981ccbd95SGleb Smirnoff 	/* Packet is compressed, so decompress. */
58081ccbd95SGleb Smirnoff 	if (proto == PROT_COMPD) {
58181ccbd95SGleb Smirnoff 		priv->stats.FramesComp++;
58281ccbd95SGleb Smirnoff 
58381ccbd95SGleb Smirnoff 		/* Check sequence number. */
584b652a5faSAlexander Motin 		rseqnum = be16dec(priv->inbuf + offset);
58581ccbd95SGleb Smirnoff 		offset += 2;
58681ccbd95SGleb Smirnoff 		if (rseqnum != priv->seqnum) {
58781ccbd95SGleb Smirnoff 			priv->stats.Errors++;
58881ccbd95SGleb Smirnoff 			log(LOG_NOTICE, "ng_deflate: wrong sequence: %u "
58981ccbd95SGleb Smirnoff 			    "instead of %u\n", rseqnum, priv->seqnum);
59081ccbd95SGleb Smirnoff 			NG_FREE_M(m);
59181ccbd95SGleb Smirnoff 			priv->seqnum = 0;
59281ccbd95SGleb Smirnoff 			return (EPIPE);
59381ccbd95SGleb Smirnoff 		}
59481ccbd95SGleb Smirnoff 
59581ccbd95SGleb Smirnoff 		outlen = DEFLATE_BUF_SIZE;
59681ccbd95SGleb Smirnoff 
59781ccbd95SGleb Smirnoff     		/* Decompress "inbuf" into "outbuf". */
59881ccbd95SGleb Smirnoff 		/* Prepare to decompress. */
59981ccbd95SGleb Smirnoff 		priv->cx.next_in = priv->inbuf + offset;
60081ccbd95SGleb Smirnoff 		priv->cx.avail_in = inlen - offset;
60181ccbd95SGleb Smirnoff 		/* Reserve space for protocol decompression. */
60281ccbd95SGleb Smirnoff 		priv->cx.next_out = priv->outbuf + 1;
60381ccbd95SGleb Smirnoff 		priv->cx.avail_out = outlen - 1;
60481ccbd95SGleb Smirnoff 
60581ccbd95SGleb Smirnoff 		/* Decompress. */
60681ccbd95SGleb Smirnoff 		rtn = inflate(&priv->cx, Z_PACKET_FLUSH);
60781ccbd95SGleb Smirnoff 
60881ccbd95SGleb Smirnoff 		/* Check return value. */
60981ccbd95SGleb Smirnoff 		if (rtn != Z_OK && rtn != Z_STREAM_END) {
61081ccbd95SGleb Smirnoff 			priv->stats.Errors++;
61181ccbd95SGleb Smirnoff 			NG_FREE_M(m);
61281ccbd95SGleb Smirnoff 			priv->seqnum = 0;
61381ccbd95SGleb Smirnoff 			log(LOG_NOTICE, "%s: decompression error: %d (%s)\n",
61481ccbd95SGleb Smirnoff 			    __func__, rtn, priv->cx.msg);
61581ccbd95SGleb Smirnoff 
61681ccbd95SGleb Smirnoff 			switch (rtn) {
61781ccbd95SGleb Smirnoff 			case Z_MEM_ERROR:
61881ccbd95SGleb Smirnoff 				return (ENOMEM);
61981ccbd95SGleb Smirnoff 			case Z_DATA_ERROR:
62081ccbd95SGleb Smirnoff 				return (EIO);
62181ccbd95SGleb Smirnoff 			default:
62281ccbd95SGleb Smirnoff 				return (EINVAL);
62381ccbd95SGleb Smirnoff 			}
62481ccbd95SGleb Smirnoff 		}
62581ccbd95SGleb Smirnoff 
62681ccbd95SGleb Smirnoff 		/* Calculate resulting size. */
62781ccbd95SGleb Smirnoff 		outlen -= priv->cx.avail_out;
62881ccbd95SGleb Smirnoff 
62981ccbd95SGleb Smirnoff 		/* Decompress protocol. */
63081ccbd95SGleb Smirnoff 		if ((priv->outbuf[1] & 0x01) != 0) {
63181ccbd95SGleb Smirnoff 			priv->outbuf[0] = 0;
63281ccbd95SGleb Smirnoff 			/* Return packet in an mbuf. */
633e4651e05SAlexander Motin 			m_copyback(m, 0, outlen, (caddr_t)priv->outbuf);
63481ccbd95SGleb Smirnoff 		} else {
63581ccbd95SGleb Smirnoff 			outlen--;
63681ccbd95SGleb Smirnoff 			/* Return packet in an mbuf. */
637e4651e05SAlexander Motin 			m_copyback(m, 0, outlen, (caddr_t)(priv->outbuf + 1));
63881ccbd95SGleb Smirnoff 		}
639e4651e05SAlexander Motin 		if (m->m_pkthdr.len < outlen) {
640e4651e05SAlexander Motin 			m_freem(m);
64181ccbd95SGleb Smirnoff 			priv->stats.Errors++;
64281ccbd95SGleb Smirnoff 			priv->seqnum = 0;
64381ccbd95SGleb Smirnoff 			return (ENOMEM);
644e4651e05SAlexander Motin 		} else if (outlen < m->m_pkthdr.len)
645e4651e05SAlexander Motin 			m_adj(m, outlen - m->m_pkthdr.len);
646e4651e05SAlexander Motin 		*resultp = m;
64781ccbd95SGleb Smirnoff 		priv->stats.FramesPlain++;
64881ccbd95SGleb Smirnoff 		priv->stats.OutOctets+=outlen;
64981ccbd95SGleb Smirnoff 
65081ccbd95SGleb Smirnoff 	} else { /* Packet is not compressed, just update dictionary. */
65181ccbd95SGleb Smirnoff 		priv->stats.FramesUncomp++;
65281ccbd95SGleb Smirnoff 		if (priv->inbuf[0] == 0) {
65381ccbd95SGleb Smirnoff 		    priv->cx.next_in = priv->inbuf + 1; /* compress protocol */
65481ccbd95SGleb Smirnoff 		    priv->cx.avail_in = inlen - 1;
65581ccbd95SGleb Smirnoff 		} else {
65681ccbd95SGleb Smirnoff 		    priv->cx.next_in = priv->inbuf;
65781ccbd95SGleb Smirnoff 		    priv->cx.avail_in = inlen;
65881ccbd95SGleb Smirnoff 		}
65981ccbd95SGleb Smirnoff 
66081ccbd95SGleb Smirnoff 		rtn = inflateIncomp(&priv->cx);
66181ccbd95SGleb Smirnoff 
66281ccbd95SGleb Smirnoff 		/* Check return value */
66381ccbd95SGleb Smirnoff 		if (rtn != Z_OK) {
66481ccbd95SGleb Smirnoff 			priv->stats.Errors++;
66581ccbd95SGleb Smirnoff 			log(LOG_NOTICE, "%s: inflateIncomp error: %d (%s)\n",
66681ccbd95SGleb Smirnoff 			    __func__, rtn, priv->cx.msg);
66781ccbd95SGleb Smirnoff 			NG_FREE_M(m);
66881ccbd95SGleb Smirnoff 			priv->seqnum = 0;
66981ccbd95SGleb Smirnoff 			return (EINVAL);
67081ccbd95SGleb Smirnoff 		}
67181ccbd95SGleb Smirnoff 
67281ccbd95SGleb Smirnoff 		*resultp = m;
67381ccbd95SGleb Smirnoff 		priv->stats.FramesPlain++;
67481ccbd95SGleb Smirnoff 		priv->stats.OutOctets += inlen;
67581ccbd95SGleb Smirnoff 	}
67681ccbd95SGleb Smirnoff 
67781ccbd95SGleb Smirnoff 	/* Update sequence number. */
67881ccbd95SGleb Smirnoff 	priv->seqnum++;
67981ccbd95SGleb Smirnoff 
68081ccbd95SGleb Smirnoff 	return (0);
68181ccbd95SGleb Smirnoff }
68281ccbd95SGleb Smirnoff 
68381ccbd95SGleb Smirnoff /*
68481ccbd95SGleb Smirnoff  * The peer has sent us a CCP ResetRequest, so reset our transmit state.
68581ccbd95SGleb Smirnoff  */
68681ccbd95SGleb Smirnoff static void
68781ccbd95SGleb Smirnoff ng_deflate_reset_req(node_p node)
68881ccbd95SGleb Smirnoff {
68981ccbd95SGleb Smirnoff 	const priv_p priv = NG_NODE_PRIVATE(node);
69081ccbd95SGleb Smirnoff 
69181ccbd95SGleb Smirnoff 	priv->seqnum = 0;
69281ccbd95SGleb Smirnoff 	if (priv->cfg.enable) {
69381ccbd95SGleb Smirnoff 	    if (priv->compress)
69481ccbd95SGleb Smirnoff 		deflateReset(&priv->cx);
69581ccbd95SGleb Smirnoff 	    else
69681ccbd95SGleb Smirnoff 		inflateReset(&priv->cx);
69781ccbd95SGleb Smirnoff 	}
69881ccbd95SGleb Smirnoff }
69981ccbd95SGleb Smirnoff 
700