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