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