1 /* $OpenBSD: ip_ipcomp.c,v 1.46 2016/08/18 06:01:10 dlg Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Jean-Jacques Bernard-Gundol (jj@wabbitt.org) 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 /* IP payload compression protocol (IPComp), see RFC 2393 */ 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/mbuf.h> 35 #include <sys/socket.h> 36 37 #include <net/if.h> 38 #include <net/if_var.h> 39 #include <net/bpf.h> 40 41 #include <netinet/in.h> 42 #include <netinet/ip.h> 43 #include <netinet/ip_var.h> 44 45 #ifdef INET6 46 #include <netinet/ip6.h> 47 #endif /* INET6 */ 48 49 #include <netinet/ip_ipsp.h> 50 #include <netinet/ip_ipcomp.h> 51 #include <net/pfkeyv2.h> 52 #include <net/if_enc.h> 53 54 #include <crypto/cryptodev.h> 55 #include <crypto/xform.h> 56 57 #include "bpfilter.h" 58 59 int ipcomp_output_cb(struct cryptop *); 60 int ipcomp_input_cb(struct cryptop *); 61 62 #ifdef ENCDEBUG 63 #define DPRINTF(x) if (encdebug) printf x 64 #else 65 #define DPRINTF(x) 66 #endif 67 68 struct ipcompstat ipcompstat; 69 70 /* 71 * ipcomp_attach() is called from the transformation code 72 */ 73 int 74 ipcomp_attach(void) 75 { 76 return 0; 77 } 78 79 /* 80 * ipcomp_init() is called when an CPI is being set up. 81 */ 82 int 83 ipcomp_init(tdbp, xsp, ii) 84 struct tdb *tdbp; 85 struct xformsw *xsp; 86 struct ipsecinit *ii; 87 { 88 struct comp_algo *tcomp = NULL; 89 struct cryptoini cric; 90 91 switch (ii->ii_compalg) { 92 case SADB_X_CALG_DEFLATE: 93 tcomp = &comp_algo_deflate; 94 break; 95 case SADB_X_CALG_LZS: 96 tcomp = &comp_algo_lzs; 97 break; 98 99 default: 100 DPRINTF(("ipcomp_init(): unsupported compression algorithm %d specified\n", 101 ii->ii_compalg)); 102 return EINVAL; 103 } 104 105 tdbp->tdb_compalgxform = tcomp; 106 107 DPRINTF(("ipcomp_init(): initialized TDB with ipcomp algorithm %s\n", 108 tcomp->name)); 109 110 tdbp->tdb_xform = xsp; 111 112 /* Initialize crypto session */ 113 memset(&cric, 0, sizeof(cric)); 114 cric.cri_alg = tdbp->tdb_compalgxform->type; 115 116 return crypto_newsession(&tdbp->tdb_cryptoid, &cric, 0); 117 } 118 119 /* 120 * ipcomp_zeroize() used when IPCA is deleted 121 */ 122 int 123 ipcomp_zeroize(tdbp) 124 struct tdb *tdbp; 125 { 126 int err; 127 128 err = crypto_freesession(tdbp->tdb_cryptoid); 129 tdbp->tdb_cryptoid = 0; 130 return err; 131 } 132 133 /* 134 * ipcomp_input() gets called to uncompress an input packet 135 */ 136 int 137 ipcomp_input(m, tdb, skip, protoff) 138 struct mbuf *m; 139 struct tdb *tdb; 140 int skip; 141 int protoff; 142 { 143 struct comp_algo *ipcompx = (struct comp_algo *) tdb->tdb_compalgxform; 144 struct tdb_crypto *tc; 145 int hlen; 146 147 struct cryptodesc *crdc = NULL; 148 struct cryptop *crp; 149 150 hlen = IPCOMP_HLENGTH; 151 152 /* Get crypto descriptors */ 153 crp = crypto_getreq(1); 154 if (crp == NULL) { 155 m_freem(m); 156 DPRINTF(("ipcomp_input(): failed to acquire crypto descriptors\n")); 157 ipcompstat.ipcomps_crypto++; 158 return ENOBUFS; 159 } 160 /* Get IPsec-specific opaque pointer */ 161 tc = malloc(sizeof(*tc), M_XDATA, M_NOWAIT | M_ZERO); 162 if (tc == NULL) { 163 m_freem(m); 164 crypto_freereq(crp); 165 DPRINTF(("ipcomp_input(): failed to allocate tdb_crypto\n")); 166 ipcompstat.ipcomps_crypto++; 167 return ENOBUFS; 168 } 169 crdc = crp->crp_desc; 170 171 crdc->crd_skip = skip + hlen; 172 crdc->crd_len = m->m_pkthdr.len - (skip + hlen); 173 crdc->crd_inject = skip; 174 175 /* Decompression operation */ 176 crdc->crd_alg = ipcompx->type; 177 178 /* Crypto operation descriptor */ 179 crp->crp_ilen = m->m_pkthdr.len - (skip + hlen); 180 crp->crp_flags = CRYPTO_F_IMBUF; 181 crp->crp_buf = (caddr_t)m; 182 crp->crp_callback = ipcomp_input_cb; 183 crp->crp_sid = tdb->tdb_cryptoid; 184 crp->crp_opaque = (caddr_t)tc; 185 186 /* These are passed as-is to the callback */ 187 tc->tc_skip = skip; 188 tc->tc_protoff = protoff; 189 tc->tc_spi = tdb->tdb_spi; 190 tc->tc_proto = IPPROTO_IPCOMP; 191 tc->tc_rdomain = tdb->tdb_rdomain; 192 bcopy(&tdb->tdb_dst, &tc->tc_dst, sizeof(union sockaddr_union)); 193 194 return crypto_dispatch(crp); 195 } 196 197 /* 198 * IPComp input callback, called directly by the crypto driver 199 */ 200 int 201 ipcomp_input_cb(struct cryptop *crp) 202 { 203 int error, s, skip, protoff, roff, hlen = IPCOMP_HLENGTH, clen; 204 u_int8_t nproto; 205 struct mbuf *m, *m1, *mo; 206 struct tdb_crypto *tc; 207 struct tdb *tdb; 208 struct ipcomp *ipcomp; 209 caddr_t addr; 210 #ifdef ENCDEBUG 211 char buf[INET6_ADDRSTRLEN]; 212 #endif 213 214 tc = (struct tdb_crypto *) crp->crp_opaque; 215 skip = tc->tc_skip; 216 protoff = tc->tc_protoff; 217 218 m = (struct mbuf *) crp->crp_buf; 219 if (m == NULL) { 220 /* Shouldn't happen... */ 221 free(tc, M_XDATA, 0); 222 crypto_freereq(crp); 223 ipcompstat.ipcomps_crypto++; 224 DPRINTF(("ipcomp_input_cb(): bogus returned buffer from crypto\n")); 225 return (EINVAL); 226 } 227 228 s = splsoftnet(); 229 230 tdb = gettdb(tc->tc_rdomain, tc->tc_spi, &tc->tc_dst, tc->tc_proto); 231 if (tdb == NULL) { 232 free(tc, M_XDATA, 0); 233 ipcompstat.ipcomps_notdb++; 234 DPRINTF(("ipcomp_input_cb(): TDB expired while in crypto")); 235 error = EPERM; 236 goto baddone; 237 } 238 239 /* update the counters */ 240 tdb->tdb_cur_bytes += m->m_pkthdr.len - (skip + hlen); 241 ipcompstat.ipcomps_ibytes += m->m_pkthdr.len - (skip + hlen); 242 243 /* Hard expiration */ 244 if ((tdb->tdb_flags & TDBF_BYTES) && 245 (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) { 246 free(tc, M_XDATA, 0); 247 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); 248 tdb_delete(tdb); 249 error = ENXIO; 250 goto baddone; 251 } 252 /* Notify on soft expiration */ 253 if ((tdb->tdb_flags & TDBF_SOFT_BYTES) && 254 (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) { 255 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT); 256 tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */ 257 } 258 259 /* Check for crypto errors */ 260 if (crp->crp_etype) { 261 if (crp->crp_etype == EAGAIN) { 262 /* Reset the session ID */ 263 if (tdb->tdb_cryptoid != 0) 264 tdb->tdb_cryptoid = crp->crp_sid; 265 splx(s); 266 return crypto_dispatch(crp); 267 } 268 free(tc, M_XDATA, 0); 269 ipcompstat.ipcomps_noxform++; 270 DPRINTF(("ipcomp_input_cb(): crypto error %d\n", 271 crp->crp_etype)); 272 error = crp->crp_etype; 273 goto baddone; 274 } 275 free(tc, M_XDATA, 0); 276 277 /* Length of data after processing */ 278 clen = crp->crp_olen; 279 280 /* In case it's not done already, adjust the size of the mbuf chain */ 281 m->m_pkthdr.len = clen + hlen + skip; 282 283 if ((m->m_len < skip + hlen) && (m = m_pullup(m, skip + hlen)) == 0) { 284 error = ENOBUFS; 285 goto baddone; 286 } 287 288 /* Find the beginning of the IPCOMP header */ 289 m1 = m_getptr(m, skip, &roff); 290 if (m1 == NULL) { 291 ipcompstat.ipcomps_hdrops++; 292 DPRINTF(("ipcomp_input_cb(): bad mbuf chain, IPCA %s/%08x\n", 293 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 294 ntohl(tdb->tdb_spi))); 295 error = EINVAL; 296 goto baddone; 297 } 298 /* Keep the next protocol field */ 299 addr = (caddr_t) mtod(m, struct ip *) + skip; 300 ipcomp = (struct ipcomp *) addr; 301 nproto = ipcomp->ipcomp_nh; 302 303 /* Remove the IPCOMP header from the mbuf */ 304 if (roff == 0) { 305 /* The IPCOMP header is at the beginning of m1 */ 306 m_adj(m1, hlen); 307 if (!(m1->m_flags & M_PKTHDR)) 308 m->m_pkthdr.len -= hlen; 309 } else if (roff + hlen >= m1->m_len) { 310 if (roff + hlen > m1->m_len) { 311 /* Adjust the next mbuf by the remainder */ 312 m_adj(m1->m_next, roff + hlen - m1->m_len); 313 314 /* 315 * The second mbuf is guaranteed not to have a 316 * pkthdr... 317 */ 318 m->m_pkthdr.len -= (roff + hlen - m1->m_len); 319 } 320 /* Now, let's unlink the mbuf chain for a second... */ 321 mo = m1->m_next; 322 m1->m_next = NULL; 323 324 /* ...and trim the end of the first part of the chain...sick */ 325 m_adj(m1, -(m1->m_len - roff)); 326 if (!(m1->m_flags & M_PKTHDR)) 327 m->m_pkthdr.len -= (m1->m_len - roff); 328 329 /* Finally, let's relink */ 330 m1->m_next = mo; 331 } else { 332 bcopy(mtod(m1, u_char *) + roff + hlen, 333 mtod(m1, u_char *) + roff, 334 m1->m_len - (roff + hlen)); 335 m1->m_len -= hlen; 336 m->m_pkthdr.len -= hlen; 337 } 338 339 /* Release the crypto descriptors */ 340 crypto_freereq(crp); 341 342 /* Restore the Next Protocol field */ 343 m_copyback(m, protoff, sizeof(u_int8_t), &nproto, M_NOWAIT); 344 345 /* Back to generic IPsec input processing */ 346 error = ipsec_common_input_cb(m, tdb, skip, protoff); 347 splx(s); 348 return error; 349 350 baddone: 351 splx(s); 352 353 m_freem(m); 354 355 crypto_freereq(crp); 356 357 return error; 358 } 359 360 /* 361 * IPComp output routine, called by ipsp_process_packet() 362 */ 363 int 364 ipcomp_output(m, tdb, mp, skip, protoff) 365 struct mbuf *m; 366 struct tdb *tdb; 367 struct mbuf **mp; 368 int skip; 369 int protoff; 370 { 371 struct comp_algo *ipcompx = (struct comp_algo *) tdb->tdb_compalgxform; 372 int hlen; 373 struct cryptodesc *crdc = NULL; 374 struct cryptop *crp; 375 struct tdb_crypto *tc; 376 struct mbuf *mi; 377 #ifdef ENCDEBUG 378 char buf[INET6_ADDRSTRLEN]; 379 #endif 380 #if NBPFILTER > 0 381 struct ifnet *encif; 382 383 if ((encif = enc_getif(0, tdb->tdb_tap)) != NULL) { 384 encif->if_opackets++; 385 encif->if_obytes += m->m_pkthdr.len; 386 387 if (encif->if_bpf) { 388 struct enchdr hdr; 389 390 memset(&hdr, 0, sizeof(hdr)); 391 392 hdr.af = tdb->tdb_dst.sa.sa_family; 393 hdr.spi = tdb->tdb_spi; 394 395 bpf_mtap_hdr(encif->if_bpf, (char *)&hdr, 396 ENC_HDRLEN, m, BPF_DIRECTION_OUT, NULL); 397 } 398 } 399 #endif 400 hlen = IPCOMP_HLENGTH; 401 402 ipcompstat.ipcomps_output++; 403 404 switch (tdb->tdb_dst.sa.sa_family) { 405 case AF_INET: 406 /* Check for IPv4 maximum packet size violations */ 407 /* 408 * Since compression is going to reduce the size, no need to 409 * worry 410 */ 411 if (m->m_pkthdr.len + hlen > IP_MAXPACKET) { 412 DPRINTF(("ipcomp_output(): packet in IPCA %s/%08x " 413 "got too big\n", ipsp_address(&tdb->tdb_dst, buf, 414 sizeof(buf)), ntohl(tdb->tdb_spi))); 415 m_freem(m); 416 ipcompstat.ipcomps_toobig++; 417 return EMSGSIZE; 418 } 419 break; 420 421 #ifdef INET6 422 case AF_INET6: 423 /* Check for IPv6 maximum packet size violations */ 424 if (m->m_pkthdr.len + hlen > IPV6_MAXPACKET) { 425 DPRINTF(("ipcomp_output(): packet in IPCA %s/%08x " 426 "got too big\n", ipsp_address(&tdb->tdb_dst, buf, 427 sizeof(buf)), ntohl(tdb->tdb_spi))); 428 m_freem(m); 429 ipcompstat.ipcomps_toobig++; 430 return EMSGSIZE; 431 } 432 #endif /* INET6 */ 433 434 default: 435 DPRINTF(("ipcomp_output(): unknown/unsupported protocol " 436 "family %d, IPCA %s/%08x\n", tdb->tdb_dst.sa.sa_family, 437 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 438 ntohl(tdb->tdb_spi))); 439 m_freem(m); 440 ipcompstat.ipcomps_nopf++; 441 return EPFNOSUPPORT; 442 } 443 444 /* Update the counters */ 445 446 tdb->tdb_cur_bytes += m->m_pkthdr.len - skip; 447 ipcompstat.ipcomps_obytes += m->m_pkthdr.len - skip; 448 449 /* Hard byte expiration */ 450 if ((tdb->tdb_flags & TDBF_BYTES) && 451 (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) { 452 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); 453 tdb_delete(tdb); 454 m_freem(m); 455 return EINVAL; 456 } 457 /* Soft byte expiration */ 458 if ((tdb->tdb_flags & TDBF_SOFT_BYTES) && 459 (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) { 460 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT); 461 tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */ 462 } 463 /* 464 * Loop through mbuf chain; if we find a readonly mbuf, 465 * copy the packet. 466 */ 467 mi = m; 468 while (mi != NULL && !M_READONLY(mi)) 469 mi = mi->m_next; 470 471 if (mi != NULL) { 472 struct mbuf *n = m_dup_pkt(m, 0, M_DONTWAIT); 473 474 if (n == NULL) { 475 DPRINTF(("ipcomp_output(): bad mbuf chain, IPCA %s/%08x\n", 476 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 477 ntohl(tdb->tdb_spi))); 478 ipcompstat.ipcomps_hdrops++; 479 m_freem(m); 480 return ENOBUFS; 481 } 482 483 m_freem(m); 484 m = n; 485 } 486 /* Ok now, we can pass to the crypto processing */ 487 488 /* Get crypto descriptors */ 489 crp = crypto_getreq(1); 490 if (crp == NULL) { 491 m_freem(m); 492 DPRINTF(("ipcomp_output(): failed to acquire crypto descriptors\n")); 493 ipcompstat.ipcomps_crypto++; 494 return ENOBUFS; 495 } 496 crdc = crp->crp_desc; 497 498 /* Compression descriptor */ 499 crdc->crd_skip = skip; 500 crdc->crd_len = m->m_pkthdr.len - skip; 501 crdc->crd_flags = CRD_F_COMP; 502 crdc->crd_inject = skip; 503 504 /* Compression operation */ 505 crdc->crd_alg = ipcompx->type; 506 507 /* IPsec-specific opaque crypto info */ 508 tc = malloc(sizeof(*tc), M_XDATA, M_NOWAIT | M_ZERO); 509 if (tc == NULL) { 510 m_freem(m); 511 crypto_freereq(crp); 512 DPRINTF(("ipcomp_output(): failed to allocate tdb_crypto\n")); 513 ipcompstat.ipcomps_crypto++; 514 return ENOBUFS; 515 } 516 517 tc->tc_spi = tdb->tdb_spi; 518 tc->tc_proto = tdb->tdb_sproto; 519 tc->tc_skip = skip; 520 tc->tc_rdomain = tdb->tdb_rdomain; 521 bcopy(&tdb->tdb_dst, &tc->tc_dst, sizeof(union sockaddr_union)); 522 523 /* Crypto operation descriptor */ 524 crp->crp_ilen = m->m_pkthdr.len; /* Total input length */ 525 crp->crp_flags = CRYPTO_F_IMBUF; 526 crp->crp_buf = (caddr_t)m; 527 crp->crp_callback = ipcomp_output_cb; 528 crp->crp_opaque = (caddr_t)tc; 529 crp->crp_sid = tdb->tdb_cryptoid; 530 531 return crypto_dispatch(crp); 532 } 533 534 /* 535 * IPComp output callback, called directly from the crypto driver 536 */ 537 int 538 ipcomp_output_cb(struct cryptop *crp) 539 { 540 struct tdb_crypto *tc; 541 struct tdb *tdb; 542 struct mbuf *m, *mo; 543 int error, s, skip, rlen; 544 u_int16_t cpi; 545 struct ip *ip; 546 #ifdef INET6 547 struct ip6_hdr *ip6; 548 #endif 549 struct ipcomp *ipcomp; 550 #ifdef ENCDEBUG 551 char buf[INET6_ADDRSTRLEN]; 552 #endif 553 554 tc = (struct tdb_crypto *) crp->crp_opaque; 555 skip = tc->tc_skip; 556 rlen = crp->crp_ilen - skip; 557 558 m = (struct mbuf *) crp->crp_buf; 559 if (m == NULL) { 560 /* Shouldn't happen... */ 561 free(tc, M_XDATA, 0); 562 crypto_freereq(crp); 563 ipcompstat.ipcomps_crypto++; 564 DPRINTF(("ipcomp_output_cb(): bogus returned buffer from " 565 "crypto\n")); 566 return (EINVAL); 567 } 568 569 s = splsoftnet(); 570 571 tdb = gettdb(tc->tc_rdomain, tc->tc_spi, &tc->tc_dst, tc->tc_proto); 572 if (tdb == NULL) { 573 free(tc, M_XDATA, 0); 574 ipcompstat.ipcomps_notdb++; 575 DPRINTF(("ipcomp_output_cb(): TDB expired while in crypto\n")); 576 error = EPERM; 577 goto baddone; 578 } 579 580 /* Check for crypto errors. */ 581 if (crp->crp_etype) { 582 if (crp->crp_etype == EAGAIN) { 583 /* Reset the session ID */ 584 if (tdb->tdb_cryptoid != 0) 585 tdb->tdb_cryptoid = crp->crp_sid; 586 splx(s); 587 return crypto_dispatch(crp); 588 } 589 free(tc, M_XDATA, 0); 590 ipcompstat.ipcomps_noxform++; 591 DPRINTF(("ipcomp_output_cb(): crypto error %d\n", 592 crp->crp_etype)); 593 error = crp->crp_etype; 594 goto baddone; 595 } 596 free(tc, M_XDATA, 0); 597 598 /* Check sizes. */ 599 if (rlen < crp->crp_olen) { 600 /* Compression was useless, we have lost time. */ 601 crypto_freereq(crp); 602 error = ipsp_process_done(m, tdb); 603 splx(s); 604 return error; 605 } 606 607 /* Inject IPCOMP header */ 608 mo = m_inject(m, skip, IPCOMP_HLENGTH, M_DONTWAIT); 609 if (mo == NULL) { 610 DPRINTF(("ipcomp_output_cb(): failed to inject IPCOMP header " 611 "for IPCA %s/%08x\n", ipsp_address(&tdb->tdb_dst, buf, 612 sizeof(buf)), ntohl(tdb->tdb_spi))); 613 ipcompstat.ipcomps_wrap++; 614 error = ENOBUFS; 615 goto baddone; 616 } 617 618 /* Initialize the IPCOMP header */ 619 ipcomp = mtod(mo, struct ipcomp *); 620 memset(ipcomp, 0, sizeof(struct ipcomp)); 621 cpi = (u_int16_t) ntohl(tdb->tdb_spi); 622 ipcomp->ipcomp_cpi = htons(cpi); 623 624 /* m_pullup before ? */ 625 switch (tdb->tdb_dst.sa.sa_family) { 626 case AF_INET: 627 ip = mtod(m, struct ip *); 628 ipcomp->ipcomp_nh = ip->ip_p; 629 ip->ip_p = IPPROTO_IPCOMP; 630 break; 631 #ifdef INET6 632 case AF_INET6: 633 ip6 = mtod(m, struct ip6_hdr *); 634 ipcomp->ipcomp_nh = ip6->ip6_nxt; 635 ip6->ip6_nxt = IPPROTO_IPCOMP; 636 break; 637 #endif 638 default: 639 DPRINTF(("ipcomp_output_cb(): unsupported protocol family %d, " 640 "IPCA %s/%08x\n", tdb->tdb_dst.sa.sa_family, 641 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 642 ntohl(tdb->tdb_spi))); 643 ipcompstat.ipcomps_nopf++; 644 error = EPFNOSUPPORT; 645 goto baddone; 646 break; 647 } 648 649 /* Release the crypto descriptor. */ 650 crypto_freereq(crp); 651 652 error = ipsp_process_done(m, tdb); 653 splx(s); 654 return error; 655 656 baddone: 657 splx(s); 658 659 m_freem(m); 660 661 crypto_freereq(crp); 662 663 return error; 664 } 665