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