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