1 /*- 2 * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29 /* 30 * IPsec output processing. 31 */ 32 #include "opt_inet.h" 33 #include "opt_inet6.h" 34 #include "opt_ipsec.h" 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/mbuf.h> 39 #include <sys/domain.h> 40 #include <sys/protosw.h> 41 #include <sys/socket.h> 42 #include <sys/errno.h> 43 #include <sys/hhook.h> 44 #include <sys/syslog.h> 45 46 #include <net/if.h> 47 #include <net/if_enc.h> 48 #include <net/if_var.h> 49 #include <net/vnet.h> 50 51 #include <netinet/in.h> 52 #include <netinet/in_systm.h> 53 #include <netinet/ip.h> 54 #include <netinet/ip_var.h> 55 #include <netinet/in_var.h> 56 #include <netinet/ip_ecn.h> 57 #ifdef INET6 58 #include <netinet6/ip6_ecn.h> 59 #endif 60 61 #include <netinet/ip6.h> 62 #ifdef INET6 63 #include <netinet6/ip6_var.h> 64 #include <netinet6/scope6_var.h> 65 #endif 66 #include <netinet/in_pcb.h> 67 #ifdef INET6 68 #include <netinet/icmp6.h> 69 #endif 70 71 #include <netipsec/ipsec.h> 72 #ifdef INET6 73 #include <netipsec/ipsec6.h> 74 #endif 75 #include <netipsec/ah_var.h> 76 #include <netipsec/esp_var.h> 77 #include <netipsec/ipcomp_var.h> 78 79 #include <netipsec/xform.h> 80 81 #include <netipsec/key.h> 82 #include <netipsec/keydb.h> 83 #include <netipsec/key_debug.h> 84 85 #include <machine/in_cksum.h> 86 87 #ifdef IPSEC_NAT_T 88 #include <netinet/udp.h> 89 #endif 90 91 int 92 ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr) 93 { 94 struct tdb_ident *tdbi; 95 struct m_tag *mtag; 96 struct secasvar *sav; 97 struct secasindex *saidx; 98 int error; 99 100 IPSEC_ASSERT(m != NULL, ("null mbuf")); 101 IPSEC_ASSERT(isr != NULL, ("null ISR")); 102 IPSEC_ASSERT(isr->sp != NULL, ("NULL isr->sp")); 103 sav = isr->sav; 104 IPSEC_ASSERT(sav != NULL, ("null SA")); 105 IPSEC_ASSERT(sav->sah != NULL, ("null SAH")); 106 107 saidx = &sav->sah->saidx; 108 switch (saidx->dst.sa.sa_family) { 109 #ifdef INET 110 case AF_INET: 111 /* Fix the header length, for AH processing. */ 112 mtod(m, struct ip *)->ip_len = htons(m->m_pkthdr.len); 113 break; 114 #endif /* INET */ 115 #ifdef INET6 116 case AF_INET6: 117 /* Fix the header length, for AH processing. */ 118 if (m->m_pkthdr.len < sizeof (struct ip6_hdr)) { 119 error = ENXIO; 120 goto bad; 121 } 122 if (m->m_pkthdr.len - sizeof (struct ip6_hdr) > IPV6_MAXPACKET) { 123 /* No jumbogram support. */ 124 error = ENXIO; /*?*/ 125 goto bad; 126 } 127 mtod(m, struct ip6_hdr *)->ip6_plen = 128 htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); 129 break; 130 #endif /* INET6 */ 131 default: 132 DPRINTF(("%s: unknown protocol family %u\n", __func__, 133 saidx->dst.sa.sa_family)); 134 error = ENXIO; 135 goto bad; 136 } 137 138 /* 139 * Add a record of what we've done or what needs to be done to the 140 * packet. 141 */ 142 mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE, 143 sizeof(struct tdb_ident), M_NOWAIT); 144 if (mtag == NULL) { 145 DPRINTF(("%s: could not get packet tag\n", __func__)); 146 error = ENOMEM; 147 goto bad; 148 } 149 150 tdbi = (struct tdb_ident *)(mtag + 1); 151 tdbi->dst = saidx->dst; 152 tdbi->proto = saidx->proto; 153 tdbi->spi = sav->spi; 154 m_tag_prepend(m, mtag); 155 156 key_sa_recordxfer(sav, m); /* record data transfer */ 157 158 /* 159 * If there's another (bundled) SA to apply, do so. 160 * Note that this puts a burden on the kernel stack size. 161 * If this is a problem we'll need to introduce a queue 162 * to set the packet on so we can unwind the stack before 163 * doing further processing. 164 */ 165 if (isr->next) { 166 /* XXX-BZ currently only support same AF bundles. */ 167 switch (saidx->dst.sa.sa_family) { 168 #ifdef INET 169 case AF_INET: 170 IPSECSTAT_INC(ips_out_bundlesa); 171 return (ipsec4_process_packet(m, isr->next)); 172 /* NOTREACHED */ 173 #endif 174 #ifdef notyet 175 #ifdef INET6 176 case AF_INET6: 177 /* XXX */ 178 IPSEC6STAT_INC(ips_out_bundlesa); 179 return (ipsec6_process_packet(m, isr->next)); 180 /* NOTREACHED */ 181 #endif /* INET6 */ 182 #endif 183 default: 184 DPRINTF(("%s: unknown protocol family %u\n", __func__, 185 saidx->dst.sa.sa_family)); 186 error = ENXIO; 187 goto bad; 188 } 189 } 190 191 /* 192 * We're done with IPsec processing, transmit the packet using the 193 * appropriate network protocol (IP or IPv6). 194 */ 195 switch (saidx->dst.sa.sa_family) { 196 #ifdef INET 197 case AF_INET: 198 #ifdef IPSEC_NAT_T 199 /* 200 * If NAT-T is enabled, now that all IPsec processing is done 201 * insert UDP encapsulation header after IP header. 202 */ 203 if (sav->natt_type) { 204 struct ip *ip = mtod(m, struct ip *); 205 const int hlen = (ip->ip_hl << 2); 206 int size, off; 207 struct mbuf *mi; 208 struct udphdr *udp; 209 210 size = sizeof(struct udphdr); 211 if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE) { 212 /* 213 * draft-ietf-ipsec-nat-t-ike-0[01].txt and 214 * draft-ietf-ipsec-udp-encaps-(00/)01.txt, 215 * ignoring possible AH mode 216 * non-IKE marker + non-ESP marker 217 * from draft-ietf-ipsec-udp-encaps-00.txt. 218 */ 219 size += sizeof(u_int64_t); 220 } 221 mi = m_makespace(m, hlen, size, &off); 222 if (mi == NULL) { 223 DPRINTF(("%s: m_makespace for udphdr failed\n", 224 __func__)); 225 error = ENOBUFS; 226 goto bad; 227 } 228 229 udp = (struct udphdr *)(mtod(mi, caddr_t) + off); 230 if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE) 231 udp->uh_sport = htons(UDP_ENCAP_ESPINUDP_PORT); 232 else 233 udp->uh_sport = 234 KEY_PORTFROMSADDR(&sav->sah->saidx.src); 235 udp->uh_dport = KEY_PORTFROMSADDR(&sav->sah->saidx.dst); 236 udp->uh_sum = 0; 237 udp->uh_ulen = htons(m->m_pkthdr.len - hlen); 238 ip->ip_len = htons(m->m_pkthdr.len); 239 ip->ip_p = IPPROTO_UDP; 240 241 if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE) 242 *(u_int64_t *)(udp + 1) = 0; 243 } 244 #endif /* IPSEC_NAT_T */ 245 246 return ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL); 247 #endif /* INET */ 248 #ifdef INET6 249 case AF_INET6: 250 /* 251 * We don't need massage, IPv6 header fields are always in 252 * net endian. 253 */ 254 return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL); 255 #endif /* INET6 */ 256 } 257 panic("ipsec_process_done"); 258 bad: 259 m_freem(m); 260 return (error); 261 } 262 263 static struct ipsecrequest * 264 ipsec_nextisr( 265 struct mbuf *m, 266 struct ipsecrequest *isr, 267 int af, 268 struct secasindex *saidx, 269 int *error 270 ) 271 { 272 #define IPSEC_OSTAT(name) do { \ 273 if (isr->saidx.proto == IPPROTO_ESP) \ 274 ESPSTAT_INC(esps_##name); \ 275 else if (isr->saidx.proto == IPPROTO_AH)\ 276 AHSTAT_INC(ahs_##name); \ 277 else \ 278 IPCOMPSTAT_INC(ipcomps_##name); \ 279 } while (0) 280 struct secasvar *sav; 281 282 IPSECREQUEST_LOCK_ASSERT(isr); 283 284 IPSEC_ASSERT(af == AF_INET || af == AF_INET6, 285 ("invalid address family %u", af)); 286 again: 287 /* 288 * Craft SA index to search for proper SA. Note that 289 * we only fillin unspecified SA peers for transport 290 * mode; for tunnel mode they must already be filled in. 291 */ 292 *saidx = isr->saidx; 293 if (isr->saidx.mode == IPSEC_MODE_TRANSPORT) { 294 /* Fillin unspecified SA peers only for transport mode */ 295 if (af == AF_INET) { 296 struct sockaddr_in *sin; 297 struct ip *ip = mtod(m, struct ip *); 298 299 if (saidx->src.sa.sa_len == 0) { 300 sin = &saidx->src.sin; 301 sin->sin_len = sizeof(*sin); 302 sin->sin_family = AF_INET; 303 sin->sin_port = IPSEC_PORT_ANY; 304 sin->sin_addr = ip->ip_src; 305 } 306 if (saidx->dst.sa.sa_len == 0) { 307 sin = &saidx->dst.sin; 308 sin->sin_len = sizeof(*sin); 309 sin->sin_family = AF_INET; 310 sin->sin_port = IPSEC_PORT_ANY; 311 sin->sin_addr = ip->ip_dst; 312 } 313 } else { 314 struct sockaddr_in6 *sin6; 315 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 316 317 if (saidx->src.sin6.sin6_len == 0) { 318 sin6 = (struct sockaddr_in6 *)&saidx->src; 319 sin6->sin6_len = sizeof(*sin6); 320 sin6->sin6_family = AF_INET6; 321 sin6->sin6_port = IPSEC_PORT_ANY; 322 sin6->sin6_addr = ip6->ip6_src; 323 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) { 324 /* fix scope id for comparing SPD */ 325 sin6->sin6_addr.s6_addr16[1] = 0; 326 sin6->sin6_scope_id = 327 ntohs(ip6->ip6_src.s6_addr16[1]); 328 } 329 } 330 if (saidx->dst.sin6.sin6_len == 0) { 331 sin6 = (struct sockaddr_in6 *)&saidx->dst; 332 sin6->sin6_len = sizeof(*sin6); 333 sin6->sin6_family = AF_INET6; 334 sin6->sin6_port = IPSEC_PORT_ANY; 335 sin6->sin6_addr = ip6->ip6_dst; 336 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) { 337 /* fix scope id for comparing SPD */ 338 sin6->sin6_addr.s6_addr16[1] = 0; 339 sin6->sin6_scope_id = 340 ntohs(ip6->ip6_dst.s6_addr16[1]); 341 } 342 } 343 } 344 } 345 346 /* 347 * Lookup SA and validate it. 348 */ 349 *error = key_checkrequest(isr, saidx); 350 if (*error != 0) { 351 /* 352 * IPsec processing is required, but no SA found. 353 * I assume that key_acquire() had been called 354 * to get/establish the SA. Here I discard 355 * this packet because it is responsibility for 356 * upper layer to retransmit the packet. 357 */ 358 switch(af) { 359 case AF_INET: 360 IPSECSTAT_INC(ips_out_nosa); 361 break; 362 #ifdef INET6 363 case AF_INET6: 364 IPSEC6STAT_INC(ips_out_nosa); 365 break; 366 #endif 367 } 368 goto bad; 369 } 370 sav = isr->sav; 371 if (sav == NULL) { 372 IPSEC_ASSERT(ipsec_get_reqlevel(isr) == IPSEC_LEVEL_USE, 373 ("no SA found, but required; level %u", 374 ipsec_get_reqlevel(isr))); 375 IPSECREQUEST_UNLOCK(isr); 376 isr = isr->next; 377 /* 378 * If isr is NULL, we found a 'use' policy w/o SA. 379 * Return w/o error and w/o isr so we can drop out 380 * and continue w/o IPsec processing. 381 */ 382 if (isr == NULL) 383 return isr; 384 IPSECREQUEST_LOCK(isr); 385 goto again; 386 } 387 388 /* 389 * Check system global policy controls. 390 */ 391 if ((isr->saidx.proto == IPPROTO_ESP && !V_esp_enable) || 392 (isr->saidx.proto == IPPROTO_AH && !V_ah_enable) || 393 (isr->saidx.proto == IPPROTO_IPCOMP && !V_ipcomp_enable)) { 394 DPRINTF(("%s: IPsec outbound packet dropped due" 395 " to policy (check your sysctls)\n", __func__)); 396 IPSEC_OSTAT(pdrops); 397 *error = EHOSTUNREACH; 398 goto bad; 399 } 400 401 /* 402 * Sanity check the SA contents for the caller 403 * before they invoke the xform output method. 404 */ 405 if (sav->tdb_xform == NULL) { 406 DPRINTF(("%s: no transform for SA\n", __func__)); 407 IPSEC_OSTAT(noxform); 408 *error = EHOSTUNREACH; 409 goto bad; 410 } 411 return isr; 412 bad: 413 IPSEC_ASSERT(*error != 0, ("error return w/ no error code")); 414 IPSECREQUEST_UNLOCK(isr); 415 return NULL; 416 #undef IPSEC_OSTAT 417 } 418 419 static int 420 ipsec_encap(struct mbuf **mp, struct secasindex *saidx) 421 { 422 #ifdef INET6 423 struct ip6_hdr *ip6; 424 #endif 425 struct ip *ip; 426 int setdf; 427 uint8_t itos, proto; 428 429 ip = mtod(*mp, struct ip *); 430 switch (ip->ip_v) { 431 #ifdef INET 432 case IPVERSION: 433 proto = IPPROTO_IPIP; 434 /* 435 * Collect IP_DF state from the inner header 436 * and honor system-wide control of how to handle it. 437 */ 438 switch (V_ip4_ipsec_dfbit) { 439 case 0: /* clear in outer header */ 440 case 1: /* set in outer header */ 441 setdf = V_ip4_ipsec_dfbit; 442 break; 443 default:/* propagate to outer header */ 444 setdf = (ip->ip_off & htons(IP_DF)) != 0; 445 } 446 itos = ip->ip_tos; 447 break; 448 #endif 449 #ifdef INET6 450 case (IPV6_VERSION >> 4): 451 proto = IPPROTO_IPV6; 452 ip6 = mtod(*mp, struct ip6_hdr *); 453 itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; 454 setdf = V_ip4_ipsec_dfbit ? 1: 0; 455 /* scoped address handling */ 456 in6_clearscope(&ip6->ip6_src); 457 in6_clearscope(&ip6->ip6_dst); 458 break; 459 #endif 460 default: 461 return (EAFNOSUPPORT); 462 } 463 switch (saidx->dst.sa.sa_family) { 464 #ifdef INET 465 case AF_INET: 466 if (saidx->src.sa.sa_family != AF_INET || 467 saidx->src.sin.sin_addr.s_addr == INADDR_ANY || 468 saidx->dst.sin.sin_addr.s_addr == INADDR_ANY) 469 return (EINVAL); 470 M_PREPEND(*mp, sizeof(struct ip), M_NOWAIT); 471 if (*mp == NULL) 472 return (ENOBUFS); 473 ip = mtod(*mp, struct ip *); 474 ip->ip_v = IPVERSION; 475 ip->ip_hl = sizeof(struct ip) >> 2; 476 ip->ip_p = proto; 477 ip->ip_len = htons((*mp)->m_pkthdr.len); 478 ip->ip_ttl = V_ip_defttl; 479 ip->ip_sum = 0; 480 ip->ip_off = setdf ? htons(IP_DF): 0; 481 ip->ip_src = saidx->src.sin.sin_addr; 482 ip->ip_dst = saidx->dst.sin.sin_addr; 483 ip_ecn_ingress(V_ip4_ipsec_ecn, &ip->ip_tos, &itos); 484 ip_fillid(ip); 485 break; 486 #endif /* INET */ 487 #ifdef INET6 488 case AF_INET6: 489 if (saidx->src.sa.sa_family != AF_INET6 || 490 IN6_IS_ADDR_UNSPECIFIED(&saidx->src.sin6.sin6_addr) || 491 IN6_IS_ADDR_UNSPECIFIED(&saidx->dst.sin6.sin6_addr)) 492 return (EINVAL); 493 M_PREPEND(*mp, sizeof(struct ip6_hdr), M_NOWAIT); 494 if (*mp == NULL) 495 return (ENOBUFS); 496 ip6 = mtod(*mp, struct ip6_hdr *); 497 ip6->ip6_flow = 0; 498 ip6->ip6_vfc = IPV6_VERSION; 499 ip6->ip6_hlim = V_ip6_defhlim; 500 ip6->ip6_nxt = proto; 501 ip6->ip6_dst = saidx->dst.sin6.sin6_addr; 502 /* For link-local address embed scope zone id */ 503 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) 504 ip6->ip6_dst.s6_addr16[1] = 505 htons(saidx->dst.sin6.sin6_scope_id & 0xffff); 506 ip6->ip6_src = saidx->src.sin6.sin6_addr; 507 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) 508 ip6->ip6_src.s6_addr16[1] = 509 htons(saidx->src.sin6.sin6_scope_id & 0xffff); 510 ip6->ip6_plen = htons((*mp)->m_pkthdr.len - sizeof(*ip6)); 511 ip_ecn_ingress(V_ip6_ipsec_ecn, &proto, &itos); 512 ip6->ip6_flow |= htonl((uint32_t)proto << 20); 513 break; 514 #endif /* INET6 */ 515 default: 516 return (EAFNOSUPPORT); 517 } 518 return (0); 519 } 520 521 #ifdef INET 522 /* 523 * IPsec output logic for IPv4. 524 */ 525 int 526 ipsec4_process_packet(struct mbuf *m, struct ipsecrequest *isr) 527 { 528 char sbuf[INET6_ADDRSTRLEN], dbuf[INET6_ADDRSTRLEN]; 529 struct ipsec_ctx_data ctx; 530 union sockaddr_union *dst; 531 struct secasindex saidx; 532 struct secasvar *sav; 533 struct ip *ip; 534 int error, i, off; 535 536 IPSEC_ASSERT(m != NULL, ("null mbuf")); 537 IPSEC_ASSERT(isr != NULL, ("null isr")); 538 539 IPSECREQUEST_LOCK(isr); /* insure SA contents don't change */ 540 541 isr = ipsec_nextisr(m, isr, AF_INET, &saidx, &error); 542 if (isr == NULL) { 543 if (error != 0) 544 goto bad; 545 return EJUSTRETURN; 546 } 547 548 sav = isr->sav; 549 if (m->m_len < sizeof(struct ip) && 550 (m = m_pullup(m, sizeof (struct ip))) == NULL) { 551 error = ENOBUFS; 552 goto bad; 553 } 554 555 IPSEC_INIT_CTX(&ctx, &m, sav, AF_INET, IPSEC_ENC_BEFORE); 556 if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0) 557 goto bad; 558 559 ip = mtod(m, struct ip *); 560 dst = &sav->sah->saidx.dst; 561 /* Do the appropriate encapsulation, if necessary */ 562 if (isr->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */ 563 dst->sa.sa_family != AF_INET || /* PF mismatch */ 564 (dst->sa.sa_family == AF_INET && /* Proxy */ 565 dst->sin.sin_addr.s_addr != INADDR_ANY && 566 dst->sin.sin_addr.s_addr != ip->ip_dst.s_addr)) { 567 /* Fix IPv4 header checksum and length */ 568 ip->ip_len = htons(m->m_pkthdr.len); 569 ip->ip_sum = 0; 570 ip->ip_sum = in_cksum(m, ip->ip_hl << 2); 571 error = ipsec_encap(&m, &sav->sah->saidx); 572 if (error != 0) { 573 DPRINTF(("%s: encapsulation for SA %s->%s " 574 "SPI 0x%08x failed with error %d\n", __func__, 575 ipsec_address(&sav->sah->saidx.src, sbuf, 576 sizeof(sbuf)), 577 ipsec_address(&sav->sah->saidx.dst, dbuf, 578 sizeof(dbuf)), ntohl(sav->spi), error)); 579 goto bad; 580 } 581 } 582 583 IPSEC_INIT_CTX(&ctx, &m, sav, dst->sa.sa_family, IPSEC_ENC_AFTER); 584 if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0) 585 goto bad; 586 587 /* 588 * Dispatch to the appropriate IPsec transform logic. The 589 * packet will be returned for transmission after crypto 590 * processing, etc. are completed. 591 * 592 * NB: m & sav are ``passed to caller'' who's responsible for 593 * for reclaiming their resources. 594 */ 595 switch(dst->sa.sa_family) { 596 case AF_INET: 597 ip = mtod(m, struct ip *); 598 i = ip->ip_hl << 2; 599 off = offsetof(struct ip, ip_p); 600 break; 601 #ifdef INET6 602 case AF_INET6: 603 i = sizeof(struct ip6_hdr); 604 off = offsetof(struct ip6_hdr, ip6_nxt); 605 break; 606 #endif /* INET6 */ 607 default: 608 DPRINTF(("%s: unsupported protocol family %u\n", 609 __func__, dst->sa.sa_family)); 610 error = EPFNOSUPPORT; 611 IPSECSTAT_INC(ips_out_inval); 612 goto bad; 613 } 614 error = (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off); 615 IPSECREQUEST_UNLOCK(isr); 616 return (error); 617 bad: 618 if (isr) 619 IPSECREQUEST_UNLOCK(isr); 620 if (m) 621 m_freem(m); 622 return error; 623 } 624 #endif 625 626 627 #ifdef INET6 628 static int 629 in6_sa_equal_addrwithscope(const struct sockaddr_in6 *sa, const struct in6_addr *ia) 630 { 631 struct in6_addr ia2; 632 633 memcpy(&ia2, &sa->sin6_addr, sizeof(ia2)); 634 if (IN6_IS_SCOPE_LINKLOCAL(&sa->sin6_addr)) 635 ia2.s6_addr16[1] = htons(sa->sin6_scope_id); 636 637 return IN6_ARE_ADDR_EQUAL(ia, &ia2); 638 } 639 640 /* 641 * IPsec output logic for IPv6. 642 */ 643 int 644 ipsec6_process_packet(struct mbuf *m, struct ipsecrequest *isr) 645 { 646 char sbuf[INET6_ADDRSTRLEN], dbuf[INET6_ADDRSTRLEN]; 647 struct ipsec_ctx_data ctx; 648 struct secasindex saidx; 649 struct secasvar *sav; 650 struct ip6_hdr *ip6; 651 int error, i, off; 652 union sockaddr_union *dst; 653 654 IPSEC_ASSERT(m != NULL, ("ipsec6_process_packet: null mbuf")); 655 IPSEC_ASSERT(isr != NULL, ("ipsec6_process_packet: null isr")); 656 657 IPSECREQUEST_LOCK(isr); /* insure SA contents don't change */ 658 659 isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error); 660 if (isr == NULL) { 661 if (error != 0) 662 goto bad; 663 return EJUSTRETURN; 664 } 665 sav = isr->sav; 666 dst = &sav->sah->saidx.dst; 667 668 IPSEC_INIT_CTX(&ctx, &m, sav, AF_INET6, IPSEC_ENC_BEFORE); 669 if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0) 670 goto bad; 671 672 ip6 = mtod(m, struct ip6_hdr *); 673 ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6)); 674 675 /* Do the appropriate encapsulation, if necessary */ 676 if (isr->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */ 677 dst->sa.sa_family != AF_INET6 || /* PF mismatch */ 678 ((dst->sa.sa_family == AF_INET6) && 679 (!IN6_IS_ADDR_UNSPECIFIED(&dst->sin6.sin6_addr)) && 680 (!in6_sa_equal_addrwithscope(&dst->sin6, 681 &ip6->ip6_dst)))) { 682 if (m->m_pkthdr.len - sizeof(*ip6) > IPV6_MAXPACKET) { 683 /* No jumbogram support. */ 684 error = ENXIO; /*XXX*/ 685 goto bad; 686 } 687 error = ipsec_encap(&m, &sav->sah->saidx); 688 if (error != 0) { 689 DPRINTF(("%s: encapsulation for SA %s->%s " 690 "SPI 0x%08x failed with error %d\n", __func__, 691 ipsec_address(&sav->sah->saidx.src, sbuf, 692 sizeof(sbuf)), 693 ipsec_address(&sav->sah->saidx.dst, dbuf, 694 sizeof(dbuf)), ntohl(sav->spi), error)); 695 goto bad; 696 } 697 } 698 699 IPSEC_INIT_CTX(&ctx, &m, sav, dst->sa.sa_family, IPSEC_ENC_AFTER); 700 if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0) 701 goto bad; 702 703 switch(dst->sa.sa_family) { 704 #ifdef INET 705 case AF_INET: 706 { 707 struct ip *ip; 708 ip = mtod(m, struct ip *); 709 i = ip->ip_hl << 2; 710 off = offsetof(struct ip, ip_p); 711 } 712 break; 713 #endif /* AF_INET */ 714 case AF_INET6: 715 i = sizeof(struct ip6_hdr); 716 off = offsetof(struct ip6_hdr, ip6_nxt); 717 break; 718 default: 719 DPRINTF(("%s: unsupported protocol family %u\n", 720 __func__, dst->sa.sa_family)); 721 error = EPFNOSUPPORT; 722 goto bad; 723 } 724 error = (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off); 725 IPSECREQUEST_UNLOCK(isr); 726 return error; 727 bad: 728 IPSEC6STAT_INC(ips_out_inval); 729 if (isr) 730 IPSECREQUEST_UNLOCK(isr); 731 if (m) 732 m_freem(m); 733 return error; 734 } 735 #endif /*INET6*/ 736