1 /* $FreeBSD$ */ 2 /* $OpenBSD: ip_ipcomp.c,v 1.1 2001/07/05 12:08:52 jjbg Exp $ */ 3 4 /*- 5 * SPDX-License-Identifier: BSD-3-Clause 6 * 7 * Copyright (c) 2001 Jean-Jacques Bernard-Gundol (jj@wabbitt.org) 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* IP payload compression protocol (IPComp), see RFC 2393 */ 34 #include "opt_inet.h" 35 #include "opt_inet6.h" 36 #include "opt_ipsec.h" 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/mbuf.h> 41 #include <sys/lock.h> 42 #include <sys/mutex.h> 43 #include <sys/socket.h> 44 #include <sys/kernel.h> 45 #include <sys/protosw.h> 46 #include <sys/sysctl.h> 47 48 #include <netinet/in.h> 49 #include <netinet/in_systm.h> 50 #include <netinet/ip.h> 51 #include <netinet/ip_var.h> 52 #include <netinet/ip_encap.h> 53 54 #include <net/netisr.h> 55 #include <net/vnet.h> 56 #include <net/if.h> /* XXXGL: net_epoch should move out there */ 57 #include <net/if_var.h> /* XXXGL: net_epoch should move out there */ 58 59 #include <netipsec/ipsec.h> 60 #include <netipsec/xform.h> 61 62 #ifdef INET6 63 #include <netinet/ip6.h> 64 #include <netinet6/ip6_var.h> 65 #include <netipsec/ipsec6.h> 66 #endif 67 68 #include <netipsec/ipcomp.h> 69 #include <netipsec/ipcomp_var.h> 70 71 #include <netipsec/key.h> 72 #include <netipsec/key_debug.h> 73 74 #include <opencrypto/cryptodev.h> 75 #include <opencrypto/deflate.h> 76 #include <opencrypto/xform.h> 77 78 VNET_DEFINE(int, ipcomp_enable) = 1; 79 VNET_PCPUSTAT_DEFINE(struct ipcompstat, ipcompstat); 80 VNET_PCPUSTAT_SYSINIT(ipcompstat); 81 82 #ifdef VIMAGE 83 VNET_PCPUSTAT_SYSUNINIT(ipcompstat); 84 #endif /* VIMAGE */ 85 86 SYSCTL_DECL(_net_inet_ipcomp); 87 SYSCTL_INT(_net_inet_ipcomp, OID_AUTO, ipcomp_enable, 88 CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ipcomp_enable), 0, ""); 89 SYSCTL_VNET_PCPUSTAT(_net_inet_ipcomp, IPSECCTL_STATS, stats, 90 struct ipcompstat, ipcompstat, 91 "IPCOMP statistics (struct ipcompstat, netipsec/ipcomp_var.h"); 92 93 static int ipcomp_input_cb(struct cryptop *crp); 94 static int ipcomp_output_cb(struct cryptop *crp); 95 96 /* 97 * RFC 3173 p 2.2. Non-Expansion Policy: 98 * If the total size of a compressed payload and the IPComp header, as 99 * defined in section 3, is not smaller than the size of the original 100 * payload, the IP datagram MUST be sent in the original non-compressed 101 * form. 102 * 103 * When we use IPComp in tunnel mode, for small packets we will receive 104 * encapsulated IP-IP datagrams without any compression and without IPComp 105 * header. 106 */ 107 static int 108 ipcomp_encapcheck(union sockaddr_union *src, union sockaddr_union *dst) 109 { 110 struct secasvar *sav; 111 112 sav = key_allocsa_tunnel(src, dst, IPPROTO_IPCOMP); 113 if (sav == NULL) 114 return (0); 115 key_freesav(&sav); 116 117 if (src->sa.sa_family == AF_INET) 118 return (sizeof(struct in_addr) << 4); 119 else 120 return (sizeof(struct in6_addr) << 4); 121 } 122 123 static int 124 ipcomp_nonexp_input(struct mbuf *m, int off, int proto, void *arg __unused) 125 { 126 int isr; 127 128 NET_EPOCH_ASSERT(); 129 130 switch (proto) { 131 #ifdef INET 132 case IPPROTO_IPV4: 133 isr = NETISR_IP; 134 break; 135 #endif 136 #ifdef INET6 137 case IPPROTO_IPV6: 138 isr = NETISR_IPV6; 139 break; 140 #endif 141 default: 142 IPCOMPSTAT_INC(ipcomps_nopf); 143 m_freem(m); 144 return (IPPROTO_DONE); 145 } 146 m_adj(m, off); 147 IPCOMPSTAT_ADD(ipcomps_ibytes, m->m_pkthdr.len); 148 IPCOMPSTAT_INC(ipcomps_input); 149 netisr_dispatch(isr, m); 150 return (IPPROTO_DONE); 151 } 152 153 /* 154 * ipcomp_init() is called when an CPI is being set up. 155 */ 156 static int 157 ipcomp_init(struct secasvar *sav, struct xformsw *xsp) 158 { 159 const struct comp_algo *tcomp; 160 struct crypto_session_params csp; 161 162 /* NB: algorithm really comes in alg_enc and not alg_comp! */ 163 tcomp = comp_algorithm_lookup(sav->alg_enc); 164 if (tcomp == NULL) { 165 DPRINTF(("%s: unsupported compression algorithm %d\n", __func__, 166 sav->alg_comp)); 167 return EINVAL; 168 } 169 sav->alg_comp = sav->alg_enc; /* set for doing histogram */ 170 sav->tdb_xform = xsp; 171 sav->tdb_compalgxform = tcomp; 172 173 /* Initialize crypto session */ 174 memset(&csp, 0, sizeof(csp)); 175 csp.csp_mode = CSP_MODE_COMPRESS; 176 csp.csp_cipher_alg = sav->tdb_compalgxform->type; 177 178 return crypto_newsession(&sav->tdb_cryptoid, &csp, V_crypto_support); 179 } 180 181 /* 182 * ipcomp_cleanup() used when IPCA is deleted 183 */ 184 static void 185 ipcomp_cleanup(struct secasvar *sav) 186 { 187 188 crypto_freesession(sav->tdb_cryptoid); 189 sav->tdb_cryptoid = NULL; 190 } 191 192 /* 193 * ipcomp_input() gets called to uncompress an input packet 194 */ 195 static int 196 ipcomp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff) 197 { 198 struct xform_data *xd; 199 struct cryptop *crp; 200 struct ipcomp *ipcomp; 201 crypto_session_t cryptoid; 202 caddr_t addr; 203 int error, hlen = IPCOMP_HLENGTH; 204 205 /* 206 * Check that the next header of the IPComp is not IPComp again, before 207 * doing any real work. Given it is not possible to do double 208 * compression it means someone is playing tricks on us. 209 */ 210 error = ENOBUFS; 211 if (m->m_len < skip + hlen && (m = m_pullup(m, skip + hlen)) == NULL) { 212 IPCOMPSTAT_INC(ipcomps_hdrops); /*XXX*/ 213 DPRINTF(("%s: m_pullup failed\n", __func__)); 214 key_freesav(&sav); 215 return (error); 216 } 217 addr = (caddr_t) mtod(m, struct ip *) + skip; 218 ipcomp = (struct ipcomp *)addr; 219 if (ipcomp->comp_nxt == IPPROTO_IPCOMP) { 220 IPCOMPSTAT_INC(ipcomps_pdrops); /* XXX have our own stats? */ 221 DPRINTF(("%s: recursive compression detected\n", __func__)); 222 error = EINVAL; 223 goto bad; 224 } 225 226 SECASVAR_LOCK(sav); 227 cryptoid = sav->tdb_cryptoid; 228 SECASVAR_UNLOCK(sav); 229 230 /* Get crypto descriptors */ 231 crp = crypto_getreq(cryptoid, M_NOWAIT); 232 if (crp == NULL) { 233 DPRINTF(("%s: no crypto descriptors\n", __func__)); 234 IPCOMPSTAT_INC(ipcomps_crypto); 235 goto bad; 236 } 237 /* Get IPsec-specific opaque pointer */ 238 xd = malloc(sizeof(*xd), M_XDATA, M_NOWAIT | M_ZERO); 239 if (xd == NULL) { 240 DPRINTF(("%s: cannot allocate xform_data\n", __func__)); 241 IPCOMPSTAT_INC(ipcomps_crypto); 242 crypto_freereq(crp); 243 goto bad; 244 } 245 246 /* Decompression operation */ 247 crp->crp_op = CRYPTO_OP_DECOMPRESS; 248 crp->crp_payload_start = skip + hlen; 249 crp->crp_payload_length = m->m_pkthdr.len - (skip + hlen); 250 251 /* Crypto operation descriptor */ 252 crp->crp_flags = CRYPTO_F_CBIFSYNC; 253 crypto_use_mbuf(crp, m); 254 crp->crp_callback = ipcomp_input_cb; 255 crp->crp_opaque = xd; 256 257 /* These are passed as-is to the callback */ 258 xd->sav = sav; 259 xd->protoff = protoff; 260 xd->skip = skip; 261 xd->vnet = curvnet; 262 xd->cryptoid = cryptoid; 263 264 SECASVAR_LOCK(sav); 265 crp->crp_session = xd->cryptoid = sav->tdb_cryptoid; 266 SECASVAR_UNLOCK(sav); 267 268 return crypto_dispatch(crp); 269 bad: 270 m_freem(m); 271 key_freesav(&sav); 272 return (error); 273 } 274 275 /* 276 * IPComp input callback from the crypto driver. 277 */ 278 static int 279 ipcomp_input_cb(struct cryptop *crp) 280 { 281 IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); 282 struct xform_data *xd; 283 struct mbuf *m; 284 struct secasvar *sav; 285 struct secasindex *saidx; 286 caddr_t addr; 287 crypto_session_t cryptoid; 288 int hlen = IPCOMP_HLENGTH, error, clen; 289 int skip, protoff; 290 uint8_t nproto; 291 292 m = crp->crp_buf.cb_mbuf; 293 xd = crp->crp_opaque; 294 CURVNET_SET(xd->vnet); 295 sav = xd->sav; 296 skip = xd->skip; 297 protoff = xd->protoff; 298 cryptoid = xd->cryptoid; 299 saidx = &sav->sah->saidx; 300 IPSEC_ASSERT(saidx->dst.sa.sa_family == AF_INET || 301 saidx->dst.sa.sa_family == AF_INET6, 302 ("unexpected protocol family %u", saidx->dst.sa.sa_family)); 303 304 /* Check for crypto errors */ 305 if (crp->crp_etype) { 306 if (crp->crp_etype == EAGAIN) { 307 /* Reset the session ID */ 308 if (ipsec_updateid(sav, &crp->crp_session, &cryptoid) != 0) 309 crypto_freesession(cryptoid); 310 xd->cryptoid = crp->crp_session; 311 CURVNET_RESTORE(); 312 return (crypto_dispatch(crp)); 313 } 314 IPCOMPSTAT_INC(ipcomps_noxform); 315 DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype)); 316 error = crp->crp_etype; 317 goto bad; 318 } 319 /* Shouldn't happen... */ 320 if (m == NULL) { 321 IPCOMPSTAT_INC(ipcomps_crypto); 322 DPRINTF(("%s: null mbuf returned from crypto\n", __func__)); 323 error = EINVAL; 324 goto bad; 325 } 326 IPCOMPSTAT_INC(ipcomps_hist[sav->alg_comp]); 327 328 clen = crp->crp_olen; /* Length of data after processing */ 329 330 /* Release the crypto descriptors */ 331 free(xd, M_XDATA), xd = NULL; 332 crypto_freereq(crp), crp = NULL; 333 334 /* In case it's not done already, adjust the size of the mbuf chain */ 335 m->m_pkthdr.len = clen + hlen + skip; 336 337 if (m->m_len < skip + hlen && (m = m_pullup(m, skip + hlen)) == NULL) { 338 IPCOMPSTAT_INC(ipcomps_hdrops); /*XXX*/ 339 DPRINTF(("%s: m_pullup failed\n", __func__)); 340 error = EINVAL; /*XXX*/ 341 goto bad; 342 } 343 344 /* Keep the next protocol field */ 345 addr = (caddr_t) mtod(m, struct ip *) + skip; 346 nproto = ((struct ipcomp *) addr)->comp_nxt; 347 348 /* Remove the IPCOMP header */ 349 error = m_striphdr(m, skip, hlen); 350 if (error) { 351 IPCOMPSTAT_INC(ipcomps_hdrops); 352 DPRINTF(("%s: bad mbuf chain, IPCA %s/%08lx\n", __func__, 353 ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)), 354 (u_long) ntohl(sav->spi))); 355 goto bad; 356 } 357 358 /* Restore the Next Protocol field */ 359 m_copyback(m, protoff, sizeof (u_int8_t), (u_int8_t *) &nproto); 360 361 switch (saidx->dst.sa.sa_family) { 362 #ifdef INET6 363 case AF_INET6: 364 error = ipsec6_common_input_cb(m, sav, skip, protoff); 365 break; 366 #endif 367 #ifdef INET 368 case AF_INET: 369 error = ipsec4_common_input_cb(m, sav, skip, protoff); 370 break; 371 #endif 372 default: 373 panic("%s: Unexpected address family: %d saidx=%p", __func__, 374 saidx->dst.sa.sa_family, saidx); 375 } 376 CURVNET_RESTORE(); 377 return error; 378 bad: 379 CURVNET_RESTORE(); 380 if (sav != NULL) 381 key_freesav(&sav); 382 if (m != NULL) 383 m_freem(m); 384 if (xd != NULL) 385 free(xd, M_XDATA); 386 if (crp != NULL) 387 crypto_freereq(crp); 388 return error; 389 } 390 391 /* 392 * IPComp output routine, called by ipsec[46]_perform_request() 393 */ 394 static int 395 ipcomp_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav, 396 u_int idx, int skip, int protoff) 397 { 398 IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); 399 const struct comp_algo *ipcompx; 400 struct cryptop *crp; 401 struct xform_data *xd; 402 crypto_session_t cryptoid; 403 int error, ralen, maxpacketsize; 404 405 IPSEC_ASSERT(sav != NULL, ("null SA")); 406 ipcompx = sav->tdb_compalgxform; 407 IPSEC_ASSERT(ipcompx != NULL, ("null compression xform")); 408 409 /* 410 * Do not touch the packet in case our payload to compress 411 * is lower than the minimal threshold of the compression 412 * alogrithm. We will just send out the data uncompressed. 413 * See RFC 3173, 2.2. Non-Expansion Policy. 414 */ 415 if (m->m_pkthdr.len <= ipcompx->minlen) { 416 IPCOMPSTAT_INC(ipcomps_threshold); 417 return ipsec_process_done(m, sp, sav, idx); 418 } 419 420 ralen = m->m_pkthdr.len - skip; /* Raw payload length before comp. */ 421 IPCOMPSTAT_INC(ipcomps_output); 422 423 /* Check for maximum packet size violations. */ 424 switch (sav->sah->saidx.dst.sa.sa_family) { 425 #ifdef INET 426 case AF_INET: 427 maxpacketsize = IP_MAXPACKET; 428 break; 429 #endif /* INET */ 430 #ifdef INET6 431 case AF_INET6: 432 maxpacketsize = IPV6_MAXPACKET; 433 break; 434 #endif /* INET6 */ 435 default: 436 IPCOMPSTAT_INC(ipcomps_nopf); 437 DPRINTF(("%s: unknown/unsupported protocol family %d, " 438 "IPCA %s/%08lx\n", __func__, 439 sav->sah->saidx.dst.sa.sa_family, 440 ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)), 441 (u_long) ntohl(sav->spi))); 442 error = EPFNOSUPPORT; 443 goto bad; 444 } 445 if (ralen + skip + IPCOMP_HLENGTH > maxpacketsize) { 446 IPCOMPSTAT_INC(ipcomps_toobig); 447 DPRINTF(("%s: packet in IPCA %s/%08lx got too big " 448 "(len %u, max len %u)\n", __func__, 449 ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)), 450 (u_long) ntohl(sav->spi), 451 ralen + skip + IPCOMP_HLENGTH, maxpacketsize)); 452 error = EMSGSIZE; 453 goto bad; 454 } 455 456 /* Update the counters */ 457 IPCOMPSTAT_ADD(ipcomps_obytes, m->m_pkthdr.len - skip); 458 459 m = m_unshare(m, M_NOWAIT); 460 if (m == NULL) { 461 IPCOMPSTAT_INC(ipcomps_hdrops); 462 DPRINTF(("%s: cannot clone mbuf chain, IPCA %s/%08lx\n", 463 __func__, ipsec_address(&sav->sah->saidx.dst, buf, 464 sizeof(buf)), (u_long) ntohl(sav->spi))); 465 error = ENOBUFS; 466 goto bad; 467 } 468 469 /* Ok now, we can pass to the crypto processing. */ 470 SECASVAR_LOCK(sav); 471 cryptoid = sav->tdb_cryptoid; 472 SECASVAR_UNLOCK(sav); 473 474 /* Get crypto descriptors */ 475 crp = crypto_getreq(cryptoid, M_NOWAIT); 476 if (crp == NULL) { 477 IPCOMPSTAT_INC(ipcomps_crypto); 478 DPRINTF(("%s: failed to acquire crypto descriptor\n",__func__)); 479 error = ENOBUFS; 480 goto bad; 481 } 482 483 /* Compression descriptor */ 484 crp->crp_op = CRYPTO_OP_COMPRESS; 485 crp->crp_payload_start = skip; 486 crp->crp_payload_length = ralen; 487 488 /* IPsec-specific opaque crypto info */ 489 xd = malloc(sizeof(struct xform_data), M_XDATA, M_NOWAIT | M_ZERO); 490 if (xd == NULL) { 491 IPCOMPSTAT_INC(ipcomps_crypto); 492 DPRINTF(("%s: failed to allocate xform_data\n", __func__)); 493 crypto_freereq(crp); 494 error = ENOBUFS; 495 goto bad; 496 } 497 498 xd->sp = sp; 499 xd->sav = sav; 500 xd->idx = idx; 501 xd->skip = skip; 502 xd->protoff = protoff; 503 xd->vnet = curvnet; 504 xd->cryptoid = cryptoid; 505 506 /* Crypto operation descriptor */ 507 crp->crp_flags = CRYPTO_F_CBIFSYNC; 508 crypto_use_mbuf(crp, m); 509 crp->crp_callback = ipcomp_output_cb; 510 crp->crp_opaque = xd; 511 512 return crypto_dispatch(crp); 513 bad: 514 if (m) 515 m_freem(m); 516 key_freesav(&sav); 517 key_freesp(&sp); 518 return (error); 519 } 520 521 /* 522 * IPComp output callback from the crypto driver. 523 */ 524 static int 525 ipcomp_output_cb(struct cryptop *crp) 526 { 527 IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); 528 struct xform_data *xd; 529 struct secpolicy *sp; 530 struct secasvar *sav; 531 struct mbuf *m; 532 crypto_session_t cryptoid; 533 u_int idx; 534 int error, skip, protoff; 535 536 m = crp->crp_buf.cb_mbuf; 537 xd = crp->crp_opaque; 538 CURVNET_SET(xd->vnet); 539 idx = xd->idx; 540 sp = xd->sp; 541 sav = xd->sav; 542 skip = xd->skip; 543 protoff = xd->protoff; 544 cryptoid = xd->cryptoid; 545 546 /* Check for crypto errors */ 547 if (crp->crp_etype) { 548 if (crp->crp_etype == EAGAIN) { 549 /* Reset the session ID */ 550 if (ipsec_updateid(sav, &crp->crp_session, &cryptoid) != 0) 551 crypto_freesession(cryptoid); 552 xd->cryptoid = crp->crp_session; 553 CURVNET_RESTORE(); 554 return (crypto_dispatch(crp)); 555 } 556 IPCOMPSTAT_INC(ipcomps_noxform); 557 DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype)); 558 error = crp->crp_etype; 559 goto bad; 560 } 561 /* Shouldn't happen... */ 562 if (m == NULL) { 563 IPCOMPSTAT_INC(ipcomps_crypto); 564 DPRINTF(("%s: bogus return buffer from crypto\n", __func__)); 565 error = EINVAL; 566 goto bad; 567 } 568 IPCOMPSTAT_INC(ipcomps_hist[sav->alg_comp]); 569 570 if (crp->crp_payload_length > crp->crp_olen) { 571 struct mbuf *mo; 572 struct ipcomp *ipcomp; 573 int roff; 574 uint8_t prot; 575 576 /* Compression helped, inject IPCOMP header. */ 577 mo = m_makespace(m, skip, IPCOMP_HLENGTH, &roff); 578 if (mo == NULL) { 579 IPCOMPSTAT_INC(ipcomps_wrap); 580 DPRINTF(("%s: IPCOMP header inject failed " 581 "for IPCA %s/%08lx\n", 582 __func__, ipsec_address(&sav->sah->saidx.dst, buf, 583 sizeof(buf)), (u_long) ntohl(sav->spi))); 584 error = ENOBUFS; 585 goto bad; 586 } 587 ipcomp = (struct ipcomp *)(mtod(mo, caddr_t) + roff); 588 589 /* Initialize the IPCOMP header */ 590 /* XXX alignment always correct? */ 591 switch (sav->sah->saidx.dst.sa.sa_family) { 592 #ifdef INET 593 case AF_INET: 594 ipcomp->comp_nxt = mtod(m, struct ip *)->ip_p; 595 break; 596 #endif /* INET */ 597 #ifdef INET6 598 case AF_INET6: 599 ipcomp->comp_nxt = mtod(m, struct ip6_hdr *)->ip6_nxt; 600 break; 601 #endif 602 } 603 ipcomp->comp_flags = 0; 604 ipcomp->comp_cpi = htons((u_int16_t) ntohl(sav->spi)); 605 606 /* Fix Next Protocol in IPv4/IPv6 header */ 607 prot = IPPROTO_IPCOMP; 608 m_copyback(m, protoff, sizeof(u_int8_t), 609 (u_char *)&prot); 610 611 /* Adjust the length in the IP header */ 612 switch (sav->sah->saidx.dst.sa.sa_family) { 613 #ifdef INET 614 case AF_INET: 615 mtod(m, struct ip *)->ip_len = htons(m->m_pkthdr.len); 616 break; 617 #endif /* INET */ 618 #ifdef INET6 619 case AF_INET6: 620 mtod(m, struct ip6_hdr *)->ip6_plen = 621 htons(m->m_pkthdr.len) - sizeof(struct ip6_hdr); 622 break; 623 #endif /* INET6 */ 624 default: 625 IPCOMPSTAT_INC(ipcomps_nopf); 626 DPRINTF(("%s: unknown/unsupported protocol " 627 "family %d, IPCA %s/%08lx\n", __func__, 628 sav->sah->saidx.dst.sa.sa_family, 629 ipsec_address(&sav->sah->saidx.dst, buf, 630 sizeof(buf)), (u_long) ntohl(sav->spi))); 631 error = EPFNOSUPPORT; 632 goto bad; 633 } 634 } else { 635 /* Compression was useless, we have lost time. */ 636 IPCOMPSTAT_INC(ipcomps_uncompr); 637 DPRINTF(("%s: compressions was useless %d <= %d\n", 638 __func__, crp->crp_payload_length, crp->crp_olen)); 639 /* XXX remember state to not compress the next couple 640 * of packets, RFC 3173, 2.2. Non-Expansion Policy */ 641 } 642 643 /* Release the crypto descriptor */ 644 free(xd, M_XDATA); 645 crypto_freereq(crp); 646 647 /* NB: m is reclaimed by ipsec_process_done. */ 648 error = ipsec_process_done(m, sp, sav, idx); 649 CURVNET_RESTORE(); 650 return (error); 651 bad: 652 if (m) 653 m_freem(m); 654 CURVNET_RESTORE(); 655 free(xd, M_XDATA); 656 crypto_freereq(crp); 657 key_freesav(&sav); 658 key_freesp(&sp); 659 return (error); 660 } 661 662 #ifdef INET 663 static int 664 ipcomp4_nonexp_encapcheck(const struct mbuf *m, int off, int proto, 665 void *arg __unused) 666 { 667 union sockaddr_union src, dst; 668 const struct ip *ip; 669 670 if (V_ipcomp_enable == 0) 671 return (0); 672 if (proto != IPPROTO_IPV4 && proto != IPPROTO_IPV6) 673 return (0); 674 bzero(&src, sizeof(src)); 675 bzero(&dst, sizeof(dst)); 676 src.sa.sa_family = dst.sa.sa_family = AF_INET; 677 src.sin.sin_len = dst.sin.sin_len = sizeof(struct sockaddr_in); 678 ip = mtod(m, const struct ip *); 679 src.sin.sin_addr = ip->ip_src; 680 dst.sin.sin_addr = ip->ip_dst; 681 return (ipcomp_encapcheck(&src, &dst)); 682 } 683 684 static const struct encaptab *ipe4_cookie = NULL; 685 static const struct encap_config ipv4_encap_cfg = { 686 .proto = -1, 687 .min_length = sizeof(struct ip), 688 .exact_match = sizeof(in_addr_t) << 4, 689 .check = ipcomp4_nonexp_encapcheck, 690 .input = ipcomp_nonexp_input 691 }; 692 #endif 693 #ifdef INET6 694 static int 695 ipcomp6_nonexp_encapcheck(const struct mbuf *m, int off, int proto, 696 void *arg __unused) 697 { 698 union sockaddr_union src, dst; 699 const struct ip6_hdr *ip6; 700 701 if (V_ipcomp_enable == 0) 702 return (0); 703 if (proto != IPPROTO_IPV4 && proto != IPPROTO_IPV6) 704 return (0); 705 bzero(&src, sizeof(src)); 706 bzero(&dst, sizeof(dst)); 707 src.sa.sa_family = dst.sa.sa_family = AF_INET; 708 src.sin6.sin6_len = dst.sin6.sin6_len = sizeof(struct sockaddr_in6); 709 ip6 = mtod(m, const struct ip6_hdr *); 710 src.sin6.sin6_addr = ip6->ip6_src; 711 dst.sin6.sin6_addr = ip6->ip6_dst; 712 if (IN6_IS_SCOPE_LINKLOCAL(&src.sin6.sin6_addr)) { 713 /* XXX: sa6_recoverscope() */ 714 src.sin6.sin6_scope_id = 715 ntohs(src.sin6.sin6_addr.s6_addr16[1]); 716 src.sin6.sin6_addr.s6_addr16[1] = 0; 717 } 718 if (IN6_IS_SCOPE_LINKLOCAL(&dst.sin6.sin6_addr)) { 719 /* XXX: sa6_recoverscope() */ 720 dst.sin6.sin6_scope_id = 721 ntohs(dst.sin6.sin6_addr.s6_addr16[1]); 722 dst.sin6.sin6_addr.s6_addr16[1] = 0; 723 } 724 return (ipcomp_encapcheck(&src, &dst)); 725 } 726 727 static const struct encaptab *ipe6_cookie = NULL; 728 static const struct encap_config ipv6_encap_cfg = { 729 .proto = -1, 730 .min_length = sizeof(struct ip6_hdr), 731 .exact_match = sizeof(struct in6_addr) << 4, 732 .check = ipcomp6_nonexp_encapcheck, 733 .input = ipcomp_nonexp_input 734 }; 735 #endif 736 737 static struct xformsw ipcomp_xformsw = { 738 .xf_type = XF_IPCOMP, 739 .xf_name = "IPcomp", 740 .xf_init = ipcomp_init, 741 .xf_cleanup = ipcomp_cleanup, 742 .xf_input = ipcomp_input, 743 .xf_output = ipcomp_output, 744 }; 745 746 static void 747 ipcomp_attach(void) 748 { 749 750 #ifdef INET 751 ipe4_cookie = ip_encap_attach(&ipv4_encap_cfg, NULL, M_WAITOK); 752 #endif 753 #ifdef INET6 754 ipe6_cookie = ip6_encap_attach(&ipv6_encap_cfg, NULL, M_WAITOK); 755 #endif 756 xform_attach(&ipcomp_xformsw); 757 } 758 759 static void 760 ipcomp_detach(void) 761 { 762 763 #ifdef INET 764 ip_encap_detach(ipe4_cookie); 765 #endif 766 #ifdef INET6 767 ip6_encap_detach(ipe6_cookie); 768 #endif 769 xform_detach(&ipcomp_xformsw); 770 } 771 772 SYSINIT(ipcomp_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, 773 ipcomp_attach, NULL); 774 SYSUNINIT(ipcomp_xform_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, 775 ipcomp_detach, NULL); 776