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