1 /* $NetBSD: xform_ipcomp.c,v 1.64 2018/05/01 08:13:37 maxv Exp $ */ 2 /* $FreeBSD: xform_ipcomp.c,v 1.1.4.1 2003/01/24 05:11:36 sam Exp $ */ 3 /* $OpenBSD: ip_ipcomp.c,v 1.1 2001/07/05 12:08:52 jjbg Exp $ */ 4 5 /* 6 * Copyright (c) 2001 Jean-Jacques Bernard-Gundol (jj@wabbitt.org) 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: xform_ipcomp.c,v 1.64 2018/05/01 08:13:37 maxv Exp $"); 34 35 /* IP payload compression protocol (IPComp), see RFC 2393 */ 36 #if defined(_KERNEL_OPT) 37 #include "opt_inet.h" 38 #endif 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/mbuf.h> 43 #include <sys/socket.h> 44 #include <sys/kernel.h> 45 #include <sys/protosw.h> 46 #include <sys/sysctl.h> 47 #include <sys/pool.h> 48 #include <sys/pserialize.h> 49 50 #include <netinet/in.h> 51 #include <netinet/in_systm.h> 52 #include <netinet/ip.h> 53 #include <netinet/ip_var.h> 54 55 #include <net/route.h> 56 #include <netipsec/ipsec.h> 57 #include <netipsec/ipsec_private.h> 58 #include <netipsec/xform.h> 59 60 #ifdef INET6 61 #include <netinet/ip6.h> 62 #include <netipsec/ipsec6.h> 63 #endif 64 65 #include <netipsec/ipcomp.h> 66 #include <netipsec/ipcomp_var.h> 67 68 #include <netipsec/key.h> 69 #include <netipsec/key_debug.h> 70 71 #include <opencrypto/cryptodev.h> 72 #include <opencrypto/deflate.h> 73 74 percpu_t *ipcompstat_percpu; 75 76 int ipcomp_enable = 1; 77 78 static int ipcomp_input_cb(struct cryptop *crp); 79 static int ipcomp_output_cb(struct cryptop *crp); 80 81 const uint8_t ipcomp_stats[256] = { SADB_CALG_STATS_INIT }; 82 83 static pool_cache_t ipcomp_tdb_crypto_pool_cache; 84 85 const struct comp_algo * 86 ipcomp_algorithm_lookup(int alg) 87 { 88 switch (alg) { 89 case SADB_X_CALG_DEFLATE: 90 return &comp_algo_deflate_nogrow; 91 } 92 return NULL; 93 } 94 95 /* 96 * ipcomp_init() is called when an CPI is being set up. 97 */ 98 static int 99 ipcomp_init(struct secasvar *sav, const struct xformsw *xsp) 100 { 101 const struct comp_algo *tcomp; 102 struct cryptoini cric; 103 int ses; 104 105 /* NB: algorithm really comes in alg_enc and not alg_comp! */ 106 tcomp = ipcomp_algorithm_lookup(sav->alg_enc); 107 if (tcomp == NULL) { 108 DPRINTF(("%s: unsupported compression algorithm %d\n", 109 __func__, sav->alg_comp)); 110 return EINVAL; 111 } 112 sav->alg_comp = sav->alg_enc; /* set for doing histogram */ 113 sav->tdb_xform = xsp; 114 sav->tdb_compalgxform = tcomp; 115 116 /* Initialize crypto session */ 117 memset(&cric, 0, sizeof(cric)); 118 cric.cri_alg = sav->tdb_compalgxform->type; 119 120 ses = crypto_newsession(&sav->tdb_cryptoid, &cric, crypto_support); 121 return ses; 122 } 123 124 /* 125 * ipcomp_zeroize() used when IPCA is deleted 126 */ 127 static int 128 ipcomp_zeroize(struct secasvar *sav) 129 { 130 int err; 131 132 err = crypto_freesession(sav->tdb_cryptoid); 133 sav->tdb_cryptoid = 0; 134 return err; 135 } 136 137 /* 138 * ipcomp_input() gets called to uncompress an input packet 139 */ 140 static int 141 ipcomp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff) 142 { 143 struct tdb_crypto *tc; 144 struct cryptodesc *crdc; 145 struct cryptop *crp; 146 int error, hlen = IPCOMP_HLENGTH, stat = IPCOMP_STAT_CRYPTO; 147 148 KASSERT(skip + hlen <= m->m_pkthdr.len); 149 150 /* Get crypto descriptors */ 151 crp = crypto_getreq(1); 152 if (crp == NULL) { 153 DPRINTF(("%s: no crypto descriptors\n", __func__)); 154 error = ENOBUFS; 155 goto error_m; 156 } 157 /* Get IPsec-specific opaque pointer */ 158 tc = pool_cache_get(ipcomp_tdb_crypto_pool_cache, PR_NOWAIT); 159 if (tc == NULL) { 160 DPRINTF(("%s: cannot allocate tdb_crypto\n", __func__)); 161 error = ENOBUFS; 162 goto error_crp; 163 } 164 165 error = m_makewritable(&m, 0, m->m_pkthdr.len, M_NOWAIT); 166 if (error) { 167 DPRINTF(("%s: m_makewritable failed\n", __func__)); 168 goto error_tc; 169 } 170 171 { 172 int s = pserialize_read_enter(); 173 174 /* 175 * Take another reference to the SA for opencrypto callback. 176 */ 177 if (__predict_false(sav->state == SADB_SASTATE_DEAD)) { 178 pserialize_read_exit(s); 179 stat = IPCOMP_STAT_NOTDB; 180 error = ENOENT; 181 goto error_tc; 182 } 183 KEY_SA_REF(sav); 184 pserialize_read_exit(s); 185 } 186 187 crdc = crp->crp_desc; 188 189 crdc->crd_skip = skip + hlen; 190 crdc->crd_len = m->m_pkthdr.len - (skip + hlen); 191 crdc->crd_inject = 0; /* unused */ 192 193 /* Decompression operation */ 194 crdc->crd_alg = sav->tdb_compalgxform->type; 195 196 /* Crypto operation descriptor */ 197 crp->crp_ilen = m->m_pkthdr.len - (skip + hlen); 198 crp->crp_olen = MCLBYTES; /* hint to decompression code */ 199 crp->crp_flags = CRYPTO_F_IMBUF; 200 crp->crp_buf = m; 201 crp->crp_callback = ipcomp_input_cb; 202 crp->crp_sid = sav->tdb_cryptoid; 203 crp->crp_opaque = tc; 204 205 /* These are passed as-is to the callback */ 206 tc->tc_spi = sav->spi; 207 tc->tc_dst = sav->sah->saidx.dst; 208 tc->tc_proto = sav->sah->saidx.proto; 209 tc->tc_protoff = protoff; 210 tc->tc_skip = skip; 211 tc->tc_sav = sav; 212 213 return crypto_dispatch(crp); 214 215 error_tc: 216 pool_cache_put(ipcomp_tdb_crypto_pool_cache, tc); 217 error_crp: 218 crypto_freereq(crp); 219 error_m: 220 m_freem(m); 221 IPCOMP_STATINC(stat); 222 return error; 223 } 224 225 #ifdef INET6 226 #define IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff) do { \ 227 if (saidx->dst.sa.sa_family == AF_INET6) { \ 228 error = ipsec6_common_input_cb(m, sav, skip, protoff); \ 229 } else { \ 230 error = ipsec4_common_input_cb(m, sav, skip, protoff); \ 231 } \ 232 } while (0) 233 #else 234 #define IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff) \ 235 (error = ipsec4_common_input_cb(m, sav, skip, protoff)) 236 #endif 237 238 /* 239 * IPComp input callback from the crypto driver. 240 */ 241 static int 242 ipcomp_input_cb(struct cryptop *crp) 243 { 244 char buf[IPSEC_ADDRSTRLEN]; 245 struct tdb_crypto *tc; 246 int skip, protoff; 247 struct mbuf *m; 248 struct secasvar *sav; 249 struct secasindex *saidx __diagused; 250 int hlen = IPCOMP_HLENGTH, error, clen; 251 uint8_t nproto; 252 struct ipcomp *ipc; 253 uint16_t dport; 254 uint16_t sport; 255 IPSEC_DECLARE_LOCK_VARIABLE; 256 257 KASSERT(crp->crp_opaque != NULL); 258 tc = crp->crp_opaque; 259 skip = tc->tc_skip; 260 protoff = tc->tc_protoff; 261 m = crp->crp_buf; 262 263 /* find the source port for NAT-T */ 264 nat_t_ports_get(m, &dport, &sport); 265 266 IPSEC_ACQUIRE_GLOBAL_LOCKS(); 267 268 sav = tc->tc_sav; 269 saidx = &sav->sah->saidx; 270 KASSERTMSG(saidx->dst.sa.sa_family == AF_INET || 271 saidx->dst.sa.sa_family == AF_INET6, 272 "unexpected protocol family %u", saidx->dst.sa.sa_family); 273 274 /* Check for crypto errors */ 275 if (crp->crp_etype) { 276 /* Reset the session ID */ 277 if (sav->tdb_cryptoid != 0) 278 sav->tdb_cryptoid = crp->crp_sid; 279 280 if (crp->crp_etype == EAGAIN) { 281 KEY_SA_UNREF(&sav); 282 IPSEC_RELEASE_GLOBAL_LOCKS(); 283 return crypto_dispatch(crp); 284 } 285 286 IPCOMP_STATINC(IPCOMP_STAT_NOXFORM); 287 DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype)); 288 error = crp->crp_etype; 289 goto bad; 290 } 291 292 IPCOMP_STATINC(IPCOMP_STAT_HIST + ipcomp_stats[sav->alg_comp]); 293 294 /* Update the counters */ 295 IPCOMP_STATADD(IPCOMP_STAT_IBYTES, m->m_pkthdr.len - skip - hlen); 296 297 /* Length of data after processing */ 298 clen = crp->crp_olen; 299 300 /* Release the crypto descriptors */ 301 pool_cache_put(ipcomp_tdb_crypto_pool_cache, tc); 302 tc = NULL; 303 crypto_freereq(crp); 304 crp = NULL; 305 306 /* In case it's not done already, adjust the size of the mbuf chain */ 307 m->m_pkthdr.len = clen + hlen + skip; 308 309 /* 310 * Get the next protocol field. 311 * 312 * XXX: Really, we should use m_copydata instead of m_pullup. 313 */ 314 if (m->m_len < skip + hlen && (m = m_pullup(m, skip + hlen)) == 0) { 315 IPCOMP_STATINC(IPCOMP_STAT_HDROPS); 316 DPRINTF(("%s: m_pullup failed\n", __func__)); 317 error = EINVAL; 318 goto bad; 319 } 320 ipc = (struct ipcomp *)(mtod(m, uint8_t *) + skip); 321 nproto = ipc->comp_nxt; 322 323 switch (nproto) { 324 case IPPROTO_IPCOMP: 325 case IPPROTO_AH: 326 case IPPROTO_ESP: 327 IPCOMP_STATINC(IPCOMP_STAT_HDROPS); 328 DPRINTF(("%s: nested ipcomp, IPCA %s/%08lx\n", __func__, 329 ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)), 330 (u_long) ntohl(sav->spi))); 331 error = EINVAL; 332 goto bad; 333 default: 334 break; 335 } 336 337 /* Remove the IPCOMP header */ 338 error = m_striphdr(m, skip, hlen); 339 if (error) { 340 IPCOMP_STATINC(IPCOMP_STAT_HDROPS); 341 DPRINTF(("%s: bad mbuf chain, IPCA %s/%08lx\n", __func__, 342 ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)), 343 (u_long) ntohl(sav->spi))); 344 goto bad; 345 } 346 347 /* Restore the Next Protocol field */ 348 m_copyback(m, protoff, sizeof(nproto), &nproto); 349 350 IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff); 351 352 KEY_SA_UNREF(&sav); 353 IPSEC_RELEASE_GLOBAL_LOCKS(); 354 return error; 355 356 bad: 357 if (sav) 358 KEY_SA_UNREF(&sav); 359 IPSEC_RELEASE_GLOBAL_LOCKS(); 360 if (m) 361 m_freem(m); 362 if (tc != NULL) 363 pool_cache_put(ipcomp_tdb_crypto_pool_cache, tc); 364 if (crp) 365 crypto_freereq(crp); 366 return error; 367 } 368 369 /* 370 * IPComp output routine, called by ipsec[46]_process_packet() 371 */ 372 static int 373 ipcomp_output(struct mbuf *m, const struct ipsecrequest *isr, 374 struct secasvar *sav, struct mbuf **mp, int skip, int protoff) 375 { 376 char buf[IPSEC_ADDRSTRLEN]; 377 const struct comp_algo *ipcompx; 378 int error, ralen, hlen, maxpacketsize; 379 struct cryptodesc *crdc; 380 struct cryptop *crp; 381 struct tdb_crypto *tc; 382 383 KASSERT(sav != NULL); 384 KASSERT(sav->tdb_compalgxform != NULL); 385 ipcompx = sav->tdb_compalgxform; 386 387 /* Raw payload length before comp. */ 388 ralen = m->m_pkthdr.len - skip; 389 390 /* Don't process the packet if it is too short */ 391 if (ralen < ipcompx->minlen) { 392 IPCOMP_STATINC(IPCOMP_STAT_MINLEN); 393 return ipsec_process_done(m, isr, sav); 394 } 395 396 hlen = IPCOMP_HLENGTH; 397 398 IPCOMP_STATINC(IPCOMP_STAT_OUTPUT); 399 400 /* Check for maximum packet size violations. */ 401 switch (sav->sah->saidx.dst.sa.sa_family) { 402 #ifdef INET 403 case AF_INET: 404 maxpacketsize = IP_MAXPACKET; 405 break; 406 #endif 407 #ifdef INET6 408 case AF_INET6: 409 maxpacketsize = IPV6_MAXPACKET; 410 break; 411 #endif 412 default: 413 IPCOMP_STATINC(IPCOMP_STAT_NOPF); 414 DPRINTF(("%s: unknown/unsupported protocol family %d" 415 ", IPCA %s/%08lx\n", __func__, 416 sav->sah->saidx.dst.sa.sa_family, 417 ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)), 418 (u_long) ntohl(sav->spi))); 419 error = EPFNOSUPPORT; 420 goto bad; 421 } 422 if (skip + hlen + ralen > maxpacketsize) { 423 IPCOMP_STATINC(IPCOMP_STAT_TOOBIG); 424 DPRINTF(("%s: packet in IPCA %s/%08lx got too big " 425 "(len %u, max len %u)\n", __func__, 426 ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)), 427 (u_long) ntohl(sav->spi), 428 skip + hlen + ralen, maxpacketsize)); 429 error = EMSGSIZE; 430 goto bad; 431 } 432 433 /* Update the counters */ 434 IPCOMP_STATADD(IPCOMP_STAT_OBYTES, m->m_pkthdr.len - skip); 435 436 m = m_clone(m); 437 if (m == NULL) { 438 IPCOMP_STATINC(IPCOMP_STAT_HDROPS); 439 DPRINTF(("%s: cannot clone mbuf chain, IPCA %s/%08lx\n", 440 __func__, 441 ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)), 442 (u_long) ntohl(sav->spi))); 443 error = ENOBUFS; 444 goto bad; 445 } 446 447 /* Ok now, we can pass to the crypto processing */ 448 449 /* Get crypto descriptors */ 450 crp = crypto_getreq(1); 451 if (crp == NULL) { 452 IPCOMP_STATINC(IPCOMP_STAT_CRYPTO); 453 DPRINTF(("%s: failed to acquire crypto descriptor\n", 454 __func__)); 455 error = ENOBUFS; 456 goto bad; 457 } 458 crdc = crp->crp_desc; 459 460 /* Compression descriptor */ 461 crdc->crd_skip = skip; 462 crdc->crd_len = m->m_pkthdr.len - skip; 463 crdc->crd_flags = CRD_F_COMP; 464 crdc->crd_inject = skip; 465 466 /* Compression operation */ 467 crdc->crd_alg = ipcompx->type; 468 469 /* IPsec-specific opaque crypto info */ 470 tc = pool_cache_get(ipcomp_tdb_crypto_pool_cache, PR_NOWAIT); 471 if (tc == NULL) { 472 IPCOMP_STATINC(IPCOMP_STAT_CRYPTO); 473 DPRINTF(("%s: failed to allocate tdb_crypto\n", __func__)); 474 crypto_freereq(crp); 475 error = ENOBUFS; 476 goto bad; 477 } 478 479 { 480 int s = pserialize_read_enter(); 481 482 /* 483 * Take another reference to the SP and the SA for opencrypto callback. 484 */ 485 if (__predict_false(isr->sp->state == IPSEC_SPSTATE_DEAD || 486 sav->state == SADB_SASTATE_DEAD)) { 487 pserialize_read_exit(s); 488 pool_cache_put(ipcomp_tdb_crypto_pool_cache, tc); 489 crypto_freereq(crp); 490 IPCOMP_STATINC(IPCOMP_STAT_NOTDB); 491 error = ENOENT; 492 goto bad; 493 } 494 KEY_SP_REF(isr->sp); 495 KEY_SA_REF(sav); 496 pserialize_read_exit(s); 497 } 498 499 tc->tc_isr = isr; 500 tc->tc_spi = sav->spi; 501 tc->tc_dst = sav->sah->saidx.dst; 502 tc->tc_proto = sav->sah->saidx.proto; 503 tc->tc_skip = skip; 504 tc->tc_protoff = protoff; 505 tc->tc_sav = sav; 506 507 /* Crypto operation descriptor */ 508 crp->crp_ilen = m->m_pkthdr.len; /* Total input length */ 509 crp->crp_flags = CRYPTO_F_IMBUF; 510 crp->crp_buf = m; 511 crp->crp_callback = ipcomp_output_cb; 512 crp->crp_opaque = tc; 513 crp->crp_sid = sav->tdb_cryptoid; 514 515 return crypto_dispatch(crp); 516 517 bad: 518 if (m) 519 m_freem(m); 520 return error; 521 } 522 523 /* 524 * IPComp output callback from the crypto driver. 525 */ 526 static int 527 ipcomp_output_cb(struct cryptop *crp) 528 { 529 char buf[IPSEC_ADDRSTRLEN]; 530 struct tdb_crypto *tc; 531 const struct ipsecrequest *isr; 532 struct secasvar *sav; 533 struct mbuf *m, *mo; 534 int error, skip, rlen, roff; 535 uint8_t prot; 536 uint16_t cpi; 537 struct ipcomp * ipcomp; 538 IPSEC_DECLARE_LOCK_VARIABLE; 539 540 KASSERT(crp->crp_opaque != NULL); 541 tc = crp->crp_opaque; 542 m = crp->crp_buf; 543 skip = tc->tc_skip; 544 rlen = crp->crp_ilen - skip; 545 546 IPSEC_ACQUIRE_GLOBAL_LOCKS(); 547 548 isr = tc->tc_isr; 549 sav = tc->tc_sav; 550 551 /* Check for crypto errors */ 552 if (crp->crp_etype) { 553 /* Reset session ID */ 554 if (sav->tdb_cryptoid != 0) 555 sav->tdb_cryptoid = crp->crp_sid; 556 557 if (crp->crp_etype == EAGAIN) { 558 IPSEC_RELEASE_GLOBAL_LOCKS(); 559 return crypto_dispatch(crp); 560 } 561 IPCOMP_STATINC(IPCOMP_STAT_NOXFORM); 562 DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype)); 563 error = crp->crp_etype; 564 goto bad; 565 } 566 567 IPCOMP_STATINC(IPCOMP_STAT_HIST + ipcomp_stats[sav->alg_comp]); 568 569 if (rlen > crp->crp_olen) { 570 /* Inject IPCOMP header */ 571 mo = m_makespace(m, skip, IPCOMP_HLENGTH, &roff); 572 if (mo == NULL) { 573 IPCOMP_STATINC(IPCOMP_STAT_WRAP); 574 DPRINTF(("%s: failed to inject IPCOMP header for " 575 "IPCA %s/%08lx\n", __func__, 576 ipsec_address(&sav->sah->saidx.dst, buf, 577 sizeof(buf)), (u_long) ntohl(sav->spi))); 578 error = ENOBUFS; 579 goto bad; 580 } 581 ipcomp = (struct ipcomp *)(mtod(mo, char *) + roff); 582 583 /* Initialize the IPCOMP header */ 584 /* XXX alignment always correct? */ 585 switch (sav->sah->saidx.dst.sa.sa_family) { 586 #ifdef INET 587 case AF_INET: 588 ipcomp->comp_nxt = mtod(m, struct ip *)->ip_p; 589 break; 590 #endif 591 #ifdef INET6 592 case AF_INET6: 593 ipcomp->comp_nxt = mtod(m, struct ip6_hdr *)->ip6_nxt; 594 break; 595 #endif 596 } 597 ipcomp->comp_flags = 0; 598 599 if ((sav->flags & SADB_X_EXT_RAWCPI) == 0) 600 cpi = sav->alg_enc; 601 else 602 cpi = ntohl(sav->spi) & 0xffff; 603 ipcomp->comp_cpi = htons(cpi); 604 605 /* Fix Next Protocol in IPv4/IPv6 header */ 606 prot = IPPROTO_IPCOMP; 607 m_copyback(m, tc->tc_protoff, sizeof(prot), &prot); 608 609 /* Adjust the length in the IP header */ 610 switch (sav->sah->saidx.dst.sa.sa_family) { 611 #ifdef INET 612 case AF_INET: 613 mtod(m, struct ip *)->ip_len = htons(m->m_pkthdr.len); 614 break; 615 #endif 616 #ifdef INET6 617 case AF_INET6: 618 mtod(m, struct ip6_hdr *)->ip6_plen = 619 htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); 620 break; 621 #endif 622 default: 623 IPCOMP_STATINC(IPCOMP_STAT_NOPF); 624 DPRINTF(("ipcomp_output: unknown/unsupported protocol " 625 "family %d, IPCA %s/%08lx\n", 626 sav->sah->saidx.dst.sa.sa_family, 627 ipsec_address(&sav->sah->saidx.dst, buf, 628 sizeof(buf)), (u_long) ntohl(sav->spi))); 629 error = EPFNOSUPPORT; 630 goto bad; 631 } 632 } else { 633 /* compression was useless, we have lost time */ 634 IPCOMP_STATINC(IPCOMP_STAT_USELESS); 635 DPRINTF(("ipcomp_output_cb: compression was useless: initial" 636 "size was %d and compressed size is %d\n", rlen, 637 crp->crp_olen)); 638 } 639 640 /* Release the crypto descriptor */ 641 pool_cache_put(ipcomp_tdb_crypto_pool_cache, tc); 642 crypto_freereq(crp); 643 644 /* NB: m is reclaimed by ipsec_process_done. */ 645 error = ipsec_process_done(m, isr, sav); 646 KEY_SA_UNREF(&sav); 647 KEY_SP_UNREF(&isr->sp); 648 IPSEC_RELEASE_GLOBAL_LOCKS(); 649 return error; 650 651 bad: 652 if (sav) 653 KEY_SA_UNREF(&sav); 654 KEY_SP_UNREF(&isr->sp); 655 IPSEC_RELEASE_GLOBAL_LOCKS(); 656 if (m) 657 m_freem(m); 658 pool_cache_put(ipcomp_tdb_crypto_pool_cache, tc); 659 crypto_freereq(crp); 660 return error; 661 } 662 663 static struct xformsw ipcomp_xformsw = { 664 .xf_type = XF_IPCOMP, 665 .xf_flags = XFT_COMP, 666 .xf_name = "IPcomp", 667 .xf_init = ipcomp_init, 668 .xf_zeroize = ipcomp_zeroize, 669 .xf_input = ipcomp_input, 670 .xf_output = ipcomp_output, 671 .xf_next = NULL, 672 }; 673 674 void 675 ipcomp_attach(void) 676 { 677 ipcompstat_percpu = percpu_alloc(sizeof(uint64_t) * IPCOMP_NSTATS); 678 ipcomp_tdb_crypto_pool_cache = pool_cache_init(sizeof(struct tdb_crypto), 679 coherency_unit, 0, 0, "ipcomp_tdb_crypto", NULL, IPL_SOFTNET, 680 NULL, NULL, NULL); 681 xform_register(&ipcomp_xformsw); 682 } 683