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