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