ipsec_output.c revision 302408
1238104Sdes/*- 2238104Sdes * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting 3238104Sdes * All rights reserved. 4238104Sdes * 5238104Sdes * Redistribution and use in source and binary forms, with or without 6238104Sdes * modification, are permitted provided that the following conditions 7238104Sdes * are met: 8238104Sdes * 1. Redistributions of source code must retain the above copyright 9238104Sdes * notice, this list of conditions and the following disclaimer. 10238104Sdes * 2. Redistributions in binary form must reproduce the above copyright 11238104Sdes * notice, this list of conditions and the following disclaimer in the 12238104Sdes * documentation and/or other materials provided with the distribution. 13238104Sdes * 14238104Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15238104Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16238104Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17238104Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18238104Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19238104Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20238104Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21238104Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22238104Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23238104Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24238104Sdes * SUCH DAMAGE. 25238104Sdes * 26238104Sdes * $FreeBSD: stable/11/sys/netipsec/ipsec_output.c 298995 2016-05-03 18:05:43Z pfg $ 27238104Sdes */ 28238104Sdes 29238104Sdes/* 30238104Sdes * IPsec output processing. 31238104Sdes */ 32238104Sdes#include "opt_inet.h" 33238104Sdes#include "opt_inet6.h" 34238104Sdes#include "opt_ipsec.h" 35238104Sdes 36238104Sdes#include <sys/param.h> 37238104Sdes#include <sys/systm.h> 38238104Sdes#include <sys/mbuf.h> 39238104Sdes#include <sys/domain.h> 40238104Sdes#include <sys/protosw.h> 41238104Sdes#include <sys/socket.h> 42238104Sdes#include <sys/errno.h> 43238104Sdes#include <sys/hhook.h> 44238104Sdes#include <sys/syslog.h> 45238104Sdes 46238104Sdes#include <net/if.h> 47238104Sdes#include <net/if_enc.h> 48238104Sdes#include <net/if_var.h> 49238104Sdes#include <net/vnet.h> 50238104Sdes 51238104Sdes#include <netinet/in.h> 52238104Sdes#include <netinet/in_systm.h> 53238104Sdes#include <netinet/ip.h> 54238104Sdes#include <netinet/ip_var.h> 55238104Sdes#include <netinet/in_var.h> 56238104Sdes#include <netinet/ip_ecn.h> 57238104Sdes#ifdef INET6 58238104Sdes#include <netinet6/ip6_ecn.h> 59238104Sdes#endif 60238104Sdes 61238104Sdes#include <netinet/ip6.h> 62238104Sdes#ifdef INET6 63238104Sdes#include <netinet6/ip6_var.h> 64238104Sdes#include <netinet6/scope6_var.h> 65238104Sdes#endif 66238104Sdes#include <netinet/in_pcb.h> 67238104Sdes#ifdef INET6 68238104Sdes#include <netinet/icmp6.h> 69238104Sdes#endif 70238104Sdes 71238104Sdes#include <netipsec/ipsec.h> 72238104Sdes#ifdef INET6 73238104Sdes#include <netipsec/ipsec6.h> 74238104Sdes#endif 75238104Sdes#include <netipsec/ah_var.h> 76238104Sdes#include <netipsec/esp_var.h> 77238104Sdes#include <netipsec/ipcomp_var.h> 78238104Sdes 79238104Sdes#include <netipsec/xform.h> 80238104Sdes 81238104Sdes#include <netipsec/key.h> 82238104Sdes#include <netipsec/keydb.h> 83238104Sdes#include <netipsec/key_debug.h> 84238104Sdes 85238104Sdes#include <machine/in_cksum.h> 86238104Sdes 87238104Sdes#ifdef IPSEC_NAT_T 88238104Sdes#include <netinet/udp.h> 89238104Sdes#endif 90238104Sdes 91238104Sdesint 92238104Sdesipsec_process_done(struct mbuf *m, struct ipsecrequest *isr) 93238104Sdes{ 94238104Sdes struct tdb_ident *tdbi; 95238104Sdes struct m_tag *mtag; 96238104Sdes struct secasvar *sav; 97238104Sdes struct secasindex *saidx; 98238104Sdes int error; 99238104Sdes 100238104Sdes IPSEC_ASSERT(m != NULL, ("null mbuf")); 101238104Sdes IPSEC_ASSERT(isr != NULL, ("null ISR")); 102238104Sdes IPSEC_ASSERT(isr->sp != NULL, ("NULL isr->sp")); 103238104Sdes sav = isr->sav; 104238104Sdes IPSEC_ASSERT(sav != NULL, ("null SA")); 105238104Sdes IPSEC_ASSERT(sav->sah != NULL, ("null SAH")); 106238104Sdes 107238104Sdes saidx = &sav->sah->saidx; 108238104Sdes switch (saidx->dst.sa.sa_family) { 109238104Sdes#ifdef INET 110238104Sdes case AF_INET: 111238104Sdes /* Fix the header length, for AH processing. */ 112238104Sdes mtod(m, struct ip *)->ip_len = htons(m->m_pkthdr.len); 113238104Sdes break; 114238104Sdes#endif /* INET */ 115238104Sdes#ifdef INET6 116238104Sdes case AF_INET6: 117238104Sdes /* Fix the header length, for AH processing. */ 118238104Sdes if (m->m_pkthdr.len < sizeof (struct ip6_hdr)) { 119238104Sdes error = ENXIO; 120238104Sdes goto bad; 121238104Sdes } 122238104Sdes if (m->m_pkthdr.len - sizeof (struct ip6_hdr) > IPV6_MAXPACKET) { 123238104Sdes /* No jumbogram support. */ 124238104Sdes error = ENXIO; /*?*/ 125238104Sdes goto bad; 126238104Sdes } 127238104Sdes mtod(m, struct ip6_hdr *)->ip6_plen = 128238104Sdes htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); 129246854Sdes break; 130238104Sdes#endif /* INET6 */ 131238104Sdes default: 132238104Sdes DPRINTF(("%s: unknown protocol family %u\n", __func__, 133238104Sdes saidx->dst.sa.sa_family)); 134266114Sdes error = ENXIO; 135238104Sdes goto bad; 136238104Sdes } 137238104Sdes 138238104Sdes /* 139238104Sdes * Add a record of what we've done or what needs to be done to the 140238104Sdes * packet. 141238104Sdes */ 142238104Sdes mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE, 143238104Sdes sizeof(struct tdb_ident), M_NOWAIT); 144238104Sdes if (mtag == NULL) { 145238104Sdes DPRINTF(("%s: could not get packet tag\n", __func__)); 146238104Sdes error = ENOMEM; 147238104Sdes goto bad; 148238104Sdes } 149238104Sdes 150238104Sdes tdbi = (struct tdb_ident *)(mtag + 1); 151238104Sdes tdbi->dst = saidx->dst; 152238104Sdes tdbi->proto = saidx->proto; 153238104Sdes tdbi->spi = sav->spi; 154238104Sdes m_tag_prepend(m, mtag); 155238104Sdes 156238104Sdes key_sa_recordxfer(sav, m); /* record data transfer */ 157238104Sdes 158238104Sdes /* 159238104Sdes * If there's another (bundled) SA to apply, do so. 160238104Sdes * Note that this puts a burden on the kernel stack size. 161238104Sdes * If this is a problem we'll need to introduce a queue 162238104Sdes * to set the packet on so we can unwind the stack before 163238104Sdes * doing further processing. 164238104Sdes */ 165238104Sdes if (isr->next) { 166238104Sdes /* XXX-BZ currently only support same AF bundles. */ 167238104Sdes switch (saidx->dst.sa.sa_family) { 168238104Sdes#ifdef INET 169238104Sdes case AF_INET: 170238104Sdes IPSECSTAT_INC(ips_out_bundlesa); 171238104Sdes return (ipsec4_process_packet(m, isr->next)); 172238104Sdes /* NOTREACHED */ 173238104Sdes#endif 174238104Sdes#ifdef notyet 175238104Sdes#ifdef INET6 176238104Sdes case AF_INET6: 177238104Sdes /* XXX */ 178238104Sdes IPSEC6STAT_INC(ips_out_bundlesa); 179238104Sdes return (ipsec6_process_packet(m, isr->next)); 180238104Sdes /* NOTREACHED */ 181238104Sdes#endif /* INET6 */ 182238104Sdes#endif 183238104Sdes default: 184238104Sdes DPRINTF(("%s: unknown protocol family %u\n", __func__, 185238104Sdes saidx->dst.sa.sa_family)); 186238104Sdes error = ENXIO; 187238104Sdes goto bad; 188238104Sdes } 189238104Sdes } 190238104Sdes 191238104Sdes /* 192238104Sdes * We're done with IPsec processing, transmit the packet using the 193238104Sdes * appropriate network protocol (IP or IPv6). 194238104Sdes */ 195238104Sdes switch (saidx->dst.sa.sa_family) { 196238104Sdes#ifdef INET 197238104Sdes case AF_INET: 198238104Sdes#ifdef IPSEC_NAT_T 199238104Sdes /* 200238104Sdes * If NAT-T is enabled, now that all IPsec processing is done 201238104Sdes * insert UDP encapsulation header after IP header. 202238104Sdes */ 203238104Sdes if (sav->natt_type) { 204238104Sdes struct ip *ip = mtod(m, struct ip *); 205238104Sdes const int hlen = (ip->ip_hl << 2); 206238104Sdes int size, off; 207238104Sdes struct mbuf *mi; 208238104Sdes struct udphdr *udp; 209238104Sdes 210238104Sdes size = sizeof(struct udphdr); 211238104Sdes if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE) { 212238104Sdes /* 213238104Sdes * draft-ietf-ipsec-nat-t-ike-0[01].txt and 214238104Sdes * draft-ietf-ipsec-udp-encaps-(00/)01.txt, 215238104Sdes * ignoring possible AH mode 216238104Sdes * non-IKE marker + non-ESP marker 217238104Sdes * from draft-ietf-ipsec-udp-encaps-00.txt. 218238104Sdes */ 219238104Sdes size += sizeof(u_int64_t); 220238104Sdes } 221238104Sdes mi = m_makespace(m, hlen, size, &off); 222238104Sdes if (mi == NULL) { 223238104Sdes DPRINTF(("%s: m_makespace for udphdr failed\n", 224238104Sdes __func__)); 225238104Sdes error = ENOBUFS; 226238104Sdes goto bad; 227238104Sdes } 228238104Sdes 229238104Sdes udp = (struct udphdr *)(mtod(mi, caddr_t) + off); 230238104Sdes if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE) 231238104Sdes udp->uh_sport = htons(UDP_ENCAP_ESPINUDP_PORT); 232238104Sdes else 233238104Sdes udp->uh_sport = 234238104Sdes KEY_PORTFROMSADDR(&sav->sah->saidx.src); 235238104Sdes udp->uh_dport = KEY_PORTFROMSADDR(&sav->sah->saidx.dst); 236238104Sdes udp->uh_sum = 0; 237238104Sdes udp->uh_ulen = htons(m->m_pkthdr.len - hlen); 238238104Sdes ip->ip_len = htons(m->m_pkthdr.len); 239238104Sdes ip->ip_p = IPPROTO_UDP; 240238104Sdes 241238104Sdes if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE) 242238104Sdes *(u_int64_t *)(udp + 1) = 0; 243238104Sdes } 244238104Sdes#endif /* IPSEC_NAT_T */ 245238104Sdes 246238104Sdes return ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL); 247238104Sdes#endif /* INET */ 248238104Sdes#ifdef INET6 249238104Sdes case AF_INET6: 250238104Sdes /* 251238104Sdes * We don't need massage, IPv6 header fields are always in 252238104Sdes * net endian. 253238104Sdes */ 254238104Sdes return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL); 255238104Sdes#endif /* INET6 */ 256238104Sdes } 257238104Sdes panic("ipsec_process_done"); 258238104Sdesbad: 259238104Sdes m_freem(m); 260238104Sdes return (error); 261238104Sdes} 262238104Sdes 263238104Sdesstatic struct ipsecrequest * 264238104Sdesipsec_nextisr( 265238104Sdes struct mbuf *m, 266238104Sdes struct ipsecrequest *isr, 267238104Sdes int af, 268238104Sdes struct secasindex *saidx, 269238104Sdes int *error 270238104Sdes) 271238104Sdes{ 272238104Sdes#define IPSEC_OSTAT(name) do { \ 273238104Sdes if (isr->saidx.proto == IPPROTO_ESP) \ 274238104Sdes ESPSTAT_INC(esps_##name); \ 275238104Sdes else if (isr->saidx.proto == IPPROTO_AH)\ 276238104Sdes AHSTAT_INC(ahs_##name); \ 277238104Sdes else \ 278238104Sdes IPCOMPSTAT_INC(ipcomps_##name); \ 279238104Sdes} while (0) 280238104Sdes struct secasvar *sav; 281238104Sdes 282238104Sdes IPSECREQUEST_LOCK_ASSERT(isr); 283238104Sdes 284238104Sdes IPSEC_ASSERT(af == AF_INET || af == AF_INET6, 285238104Sdes ("invalid address family %u", af)); 286238104Sdesagain: 287238104Sdes /* 288238104Sdes * Craft SA index to search for proper SA. Note that 289238104Sdes * we only fillin unspecified SA peers for transport 290238104Sdes * mode; for tunnel mode they must already be filled in. 291238104Sdes */ 292238104Sdes *saidx = isr->saidx; 293238104Sdes if (isr->saidx.mode == IPSEC_MODE_TRANSPORT) { 294238104Sdes /* Fillin unspecified SA peers only for transport mode */ 295238104Sdes if (af == AF_INET) { 296238104Sdes struct sockaddr_in *sin; 297238104Sdes struct ip *ip = mtod(m, struct ip *); 298238104Sdes 299238104Sdes if (saidx->src.sa.sa_len == 0) { 300238104Sdes sin = &saidx->src.sin; 301238104Sdes sin->sin_len = sizeof(*sin); 302238104Sdes sin->sin_family = AF_INET; 303238104Sdes sin->sin_port = IPSEC_PORT_ANY; 304238104Sdes sin->sin_addr = ip->ip_src; 305238104Sdes } 306238104Sdes if (saidx->dst.sa.sa_len == 0) { 307266114Sdes sin = &saidx->dst.sin; 308266114Sdes sin->sin_len = sizeof(*sin); 309266114Sdes sin->sin_family = AF_INET; 310266114Sdes sin->sin_port = IPSEC_PORT_ANY; 311266114Sdes sin->sin_addr = ip->ip_dst; 312266114Sdes } 313238104Sdes } else { 314266114Sdes struct sockaddr_in6 *sin6; 315266114Sdes struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 316266114Sdes 317266114Sdes if (saidx->src.sin6.sin6_len == 0) { 318266114Sdes sin6 = (struct sockaddr_in6 *)&saidx->src; 319238104Sdes sin6->sin6_len = sizeof(*sin6); 320266114Sdes sin6->sin6_family = AF_INET6; 321238104Sdes sin6->sin6_port = IPSEC_PORT_ANY; 322238104Sdes sin6->sin6_addr = ip6->ip6_src; 323238104Sdes if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) { 324238104Sdes /* fix scope id for comparing SPD */ 325238104Sdes sin6->sin6_addr.s6_addr16[1] = 0; 326238104Sdes sin6->sin6_scope_id = 327238104Sdes ntohs(ip6->ip6_src.s6_addr16[1]); 328238104Sdes } 329238104Sdes } 330238104Sdes if (saidx->dst.sin6.sin6_len == 0) { 331238104Sdes sin6 = (struct sockaddr_in6 *)&saidx->dst; 332238104Sdes sin6->sin6_len = sizeof(*sin6); 333238104Sdes sin6->sin6_family = AF_INET6; 334238104Sdes sin6->sin6_port = IPSEC_PORT_ANY; 335238104Sdes sin6->sin6_addr = ip6->ip6_dst; 336238104Sdes if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) { 337238104Sdes /* fix scope id for comparing SPD */ 338238104Sdes sin6->sin6_addr.s6_addr16[1] = 0; 339238104Sdes sin6->sin6_scope_id = 340238104Sdes ntohs(ip6->ip6_dst.s6_addr16[1]); 341238104Sdes } 342238104Sdes } 343238104Sdes } 344266114Sdes } 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; 412bad: 413 IPSEC_ASSERT(*error != 0, ("error return w/ no error code")); 414 IPSECREQUEST_UNLOCK(isr); 415 return NULL; 416#undef IPSEC_OSTAT 417} 418 419static int 420ipsec_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 */ 525int 526ipsec4_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); 617bad: 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 628static int 629in6_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 */ 643int 644ipsec6_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; 727bad: 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