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