1112758Ssam/* $OpenBSD: ipsec_input.c,v 1.63 2003/02/20 18:35:43 deraadt Exp $ */ 2139823Simp/*- 3112758Ssam * The authors of this code are John Ioannidis (ji@tla.org), 4112758Ssam * Angelos D. Keromytis (kermit@csd.uch.gr) and 5112758Ssam * Niels Provos (provos@physnet.uni-hamburg.de). 6112758Ssam * 7112758Ssam * This code was written by John Ioannidis for BSD/OS in Athens, Greece, 8112758Ssam * in November 1995. 9112758Ssam * 10112758Ssam * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, 11112758Ssam * by Angelos D. Keromytis. 12112758Ssam * 13112758Ssam * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis 14112758Ssam * and Niels Provos. 15112758Ssam * 16112758Ssam * Additional features in 1999 by Angelos D. Keromytis. 17112758Ssam * 18112758Ssam * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, 19112758Ssam * Angelos D. Keromytis and Niels Provos. 20112758Ssam * Copyright (c) 2001, Angelos D. Keromytis. 21315514Sae * Copyright (c) 2016 Andrey V. Elsukov <ae@FreeBSD.org> 22112758Ssam * 23112758Ssam * Permission to use, copy, and modify this software with or without fee 24112758Ssam * is hereby granted, provided that this entire notice is included in 25112758Ssam * all copies of any software which is or includes a copy or 26112758Ssam * modification of this software. 27112758Ssam * You may use this code under the GNU public license if you so wish. Please 28112758Ssam * contribute changes back to the authors under this freer than GPL license 29112758Ssam * so that we may further the use of strong encryption without limitations to 30112758Ssam * all. 31112758Ssam * 32112758Ssam * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 33112758Ssam * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY 34112758Ssam * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 35112758Ssam * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 36112758Ssam * PURPOSE. 37112758Ssam */ 38105197Ssam 39105197Ssam/* 40105197Ssam * IPsec input processing. 41105197Ssam */ 42105197Ssam 43315514Sae#include <sys/cdefs.h> 44315514Sae__FBSDID("$FreeBSD: stable/11/sys/netipsec/ipsec_input.c 322741 2017-08-21 09:03:20Z ae $"); 45315514Sae 46105197Ssam#include "opt_inet.h" 47105197Ssam#include "opt_inet6.h" 48105197Ssam#include "opt_ipsec.h" 49105197Ssam 50105197Ssam#include <sys/param.h> 51105197Ssam#include <sys/systm.h> 52105197Ssam#include <sys/malloc.h> 53105197Ssam#include <sys/mbuf.h> 54105197Ssam#include <sys/domain.h> 55105197Ssam#include <sys/protosw.h> 56105197Ssam#include <sys/socket.h> 57105197Ssam#include <sys/errno.h> 58291292Sae#include <sys/hhook.h> 59105197Ssam#include <sys/syslog.h> 60105197Ssam 61105197Ssam#include <net/if.h> 62257176Sglebius#include <net/if_var.h> 63291292Sae#include <net/if_enc.h> 64105197Ssam#include <net/netisr.h> 65195699Srwatson#include <net/vnet.h> 66105197Ssam 67105197Ssam#include <netinet/in.h> 68105197Ssam#include <netinet/in_systm.h> 69105197Ssam#include <netinet/ip.h> 70105197Ssam#include <netinet/ip_var.h> 71105197Ssam#include <netinet/in_var.h> 72105197Ssam 73105197Ssam#include <netinet/ip6.h> 74105197Ssam#ifdef INET6 75105197Ssam#include <netinet6/ip6_var.h> 76105197Ssam#endif 77105197Ssam#include <netinet/in_pcb.h> 78105197Ssam#ifdef INET6 79105197Ssam#include <netinet/icmp6.h> 80105197Ssam#endif 81105197Ssam 82105197Ssam#include <netipsec/ipsec.h> 83105197Ssam#ifdef INET6 84105197Ssam#include <netipsec/ipsec6.h> 85105197Ssam#endif 86105197Ssam#include <netipsec/ah_var.h> 87105197Ssam#include <netipsec/esp.h> 88105197Ssam#include <netipsec/esp_var.h> 89105197Ssam#include <netipsec/ipcomp_var.h> 90105197Ssam 91105197Ssam#include <netipsec/key.h> 92105197Ssam#include <netipsec/keydb.h> 93315514Sae#include <netipsec/key_debug.h> 94105197Ssam 95105197Ssam#include <netipsec/xform.h> 96105197Ssam#include <netinet6/ip6protosw.h> 97105197Ssam 98105197Ssam#include <machine/in_cksum.h> 99105197Ssam#include <machine/stdarg.h> 100105197Ssam 101181627Svanhu 102252028Sae#define IPSEC_ISTAT(proto, name) do { \ 103252028Sae if ((proto) == IPPROTO_ESP) \ 104252028Sae ESPSTAT_INC(esps_##name); \ 105252028Sae else if ((proto) == IPPROTO_AH) \ 106252028Sae AHSTAT_INC(ahs_##name); \ 107252028Sae else \ 108252028Sae IPCOMPSTAT_INC(ipcomps_##name); \ 109252028Sae} while (0) 110105197Ssam 111105197Ssam/* 112105197Ssam * ipsec_common_input gets called when an IPsec-protected packet 113214351Sthomas * is received by IPv4 or IPv6. Its job is to find the right SA 114170793Sbz * and call the appropriate transform. The transform callback 115105197Ssam * takes care of further processing (like ingress filtering). 116105197Ssam */ 117315514Saestatic int 118105197Ssamipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto) 119105197Ssam{ 120319599Sae IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); 121105197Ssam union sockaddr_union dst_address; 122105197Ssam struct secasvar *sav; 123315514Sae uint32_t spi; 124119643Ssam int error; 125105197Ssam 126252028Sae IPSEC_ISTAT(sproto, input); 127105197Ssam 128120585Ssam IPSEC_ASSERT(m != NULL, ("null packet")); 129105197Ssam 130170792Sbz IPSEC_ASSERT(sproto == IPPROTO_ESP || sproto == IPPROTO_AH || 131170792Sbz sproto == IPPROTO_IPCOMP, 132170792Sbz ("unexpected security protocol %u", sproto)); 133170792Sbz 134181803Sbz if ((sproto == IPPROTO_ESP && !V_esp_enable) || 135181803Sbz (sproto == IPPROTO_AH && !V_ah_enable) || 136181803Sbz (sproto == IPPROTO_IPCOMP && !V_ipcomp_enable)) { 137105197Ssam m_freem(m); 138252028Sae IPSEC_ISTAT(sproto, pdrops); 139105197Ssam return EOPNOTSUPP; 140105197Ssam } 141105197Ssam 142105197Ssam if (m->m_pkthdr.len - skip < 2 * sizeof (u_int32_t)) { 143105197Ssam m_freem(m); 144252028Sae IPSEC_ISTAT(sproto, hdrops); 145120585Ssam DPRINTF(("%s: packet too small\n", __func__)); 146105197Ssam return EINVAL; 147105197Ssam } 148105197Ssam 149105197Ssam /* Retrieve the SPI from the relevant IPsec header */ 150105197Ssam if (sproto == IPPROTO_ESP) 151105197Ssam m_copydata(m, skip, sizeof(u_int32_t), (caddr_t) &spi); 152105197Ssam else if (sproto == IPPROTO_AH) 153105197Ssam m_copydata(m, skip + sizeof(u_int32_t), sizeof(u_int32_t), 154105197Ssam (caddr_t) &spi); 155105197Ssam else if (sproto == IPPROTO_IPCOMP) { 156105197Ssam u_int16_t cpi; 157105197Ssam m_copydata(m, skip + sizeof(u_int16_t), sizeof(u_int16_t), 158105197Ssam (caddr_t) &cpi); 159105197Ssam spi = ntohl(htons(cpi)); 160105197Ssam } 161105197Ssam 162105197Ssam /* 163105197Ssam * Find the SA and (indirectly) call the appropriate 164105197Ssam * kernel crypto routine. The resulting mbuf chain is a valid 165105197Ssam * IP packet ready to go through input processing. 166105197Ssam */ 167105197Ssam bzero(&dst_address, sizeof (dst_address)); 168105197Ssam dst_address.sa.sa_family = af; 169105197Ssam switch (af) { 170105197Ssam#ifdef INET 171105197Ssam case AF_INET: 172105197Ssam dst_address.sin.sin_len = sizeof(struct sockaddr_in); 173105197Ssam m_copydata(m, offsetof(struct ip, ip_dst), 174105197Ssam sizeof(struct in_addr), 175105197Ssam (caddr_t) &dst_address.sin.sin_addr); 176105197Ssam break; 177105197Ssam#endif /* INET */ 178105197Ssam#ifdef INET6 179105197Ssam case AF_INET6: 180105197Ssam dst_address.sin6.sin6_len = sizeof(struct sockaddr_in6); 181105197Ssam m_copydata(m, offsetof(struct ip6_hdr, ip6_dst), 182105197Ssam sizeof(struct in6_addr), 183105197Ssam (caddr_t) &dst_address.sin6.sin6_addr); 184281693Sae /* We keep addresses in SADB without embedded scope id */ 185281693Sae if (IN6_IS_SCOPE_LINKLOCAL(&dst_address.sin6.sin6_addr)) { 186281693Sae /* XXX: sa6_recoverscope() */ 187281693Sae dst_address.sin6.sin6_scope_id = 188281693Sae ntohs(dst_address.sin6.sin6_addr.s6_addr16[1]); 189281693Sae dst_address.sin6.sin6_addr.s6_addr16[1] = 0; 190281693Sae } 191105197Ssam break; 192105197Ssam#endif /* INET6 */ 193105197Ssam default: 194120585Ssam DPRINTF(("%s: unsupported protocol family %u\n", __func__, af)); 195105197Ssam m_freem(m); 196252028Sae IPSEC_ISTAT(sproto, nopf); 197105197Ssam return EPFNOSUPPORT; 198105197Ssam } 199105197Ssam 200105197Ssam /* NB: only pass dst since key_allocsa follows RFC2401 */ 201315514Sae sav = key_allocsa(&dst_address, sproto, spi); 202105197Ssam if (sav == NULL) { 203120585Ssam DPRINTF(("%s: no key association found for SA %s/%08lx/%u\n", 204281695Sae __func__, ipsec_address(&dst_address, buf, sizeof(buf)), 205281695Sae (u_long) ntohl(spi), sproto)); 206252028Sae IPSEC_ISTAT(sproto, notdb); 207105197Ssam m_freem(m); 208105197Ssam return ENOENT; 209105197Ssam } 210105197Ssam 211105197Ssam if (sav->tdb_xform == NULL) { 212120585Ssam DPRINTF(("%s: attempted to use uninitialized SA %s/%08lx/%u\n", 213281695Sae __func__, ipsec_address(&dst_address, buf, sizeof(buf)), 214281695Sae (u_long) ntohl(spi), sproto)); 215252028Sae IPSEC_ISTAT(sproto, noxform); 216315514Sae key_freesav(&sav); 217105197Ssam m_freem(m); 218105197Ssam return ENXIO; 219105197Ssam } 220105197Ssam 221105197Ssam /* 222105197Ssam * Call appropriate transform and return -- callback takes care of 223105197Ssam * everything else. 224105197Ssam */ 225105197Ssam error = (*sav->tdb_xform->xf_input)(m, sav, skip, protoff); 226315514Sae return (error); 227105197Ssam} 228105197Ssam 229105197Ssam#ifdef INET 230315514Saeextern struct protosw inetsw[]; 231269699Skevlo 232315514Sae/* 233315514Sae * IPSEC_INPUT() method implementation for IPv4. 234315514Sae * 0 - Permitted by inbound security policy for further processing. 235315514Sae * EACCES - Forbidden by inbound security policy. 236315514Sae * EINPROGRESS - consumed by IPsec. 237315514Sae */ 238269699Skevloint 239315514Saeipsec4_input(struct mbuf *m, int offset, int proto) 240106680Ssam{ 241269699Skevlo 242315514Sae switch (proto) { 243315514Sae case IPPROTO_AH: 244315514Sae case IPPROTO_ESP: 245315514Sae case IPPROTO_IPCOMP: 246315514Sae /* Do inbound IPsec processing for AH/ESP/IPCOMP */ 247315514Sae ipsec_common_input(m, offset, 248315514Sae offsetof(struct ip, ip_p), AF_INET, proto); 249315514Sae return (EINPROGRESS); /* mbuf consumed by IPsec */ 250315514Sae default: 251315514Sae /* 252315514Sae * Protocols with further headers get their IPsec treatment 253315514Sae * within the protocol specific processing. 254315514Sae */ 255315514Sae if ((inetsw[ip_protox[proto]].pr_flags & PR_LASTHDR) == 0) 256315514Sae return (0); 257315514Sae /* FALLTHROUGH */ 258315514Sae }; 259315514Sae /* 260315514Sae * Enforce IPsec policy checking if we are seeing last header. 261315514Sae */ 262315514Sae if (ipsec4_in_reject(m, NULL) != 0) { 263315514Sae /* Forbidden by inbound security policy */ 264315514Sae m_freem(m); 265315514Sae return (EACCES); 266315514Sae } 267315514Sae return (0); 268106680Ssam} 269269699Skevlo 270105197Ssam/* 271105197Ssam * IPsec input callback for INET protocols. 272105197Ssam * This routine is called as the transform callback. 273105197Ssam * Takes care of filtering and other sanity checks on 274105197Ssam * the processed packet. 275105197Ssam */ 276105197Ssamint 277275707Saeipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, 278275707Sae int protoff) 279105197Ssam{ 280319599Sae IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); 281291292Sae struct ipsec_ctx_data ctx; 282315514Sae struct xform_history *xh; 283315514Sae struct secasindex *saidx; 284315514Sae struct m_tag *mtag; 285105197Ssam struct ip *ip; 286315514Sae int error, prot, af, sproto, isr_prot; 287105197Ssam 288120585Ssam IPSEC_ASSERT(sav != NULL, ("null SA")); 289120585Ssam IPSEC_ASSERT(sav->sah != NULL, ("null SAH")); 290105197Ssam saidx = &sav->sah->saidx; 291105197Ssam af = saidx->dst.sa.sa_family; 292120585Ssam IPSEC_ASSERT(af == AF_INET, ("unexpected af %u", af)); 293105197Ssam sproto = saidx->proto; 294120585Ssam IPSEC_ASSERT(sproto == IPPROTO_ESP || sproto == IPPROTO_AH || 295105197Ssam sproto == IPPROTO_IPCOMP, 296120585Ssam ("unexpected security protocol %u", sproto)); 297105197Ssam 298105197Ssam if (skip != 0) { 299241922Sglebius /* 300241922Sglebius * Fix IPv4 header 301241922Sglebius */ 302105197Ssam if (m->m_len < skip && (m = m_pullup(m, skip)) == NULL) { 303120585Ssam DPRINTF(("%s: processing failed for SA %s/%08lx\n", 304281695Sae __func__, ipsec_address(&sav->sah->saidx.dst, 305281695Sae buf, sizeof(buf)), (u_long) ntohl(sav->spi))); 306252028Sae IPSEC_ISTAT(sproto, hdrops); 307105197Ssam error = ENOBUFS; 308105197Ssam goto bad; 309105197Ssam } 310105197Ssam 311105197Ssam ip = mtod(m, struct ip *); 312105197Ssam ip->ip_len = htons(m->m_pkthdr.len); 313105197Ssam ip->ip_sum = 0; 314105197Ssam ip->ip_sum = in_cksum(m, ip->ip_hl << 2); 315105197Ssam } else { 316105197Ssam ip = mtod(m, struct ip *); 317105197Ssam } 318105197Ssam prot = ip->ip_p; 319315514Sae /* 320315514Sae * Check that we have NAT-T enabled and apply transport mode 321315514Sae * decapsulation NAT procedure (RFC3948). 322315514Sae * Do this before invoking into the PFIL. 323315514Sae */ 324315514Sae if (sav->natt != NULL && 325315514Sae (prot == IPPROTO_UDP || prot == IPPROTO_TCP)) 326315514Sae udp_ipsec_adjust_cksum(m, sav, prot, skip); 327105197Ssam 328322741Sae IPSEC_INIT_CTX(&ctx, &m, NULL, sav, AF_INET, IPSEC_ENC_BEFORE); 329291292Sae if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0) 330291292Sae goto bad; 331315514Sae ip = mtod(m, struct ip *); /* update pointer */ 332266800Svanhu 333105197Ssam /* IP-in-IP encapsulation */ 334272394Sae if (prot == IPPROTO_IPIP && 335272394Sae saidx->mode != IPSEC_MODE_TRANSPORT) { 336118888Ssam if (m->m_pkthdr.len - skip < sizeof(struct ip)) { 337252028Sae IPSEC_ISTAT(sproto, hdrops); 338118888Ssam error = EINVAL; 339118888Ssam goto bad; 340118888Ssam } 341266800Svanhu /* enc0: strip outer IPv4 header */ 342266800Svanhu m_striphdr(m, 0, ip->ip_hl << 2); 343105197Ssam } 344159237Spjd#ifdef INET6 345105197Ssam /* IPv6-in-IP encapsulation. */ 346274193Sae else if (prot == IPPROTO_IPV6 && 347272394Sae saidx->mode != IPSEC_MODE_TRANSPORT) { 348118888Ssam if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) { 349252028Sae IPSEC_ISTAT(sproto, hdrops); 350118888Ssam error = EINVAL; 351118888Ssam goto bad; 352118888Ssam } 353266800Svanhu /* enc0: strip IPv4 header, keep IPv6 header only */ 354266800Svanhu m_striphdr(m, 0, ip->ip_hl << 2); 355105197Ssam } 356105197Ssam#endif /* INET6 */ 357274193Sae else if (prot != IPPROTO_IPV6 && saidx->mode == IPSEC_MODE_ANY) { 358274193Sae /* 359274193Sae * When mode is wildcard, inner protocol is IPv6 and 360274193Sae * we have no INET6 support - drop this packet a bit later. 361315514Sae * In other cases we assume transport mode. Set prot to 362315514Sae * correctly choose netisr. 363274193Sae */ 364274193Sae prot = IPPROTO_IPIP; 365274193Sae } 366105197Ssam 367105197Ssam /* 368105197Ssam * Record what we've done to the packet (under what SA it was 369275707Sae * processed). 370105197Ssam */ 371275707Sae if (sproto != IPPROTO_IPCOMP) { 372105197Ssam mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE, 373315514Sae sizeof(struct xform_history), M_NOWAIT); 374105197Ssam if (mtag == NULL) { 375120585Ssam DPRINTF(("%s: failed to get tag\n", __func__)); 376252028Sae IPSEC_ISTAT(sproto, hdrops); 377105197Ssam error = ENOMEM; 378105197Ssam goto bad; 379105197Ssam } 380105197Ssam 381315514Sae xh = (struct xform_history *)(mtag + 1); 382315514Sae bcopy(&saidx->dst, &xh->dst, saidx->dst.sa.sa_len); 383315514Sae xh->spi = sav->spi; 384315514Sae xh->proto = sproto; 385315514Sae xh->mode = saidx->mode; 386105197Ssam m_tag_prepend(m, mtag); 387105197Ssam } 388105197Ssam 389105197Ssam key_sa_recordxfer(sav, m); /* record data transfer */ 390105197Ssam 391272394Sae /* 392272394Sae * In transport mode requeue decrypted mbuf back to IPv4 protocol 393272394Sae * handler. This is necessary to correctly expose rcvif. 394272394Sae */ 395272394Sae if (saidx->mode == IPSEC_MODE_TRANSPORT) 396272394Sae prot = IPPROTO_IPIP; 397105197Ssam /* 398105197Ssam * Re-dispatch via software interrupt. 399105197Ssam */ 400266800Svanhu switch (prot) { 401266800Svanhu case IPPROTO_IPIP: 402266800Svanhu isr_prot = NETISR_IP; 403291292Sae af = AF_INET; 404266800Svanhu break; 405266800Svanhu#ifdef INET6 406266800Svanhu case IPPROTO_IPV6: 407266800Svanhu isr_prot = NETISR_IPV6; 408291292Sae af = AF_INET6; 409266800Svanhu break; 410266800Svanhu#endif 411266800Svanhu default: 412266800Svanhu DPRINTF(("%s: cannot handle inner ip proto %d\n", 413266800Svanhu __func__, prot)); 414266800Svanhu IPSEC_ISTAT(sproto, nopf); 415266800Svanhu error = EPFNOSUPPORT; 416266800Svanhu goto bad; 417266800Svanhu } 418266800Svanhu 419322741Sae IPSEC_INIT_CTX(&ctx, &m, NULL, sav, af, IPSEC_ENC_AFTER); 420291292Sae if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0) 421291292Sae goto bad; 422315514Sae 423315514Sae /* Handle virtual tunneling interfaces */ 424315514Sae if (saidx->mode == IPSEC_MODE_TUNNEL) 425315514Sae error = ipsec_if_input(m, sav, af); 426315514Sae if (error == 0) { 427315514Sae error = netisr_queue_src(isr_prot, (uintptr_t)sav->spi, m); 428315514Sae if (error) { 429315514Sae IPSEC_ISTAT(sproto, qfull); 430315514Sae DPRINTF(("%s: queue full; proto %u packet dropped\n", 431315514Sae __func__, sproto)); 432315514Sae } 433105197Ssam } 434315514Sae key_freesav(&sav); 435315514Sae return (error); 436105197Ssambad: 437315514Sae key_freesav(&sav); 438315514Sae if (m != NULL) 439315514Sae m_freem(m); 440315514Sae return (error); 441105197Ssam} 442105197Ssam#endif /* INET */ 443105197Ssam 444105197Ssam#ifdef INET6 445315514Sae/* 446315514Sae * IPSEC_INPUT() method implementation for IPv6. 447315514Sae * 0 - Permitted by inbound security policy for further processing. 448315514Sae * EACCES - Forbidden by inbound security policy. 449315514Sae * EINPROGRESS - consumed by IPsec. 450315514Sae */ 451105197Ssamint 452315514Saeipsec6_input(struct mbuf *m, int offset, int proto) 453105197Ssam{ 454105197Ssam 455315514Sae switch (proto) { 456315514Sae case IPPROTO_AH: 457315514Sae case IPPROTO_ESP: 458315514Sae case IPPROTO_IPCOMP: 459315514Sae /* Do inbound IPsec processing for AH/ESP/IPCOMP */ 460315514Sae ipsec_common_input(m, offset, 461315514Sae offsetof(struct ip6_hdr, ip6_nxt), AF_INET6, proto); 462315514Sae return (EINPROGRESS); /* mbuf consumed by IPsec */ 463315514Sae default: 464315514Sae /* 465315514Sae * Protocols with further headers get their IPsec treatment 466315514Sae * within the protocol specific processing. 467315514Sae */ 468315514Sae if ((inet6sw[ip6_protox[proto]].pr_flags & PR_LASTHDR) == 0) 469315514Sae return (0); 470315514Sae /* FALLTHROUGH */ 471315514Sae }; 472315514Sae /* 473315514Sae * Enforce IPsec policy checking if we are seeing last header. 474315514Sae */ 475315514Sae if (ipsec6_in_reject(m, NULL) != 0) { 476315514Sae /* Forbidden by inbound security policy */ 477315514Sae m_freem(m); 478315514Sae return (EACCES); 479105197Ssam } 480315514Sae return (0); 481105197Ssam} 482105197Ssam 483105197Ssam/* 484105197Ssam * IPsec input callback, called by the transform callback. Takes care of 485105197Ssam * filtering and other sanity checks on the processed packet. 486105197Ssam */ 487105197Ssamint 488275707Saeipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, 489275707Sae int protoff) 490105197Ssam{ 491319599Sae IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); 492291292Sae struct ipsec_ctx_data ctx; 493315514Sae struct xform_history *xh; 494315514Sae struct secasindex *saidx; 495105197Ssam struct ip6_hdr *ip6; 496105197Ssam struct m_tag *mtag; 497315514Sae int prot, af, sproto; 498281694Sae int nxt, isr_prot; 499105197Ssam int error, nest; 500315514Sae uint8_t nxt8; 501105197Ssam 502120585Ssam IPSEC_ASSERT(sav != NULL, ("null SA")); 503120585Ssam IPSEC_ASSERT(sav->sah != NULL, ("null SAH")); 504105197Ssam saidx = &sav->sah->saidx; 505105197Ssam af = saidx->dst.sa.sa_family; 506120585Ssam IPSEC_ASSERT(af == AF_INET6, ("unexpected af %u", af)); 507105197Ssam sproto = saidx->proto; 508120585Ssam IPSEC_ASSERT(sproto == IPPROTO_ESP || sproto == IPPROTO_AH || 509105197Ssam sproto == IPPROTO_IPCOMP, 510120585Ssam ("unexpected security protocol %u", sproto)); 511105197Ssam 512105197Ssam /* Fix IPv6 header */ 513105197Ssam if (m->m_len < sizeof(struct ip6_hdr) && 514105197Ssam (m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) { 515105197Ssam 516120585Ssam DPRINTF(("%s: processing failed for SA %s/%08lx\n", 517281695Sae __func__, ipsec_address(&sav->sah->saidx.dst, buf, 518281695Sae sizeof(buf)), (u_long) ntohl(sav->spi))); 519105197Ssam 520252028Sae IPSEC_ISTAT(sproto, hdrops); 521105197Ssam error = EACCES; 522105197Ssam goto bad; 523105197Ssam } 524105197Ssam 525322741Sae IPSEC_INIT_CTX(&ctx, &m, NULL, sav, af, IPSEC_ENC_BEFORE); 526315514Sae if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0) 527315514Sae goto bad; 528315514Sae 529105197Ssam ip6 = mtod(m, struct ip6_hdr *); 530105197Ssam ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); 531105197Ssam 532105197Ssam /* Save protocol */ 533274466Sae m_copydata(m, protoff, 1, &nxt8); 534274466Sae prot = nxt8; 535105197Ssam 536274466Sae /* IPv6-in-IP encapsulation */ 537274466Sae if (prot == IPPROTO_IPV6 && 538274466Sae saidx->mode != IPSEC_MODE_TRANSPORT) { 539274466Sae if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) { 540252028Sae IPSEC_ISTAT(sproto, hdrops); 541118888Ssam error = EINVAL; 542118888Ssam goto bad; 543118888Ssam } 544274466Sae /* ip6n will now contain the inner IPv6 header. */ 545274466Sae m_striphdr(m, 0, skip); 546266800Svanhu skip = 0; 547105197Ssam } 548274466Sae#ifdef INET 549274466Sae /* IP-in-IP encapsulation */ 550274466Sae else if (prot == IPPROTO_IPIP && 551274466Sae saidx->mode != IPSEC_MODE_TRANSPORT) { 552274466Sae if (m->m_pkthdr.len - skip < sizeof(struct ip)) { 553252028Sae IPSEC_ISTAT(sproto, hdrops); 554118888Ssam error = EINVAL; 555118888Ssam goto bad; 556118888Ssam } 557274466Sae /* ipn will now contain the inner IPv4 header */ 558315514Sae m_striphdr(m, 0, skip); 559266800Svanhu skip = 0; 560159215Sgnn } 561274466Sae#endif /* INET */ 562274466Sae else { 563274466Sae prot = IPPROTO_IPV6; /* for correct BPF processing */ 564274466Sae } 565105197Ssam 566105197Ssam /* 567105197Ssam * Record what we've done to the packet (under what SA it was 568275707Sae * processed). 569105197Ssam */ 570275707Sae if (sproto != IPPROTO_IPCOMP) { 571105197Ssam mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE, 572315514Sae sizeof(struct xform_history), M_NOWAIT); 573105197Ssam if (mtag == NULL) { 574120585Ssam DPRINTF(("%s: failed to get tag\n", __func__)); 575252028Sae IPSEC_ISTAT(sproto, hdrops); 576105197Ssam error = ENOMEM; 577105197Ssam goto bad; 578105197Ssam } 579105197Ssam 580315514Sae xh = (struct xform_history *)(mtag + 1); 581315514Sae bcopy(&saidx->dst, &xh->dst, saidx->dst.sa.sa_len); 582315514Sae xh->spi = sav->spi; 583315514Sae xh->proto = sproto; 584315514Sae xh->mode = saidx->mode; 585105197Ssam m_tag_prepend(m, mtag); 586105197Ssam } 587105197Ssam 588105197Ssam key_sa_recordxfer(sav, m); 589105197Ssam 590266800Svanhu#ifdef INET 591266800Svanhu if (prot == IPPROTO_IPIP) 592291292Sae af = AF_INET; 593291292Sae else 594174054Sbz#endif 595291292Sae af = AF_INET6; 596322741Sae IPSEC_INIT_CTX(&ctx, &m, NULL, sav, af, IPSEC_ENC_AFTER); 597291292Sae if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0) 598291292Sae goto bad; 599281694Sae if (skip == 0) { 600281694Sae /* 601281694Sae * We stripped outer IPv6 header. 602281694Sae * Now we should requeue decrypted packet via netisr. 603281694Sae */ 604281694Sae switch (prot) { 605281694Sae#ifdef INET 606281694Sae case IPPROTO_IPIP: 607281694Sae isr_prot = NETISR_IP; 608281694Sae break; 609281694Sae#endif 610281694Sae case IPPROTO_IPV6: 611281694Sae isr_prot = NETISR_IPV6; 612281694Sae break; 613281694Sae default: 614281694Sae DPRINTF(("%s: cannot handle inner ip proto %d\n", 615281694Sae __func__, prot)); 616281694Sae IPSEC_ISTAT(sproto, nopf); 617281694Sae error = EPFNOSUPPORT; 618281694Sae goto bad; 619281694Sae } 620315514Sae /* Handle virtual tunneling interfaces */ 621315514Sae if (saidx->mode == IPSEC_MODE_TUNNEL) 622315514Sae error = ipsec_if_input(m, sav, af); 623315514Sae if (error == 0) { 624315514Sae error = netisr_queue_src(isr_prot, 625315514Sae (uintptr_t)sav->spi, m); 626315514Sae if (error) { 627315514Sae IPSEC_ISTAT(sproto, qfull); 628315514Sae DPRINTF(("%s: queue full; proto %u packet" 629315514Sae " dropped\n", __func__, sproto)); 630315514Sae } 631281694Sae } 632315514Sae key_freesav(&sav); 633281694Sae return (error); 634281694Sae } 635105197Ssam /* 636105197Ssam * See the end of ip6_input for this logic. 637105197Ssam * IPPROTO_IPV[46] case will be processed just like other ones 638105197Ssam */ 639105197Ssam nest = 0; 640105197Ssam nxt = nxt8; 641105197Ssam while (nxt != IPPROTO_DONE) { 642181803Sbz if (V_ip6_hdrnestlimit && (++nest > V_ip6_hdrnestlimit)) { 643249294Sae IP6STAT_INC(ip6s_toomanyhdr); 644105197Ssam error = EINVAL; 645105197Ssam goto bad; 646105197Ssam } 647105197Ssam 648105197Ssam /* 649105197Ssam * Protection against faulty packet - there should be 650105197Ssam * more sanity checks in header chain processing. 651105197Ssam */ 652105197Ssam if (m->m_pkthdr.len < skip) { 653249294Sae IP6STAT_INC(ip6s_tooshort); 654105197Ssam in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); 655105197Ssam error = EINVAL; 656105197Ssam goto bad; 657105197Ssam } 658105197Ssam /* 659105197Ssam * Enforce IPsec policy checking if we are seeing last header. 660105197Ssam * note that we do not visit this with protocols with pcb layer 661105197Ssam * code - like udp/tcp/raw ip. 662105197Ssam */ 663105197Ssam if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 && 664105197Ssam ipsec6_in_reject(m, NULL)) { 665105197Ssam error = EINVAL; 666105197Ssam goto bad; 667105197Ssam } 668105197Ssam nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &skip, nxt); 669105197Ssam } 670315514Sae key_freesav(&sav); 671315514Sae return (0); 672105197Ssambad: 673315514Sae key_freesav(&sav); 674105197Ssam if (m) 675105197Ssam m_freem(m); 676315514Sae return (error); 677105197Ssam} 678105197Ssam#endif /* INET6 */ 679