1/*
2 * Copyright (c) 2008-2013 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29/*	$FreeBSD: src/sys/netinet6/esp_input.c,v 1.1.2.3 2001/07/03 11:01:50 ume Exp $	*/
30/*	$KAME: esp_input.c,v 1.55 2001/03/23 08:08:47 itojun Exp $	*/
31
32/*
33 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 *    notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 *    notice, this list of conditions and the following disclaimer in the
43 *    documentation and/or other materials provided with the distribution.
44 * 3. Neither the name of the project nor the names of its contributors
45 *    may be used to endorse or promote products derived from this software
46 *    without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 */
60
61/*
62 * RFC1827/2406 Encapsulated Security Payload.
63 */
64
65#include <sys/param.h>
66#include <sys/systm.h>
67#include <sys/malloc.h>
68#include <sys/mbuf.h>
69#include <sys/mcache.h>
70#include <sys/domain.h>
71#include <sys/protosw.h>
72#include <sys/socket.h>
73#include <sys/errno.h>
74#include <sys/time.h>
75#include <sys/kernel.h>
76#include <sys/syslog.h>
77
78#include <net/if.h>
79#include <net/if_ipsec.h>
80#include <net/route.h>
81#include <kern/cpu_number.h>
82#include <kern/locks.h>
83
84#include <netinet/in.h>
85#include <netinet/in_systm.h>
86#include <netinet/ip.h>
87#include <netinet/ip_var.h>
88#include <netinet/in_var.h>
89#include <netinet/ip_ecn.h>
90#include <netinet/in_pcb.h>
91#include <netinet/udp.h>
92#if INET6
93#include <netinet6/ip6_ecn.h>
94#endif
95
96#if INET6
97#include <netinet/ip6.h>
98#include <netinet6/in6_pcb.h>
99#include <netinet6/ip6_var.h>
100#include <netinet/icmp6.h>
101#include <netinet6/ip6protosw.h>
102#endif
103
104#include <netinet6/ipsec.h>
105#if INET6
106#include <netinet6/ipsec6.h>
107#endif
108#include <netinet6/ah.h>
109#if INET6
110#include <netinet6/ah6.h>
111#endif
112#include <netinet6/esp.h>
113#if INET6
114#include <netinet6/esp6.h>
115#endif
116#include <netkey/key.h>
117#include <netkey/keydb.h>
118#include <netkey/key_debug.h>
119
120#include <net/kpi_protocol.h>
121#include <netinet/kpi_ipfilter_var.h>
122
123#include <net/net_osdep.h>
124#include <mach/sdt.h>
125
126#include <sys/kdebug.h>
127#define DBG_LAYER_BEG		NETDBG_CODE(DBG_NETIPSEC, 1)
128#define DBG_LAYER_END		NETDBG_CODE(DBG_NETIPSEC, 3)
129#define DBG_FNC_ESPIN		NETDBG_CODE(DBG_NETIPSEC, (6 << 8))
130#define DBG_FNC_DECRYPT		NETDBG_CODE(DBG_NETIPSEC, (7 << 8))
131#define IPLEN_FLIPPED
132
133extern lck_mtx_t  *sadb_mutex;
134
135#if INET
136#define ESPMAXLEN \
137	(sizeof(struct esp) < sizeof(struct newesp) \
138		? sizeof(struct newesp) : sizeof(struct esp))
139
140static struct ip *
141esp4_input_strip_UDP_encap (struct mbuf *m, int iphlen)
142{
143	// strip the udp header that's encapsulating ESP
144	struct ip *ip;
145	size_t     stripsiz = sizeof(struct udphdr);
146
147	ip = mtod(m, __typeof__(ip));
148	ovbcopy((caddr_t)ip, (caddr_t)(((u_char *)ip) + stripsiz), iphlen);
149	m->m_data += stripsiz;
150	m->m_len -= stripsiz;
151	m->m_pkthdr.len -= stripsiz;
152	ip = mtod(m, __typeof__(ip));
153	ip->ip_len = ip->ip_len - stripsiz;
154	ip->ip_p = IPPROTO_ESP;
155	return ip;
156}
157
158void
159esp4_input(m, off)
160	struct mbuf *m;
161	int off;
162{
163	struct ip *ip;
164#if INET6
165	struct ip6_hdr *ip6;
166#endif /* INET6 */
167	struct esp *esp;
168	struct esptail esptail;
169	u_int32_t spi;
170	u_int32_t seq;
171	struct secasvar *sav = NULL;
172	size_t taillen;
173	u_int16_t nxt;
174	const struct esp_algorithm *algo;
175	int ivlen;
176	size_t hlen;
177	size_t esplen;
178	sa_family_t	ifamily;
179
180	KERNEL_DEBUG(DBG_FNC_ESPIN | DBG_FUNC_START, 0,0,0,0,0);
181	/* sanity check for alignment. */
182	if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) {
183		ipseclog((LOG_ERR, "IPv4 ESP input: packet alignment problem "
184			"(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len));
185		IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
186		goto bad;
187	}
188
189	if (m->m_len < off + ESPMAXLEN) {
190		m = m_pullup(m, off + ESPMAXLEN);
191		if (!m) {
192			ipseclog((LOG_DEBUG,
193			    "IPv4 ESP input: can't pullup in esp4_input\n"));
194			IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
195			goto bad;
196		}
197	}
198
199	/* Expect 32-bit aligned data pointer on strict-align platforms */
200	MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
201
202	ip = mtod(m, struct ip *);
203	// expect udp-encap and esp packets only
204	if (ip->ip_p != IPPROTO_ESP &&
205	    !(ip->ip_p == IPPROTO_UDP && off >= sizeof(struct udphdr))) {
206		ipseclog((LOG_DEBUG,
207			  "IPv4 ESP input: invalid protocol type\n"));
208		IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
209		goto bad;
210	}
211	esp = (struct esp *)(void *)(((u_int8_t *)ip) + off);
212#ifdef _IP_VHL
213	hlen = IP_VHL_HL(ip->ip_vhl) << 2;
214#else
215	hlen = ip->ip_hl << 2;
216#endif
217
218	/* find the sassoc. */
219	spi = esp->esp_spi;
220
221	if ((sav = key_allocsa(AF_INET,
222	                      (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst,
223	                      IPPROTO_ESP, spi)) == 0) {
224		ipseclog((LOG_WARNING,
225		    "IPv4 ESP input: no key association found for spi %u\n",
226		    (u_int32_t)ntohl(spi)));
227		IPSEC_STAT_INCREMENT(ipsecstat.in_nosa);
228		goto bad;
229	}
230	KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
231	    printf("DP esp4_input called to allocate SA:0x%llx\n",
232	    (uint64_t)VM_KERNEL_ADDRPERM(sav)));
233	if (sav->state != SADB_SASTATE_MATURE
234	 && sav->state != SADB_SASTATE_DYING) {
235		ipseclog((LOG_DEBUG,
236		    "IPv4 ESP input: non-mature/dying SA found for spi %u\n",
237		    (u_int32_t)ntohl(spi)));
238		IPSEC_STAT_INCREMENT(ipsecstat.in_badspi);
239		goto bad;
240	}
241	algo = esp_algorithm_lookup(sav->alg_enc);
242	if (!algo) {
243		ipseclog((LOG_DEBUG, "IPv4 ESP input: "
244		    "unsupported encryption algorithm for spi %u\n",
245		    (u_int32_t)ntohl(spi)));
246		IPSEC_STAT_INCREMENT(ipsecstat.in_badspi);
247		goto bad;
248	}
249
250	/* check if we have proper ivlen information */
251	ivlen = sav->ivlen;
252	if (ivlen < 0) {
253		ipseclog((LOG_ERR, "inproper ivlen in IPv4 ESP input: %s %s\n",
254		    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
255		IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
256		goto bad;
257	}
258
259	seq = ntohl(((struct newesp *)esp)->esp_seq);
260	if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay
261	 && (sav->alg_auth && sav->key_auth)))
262		goto noreplaycheck;
263
264	if (sav->alg_auth == SADB_X_AALG_NULL ||
265	    sav->alg_auth == SADB_AALG_NONE)
266		goto noreplaycheck;
267
268	/*
269	 * check for sequence number.
270	 */
271	if (ipsec_chkreplay(seq, sav))
272		; /*okey*/
273	else {
274		IPSEC_STAT_INCREMENT(ipsecstat.in_espreplay);
275		ipseclog((LOG_WARNING,
276		    "replay packet in IPv4 ESP input: %s %s\n",
277		    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
278		goto bad;
279	}
280
281	/* check ICV */
282    {
283	u_char sum0[AH_MAXSUMSIZE] __attribute__((aligned(4)));
284	u_char sum[AH_MAXSUMSIZE] __attribute__((aligned(4)));
285	const struct ah_algorithm *sumalgo;
286	size_t siz;
287
288	sumalgo = ah_algorithm_lookup(sav->alg_auth);
289	if (!sumalgo)
290		goto noreplaycheck;
291	siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1));
292	if (m->m_pkthdr.len < off + ESPMAXLEN + siz) {
293		IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
294		goto bad;
295	}
296	if (AH_MAXSUMSIZE < siz) {
297		ipseclog((LOG_DEBUG,
298		    "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
299		    (u_int32_t)siz));
300		IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
301		goto bad;
302	}
303
304	m_copydata(m, m->m_pkthdr.len - siz, siz, (caddr_t) &sum0[0]);
305
306	if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) {
307		ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n",
308		    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
309		IPSEC_STAT_INCREMENT(ipsecstat.in_espauthfail);
310		goto bad;
311	}
312
313	if (bcmp(sum0, sum, siz) != 0) {
314		ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n",
315		    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
316		IPSEC_STAT_INCREMENT(ipsecstat.in_espauthfail);
317		goto bad;
318	}
319
320	/* strip off the authentication data */
321	m_adj(m, -siz);
322	ip = mtod(m, struct ip *);
323#ifdef IPLEN_FLIPPED
324	ip->ip_len = ip->ip_len - siz;
325#else
326	ip->ip_len = htons(ntohs(ip->ip_len) - siz);
327#endif
328	m->m_flags |= M_AUTHIPDGM;
329	IPSEC_STAT_INCREMENT(ipsecstat.in_espauthsucc);
330    }
331
332	/*
333	 * update sequence number.
334	 */
335	if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
336		if (ipsec_updatereplay(seq, sav)) {
337			IPSEC_STAT_INCREMENT(ipsecstat.in_espreplay);
338			goto bad;
339		}
340	}
341
342noreplaycheck:
343
344	/* process main esp header. */
345	if (sav->flags & SADB_X_EXT_OLD) {
346		/* RFC 1827 */
347		esplen = sizeof(struct esp);
348	} else {
349		/* RFC 2406 */
350		if (sav->flags & SADB_X_EXT_DERIV)
351			esplen = sizeof(struct esp);
352		else
353			esplen = sizeof(struct newesp);
354	}
355
356	if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) {
357		ipseclog((LOG_WARNING,
358		    "IPv4 ESP input: packet too short\n"));
359		IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
360		goto bad;
361	}
362
363	if (m->m_len < off + esplen + ivlen) {
364		m = m_pullup(m, off + esplen + ivlen);
365		if (!m) {
366			ipseclog((LOG_DEBUG,
367			    "IPv4 ESP input: can't pullup in esp4_input\n"));
368			IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
369			goto bad;
370		}
371	}
372
373	/*
374	 * pre-compute and cache intermediate key
375	 */
376	if (esp_schedule(algo, sav) != 0) {
377		IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
378		goto bad;
379	}
380
381	/*
382	 * decrypt the packet.
383	 */
384	if (!algo->decrypt)
385		panic("internal error: no decrypt function");
386	KERNEL_DEBUG(DBG_FNC_DECRYPT | DBG_FUNC_START, 0,0,0,0,0);
387	if ((*algo->decrypt)(m, off, sav, algo, ivlen)) {
388		/* m is already freed */
389		m = NULL;
390		ipseclog((LOG_ERR, "decrypt fail in IPv4 ESP input: %s\n",
391		    ipsec_logsastr(sav)));
392		IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
393		KERNEL_DEBUG(DBG_FNC_DECRYPT | DBG_FUNC_END, 1,0,0,0,0);
394		goto bad;
395	}
396	KERNEL_DEBUG(DBG_FNC_DECRYPT | DBG_FUNC_END, 2,0,0,0,0);
397	IPSEC_STAT_INCREMENT(ipsecstat.in_esphist[sav->alg_enc]);
398
399	m->m_flags |= M_DECRYPTED;
400
401	/*
402	 * find the trailer of the ESP.
403	 */
404	m_copydata(m, m->m_pkthdr.len - sizeof(esptail), sizeof(esptail),
405	     (caddr_t)&esptail);
406	nxt = esptail.esp_nxt;
407	taillen = esptail.esp_padlen + sizeof(esptail);
408
409	if (m->m_pkthdr.len < taillen
410	 || m->m_pkthdr.len - taillen < hlen) {	/*?*/
411		ipseclog((LOG_WARNING,
412		    "bad pad length in IPv4 ESP input: %s %s\n",
413		    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
414		IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
415		goto bad;
416	}
417
418	/* strip off the trailing pad area. */
419	m_adj(m, -taillen);
420	ip = mtod(m, struct ip *);
421#ifdef IPLEN_FLIPPED
422	ip->ip_len = ip->ip_len - taillen;
423#else
424	ip->ip_len = htons(ntohs(ip->ip_len) - taillen);
425#endif
426	if (ip->ip_p == IPPROTO_UDP) {
427		// offset includes the outer ip and udp header lengths.
428		if (m->m_len < off) {
429			m = m_pullup(m, off);
430			if (!m) {
431				ipseclog((LOG_DEBUG,
432					  "IPv4 ESP input: invalid udp encapsulated ESP packet length \n"));
433				IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
434				goto bad;
435			}
436		}
437
438		// check the UDP encap header to detect changes in the source port, and then strip the header
439		off -= sizeof(struct udphdr); // off no longer includes the udphdr's size
440		// if peer is behind nat and this is the latest esp packet
441		if ((sav->flags & SADB_X_EXT_NATT_DETECTED_PEER) != 0 &&
442		    (sav->flags & SADB_X_EXT_OLD) == 0 &&
443		    seq && sav->replay &&
444		    seq >= sav->replay->lastseq)  {
445			struct udphdr *encap_uh = (__typeof__(encap_uh))(void *)((caddr_t)ip + off);
446			if (encap_uh->uh_sport &&
447			    ntohs(encap_uh->uh_sport) != sav->remote_ike_port) {
448				sav->remote_ike_port = ntohs(encap_uh->uh_sport);
449			}
450		}
451		ip = esp4_input_strip_UDP_encap(m, off);
452		esp = (struct esp *)(void *)(((u_int8_t *)ip) + off);
453	}
454
455	if (sav->utun_is_keepalive_fn) {
456		if (sav->utun_is_keepalive_fn(sav->utun_pcb, &m, nxt, sav->flags, (off + esplen + ivlen))) {
457			if (m) {
458				// not really bad, we just wanna exit
459				IPSEC_STAT_INCREMENT(ipsecstat.in_success);
460				m = NULL;
461			}
462			goto bad;
463		}
464	}
465
466	/* was it transmitted over the IPsec tunnel SA? */
467	if (ipsec4_tunnel_validate(m, off + esplen + ivlen, nxt, sav, &ifamily)) {
468		ifaddr_t ifa;
469		struct sockaddr_storage addr;
470
471		/*
472		 * strip off all the headers that precedes ESP header.
473		 *	IP4 xx ESP IP4' payload -> IP4' payload
474		 *
475		 * XXX more sanity checks
476		 * XXX relationship with gif?
477		 */
478		u_int8_t tos;
479
480		tos = ip->ip_tos;
481		m_adj(m, off + esplen + ivlen);
482		if (ifamily == AF_INET) {
483			struct sockaddr_in *ipaddr;
484
485			if (m->m_len < sizeof(*ip)) {
486				m = m_pullup(m, sizeof(*ip));
487				if (!m) {
488					IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
489					goto bad;
490				}
491			}
492			ip = mtod(m, struct ip *);
493			/* ECN consideration. */
494			ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos);
495			if (!key_checktunnelsanity(sav, AF_INET,
496			    (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst)) {
497				ipseclog((LOG_ERR, "ipsec tunnel address mismatch "
498			    "in ESP input: %s %s\n",
499			    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
500				IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
501				goto bad;
502			}
503
504			if (ip_doscopedroute) {
505				bzero(&addr, sizeof(addr));
506				ipaddr = (__typeof__(ipaddr))&addr;
507				ipaddr->sin_family = AF_INET;
508				ipaddr->sin_len = sizeof(*ipaddr);
509				ipaddr->sin_addr = ip->ip_dst;
510			}
511#if INET6
512		} else if (ifamily == AF_INET6) {
513			struct sockaddr_in6 *ip6addr;
514
515			/*
516			 * m_pullup is prohibited in KAME IPv6 input processing
517			 * but there's no other way!
518			 */
519			if (m->m_len < sizeof(*ip6)) {
520				m = m_pullup(m, sizeof(*ip6));
521				if (!m) {
522					IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
523					goto bad;
524				}
525			}
526
527			/*
528			 * Expect 32-bit aligned data pointer on strict-align
529			 * platforms.
530			 */
531			MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
532
533			ip6 = mtod(m, struct ip6_hdr *);
534
535			/* ECN consideration. */
536			/* XXX To be fixed later if needed */
537			//  ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos);
538
539			if (!key_checktunnelsanity(sav, AF_INET6,
540			    (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst)) {
541				ipseclog((LOG_ERR, "ipsec tunnel address mismatch "
542			    "in ESP input: %s %s\n",
543			    ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
544				IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
545				goto bad;
546			}
547
548			if (ip6_doscopedroute) {
549				bzero(&addr, sizeof(addr));
550				ip6addr = (__typeof__(ip6addr))&addr;
551				ip6addr->sin6_family = AF_INET6;
552				ip6addr->sin6_len = sizeof(*ip6addr);
553				ip6addr->sin6_addr = ip6->ip6_dst;
554			}
555#endif /* INET6 */
556		} else {
557			ipseclog((LOG_ERR, "ipsec tunnel unsupported address family "
558				  "in ESP input\n"));
559			goto bad;
560		}
561
562		key_sa_recordxfer(sav, m);
563		if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 ||
564		    ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) {
565			IPSEC_STAT_INCREMENT(ipsecstat.in_nomem);
566			goto bad;
567		}
568
569		if (ip_doscopedroute || ip6_doscopedroute) {
570			// update the receiving interface address based on the inner address
571			ifa = ifa_ifwithaddr((struct sockaddr *)&addr);
572			if (ifa) {
573				m->m_pkthdr.rcvif = ifa->ifa_ifp;
574				IFA_REMREF(ifa);
575			}
576		}
577
578		/* Clear the csum flags, they can't be valid for the inner headers */
579		m->m_pkthdr.csum_flags = 0;
580
581		// Input via IPSec interface
582		if (sav->sah->ipsec_if != NULL) {
583			if (ipsec_inject_inbound_packet(sav->sah->ipsec_if, m) == 0) {
584				m = NULL;
585				goto done;
586			} else {
587				goto bad;
588			}
589		}
590
591		if (sav->utun_in_fn) {
592			if (!(sav->utun_in_fn(sav->utun_pcb, &m, ifamily == AF_INET ? PF_INET : PF_INET6))) {
593				m = NULL;
594				// we just wanna exit since packet has been completely processed
595				goto bad;
596			}
597		}
598
599		if (proto_input(ifamily == AF_INET ? PF_INET : PF_INET6, m) != 0)
600			goto bad;
601
602		nxt = IPPROTO_DONE;
603		KERNEL_DEBUG(DBG_FNC_ESPIN | DBG_FUNC_END, 2,0,0,0,0);
604	} else {
605		/*
606		 * strip off ESP header and IV.
607		 * even in m_pulldown case, we need to strip off ESP so that
608		 * we can always compute checksum for AH correctly.
609		 */
610		size_t stripsiz;
611
612		stripsiz = esplen + ivlen;
613
614		ip = mtod(m, struct ip *);
615		ovbcopy((caddr_t)ip, (caddr_t)(((u_char *)ip) + stripsiz), off);
616		m->m_data += stripsiz;
617		m->m_len -= stripsiz;
618		m->m_pkthdr.len -= stripsiz;
619
620		ip = mtod(m, struct ip *);
621#ifdef IPLEN_FLIPPED
622		ip->ip_len = ip->ip_len - stripsiz;
623#else
624		ip->ip_len = htons(ntohs(ip->ip_len) - stripsiz);
625#endif
626		ip->ip_p = nxt;
627
628		key_sa_recordxfer(sav, m);
629		if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) {
630			IPSEC_STAT_INCREMENT(ipsecstat.in_nomem);
631			goto bad;
632		}
633
634		/*
635		 * Set the csum valid flag, if we authenticated the
636		 * packet, the payload shouldn't be corrupt unless
637		 * it was corrupted before being signed on the other
638		 * side.
639		 */
640		if (nxt == IPPROTO_TCP || nxt == IPPROTO_UDP) {
641			m->m_pkthdr.csum_flags = CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
642			m->m_pkthdr.csum_data = 0xFFFF;
643		}
644
645		if (nxt != IPPROTO_DONE) {
646			if ((ip_protox[nxt]->pr_flags & PR_LASTHDR) != 0 &&
647			    ipsec4_in_reject(m, NULL)) {
648				IPSEC_STAT_INCREMENT(ipsecstat.in_polvio);
649				goto bad;
650			}
651			KERNEL_DEBUG(DBG_FNC_ESPIN | DBG_FUNC_END, 3,0,0,0,0);
652
653			/* translate encapsulated UDP port ? */
654			if ((sav->flags & SADB_X_EXT_NATT_MULTIPLEUSERS) != 0)  {
655				struct udphdr	*udp;
656
657				if (nxt != IPPROTO_UDP)	{	/* not UPD packet - drop it */
658					IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
659					goto bad;
660				}
661
662				if (m->m_len < off + sizeof(struct udphdr)) {
663					m = m_pullup(m, off + sizeof(struct udphdr));
664					if (!m) {
665						ipseclog((LOG_DEBUG,
666							"IPv4 ESP input: can't pullup UDP header in esp4_input\n"));
667						IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
668						goto bad;
669					}
670					ip = mtod(m, struct ip *);
671				}
672				udp = (struct udphdr *)(void *)(((u_int8_t *)ip) + off);
673
674				lck_mtx_lock(sadb_mutex);
675				if (sav->natt_encapsulated_src_port == 0) {
676					sav->natt_encapsulated_src_port = udp->uh_sport;
677				} else if (sav->natt_encapsulated_src_port != udp->uh_sport) {	/* something wrong */
678					IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
679					lck_mtx_unlock(sadb_mutex);
680					goto bad;
681				}
682				lck_mtx_unlock(sadb_mutex);
683				udp->uh_sport = htons(sav->remote_ike_port);
684				udp->uh_sum = 0;
685			}
686
687			DTRACE_IP6(receive, struct mbuf *, m, struct inpcb *, NULL,
688                        	struct ip *, ip, struct ifnet *, m->m_pkthdr.rcvif,
689                        	struct ip *, ip, struct ip6_hdr *, NULL);
690
691			// Input via IPSec interface
692			if (sav->sah->ipsec_if != NULL) {
693				ip->ip_len = htons(ip->ip_len + hlen);
694				ip->ip_off = htons(ip->ip_off);
695				ip->ip_sum = 0;
696				ip->ip_sum = ip_cksum_hdr_in(m, hlen);
697				if (ipsec_inject_inbound_packet(sav->sah->ipsec_if, m) == 0) {
698					m = NULL;
699					goto done;
700				} else {
701					goto bad;
702				}
703			}
704
705			if (sav->utun_in_fn) {
706				if (!(sav->utun_in_fn(sav->utun_pcb, &m, PF_INET))) {
707					m = NULL;
708					// we just wanna exit since packet has been completely processed
709					goto bad;
710				}
711			}
712
713			ip_proto_dispatch_in(m, off, nxt, 0);
714		} else
715			m_freem(m);
716		m = NULL;
717	}
718
719done:
720	if (sav) {
721		KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
722		    printf("DP esp4_input call free SA:0x%llx\n",
723		    (uint64_t)VM_KERNEL_ADDRPERM(sav)));
724		key_freesav(sav, KEY_SADB_UNLOCKED);
725	}
726	IPSEC_STAT_INCREMENT(ipsecstat.in_success);
727	return;
728
729bad:
730	if (sav) {
731		KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
732		    printf("DP esp4_input call free SA:0x%llx\n",
733		    (uint64_t)VM_KERNEL_ADDRPERM(sav)));
734		key_freesav(sav, KEY_SADB_UNLOCKED);
735	}
736	if (m)
737		m_freem(m);
738	KERNEL_DEBUG(DBG_FNC_ESPIN | DBG_FUNC_END, 4,0,0,0,0);
739	return;
740}
741#endif /* INET */
742
743#if INET6
744int
745esp6_input(struct mbuf **mp, int *offp, int proto)
746{
747#pragma unused(proto)
748	struct mbuf *m = *mp;
749	int off = *offp;
750	struct ip6_hdr *ip6;
751	struct esp *esp;
752	struct esptail esptail;
753	u_int32_t spi;
754	u_int32_t seq;
755	struct secasvar *sav = NULL;
756	size_t taillen;
757	u_int16_t nxt;
758	const struct esp_algorithm *algo;
759	int ivlen;
760	size_t esplen;
761
762	/* sanity check for alignment. */
763	if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) {
764		ipseclog((LOG_ERR, "IPv6 ESP input: packet alignment problem "
765			"(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len));
766		IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
767		goto bad;
768	}
769
770#ifndef PULLDOWN_TEST
771	IP6_EXTHDR_CHECK(m, off, ESPMAXLEN, {return IPPROTO_DONE;});
772	esp = (struct esp *)(void *)(mtod(m, caddr_t) + off);
773#else
774	IP6_EXTHDR_GET(esp, struct esp *, m, off, ESPMAXLEN);
775	if (esp == NULL) {
776		IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
777		return IPPROTO_DONE;
778	}
779#endif
780	/* Expect 32-bit data aligned pointer on strict-align platforms */
781	MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
782
783	ip6 = mtod(m, struct ip6_hdr *);
784
785	if (ntohs(ip6->ip6_plen) == 0) {
786		ipseclog((LOG_ERR, "IPv6 ESP input: "
787		    "ESP with IPv6 jumbogram is not supported.\n"));
788		IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
789		goto bad;
790	}
791
792	/* find the sassoc. */
793	spi = esp->esp_spi;
794
795	if ((sav = key_allocsa(AF_INET6,
796	                      (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst,
797	                      IPPROTO_ESP, spi)) == 0) {
798		ipseclog((LOG_WARNING,
799		    "IPv6 ESP input: no key association found for spi %u\n",
800		    (u_int32_t)ntohl(spi)));
801		IPSEC_STAT_INCREMENT(ipsec6stat.in_nosa);
802		goto bad;
803	}
804	KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
805	    printf("DP esp6_input called to allocate SA:0x%llx\n",
806	    (uint64_t)VM_KERNEL_ADDRPERM(sav)));
807	if (sav->state != SADB_SASTATE_MATURE
808	 && sav->state != SADB_SASTATE_DYING) {
809		ipseclog((LOG_DEBUG,
810		    "IPv6 ESP input: non-mature/dying SA found for spi %u\n",
811		    (u_int32_t)ntohl(spi)));
812		IPSEC_STAT_INCREMENT(ipsec6stat.in_badspi);
813		goto bad;
814	}
815	algo = esp_algorithm_lookup(sav->alg_enc);
816	if (!algo) {
817		ipseclog((LOG_DEBUG, "IPv6 ESP input: "
818		    "unsupported encryption algorithm for spi %u\n",
819		    (u_int32_t)ntohl(spi)));
820		IPSEC_STAT_INCREMENT(ipsec6stat.in_badspi);
821		goto bad;
822	}
823
824	/* check if we have proper ivlen information */
825	ivlen = sav->ivlen;
826	if (ivlen < 0) {
827		ipseclog((LOG_ERR, "inproper ivlen in IPv6 ESP input: %s %s\n",
828		    ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
829		IPSEC_STAT_INCREMENT(ipsec6stat.in_badspi);
830		goto bad;
831	}
832
833	seq = ntohl(((struct newesp *)esp)->esp_seq);
834
835	if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay
836	 && (sav->alg_auth && sav->key_auth)))
837		goto noreplaycheck;
838
839	if (sav->alg_auth == SADB_X_AALG_NULL ||
840	    sav->alg_auth == SADB_AALG_NONE)
841		goto noreplaycheck;
842
843	/*
844	 * check for sequence number.
845	 */
846	if (ipsec_chkreplay(seq, sav))
847		; /*okey*/
848	else {
849		IPSEC_STAT_INCREMENT(ipsec6stat.in_espreplay);
850		ipseclog((LOG_WARNING,
851		    "replay packet in IPv6 ESP input: %s %s\n",
852		    ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
853		goto bad;
854	}
855
856	/* check ICV */
857    {
858	u_char sum0[AH_MAXSUMSIZE] __attribute__((aligned(4)));
859	u_char sum[AH_MAXSUMSIZE] __attribute__((aligned(4)));
860	const struct ah_algorithm *sumalgo;
861	size_t siz;
862
863	sumalgo = ah_algorithm_lookup(sav->alg_auth);
864	if (!sumalgo)
865		goto noreplaycheck;
866	siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1));
867	if (m->m_pkthdr.len < off + ESPMAXLEN + siz) {
868		IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
869		goto bad;
870	}
871	if (AH_MAXSUMSIZE < siz) {
872		ipseclog((LOG_DEBUG,
873		    "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
874		    (u_int32_t)siz));
875		IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
876		goto bad;
877	}
878
879	m_copydata(m, m->m_pkthdr.len - siz, siz, (caddr_t) &sum0[0]);
880
881	if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) {
882		ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n",
883		    ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
884		IPSEC_STAT_INCREMENT(ipsec6stat.in_espauthfail);
885		goto bad;
886	}
887
888	if (bcmp(sum0, sum, siz) != 0) {
889		ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n",
890		    ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
891		IPSEC_STAT_INCREMENT(ipsec6stat.in_espauthfail);
892		goto bad;
893	}
894
895	/* strip off the authentication data */
896	m_adj(m, -siz);
897	ip6 = mtod(m, struct ip6_hdr *);
898	ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - siz);
899
900	m->m_flags |= M_AUTHIPDGM;
901	IPSEC_STAT_INCREMENT(ipsec6stat.in_espauthsucc);
902    }
903
904	/*
905	 * update sequence number.
906	 */
907	if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
908		if (ipsec_updatereplay(seq, sav)) {
909			IPSEC_STAT_INCREMENT(ipsec6stat.in_espreplay);
910			goto bad;
911		}
912	}
913
914noreplaycheck:
915
916	/* process main esp header. */
917	if (sav->flags & SADB_X_EXT_OLD) {
918		/* RFC 1827 */
919		esplen = sizeof(struct esp);
920	} else {
921		/* RFC 2406 */
922		if (sav->flags & SADB_X_EXT_DERIV)
923			esplen = sizeof(struct esp);
924		else
925			esplen = sizeof(struct newesp);
926	}
927
928	if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) {
929		ipseclog((LOG_WARNING,
930		    "IPv6 ESP input: packet too short\n"));
931		IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
932		goto bad;
933	}
934
935#ifndef PULLDOWN_TEST
936	IP6_EXTHDR_CHECK(m, off, esplen + ivlen, return IPPROTO_DONE);	/*XXX*/
937#else
938	IP6_EXTHDR_GET(esp, struct esp *, m, off, esplen + ivlen);
939	if (esp == NULL) {
940		IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
941		m = NULL;
942		goto bad;
943	}
944#endif
945	ip6 = mtod(m, struct ip6_hdr *);	/*set it again just in case*/
946
947	/*
948	 * pre-compute and cache intermediate key
949	 */
950	if (esp_schedule(algo, sav) != 0) {
951		IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
952		goto bad;
953	}
954
955	/*
956	 * decrypt the packet.
957	 */
958	if (!algo->decrypt)
959		panic("internal error: no decrypt function");
960	if ((*algo->decrypt)(m, off, sav, algo, ivlen)) {
961		/* m is already freed */
962		m = NULL;
963		ipseclog((LOG_ERR, "decrypt fail in IPv6 ESP input: %s\n",
964		    ipsec_logsastr(sav)));
965		IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
966		goto bad;
967	}
968	IPSEC_STAT_INCREMENT(ipsec6stat.in_esphist[sav->alg_enc]);
969
970	m->m_flags |= M_DECRYPTED;
971
972	/*
973	 * find the trailer of the ESP.
974	 */
975	m_copydata(m, m->m_pkthdr.len - sizeof(esptail), sizeof(esptail),
976	     (caddr_t)&esptail);
977	nxt = esptail.esp_nxt;
978	taillen = esptail.esp_padlen + sizeof(esptail);
979
980	if (m->m_pkthdr.len < taillen
981	 || m->m_pkthdr.len - taillen < sizeof(struct ip6_hdr)) {	/*?*/
982		ipseclog((LOG_WARNING,
983		    "bad pad length in IPv6 ESP input: %s %s\n",
984		    ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
985		IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
986		goto bad;
987	}
988
989	/* strip off the trailing pad area. */
990	m_adj(m, -taillen);
991	ip6 = mtod(m, struct ip6_hdr *);
992	ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - taillen);
993
994	if (sav->utun_is_keepalive_fn) {
995		if (sav->utun_is_keepalive_fn(sav->utun_pcb, &m, nxt, sav->flags, (off + esplen + ivlen))) {
996			if (m) {
997				// not really bad, we just wanna exit
998				IPSEC_STAT_INCREMENT(ipsec6stat.in_success);
999				m = NULL;
1000			}
1001			goto bad;
1002		}
1003	}
1004
1005	/* was it transmitted over the IPsec tunnel SA? */
1006	if (ipsec6_tunnel_validate(m, off + esplen + ivlen, nxt, sav)) {
1007		ifaddr_t ifa;
1008		struct sockaddr_storage addr;
1009
1010		/*
1011		 * strip off all the headers that precedes ESP header.
1012		 *	IP6 xx ESP IP6' payload -> IP6' payload
1013		 *
1014		 * XXX more sanity checks
1015		 * XXX relationship with gif?
1016		 */
1017		u_int32_t flowinfo;	/*net endian*/
1018		flowinfo = ip6->ip6_flow;
1019		m_adj(m, off + esplen + ivlen);
1020		if (m->m_len < sizeof(*ip6)) {
1021#ifndef PULLDOWN_TEST
1022			/*
1023			 * m_pullup is prohibited in KAME IPv6 input processing
1024			 * but there's no other way!
1025			 */
1026#else
1027			/* okay to pullup in m_pulldown style */
1028#endif
1029			m = m_pullup(m, sizeof(*ip6));
1030			if (!m) {
1031				IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1032				goto bad;
1033			}
1034		}
1035		ip6 = mtod(m, struct ip6_hdr *);
1036		/* ECN consideration. */
1037		ip6_ecn_egress(ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow);
1038		if (!key_checktunnelsanity(sav, AF_INET6,
1039			    (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst)) {
1040			ipseclog((LOG_ERR, "ipsec tunnel address mismatch "
1041			    "in IPv6 ESP input: %s %s\n",
1042			    ipsec6_logpacketstr(ip6, spi),
1043			    ipsec_logsastr(sav)));
1044			IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1045			goto bad;
1046		}
1047
1048		key_sa_recordxfer(sav, m);
1049		if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 ||
1050		    ipsec_addhist(m, IPPROTO_IPV6, 0) != 0) {
1051			IPSEC_STAT_INCREMENT(ipsec6stat.in_nomem);
1052			goto bad;
1053		}
1054
1055		if (ip6_doscopedroute) {
1056			struct sockaddr_in6 *ip6addr;
1057
1058			bzero(&addr, sizeof(addr));
1059			ip6addr = (__typeof__(ip6addr))&addr;
1060			ip6addr->sin6_family = AF_INET6;
1061			ip6addr->sin6_len = sizeof(*ip6addr);
1062			ip6addr->sin6_addr = ip6->ip6_dst;
1063
1064			// update the receiving interface address based on the inner address
1065			ifa = ifa_ifwithaddr((struct sockaddr *)&addr);
1066			if (ifa) {
1067				m->m_pkthdr.rcvif = ifa->ifa_ifp;
1068				IFA_REMREF(ifa);
1069			}
1070		}
1071
1072		// Input via IPSec interface
1073		if (sav->sah->ipsec_if != NULL) {
1074			if (ipsec_inject_inbound_packet(sav->sah->ipsec_if, m) == 0) {
1075				m = NULL;
1076				nxt = IPPROTO_DONE;
1077				goto done;
1078			} else {
1079				goto bad;
1080			}
1081		}
1082
1083		if (sav->utun_in_fn) {
1084			if (!(sav->utun_in_fn(sav->utun_pcb, &m, PF_INET6))) {
1085				m = NULL;
1086				// we just wanna exit since packet has been completely processed
1087				goto bad;
1088			}
1089		}
1090
1091		if (proto_input(PF_INET6, m) != 0)
1092			goto bad;
1093		nxt = IPPROTO_DONE;
1094	} else {
1095		/*
1096		 * strip off ESP header and IV.
1097		 * even in m_pulldown case, we need to strip off ESP so that
1098		 * we can always compute checksum for AH correctly.
1099		 */
1100		size_t stripsiz;
1101		char *prvnxtp;
1102
1103		/*
1104		 * Set the next header field of the previous header correctly.
1105		 */
1106		prvnxtp = ip6_get_prevhdr(m, off); /* XXX */
1107		*prvnxtp = nxt;
1108
1109		stripsiz = esplen + ivlen;
1110
1111		ip6 = mtod(m, struct ip6_hdr *);
1112		if (m->m_len >= stripsiz + off) {
1113			ovbcopy((caddr_t)ip6, ((caddr_t)ip6) + stripsiz, off);
1114			m->m_data += stripsiz;
1115			m->m_len -= stripsiz;
1116			m->m_pkthdr.len -= stripsiz;
1117		} else {
1118			/*
1119			 * this comes with no copy if the boundary is on
1120			 * cluster
1121			 */
1122			struct mbuf *n;
1123
1124			n = m_split(m, off, M_DONTWAIT);
1125			if (n == NULL) {
1126				/* m is retained by m_split */
1127				goto bad;
1128			}
1129			m_adj(n, stripsiz);
1130			/* m_cat does not update m_pkthdr.len */
1131			m->m_pkthdr.len += n->m_pkthdr.len;
1132			m_cat(m, n);
1133		}
1134
1135#ifndef PULLDOWN_TEST
1136		/*
1137		 * KAME requires that the packet to be contiguous on the
1138		 * mbuf.  We need to make that sure.
1139		 * this kind of code should be avoided.
1140		 * XXX other conditions to avoid running this part?
1141		 */
1142		if (m->m_len != m->m_pkthdr.len) {
1143			struct mbuf *n = NULL;
1144			int maxlen;
1145
1146			MGETHDR(n, M_DONTWAIT, MT_HEADER);	/* MAC-OK */
1147			maxlen = MHLEN;
1148			if (n)
1149				M_COPY_PKTHDR(n, m);
1150			if (n && m->m_pkthdr.len > maxlen) {
1151				MCLGET(n, M_DONTWAIT);
1152				maxlen = MCLBYTES;
1153				if ((n->m_flags & M_EXT) == 0) {
1154					m_free(n);
1155					n = NULL;
1156				}
1157			}
1158			if (!n) {
1159				printf("esp6_input: mbuf allocation failed\n");
1160				goto bad;
1161			}
1162
1163			if (m->m_pkthdr.len <= maxlen) {
1164				m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t));
1165				n->m_len = m->m_pkthdr.len;
1166				n->m_pkthdr.len = m->m_pkthdr.len;
1167				n->m_next = NULL;
1168				m_freem(m);
1169			} else {
1170				m_copydata(m, 0, maxlen, mtod(n, caddr_t));
1171				n->m_len = maxlen;
1172				n->m_pkthdr.len = m->m_pkthdr.len;
1173				n->m_next = m;
1174				m_adj(m, maxlen);
1175				m->m_flags &= ~M_PKTHDR;
1176			}
1177			m = n;
1178		}
1179#endif
1180
1181		ip6 = mtod(m, struct ip6_hdr *);
1182		ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - stripsiz);
1183
1184		key_sa_recordxfer(sav, m);
1185		if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) {
1186			IPSEC_STAT_INCREMENT(ipsec6stat.in_nomem);
1187			goto bad;
1188		}
1189
1190		// Input via IPSec interface
1191		if (sav->sah->ipsec_if != NULL) {
1192			if (ipsec_inject_inbound_packet(sav->sah->ipsec_if, m) == 0) {
1193				m = NULL;
1194				nxt = IPPROTO_DONE;
1195				goto done;
1196			} else {
1197				goto bad;
1198			}
1199		}
1200
1201		if (sav->utun_in_fn) {
1202			if (!(sav->utun_in_fn(sav->utun_pcb, &m, PF_INET6))) {
1203				m = NULL;
1204				// we just wanna exit since packet has been completely processed
1205				goto bad;
1206			}
1207		}
1208	}
1209
1210done:
1211	*offp = off;
1212	*mp = m;
1213	if (sav) {
1214		KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
1215		    printf("DP esp6_input call free SA:0x%llx\n",
1216		    (uint64_t)VM_KERNEL_ADDRPERM(sav)));
1217		key_freesav(sav, KEY_SADB_UNLOCKED);
1218	}
1219	IPSEC_STAT_INCREMENT(ipsec6stat.in_success);
1220	return nxt;
1221
1222bad:
1223	if (sav) {
1224		KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
1225		    printf("DP esp6_input call free SA:0x%llx\n",
1226		    (uint64_t)VM_KERNEL_ADDRPERM(sav)));
1227		key_freesav(sav, KEY_SADB_UNLOCKED);
1228	}
1229	if (m)
1230		m_freem(m);
1231	return IPPROTO_DONE;
1232}
1233
1234void
1235esp6_ctlinput(cmd, sa, d)
1236	int cmd;
1237	struct sockaddr *sa;
1238	void *d;
1239{
1240	const struct newesp *espp;
1241	struct newesp esp;
1242	struct ip6ctlparam *ip6cp = NULL, ip6cp1;
1243	struct secasvar *sav;
1244	struct ip6_hdr *ip6;
1245	struct mbuf *m;
1246	int off;
1247	struct sockaddr_in6 *sa6_src, *sa6_dst;
1248
1249	if (sa->sa_family != AF_INET6 ||
1250	    sa->sa_len != sizeof(struct sockaddr_in6))
1251		return;
1252	if ((unsigned)cmd >= PRC_NCMDS)
1253		return;
1254
1255	/* if the parameter is from icmp6, decode it. */
1256	if (d != NULL) {
1257		ip6cp = (struct ip6ctlparam *)d;
1258		m = ip6cp->ip6c_m;
1259		ip6 = ip6cp->ip6c_ip6;
1260		off = ip6cp->ip6c_off;
1261	} else {
1262		m = NULL;
1263		ip6 = NULL;
1264	}
1265
1266	if (ip6) {
1267		/*
1268		 * Notify the error to all possible sockets via pfctlinput2.
1269		 * Since the upper layer information (such as protocol type,
1270		 * source and destination ports) is embedded in the encrypted
1271		 * data and might have been cut, we can't directly call
1272		 * an upper layer ctlinput function. However, the pcbnotify
1273		 * function will consider source and destination addresses
1274		 * as well as the flow info value, and may be able to find
1275		 * some PCB that should be notified.
1276		 * Although pfctlinput2 will call esp6_ctlinput(), there is
1277		 * no possibility of an infinite loop of function calls,
1278		 * because we don't pass the inner IPv6 header.
1279		 */
1280		bzero(&ip6cp1, sizeof(ip6cp1));
1281		ip6cp1.ip6c_src = ip6cp->ip6c_src;
1282		pfctlinput2(cmd, sa, (void *)&ip6cp1);
1283
1284		/*
1285		 * Then go to special cases that need ESP header information.
1286		 * XXX: We assume that when ip6 is non NULL,
1287		 * M and OFF are valid.
1288		 */
1289
1290		/* check if we can safely examine src and dst ports */
1291		if (m->m_pkthdr.len < off + sizeof(esp))
1292			return;
1293
1294		if (m->m_len < off + sizeof(esp)) {
1295			/*
1296			 * this should be rare case,
1297			 * so we compromise on this copy...
1298			 */
1299			m_copydata(m, off, sizeof(esp), (caddr_t)&esp);
1300			espp = &esp;
1301		} else
1302			espp = (struct newesp*)(void *)(mtod(m, caddr_t) + off);
1303
1304		if (cmd == PRC_MSGSIZE) {
1305			int valid = 0;
1306
1307			/*
1308			 * Check to see if we have a valid SA corresponding to
1309			 * the address in the ICMP message payload.
1310			 */
1311			sa6_src = ip6cp->ip6c_src;
1312			sa6_dst = (struct sockaddr_in6 *)(void *)sa;
1313			sav = key_allocsa(AF_INET6,
1314					  (caddr_t)&sa6_src->sin6_addr,
1315					  (caddr_t)&sa6_dst->sin6_addr,
1316					  IPPROTO_ESP, espp->esp_spi);
1317			if (sav) {
1318				if (sav->state == SADB_SASTATE_MATURE ||
1319				    sav->state == SADB_SASTATE_DYING)
1320					valid++;
1321				key_freesav(sav, KEY_SADB_LOCKED);
1322			}
1323
1324			/* XXX Further validation? */
1325
1326			/*
1327			 * Depending on the value of "valid" and routing table
1328			 * size (mtudisc_{hi,lo}wat), we will:
1329			 * - recalcurate the new MTU and create the
1330			 *   corresponding routing entry, or
1331			 * - ignore the MTU change notification.
1332			 */
1333			icmp6_mtudisc_update((struct ip6ctlparam *)d, valid);
1334		}
1335	} else {
1336		/* we normally notify any pcb here */
1337	}
1338}
1339#endif /* INET6 */
1340