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