1112758Ssam/*- 2112758Ssam * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting 3315514Sae * Copyright (c) 2016 Andrey V. Elsukov <ae@FreeBSD.org> 4112758Ssam * All rights reserved. 5112758Ssam * 6112758Ssam * Redistribution and use in source and binary forms, with or without 7112758Ssam * modification, are permitted provided that the following conditions 8112758Ssam * are met: 9112758Ssam * 1. Redistributions of source code must retain the above copyright 10112758Ssam * notice, this list of conditions and the following disclaimer. 11112758Ssam * 2. Redistributions in binary form must reproduce the above copyright 12112758Ssam * notice, this list of conditions and the following disclaimer in the 13112758Ssam * documentation and/or other materials provided with the distribution. 14112758Ssam * 15112758Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16112758Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17112758Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18112758Ssam * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19112758Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20112758Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21112758Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22112758Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23112758Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24112758Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25112758Ssam * SUCH DAMAGE. 26112758Ssam * 27112758Ssam * $FreeBSD: stable/11/sys/netipsec/ipsec_output.c 322966 2017-08-28 10:02:47Z ae $ 28112758Ssam */ 29105197Ssam 30105197Ssam/* 31105197Ssam * IPsec output processing. 32105197Ssam */ 33105197Ssam#include "opt_inet.h" 34105197Ssam#include "opt_inet6.h" 35105197Ssam#include "opt_ipsec.h" 36315514Sae#include "opt_sctp.h" 37105197Ssam 38105197Ssam#include <sys/param.h> 39105197Ssam#include <sys/systm.h> 40105197Ssam#include <sys/mbuf.h> 41105197Ssam#include <sys/domain.h> 42105197Ssam#include <sys/protosw.h> 43105197Ssam#include <sys/socket.h> 44105197Ssam#include <sys/errno.h> 45291292Sae#include <sys/hhook.h> 46105197Ssam#include <sys/syslog.h> 47105197Ssam 48105197Ssam#include <net/if.h> 49291292Sae#include <net/if_enc.h> 50257176Sglebius#include <net/if_var.h> 51195699Srwatson#include <net/vnet.h> 52105197Ssam 53105197Ssam#include <netinet/in.h> 54105197Ssam#include <netinet/in_systm.h> 55105197Ssam#include <netinet/ip.h> 56105197Ssam#include <netinet/ip_var.h> 57105197Ssam#include <netinet/in_var.h> 58105197Ssam#include <netinet/ip_ecn.h> 59105197Ssam#ifdef INET6 60105197Ssam#include <netinet6/ip6_ecn.h> 61105197Ssam#endif 62105197Ssam 63105197Ssam#include <netinet/ip6.h> 64105197Ssam#ifdef INET6 65105197Ssam#include <netinet6/ip6_var.h> 66281692Sae#include <netinet6/scope6_var.h> 67105197Ssam#endif 68105197Ssam#include <netinet/in_pcb.h> 69105197Ssam#ifdef INET6 70105197Ssam#include <netinet/icmp6.h> 71105197Ssam#endif 72315514Sae#ifdef SCTP 73315514Sae#include <netinet/sctp_crc32.h> 74315514Sae#endif 75105197Ssam 76315514Sae#include <netinet/udp.h> 77315514Sae#include <netipsec/ah.h> 78315514Sae#include <netipsec/esp.h> 79105197Ssam#include <netipsec/ipsec.h> 80105197Ssam#ifdef INET6 81105197Ssam#include <netipsec/ipsec6.h> 82105197Ssam#endif 83105197Ssam#include <netipsec/ah_var.h> 84105197Ssam#include <netipsec/esp_var.h> 85105197Ssam#include <netipsec/ipcomp_var.h> 86105197Ssam 87105197Ssam#include <netipsec/xform.h> 88105197Ssam 89105197Ssam#include <netipsec/key.h> 90105197Ssam#include <netipsec/keydb.h> 91105197Ssam#include <netipsec/key_debug.h> 92105197Ssam 93105197Ssam#include <machine/in_cksum.h> 94105197Ssam 95315514Sae#define IPSEC_OSTAT_INC(proto, name) do { \ 96315514Sae if ((proto) == IPPROTO_ESP) \ 97315514Sae ESPSTAT_INC(esps_##name); \ 98315514Sae else if ((proto) == IPPROTO_AH)\ 99315514Sae AHSTAT_INC(ahs_##name); \ 100315514Sae else \ 101315514Sae IPCOMPSTAT_INC(ipcomps_##name); \ 102315514Sae} while (0) 103315514Sae 104315514Saestatic int ipsec_encap(struct mbuf **mp, struct secasindex *saidx); 105315514Sae 106315514Sae#ifdef INET 107315514Saestatic struct secasvar * 108315514Saeipsec4_allocsa(struct mbuf *m, struct secpolicy *sp, u_int *pidx, int *error) 109315514Sae{ 110315514Sae struct secasindex *saidx, tmpsaidx; 111315514Sae struct ipsecrequest *isr; 112315514Sae struct sockaddr_in *sin; 113315514Sae struct secasvar *sav; 114315514Sae struct ip *ip; 115315514Sae 116315514Sae /* 117315514Sae * Check system global policy controls. 118315514Sae */ 119315514Saenext: 120315514Sae isr = sp->req[*pidx]; 121315514Sae if ((isr->saidx.proto == IPPROTO_ESP && !V_esp_enable) || 122315514Sae (isr->saidx.proto == IPPROTO_AH && !V_ah_enable) || 123315514Sae (isr->saidx.proto == IPPROTO_IPCOMP && !V_ipcomp_enable)) { 124315514Sae DPRINTF(("%s: IPsec outbound packet dropped due" 125315514Sae " to policy (check your sysctls)\n", __func__)); 126315514Sae IPSEC_OSTAT_INC(isr->saidx.proto, pdrops); 127315514Sae *error = EHOSTUNREACH; 128315514Sae return (NULL); 129315514Sae } 130315514Sae /* 131315514Sae * Craft SA index to search for proper SA. Note that 132315514Sae * we only initialize unspecified SA peers for transport 133315514Sae * mode; for tunnel mode they must already be filled in. 134315514Sae */ 135315514Sae if (isr->saidx.mode == IPSEC_MODE_TRANSPORT) { 136315514Sae saidx = &tmpsaidx; 137315514Sae *saidx = isr->saidx; 138315514Sae ip = mtod(m, struct ip *); 139315514Sae if (saidx->src.sa.sa_len == 0) { 140315514Sae sin = &saidx->src.sin; 141315514Sae sin->sin_len = sizeof(*sin); 142315514Sae sin->sin_family = AF_INET; 143315514Sae sin->sin_port = IPSEC_PORT_ANY; 144315514Sae sin->sin_addr = ip->ip_src; 145315514Sae } 146315514Sae if (saidx->dst.sa.sa_len == 0) { 147315514Sae sin = &saidx->dst.sin; 148315514Sae sin->sin_len = sizeof(*sin); 149315514Sae sin->sin_family = AF_INET; 150315514Sae sin->sin_port = IPSEC_PORT_ANY; 151315514Sae sin->sin_addr = ip->ip_dst; 152315514Sae } 153315514Sae } else 154315514Sae saidx = &sp->req[*pidx]->saidx; 155315514Sae /* 156315514Sae * Lookup SA and validate it. 157315514Sae */ 158315514Sae sav = key_allocsa_policy(sp, saidx, error); 159315514Sae if (sav == NULL) { 160315514Sae IPSECSTAT_INC(ips_out_nosa); 161315514Sae if (*error != 0) 162315514Sae return (NULL); 163315514Sae if (ipsec_get_reqlevel(sp, *pidx) != IPSEC_LEVEL_REQUIRE) { 164315514Sae /* 165315514Sae * We have no SA and policy that doesn't require 166315514Sae * this IPsec transform, thus we can continue w/o 167315514Sae * IPsec processing, i.e. return EJUSTRETURN. 168315514Sae * But first check if there is some bundled transform. 169315514Sae */ 170315514Sae if (sp->tcount > ++(*pidx)) 171315514Sae goto next; 172315514Sae *error = EJUSTRETURN; 173315514Sae } 174315514Sae return (NULL); 175315514Sae } 176315514Sae IPSEC_ASSERT(sav->tdb_xform != NULL, ("SA with NULL tdb_xform")); 177315514Sae return (sav); 178315514Sae} 179315514Sae 180315514Sae/* 181315514Sae * IPsec output logic for IPv4. 182315514Sae */ 183315514Saestatic int 184322741Saeipsec4_perform_request(struct mbuf *m, struct secpolicy *sp, 185322741Sae struct inpcb *inp, u_int idx) 186315514Sae{ 187315514Sae struct ipsec_ctx_data ctx; 188315514Sae union sockaddr_union *dst; 189315514Sae struct secasvar *sav; 190315514Sae struct ip *ip; 191315514Sae int error, i, off; 192315514Sae 193315514Sae IPSEC_ASSERT(idx < sp->tcount, ("Wrong IPsec request index %d", idx)); 194315514Sae 195315514Sae /* 196315514Sae * We hold the reference to SP. Content of SP couldn't be changed. 197315514Sae * Craft secasindex and do lookup for suitable SA. 198315514Sae * Then do encapsulation if needed and call xform's output. 199315514Sae * We need to store SP in the xform callback parameters. 200315514Sae * In xform callback we will extract SP and it can be used to 201315514Sae * determine next transform. At the end of transform we can 202315514Sae * release reference to SP. 203315514Sae */ 204315514Sae sav = ipsec4_allocsa(m, sp, &idx, &error); 205315514Sae if (sav == NULL) { 206315514Sae if (error == EJUSTRETURN) { /* No IPsec required */ 207315514Sae key_freesp(&sp); 208315514Sae return (error); 209315514Sae } 210315514Sae goto bad; 211315514Sae } 212315514Sae /* 213315514Sae * XXXAE: most likely ip_sum at this point is wrong. 214315514Sae */ 215322741Sae IPSEC_INIT_CTX(&ctx, &m, inp, sav, AF_INET, IPSEC_ENC_BEFORE); 216315514Sae if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0) 217315514Sae goto bad; 218315514Sae 219315514Sae ip = mtod(m, struct ip *); 220315514Sae dst = &sav->sah->saidx.dst; 221315514Sae /* Do the appropriate encapsulation, if necessary */ 222315514Sae if (sp->req[idx]->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */ 223315514Sae dst->sa.sa_family != AF_INET || /* PF mismatch */ 224315514Sae (dst->sa.sa_family == AF_INET && /* Proxy */ 225315514Sae dst->sin.sin_addr.s_addr != INADDR_ANY && 226315514Sae dst->sin.sin_addr.s_addr != ip->ip_dst.s_addr)) { 227315514Sae /* Fix IPv4 header checksum and length */ 228315514Sae ip->ip_len = htons(m->m_pkthdr.len); 229315514Sae ip->ip_sum = 0; 230315514Sae ip->ip_sum = in_cksum(m, ip->ip_hl << 2); 231315514Sae error = ipsec_encap(&m, &sav->sah->saidx); 232315514Sae if (error != 0) { 233319599Sae DPRINTF(("%s: encapsulation for SPI 0x%08x failed " 234319599Sae "with error %d\n", __func__, ntohl(sav->spi), 235319599Sae error)); 236315514Sae /* XXXAE: IPSEC_OSTAT_INC(tunnel); */ 237315514Sae goto bad; 238315514Sae } 239322741Sae inp = NULL; 240315514Sae } 241315514Sae 242322741Sae IPSEC_INIT_CTX(&ctx, &m, inp, sav, dst->sa.sa_family, IPSEC_ENC_AFTER); 243315514Sae if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0) 244315514Sae goto bad; 245315514Sae 246315514Sae /* 247315514Sae * Dispatch to the appropriate IPsec transform logic. The 248315514Sae * packet will be returned for transmission after crypto 249315514Sae * processing, etc. are completed. 250315514Sae * 251315514Sae * NB: m & sav are ``passed to caller'' who's responsible for 252315514Sae * reclaiming their resources. 253315514Sae */ 254315514Sae switch(dst->sa.sa_family) { 255315514Sae case AF_INET: 256315514Sae ip = mtod(m, struct ip *); 257315514Sae i = ip->ip_hl << 2; 258315514Sae off = offsetof(struct ip, ip_p); 259315514Sae break; 260315514Sae#ifdef INET6 261315514Sae case AF_INET6: 262315514Sae i = sizeof(struct ip6_hdr); 263315514Sae off = offsetof(struct ip6_hdr, ip6_nxt); 264315514Sae break; 265315514Sae#endif /* INET6 */ 266315514Sae default: 267315514Sae DPRINTF(("%s: unsupported protocol family %u\n", 268315514Sae __func__, dst->sa.sa_family)); 269315514Sae error = EPFNOSUPPORT; 270315514Sae IPSEC_OSTAT_INC(sav->sah->saidx.proto, nopf); 271315514Sae goto bad; 272315514Sae } 273315514Sae error = (*sav->tdb_xform->xf_output)(m, sp, sav, idx, i, off); 274315514Sae return (error); 275315514Saebad: 276315514Sae IPSECSTAT_INC(ips_out_inval); 277315514Sae if (m != NULL) 278315514Sae m_freem(m); 279315514Sae if (sav != NULL) 280315514Sae key_freesav(&sav); 281315514Sae key_freesp(&sp); 282315514Sae return (error); 283315514Sae} 284315514Sae 285315514Saeint 286315514Saeipsec4_process_packet(struct mbuf *m, struct secpolicy *sp, 287315514Sae struct inpcb *inp) 288315514Sae{ 289315514Sae 290322741Sae return (ipsec4_perform_request(m, sp, inp, 0)); 291315514Sae} 292315514Sae 293315514Saestatic int 294315514Saeipsec4_common_output(struct mbuf *m, struct inpcb *inp, int forwarding) 295315514Sae{ 296315514Sae struct secpolicy *sp; 297315514Sae int error; 298315514Sae 299315514Sae /* Lookup for the corresponding outbound security policy */ 300322966Sae sp = ipsec4_checkpolicy(m, inp, &error, !forwarding); 301315514Sae if (sp == NULL) { 302315514Sae if (error == -EINVAL) { 303315514Sae /* Discarded by policy. */ 304315514Sae m_freem(m); 305315514Sae return (EACCES); 306315514Sae } 307315514Sae return (0); /* No IPsec required. */ 308315514Sae } 309315514Sae 310315514Sae /* 311315514Sae * Usually we have to have tunnel mode IPsec security policy 312315514Sae * when we are forwarding a packet. Otherwise we could not handle 313315514Sae * encrypted replies, because they are not destined for us. But 314315514Sae * some users are doing source address translation for forwarded 315315514Sae * packets, and thus, even if they are forwarded, the replies will 316315514Sae * return back to us. 317315514Sae */ 318315514Sae if (!forwarding) { 319315514Sae /* 320315514Sae * Do delayed checksums now because we send before 321315514Sae * this is done in the normal processing path. 322315514Sae */ 323315514Sae if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { 324315514Sae in_delayed_cksum(m); 325315514Sae m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; 326315514Sae } 327315514Sae#ifdef SCTP 328315514Sae if (m->m_pkthdr.csum_flags & CSUM_SCTP) { 329315514Sae struct ip *ip = mtod(m, struct ip *); 330315514Sae 331315514Sae sctp_delayed_cksum(m, (uint32_t)(ip->ip_hl << 2)); 332315514Sae m->m_pkthdr.csum_flags &= ~CSUM_SCTP; 333315514Sae } 334194062Svanhu#endif 335315514Sae } 336315514Sae /* NB: callee frees mbuf and releases reference to SP */ 337315514Sae error = ipsec4_process_packet(m, sp, inp); 338315514Sae if (error == EJUSTRETURN) { 339315514Sae /* 340315514Sae * We had a SP with a level of 'use' and no SA. We 341315514Sae * will just continue to process the packet without 342315514Sae * IPsec processing and return without error. 343315514Sae */ 344315514Sae return (0); 345315514Sae } 346315514Sae if (error == 0) 347315514Sae return (EINPROGRESS); /* consumed by IPsec */ 348315514Sae return (error); 349315514Sae} 350194062Svanhu 351315514Sae/* 352315514Sae * IPSEC_OUTPUT() method implementation for IPv4. 353315514Sae * 0 - no IPsec handling needed 354315514Sae * other values - mbuf consumed by IPsec. 355315514Sae */ 356105197Ssamint 357315514Saeipsec4_output(struct mbuf *m, struct inpcb *inp) 358105197Ssam{ 359315514Sae 360315514Sae /* 361315514Sae * If the packet is resubmitted to ip_output (e.g. after 362315514Sae * AH, ESP, etc. processing), there will be a tag to bypass 363315514Sae * the lookup and related policy checking. 364315514Sae */ 365315514Sae if (m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, NULL) != NULL) 366315514Sae return (0); 367315514Sae 368315514Sae return (ipsec4_common_output(m, inp, 0)); 369315514Sae} 370315514Sae 371315514Sae/* 372315514Sae * IPSEC_FORWARD() method implementation for IPv4. 373315514Sae * 0 - no IPsec handling needed 374315514Sae * other values - mbuf consumed by IPsec. 375315514Sae */ 376315514Saeint 377315514Saeipsec4_forward(struct mbuf *m) 378315514Sae{ 379315514Sae 380315514Sae /* 381315514Sae * Check if this packet has an active inbound SP and needs to be 382315514Sae * dropped instead of forwarded. 383315514Sae */ 384315514Sae if (ipsec4_in_reject(m, NULL) != 0) { 385315514Sae m_freem(m); 386315514Sae return (EACCES); 387315514Sae } 388315514Sae return (ipsec4_common_output(m, NULL, 1)); 389315514Sae} 390315514Sae#endif 391315514Sae 392315514Sae#ifdef INET6 393315514Saestatic int 394315514Saein6_sa_equal_addrwithscope(const struct sockaddr_in6 *sa, 395315514Sae const struct in6_addr *ia) 396315514Sae{ 397315514Sae struct in6_addr ia2; 398315514Sae 399315514Sae if (IN6_IS_SCOPE_LINKLOCAL(&sa->sin6_addr)) { 400315514Sae memcpy(&ia2, &sa->sin6_addr, sizeof(ia2)); 401315514Sae ia2.s6_addr16[1] = htons(sa->sin6_scope_id); 402315514Sae return (IN6_ARE_ADDR_EQUAL(ia, &ia2)); 403315514Sae } 404315514Sae return (IN6_ARE_ADDR_EQUAL(&sa->sin6_addr, ia)); 405315514Sae} 406315514Sae 407315514Saestatic struct secasvar * 408315514Saeipsec6_allocsa(struct mbuf *m, struct secpolicy *sp, u_int *pidx, int *error) 409315514Sae{ 410315514Sae struct secasindex *saidx, tmpsaidx; 411315514Sae struct ipsecrequest *isr; 412315514Sae struct sockaddr_in6 *sin6; 413105197Ssam struct secasvar *sav; 414315514Sae struct ip6_hdr *ip6; 415315514Sae 416315514Sae /* 417315514Sae * Check system global policy controls. 418315514Sae */ 419315514Saenext: 420315514Sae isr = sp->req[*pidx]; 421315514Sae if ((isr->saidx.proto == IPPROTO_ESP && !V_esp_enable) || 422315514Sae (isr->saidx.proto == IPPROTO_AH && !V_ah_enable) || 423315514Sae (isr->saidx.proto == IPPROTO_IPCOMP && !V_ipcomp_enable)) { 424315514Sae DPRINTF(("%s: IPsec outbound packet dropped due" 425315514Sae " to policy (check your sysctls)\n", __func__)); 426315514Sae IPSEC_OSTAT_INC(isr->saidx.proto, pdrops); 427315514Sae *error = EHOSTUNREACH; 428315514Sae return (NULL); 429315514Sae } 430315514Sae /* 431315514Sae * Craft SA index to search for proper SA. Note that 432315514Sae * we only fillin unspecified SA peers for transport 433315514Sae * mode; for tunnel mode they must already be filled in. 434315514Sae */ 435315514Sae if (isr->saidx.mode == IPSEC_MODE_TRANSPORT) { 436315514Sae saidx = &tmpsaidx; 437315514Sae *saidx = isr->saidx; 438315514Sae ip6 = mtod(m, struct ip6_hdr *); 439315514Sae if (saidx->src.sin6.sin6_len == 0) { 440315514Sae sin6 = (struct sockaddr_in6 *)&saidx->src; 441315514Sae sin6->sin6_len = sizeof(*sin6); 442315514Sae sin6->sin6_family = AF_INET6; 443315514Sae sin6->sin6_port = IPSEC_PORT_ANY; 444315514Sae sin6->sin6_addr = ip6->ip6_src; 445315514Sae if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) { 446315514Sae /* fix scope id for comparing SPD */ 447315514Sae sin6->sin6_addr.s6_addr16[1] = 0; 448315514Sae sin6->sin6_scope_id = 449315514Sae ntohs(ip6->ip6_src.s6_addr16[1]); 450315514Sae } 451315514Sae } 452315514Sae if (saidx->dst.sin6.sin6_len == 0) { 453315514Sae sin6 = (struct sockaddr_in6 *)&saidx->dst; 454315514Sae sin6->sin6_len = sizeof(*sin6); 455315514Sae sin6->sin6_family = AF_INET6; 456315514Sae sin6->sin6_port = IPSEC_PORT_ANY; 457315514Sae sin6->sin6_addr = ip6->ip6_dst; 458315514Sae if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) { 459315514Sae /* fix scope id for comparing SPD */ 460315514Sae sin6->sin6_addr.s6_addr16[1] = 0; 461315514Sae sin6->sin6_scope_id = 462315514Sae ntohs(ip6->ip6_dst.s6_addr16[1]); 463315514Sae } 464315514Sae } 465315514Sae } else 466315514Sae saidx = &sp->req[*pidx]->saidx; 467315514Sae /* 468315514Sae * Lookup SA and validate it. 469315514Sae */ 470315514Sae sav = key_allocsa_policy(sp, saidx, error); 471315514Sae if (sav == NULL) { 472315514Sae IPSEC6STAT_INC(ips_out_nosa); 473315514Sae if (*error != 0) 474315514Sae return (NULL); 475315514Sae if (ipsec_get_reqlevel(sp, *pidx) != IPSEC_LEVEL_REQUIRE) { 476315514Sae /* 477315514Sae * We have no SA and policy that doesn't require 478315514Sae * this IPsec transform, thus we can continue w/o 479315514Sae * IPsec processing, i.e. return EJUSTRETURN. 480315514Sae * But first check if there is some bundled transform. 481315514Sae */ 482315514Sae if (sp->tcount > ++(*pidx)) 483315514Sae goto next; 484315514Sae *error = EJUSTRETURN; 485315514Sae } 486315514Sae return (NULL); 487315514Sae } 488315514Sae IPSEC_ASSERT(sav->tdb_xform != NULL, ("SA with NULL tdb_xform")); 489315514Sae return (sav); 490315514Sae} 491315514Sae 492315514Sae/* 493315514Sae * IPsec output logic for IPv6. 494315514Sae */ 495315514Saestatic int 496322741Saeipsec6_perform_request(struct mbuf *m, struct secpolicy *sp, 497322741Sae struct inpcb *inp, u_int idx) 498315514Sae{ 499315514Sae struct ipsec_ctx_data ctx; 500315514Sae union sockaddr_union *dst; 501315514Sae struct secasvar *sav; 502315514Sae struct ip6_hdr *ip6; 503315514Sae int error, i, off; 504315514Sae 505315514Sae IPSEC_ASSERT(idx < sp->tcount, ("Wrong IPsec request index %d", idx)); 506315514Sae 507315514Sae sav = ipsec6_allocsa(m, sp, &idx, &error); 508315514Sae if (sav == NULL) { 509315514Sae if (error == EJUSTRETURN) { /* No IPsec required */ 510315514Sae key_freesp(&sp); 511315514Sae return (error); 512315514Sae } 513315514Sae goto bad; 514315514Sae } 515315514Sae 516315514Sae /* Fix IP length in case if it is not set yet. */ 517315514Sae ip6 = mtod(m, struct ip6_hdr *); 518315514Sae ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6)); 519315514Sae 520322741Sae IPSEC_INIT_CTX(&ctx, &m, inp, sav, AF_INET6, IPSEC_ENC_BEFORE); 521315514Sae if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0) 522315514Sae goto bad; 523315514Sae 524315514Sae ip6 = mtod(m, struct ip6_hdr *); /* pfil can change mbuf */ 525315514Sae dst = &sav->sah->saidx.dst; 526315514Sae 527315514Sae /* Do the appropriate encapsulation, if necessary */ 528315514Sae if (sp->req[idx]->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */ 529315514Sae dst->sa.sa_family != AF_INET6 || /* PF mismatch */ 530315514Sae ((dst->sa.sa_family == AF_INET6) && 531315514Sae (!IN6_IS_ADDR_UNSPECIFIED(&dst->sin6.sin6_addr)) && 532315514Sae (!in6_sa_equal_addrwithscope(&dst->sin6, &ip6->ip6_dst)))) { 533315514Sae if (m->m_pkthdr.len - sizeof(*ip6) > IPV6_MAXPACKET) { 534315514Sae /* No jumbogram support. */ 535315514Sae error = ENXIO; /*XXX*/ 536315514Sae goto bad; 537315514Sae } 538315514Sae error = ipsec_encap(&m, &sav->sah->saidx); 539315514Sae if (error != 0) { 540319599Sae DPRINTF(("%s: encapsulation for SPI 0x%08x failed " 541319599Sae "with error %d\n", __func__, ntohl(sav->spi), 542319599Sae error)); 543315514Sae /* XXXAE: IPSEC_OSTAT_INC(tunnel); */ 544315514Sae goto bad; 545315514Sae } 546322741Sae inp = NULL; 547315514Sae } 548315514Sae 549322741Sae IPSEC_INIT_CTX(&ctx, &m, inp, sav, dst->sa.sa_family, IPSEC_ENC_AFTER); 550315514Sae if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0) 551315514Sae goto bad; 552315514Sae 553315514Sae switch(dst->sa.sa_family) { 554315514Sae#ifdef INET 555315514Sae case AF_INET: 556315514Sae { 557315514Sae struct ip *ip; 558315514Sae ip = mtod(m, struct ip *); 559315514Sae i = ip->ip_hl << 2; 560315514Sae off = offsetof(struct ip, ip_p); 561315514Sae } 562315514Sae break; 563315514Sae#endif /* AF_INET */ 564315514Sae case AF_INET6: 565315514Sae i = sizeof(struct ip6_hdr); 566315514Sae off = offsetof(struct ip6_hdr, ip6_nxt); 567315514Sae break; 568315514Sae default: 569315514Sae DPRINTF(("%s: unsupported protocol family %u\n", 570315514Sae __func__, dst->sa.sa_family)); 571315514Sae error = EPFNOSUPPORT; 572315514Sae IPSEC_OSTAT_INC(sav->sah->saidx.proto, nopf); 573315514Sae goto bad; 574315514Sae } 575315514Sae error = (*sav->tdb_xform->xf_output)(m, sp, sav, idx, i, off); 576315514Sae return (error); 577315514Saebad: 578315514Sae IPSEC6STAT_INC(ips_out_inval); 579315514Sae if (m != NULL) 580315514Sae m_freem(m); 581315514Sae if (sav != NULL) 582315514Sae key_freesav(&sav); 583315514Sae key_freesp(&sp); 584315514Sae return (error); 585315514Sae} 586315514Sae 587315514Saeint 588315514Saeipsec6_process_packet(struct mbuf *m, struct secpolicy *sp, 589315514Sae struct inpcb *inp) 590315514Sae{ 591315514Sae 592322741Sae return (ipsec6_perform_request(m, sp, inp, 0)); 593315514Sae} 594315514Sae 595315514Saestatic int 596315514Saeipsec6_common_output(struct mbuf *m, struct inpcb *inp, int forwarding) 597315514Sae{ 598315514Sae struct secpolicy *sp; 599315514Sae int error; 600315514Sae 601315514Sae /* Lookup for the corresponding outbound security policy */ 602322966Sae sp = ipsec6_checkpolicy(m, inp, &error, !forwarding); 603315514Sae if (sp == NULL) { 604315514Sae if (error == -EINVAL) { 605315514Sae /* Discarded by policy. */ 606315514Sae m_freem(m); 607315514Sae return (EACCES); 608315514Sae } 609315514Sae return (0); /* No IPsec required. */ 610315514Sae } 611315514Sae 612315514Sae if (!forwarding) { 613315514Sae /* 614315514Sae * Do delayed checksums now because we send before 615315514Sae * this is done in the normal processing path. 616315514Sae */ 617315514Sae if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) { 618315514Sae in6_delayed_cksum(m, m->m_pkthdr.len - 619315514Sae sizeof(struct ip6_hdr), sizeof(struct ip6_hdr)); 620315514Sae m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6; 621315514Sae } 622315514Sae#ifdef SCTP 623315514Sae if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6) { 624315514Sae sctp_delayed_cksum(m, sizeof(struct ip6_hdr)); 625315514Sae m->m_pkthdr.csum_flags &= ~CSUM_SCTP_IPV6; 626315514Sae } 627315514Sae#endif 628315514Sae } 629315514Sae /* NB: callee frees mbuf and releases reference to SP */ 630315514Sae error = ipsec6_process_packet(m, sp, inp); 631315514Sae if (error == EJUSTRETURN) { 632315514Sae /* 633315514Sae * We had a SP with a level of 'use' and no SA. We 634315514Sae * will just continue to process the packet without 635315514Sae * IPsec processing and return without error. 636315514Sae */ 637315514Sae return (0); 638315514Sae } 639315514Sae if (error == 0) 640315514Sae return (EINPROGRESS); /* consumed by IPsec */ 641315514Sae return (error); 642315514Sae} 643315514Sae 644315514Sae/* 645315514Sae * IPSEC_OUTPUT() method implementation for IPv6. 646315514Sae * 0 - no IPsec handling needed 647315514Sae * other values - mbuf consumed by IPsec. 648315514Sae */ 649315514Saeint 650315514Saeipsec6_output(struct mbuf *m, struct inpcb *inp) 651315514Sae{ 652315514Sae 653315514Sae /* 654315514Sae * If the packet is resubmitted to ip_output (e.g. after 655315514Sae * AH, ESP, etc. processing), there will be a tag to bypass 656315514Sae * the lookup and related policy checking. 657315514Sae */ 658315514Sae if (m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, NULL) != NULL) 659315514Sae return (0); 660315514Sae 661315514Sae return (ipsec6_common_output(m, inp, 0)); 662315514Sae} 663315514Sae 664315514Sae/* 665315514Sae * IPSEC_FORWARD() method implementation for IPv6. 666315514Sae * 0 - no IPsec handling needed 667315514Sae * other values - mbuf consumed by IPsec. 668315514Sae */ 669315514Saeint 670315514Saeipsec6_forward(struct mbuf *m) 671315514Sae{ 672315514Sae 673315514Sae /* 674315514Sae * Check if this packet has an active inbound SP and needs to be 675315514Sae * dropped instead of forwarded. 676315514Sae */ 677315514Sae if (ipsec6_in_reject(m, NULL) != 0) { 678315514Sae m_freem(m); 679315514Sae return (EACCES); 680315514Sae } 681315514Sae return (ipsec6_common_output(m, NULL, 1)); 682315514Sae} 683315514Sae#endif /* INET6 */ 684315514Sae 685315514Saeint 686315514Saeipsec_process_done(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav, 687315514Sae u_int idx) 688315514Sae{ 689315514Sae struct xform_history *xh; 690105197Ssam struct secasindex *saidx; 691315514Sae struct m_tag *mtag; 692105197Ssam int error; 693105197Ssam 694105197Ssam saidx = &sav->sah->saidx; 695105197Ssam switch (saidx->dst.sa.sa_family) { 696105197Ssam#ifdef INET 697105197Ssam case AF_INET: 698105197Ssam /* Fix the header length, for AH processing. */ 699105197Ssam mtod(m, struct ip *)->ip_len = htons(m->m_pkthdr.len); 700105197Ssam break; 701105197Ssam#endif /* INET */ 702105197Ssam#ifdef INET6 703105197Ssam case AF_INET6: 704105197Ssam /* Fix the header length, for AH processing. */ 705105197Ssam if (m->m_pkthdr.len < sizeof (struct ip6_hdr)) { 706105197Ssam error = ENXIO; 707105197Ssam goto bad; 708105197Ssam } 709105197Ssam if (m->m_pkthdr.len - sizeof (struct ip6_hdr) > IPV6_MAXPACKET) { 710105197Ssam /* No jumbogram support. */ 711105197Ssam error = ENXIO; /*?*/ 712105197Ssam goto bad; 713105197Ssam } 714105197Ssam mtod(m, struct ip6_hdr *)->ip6_plen = 715105197Ssam htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); 716105197Ssam break; 717105197Ssam#endif /* INET6 */ 718105197Ssam default: 719120585Ssam DPRINTF(("%s: unknown protocol family %u\n", __func__, 720105197Ssam saidx->dst.sa.sa_family)); 721105197Ssam error = ENXIO; 722105197Ssam goto bad; 723105197Ssam } 724105197Ssam 725105197Ssam /* 726315514Sae * Add a record of what we've done to the packet. 727105197Ssam */ 728315514Sae mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE, sizeof(*xh), M_NOWAIT); 729105197Ssam if (mtag == NULL) { 730120585Ssam DPRINTF(("%s: could not get packet tag\n", __func__)); 731105197Ssam error = ENOMEM; 732105197Ssam goto bad; 733105197Ssam } 734105197Ssam 735315514Sae xh = (struct xform_history *)(mtag + 1); 736315514Sae xh->dst = saidx->dst; 737315514Sae xh->proto = saidx->proto; 738315514Sae xh->mode = saidx->mode; 739315514Sae xh->spi = sav->spi; 740105197Ssam m_tag_prepend(m, mtag); 741105197Ssam 742286095Seri key_sa_recordxfer(sav, m); /* record data transfer */ 743286095Seri 744105197Ssam /* 745105197Ssam * If there's another (bundled) SA to apply, do so. 746105197Ssam * Note that this puts a burden on the kernel stack size. 747105197Ssam * If this is a problem we'll need to introduce a queue 748105197Ssam * to set the packet on so we can unwind the stack before 749105197Ssam * doing further processing. 750105197Ssam */ 751315514Sae if (++idx < sp->tcount) { 752221129Sbz switch (saidx->dst.sa.sa_family) { 753221129Sbz#ifdef INET 754221129Sbz case AF_INET: 755315514Sae key_freesav(&sav); 756274467Sae IPSECSTAT_INC(ips_out_bundlesa); 757322741Sae return (ipsec4_perform_request(m, sp, NULL, idx)); 758221129Sbz /* NOTREACHED */ 759221129Sbz#endif 760221129Sbz#ifdef INET6 761221129Sbz case AF_INET6: 762315514Sae key_freesav(&sav); 763274467Sae IPSEC6STAT_INC(ips_out_bundlesa); 764322741Sae return (ipsec6_perform_request(m, sp, NULL, idx)); 765221129Sbz /* NOTREACHED */ 766221129Sbz#endif /* INET6 */ 767221129Sbz default: 768221129Sbz DPRINTF(("%s: unknown protocol family %u\n", __func__, 769221129Sbz saidx->dst.sa.sa_family)); 770315514Sae error = EPFNOSUPPORT; 771221129Sbz goto bad; 772221129Sbz } 773105197Ssam } 774105197Ssam 775315514Sae key_freesp(&sp), sp = NULL; /* Release reference to SP */ 776315514Sae#ifdef INET 777105197Ssam /* 778315514Sae * Do UDP encapsulation if SA requires it. 779315514Sae */ 780315514Sae if (sav->natt != NULL) { 781315514Sae error = udp_ipsec_output(m, sav); 782315514Sae if (error != 0) 783315514Sae goto bad; 784315514Sae } 785315514Sae#endif /* INET */ 786315514Sae /* 787105197Ssam * We're done with IPsec processing, transmit the packet using the 788282139Sae * appropriate network protocol (IP or IPv6). 789105197Ssam */ 790105197Ssam switch (saidx->dst.sa.sa_family) { 791105197Ssam#ifdef INET 792105197Ssam case AF_INET: 793315514Sae key_freesav(&sav); 794105197Ssam return ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL); 795105197Ssam#endif /* INET */ 796105197Ssam#ifdef INET6 797105197Ssam case AF_INET6: 798315514Sae key_freesav(&sav); 799105197Ssam return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL); 800105197Ssam#endif /* INET6 */ 801105197Ssam } 802105197Ssam panic("ipsec_process_done"); 803105197Ssambad: 804105197Ssam m_freem(m); 805315514Sae key_freesav(&sav); 806315514Sae if (sp != NULL) 807315514Sae key_freesp(&sp); 808105197Ssam return (error); 809105197Ssam} 810105197Ssam 811315514Sae/* 812315514Sae * ipsec_prepend() is optimized version of M_PREPEND(). 813315514Sae * ipsec_encap() is called by IPsec output routine for tunnel mode SA. 814315514Sae * It is expected that after IP encapsulation some IPsec transform will 815315514Sae * be performed. Each IPsec transform inserts its variable length header 816315514Sae * just after outer IP header using m_makespace(). If given mbuf has not 817315514Sae * enough free space at the beginning, we allocate new mbuf and reserve 818315514Sae * some space at the beginning and at the end. 819315514Sae * This helps avoid allocating of new mbuf and data copying in m_makespace(), 820315514Sae * we place outer header in the middle of mbuf's data with reserved leading 821315514Sae * and trailing space: 822315514Sae * [ LEADINGSPACE ][ Outer IP header ][ TRAILINGSPACE ] 823315514Sae * LEADINGSPACE will be used to add ethernet header, TRAILINGSPACE will 824315514Sae * be used to inject AH/ESP/IPCOMP header. 825315514Sae */ 826315514Sae#define IPSEC_TRAILINGSPACE (sizeof(struct udphdr) +/* NAT-T */ \ 827315514Sae max(sizeof(struct newesp) + EALG_MAX_BLOCK_LEN, /* ESP + IV */ \ 828315514Sae sizeof(struct newah) + HASH_MAX_LEN /* AH + ICV */)) 829315514Saestatic struct mbuf * 830315514Saeipsec_prepend(struct mbuf *m, int len, int how) 831105197Ssam{ 832315514Sae struct mbuf *n; 833105197Ssam 834315514Sae M_ASSERTPKTHDR(m); 835315514Sae IPSEC_ASSERT(len < MHLEN, ("wrong length")); 836315514Sae if (M_LEADINGSPACE(m) >= len) { 837315514Sae /* No need to allocate new mbuf. */ 838315514Sae m->m_data -= len; 839315514Sae m->m_len += len; 840315514Sae m->m_pkthdr.len += len; 841315514Sae return (m); 842105197Ssam } 843315514Sae n = m_gethdr(how, m->m_type); 844315514Sae if (n == NULL) { 845315514Sae m_freem(m); 846315514Sae return (NULL); 847105197Ssam } 848315514Sae m_move_pkthdr(n, m); 849315514Sae n->m_next = m; 850315514Sae if (len + IPSEC_TRAILINGSPACE < M_SIZE(n)) 851315514Sae m_align(n, len + IPSEC_TRAILINGSPACE); 852315514Sae n->m_len = len; 853315514Sae n->m_pkthdr.len += len; 854315514Sae return (n); 855105197Ssam} 856105197Ssam 857281692Saestatic int 858281692Saeipsec_encap(struct mbuf **mp, struct secasindex *saidx) 859281692Sae{ 860281692Sae#ifdef INET6 861281692Sae struct ip6_hdr *ip6; 862281692Sae#endif 863281692Sae struct ip *ip; 864281692Sae int setdf; 865281692Sae uint8_t itos, proto; 866281692Sae 867281692Sae ip = mtod(*mp, struct ip *); 868281692Sae switch (ip->ip_v) { 869105197Ssam#ifdef INET 870281692Sae case IPVERSION: 871281692Sae proto = IPPROTO_IPIP; 872281692Sae /* 873281692Sae * Collect IP_DF state from the inner header 874281692Sae * and honor system-wide control of how to handle it. 875281692Sae */ 876281692Sae switch (V_ip4_ipsec_dfbit) { 877281692Sae case 0: /* clear in outer header */ 878281692Sae case 1: /* set in outer header */ 879281692Sae setdf = V_ip4_ipsec_dfbit; 880281692Sae break; 881281692Sae default:/* propagate to outer header */ 882297014Sae setdf = (ip->ip_off & htons(IP_DF)) != 0; 883281692Sae } 884281692Sae itos = ip->ip_tos; 885281692Sae break; 886281692Sae#endif 887281692Sae#ifdef INET6 888281692Sae case (IPV6_VERSION >> 4): 889281692Sae proto = IPPROTO_IPV6; 890281692Sae ip6 = mtod(*mp, struct ip6_hdr *); 891281692Sae itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; 892281692Sae setdf = V_ip4_ipsec_dfbit ? 1: 0; 893281692Sae /* scoped address handling */ 894281692Sae in6_clearscope(&ip6->ip6_src); 895281692Sae in6_clearscope(&ip6->ip6_dst); 896281692Sae break; 897281692Sae#endif 898281692Sae default: 899281692Sae return (EAFNOSUPPORT); 900281692Sae } 901281692Sae switch (saidx->dst.sa.sa_family) { 902281692Sae#ifdef INET 903281692Sae case AF_INET: 904281692Sae if (saidx->src.sa.sa_family != AF_INET || 905281692Sae saidx->src.sin.sin_addr.s_addr == INADDR_ANY || 906281692Sae saidx->dst.sin.sin_addr.s_addr == INADDR_ANY) 907281692Sae return (EINVAL); 908315514Sae *mp = ipsec_prepend(*mp, sizeof(struct ip), M_NOWAIT); 909281692Sae if (*mp == NULL) 910281692Sae return (ENOBUFS); 911281692Sae ip = mtod(*mp, struct ip *); 912281692Sae ip->ip_v = IPVERSION; 913281692Sae ip->ip_hl = sizeof(struct ip) >> 2; 914281692Sae ip->ip_p = proto; 915281692Sae ip->ip_len = htons((*mp)->m_pkthdr.len); 916281692Sae ip->ip_ttl = V_ip_defttl; 917281692Sae ip->ip_sum = 0; 918281692Sae ip->ip_off = setdf ? htons(IP_DF): 0; 919281692Sae ip->ip_src = saidx->src.sin.sin_addr; 920281692Sae ip->ip_dst = saidx->dst.sin.sin_addr; 921281692Sae ip_ecn_ingress(V_ip4_ipsec_ecn, &ip->ip_tos, &itos); 922281692Sae ip_fillid(ip); 923281692Sae break; 924281692Sae#endif /* INET */ 925281692Sae#ifdef INET6 926281692Sae case AF_INET6: 927281692Sae if (saidx->src.sa.sa_family != AF_INET6 || 928281692Sae IN6_IS_ADDR_UNSPECIFIED(&saidx->src.sin6.sin6_addr) || 929281692Sae IN6_IS_ADDR_UNSPECIFIED(&saidx->dst.sin6.sin6_addr)) 930281692Sae return (EINVAL); 931315514Sae *mp = ipsec_prepend(*mp, sizeof(struct ip6_hdr), M_NOWAIT); 932281692Sae if (*mp == NULL) 933281692Sae return (ENOBUFS); 934281692Sae ip6 = mtod(*mp, struct ip6_hdr *); 935281692Sae ip6->ip6_flow = 0; 936281692Sae ip6->ip6_vfc = IPV6_VERSION; 937281692Sae ip6->ip6_hlim = V_ip6_defhlim; 938281692Sae ip6->ip6_nxt = proto; 939281692Sae ip6->ip6_dst = saidx->dst.sin6.sin6_addr; 940281693Sae /* For link-local address embed scope zone id */ 941281693Sae if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) 942281693Sae ip6->ip6_dst.s6_addr16[1] = 943281693Sae htons(saidx->dst.sin6.sin6_scope_id & 0xffff); 944281692Sae ip6->ip6_src = saidx->src.sin6.sin6_addr; 945281693Sae if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) 946281693Sae ip6->ip6_src.s6_addr16[1] = 947281693Sae htons(saidx->src.sin6.sin6_scope_id & 0xffff); 948281692Sae ip6->ip6_plen = htons((*mp)->m_pkthdr.len - sizeof(*ip6)); 949281692Sae ip_ecn_ingress(V_ip6_ipsec_ecn, &proto, &itos); 950281692Sae ip6->ip6_flow |= htonl((uint32_t)proto << 20); 951281692Sae break; 952281692Sae#endif /* INET6 */ 953281692Sae default: 954281692Sae return (EAFNOSUPPORT); 955281692Sae } 956315514Sae (*mp)->m_flags &= ~(M_BCAST | M_MCAST); 957281692Sae return (0); 958281692Sae} 959281692Sae 960