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