1/*
2 * Copyright (c) 2008-2011 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/route.h>
80#include <kern/cpu_number.h>
81#include <kern/locks.h>
82
83#include <netinet/in.h>
84#include <netinet/in_systm.h>
85#include <netinet/ip.h>
86#include <netinet/ip_var.h>
87#include <netinet/in_var.h>
88#include <netinet/ip_ecn.h>
89#include <netinet/in_pcb.h>
90#include <netinet/udp.h>
91#if INET6
92#include <netinet6/ip6_ecn.h>
93#endif
94
95#if INET6
96#include <netinet/ip6.h>
97#include <netinet6/in6_pcb.h>
98#include <netinet6/ip6_var.h>
99#include <netinet/icmp6.h>
100#include <netinet6/ip6protosw.h>
101#endif
102
103#include <netinet6/ipsec.h>
104#if INET6
105#include <netinet6/ipsec6.h>
106#endif
107#include <netinet6/ah.h>
108#if INET6
109#include <netinet6/ah6.h>
110#endif
111#include <netinet6/esp.h>
112#if INET6
113#include <netinet6/esp6.h>
114#endif
115#include <netkey/key.h>
116#include <netkey/keydb.h>
117#include <netkey/key_debug.h>
118
119#include <net/kpi_protocol.h>
120#include <netinet/kpi_ipfilter_var.h>
121
122#include <net/net_osdep.h>
123#include <mach/sdt.h>
124
125#include <sys/kdebug.h>
126#define DBG_LAYER_BEG		NETDBG_CODE(DBG_NETIPSEC, 1)
127#define DBG_LAYER_END		NETDBG_CODE(DBG_NETIPSEC, 3)
128#define DBG_FNC_ESPIN		NETDBG_CODE(DBG_NETIPSEC, (6 << 8))
129#define DBG_FNC_DECRYPT		NETDBG_CODE(DBG_NETIPSEC, (7 << 8))
130#define IPLEN_FLIPPED
131
132extern lck_mtx_t  *sadb_mutex;
133
134#if INET
135extern struct protosw inetsw[];
136
137#define ESPMAXLEN \
138	(sizeof(struct esp) < sizeof(struct newesp) \
139		? sizeof(struct newesp) : sizeof(struct esp))
140
141static struct ip *
142esp4_input_strip_UDP_encap (struct mbuf *m, int iphlen)
143{
144	// strip the udp header that's encapsulating ESP
145	struct ip *ip;
146	size_t     stripsiz = sizeof(struct udphdr);
147
148	ip = mtod(m, __typeof__(ip));
149	ovbcopy((caddr_t)ip, (caddr_t)(((u_char *)ip) + stripsiz), iphlen);
150	m->m_data += stripsiz;
151	m->m_len -= stripsiz;
152	m->m_pkthdr.len -= stripsiz;
153	ip = mtod(m, __typeof__(ip));
154	ip->ip_len = ip->ip_len - stripsiz;
155	ip->ip_p = IPPROTO_ESP;
156	return ip;
157}
158
159void
160esp4_input(m, off)
161	struct mbuf *m;
162	int off;
163{
164	struct ip *ip;
165#if INET6
166	struct ip6_hdr *ip6;
167#endif /* INET6 */
168	struct esp *esp;
169	struct esptail esptail;
170	u_int32_t spi;
171	u_int32_t seq;
172	struct secasvar *sav = NULL;
173	size_t taillen;
174	u_int16_t nxt;
175	const struct esp_algorithm *algo;
176	int ivlen;
177	size_t hlen;
178	size_t esplen;
179	sa_family_t	ifamily;
180
181	KERNEL_DEBUG(DBG_FNC_ESPIN | DBG_FUNC_START, 0,0,0,0,0);
182	/* sanity check for alignment. */
183	if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) {
184		ipseclog((LOG_ERR, "IPv4 ESP input: packet alignment problem "
185			"(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len));
186		IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
187		goto bad;
188	}
189
190	if (m->m_len < off + ESPMAXLEN) {
191		m = m_pullup(m, off + ESPMAXLEN);
192		if (!m) {
193			ipseclog((LOG_DEBUG,
194			    "IPv4 ESP input: can't pullup in esp4_input\n"));
195			IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
196			goto bad;
197		}
198	}
199
200	/* Expect 32-bit aligned data pointer on strict-align platforms */
201	MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
202
203	ip = mtod(m, struct ip *);
204	// expect udp-encap and esp packets only
205	if (ip->ip_p != IPPROTO_ESP &&
206	    !(ip->ip_p == IPPROTO_UDP && off >= sizeof(struct udphdr))) {
207		ipseclog((LOG_DEBUG,
208			  "IPv4 ESP input: invalid protocol type\n"));
209		IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
210		goto bad;
211	}
212	esp = (struct esp *)(void *)(((u_int8_t *)ip) + off);
213#ifdef _IP_VHL
214	hlen = IP_VHL_HL(ip->ip_vhl) << 2;
215#else
216	hlen = ip->ip_hl << 2;
217#endif
218
219	/* find the sassoc. */
220	spi = esp->esp_spi;
221
222	if ((sav = key_allocsa(AF_INET,
223	                      (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst,
224	                      IPPROTO_ESP, spi)) == 0) {
225		ipseclog((LOG_WARNING,
226		    "IPv4 ESP input: no key association found for spi %u\n",
227		    (u_int32_t)ntohl(spi)));
228		IPSEC_STAT_INCREMENT(ipsecstat.in_nosa);
229		goto bad;
230	}
231	KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
232		printf("DP esp4_input called to allocate SA:%p\n", 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#ifndef PULLDOWN_TEST
516			/*
517			 * m_pullup is prohibited in KAME IPv6 input processing
518			 * but there's no other way!
519			 */
520#else
521			/* okay to pullup in m_pulldown style */
522#endif
523			if (m->m_len < sizeof(*ip6)) {
524				m = m_pullup(m, sizeof(*ip6));
525				if (!m) {
526					IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
527					goto bad;
528				}
529			}
530
531			/*
532			 * Expect 32-bit aligned data pointer on strict-align
533			 * platforms.
534			 */
535			MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
536
537			ip6 = mtod(m, struct ip6_hdr *);
538
539			/* ECN consideration. */
540			/* XXX To be fixed later if needed */
541			//  ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos);
542
543			if (!key_checktunnelsanity(sav, AF_INET6,
544			    (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst)) {
545				ipseclog((LOG_ERR, "ipsec tunnel address mismatch "
546			    "in ESP input: %s %s\n",
547			    ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
548				IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
549				goto bad;
550			}
551
552			if (ip6_doscopedroute) {
553				bzero(&addr, sizeof(addr));
554				ip6addr = (__typeof__(ip6addr))&addr;
555				ip6addr->sin6_family = AF_INET6;
556				ip6addr->sin6_len = sizeof(*ip6addr);
557				ip6addr->sin6_addr = ip6->ip6_dst;
558			}
559#endif /* INET6 */
560		} else {
561			ipseclog((LOG_ERR, "ipsec tunnel unsupported address family "
562				  "in ESP input\n"));
563			goto bad;
564		}
565
566		key_sa_recordxfer(sav, m);
567		if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 ||
568		    ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) {
569			IPSEC_STAT_INCREMENT(ipsecstat.in_nomem);
570			goto bad;
571		}
572
573		if (ip_doscopedroute || ip6_doscopedroute) {
574			// update the receiving interface address based on the inner address
575			ifa = ifa_ifwithaddr((struct sockaddr *)&addr);
576			if (ifa) {
577				m->m_pkthdr.rcvif = ifa->ifa_ifp;
578				IFA_REMREF(ifa);
579			}
580		}
581
582		/* Clear the csum flags, they can't be valid for the inner headers */
583		m->m_pkthdr.csum_flags = 0;
584
585		if (sav->utun_in_fn) {
586			if (!(sav->utun_in_fn(sav->utun_pcb, &m, ifamily == AF_INET ? PF_INET : PF_INET6))) {
587				m = NULL;
588				// we just wanna exit since packet has been completely processed
589				goto bad;
590			}
591		}
592
593		if (proto_input(ifamily == AF_INET ? PF_INET : PF_INET6, m) != 0)
594			goto bad;
595
596		nxt = IPPROTO_DONE;
597		KERNEL_DEBUG(DBG_FNC_ESPIN | DBG_FUNC_END, 2,0,0,0,0);
598	} else {
599		/*
600		 * strip off ESP header and IV.
601		 * even in m_pulldown case, we need to strip off ESP so that
602		 * we can always compute checksum for AH correctly.
603		 */
604		size_t stripsiz;
605
606		stripsiz = esplen + ivlen;
607
608		ip = mtod(m, struct ip *);
609		ovbcopy((caddr_t)ip, (caddr_t)(((u_char *)ip) + stripsiz), off);
610		m->m_data += stripsiz;
611		m->m_len -= stripsiz;
612		m->m_pkthdr.len -= stripsiz;
613
614		ip = mtod(m, struct ip *);
615#ifdef IPLEN_FLIPPED
616		ip->ip_len = ip->ip_len - stripsiz;
617#else
618		ip->ip_len = htons(ntohs(ip->ip_len) - stripsiz);
619#endif
620		ip->ip_p = nxt;
621
622		key_sa_recordxfer(sav, m);
623		if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) {
624			IPSEC_STAT_INCREMENT(ipsecstat.in_nomem);
625			goto bad;
626		}
627
628		/*
629		 * Set the csum valid flag, if we authenticated the
630		 * packet, the payload shouldn't be corrupt unless
631		 * it was corrupted before being signed on the other
632		 * side.
633		 */
634		if (nxt == IPPROTO_TCP || nxt == IPPROTO_UDP) {
635			m->m_pkthdr.csum_flags = CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
636			m->m_pkthdr.csum_data = 0xFFFF;
637		}
638
639		if (nxt != IPPROTO_DONE) {
640			if ((ip_protox[nxt]->pr_flags & PR_LASTHDR) != 0 &&
641			    ipsec4_in_reject(m, NULL)) {
642				IPSEC_STAT_INCREMENT(ipsecstat.in_polvio);
643				goto bad;
644			}
645			KERNEL_DEBUG(DBG_FNC_ESPIN | DBG_FUNC_END, 3,0,0,0,0);
646
647			/* translate encapsulated UDP port ? */
648			if ((sav->flags & SADB_X_EXT_NATT_MULTIPLEUSERS) != 0)  {
649				struct udphdr	*udp;
650
651				if (nxt != IPPROTO_UDP)	{	/* not UPD packet - drop it */
652					IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
653					goto bad;
654				}
655
656				if (m->m_len < off + sizeof(struct udphdr)) {
657					m = m_pullup(m, off + sizeof(struct udphdr));
658					if (!m) {
659						ipseclog((LOG_DEBUG,
660							"IPv4 ESP input: can't pullup UDP header in esp4_input\n"));
661						IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
662						goto bad;
663					}
664					ip = mtod(m, struct ip *);
665				}
666				udp = (struct udphdr *)(void *)(((u_int8_t *)ip) + off);
667
668				lck_mtx_lock(sadb_mutex);
669				if (sav->natt_encapsulated_src_port == 0) {
670					sav->natt_encapsulated_src_port = udp->uh_sport;
671				} else if (sav->natt_encapsulated_src_port != udp->uh_sport) {	/* something wrong */
672					IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
673					lck_mtx_unlock(sadb_mutex);
674					goto bad;
675				}
676				lck_mtx_unlock(sadb_mutex);
677				udp->uh_sport = htons(sav->remote_ike_port);
678				udp->uh_sum = 0;
679			}
680
681			DTRACE_IP6(receive, struct mbuf *, m, struct inpcb *, NULL,
682                        	struct ip *, ip, struct ifnet *, m->m_pkthdr.rcvif,
683                        	struct ip *, ip, struct ip6_hdr *, NULL);
684
685			if (sav->utun_in_fn) {
686				if (!(sav->utun_in_fn(sav->utun_pcb, &m, PF_INET))) {
687					m = NULL;
688					// we just wanna exit since packet has been completely processed
689					goto bad;
690				}
691			}
692
693			ip_proto_dispatch_in(m, off, nxt, 0);
694		} else
695			m_freem(m);
696		m = NULL;
697	}
698
699	if (sav) {
700		KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
701			printf("DP esp4_input call free SA:%p\n", sav));
702		key_freesav(sav, KEY_SADB_UNLOCKED);
703	}
704	IPSEC_STAT_INCREMENT(ipsecstat.in_success);
705	return;
706
707bad:
708	if (sav) {
709		KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
710			printf("DP esp4_input call free SA:%p\n", sav));
711		key_freesav(sav, KEY_SADB_UNLOCKED);
712	}
713	if (m)
714		m_freem(m);
715	KERNEL_DEBUG(DBG_FNC_ESPIN | DBG_FUNC_END, 4,0,0,0,0);
716	return;
717}
718#endif /* INET */
719
720#if INET6
721int
722esp6_input(struct mbuf **mp, int *offp, int proto)
723{
724#pragma unused(proto)
725	struct mbuf *m = *mp;
726	int off = *offp;
727	struct ip6_hdr *ip6;
728	struct esp *esp;
729	struct esptail esptail;
730	u_int32_t spi;
731	u_int32_t seq;
732	struct secasvar *sav = NULL;
733	size_t taillen;
734	u_int16_t nxt;
735	const struct esp_algorithm *algo;
736	int ivlen;
737	size_t esplen;
738
739	/* sanity check for alignment. */
740	if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) {
741		ipseclog((LOG_ERR, "IPv6 ESP input: packet alignment problem "
742			"(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len));
743		IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
744		goto bad;
745	}
746
747#ifndef PULLDOWN_TEST
748	IP6_EXTHDR_CHECK(m, off, ESPMAXLEN, {return IPPROTO_DONE;});
749	esp = (struct esp *)(void *)(mtod(m, caddr_t) + off);
750#else
751	IP6_EXTHDR_GET(esp, struct esp *, m, off, ESPMAXLEN);
752	if (esp == NULL) {
753		IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
754		return IPPROTO_DONE;
755	}
756#endif
757	/* Expect 32-bit data aligned pointer on strict-align platforms */
758	MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
759
760	ip6 = mtod(m, struct ip6_hdr *);
761
762	if (ntohs(ip6->ip6_plen) == 0) {
763		ipseclog((LOG_ERR, "IPv6 ESP input: "
764		    "ESP with IPv6 jumbogram is not supported.\n"));
765		IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
766		goto bad;
767	}
768
769	/* find the sassoc. */
770	spi = esp->esp_spi;
771
772	if ((sav = key_allocsa(AF_INET6,
773	                      (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst,
774	                      IPPROTO_ESP, spi)) == 0) {
775		ipseclog((LOG_WARNING,
776		    "IPv6 ESP input: no key association found for spi %u\n",
777		    (u_int32_t)ntohl(spi)));
778		IPSEC_STAT_INCREMENT(ipsec6stat.in_nosa);
779		goto bad;
780	}
781	KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
782		printf("DP esp6_input called to allocate SA:%p\n", sav));
783	if (sav->state != SADB_SASTATE_MATURE
784	 && sav->state != SADB_SASTATE_DYING) {
785		ipseclog((LOG_DEBUG,
786		    "IPv6 ESP input: non-mature/dying SA found for spi %u\n",
787		    (u_int32_t)ntohl(spi)));
788		IPSEC_STAT_INCREMENT(ipsec6stat.in_badspi);
789		goto bad;
790	}
791	algo = esp_algorithm_lookup(sav->alg_enc);
792	if (!algo) {
793		ipseclog((LOG_DEBUG, "IPv6 ESP input: "
794		    "unsupported encryption algorithm for spi %u\n",
795		    (u_int32_t)ntohl(spi)));
796		IPSEC_STAT_INCREMENT(ipsec6stat.in_badspi);
797		goto bad;
798	}
799
800	/* check if we have proper ivlen information */
801	ivlen = sav->ivlen;
802	if (ivlen < 0) {
803		ipseclog((LOG_ERR, "inproper ivlen in IPv6 ESP input: %s %s\n",
804		    ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
805		IPSEC_STAT_INCREMENT(ipsec6stat.in_badspi);
806		goto bad;
807	}
808
809	seq = ntohl(((struct newesp *)esp)->esp_seq);
810
811	if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay
812	 && (sav->alg_auth && sav->key_auth)))
813		goto noreplaycheck;
814
815	if (sav->alg_auth == SADB_X_AALG_NULL ||
816	    sav->alg_auth == SADB_AALG_NONE)
817		goto noreplaycheck;
818
819	/*
820	 * check for sequence number.
821	 */
822	if (ipsec_chkreplay(seq, sav))
823		; /*okey*/
824	else {
825		IPSEC_STAT_INCREMENT(ipsec6stat.in_espreplay);
826		ipseclog((LOG_WARNING,
827		    "replay packet in IPv6 ESP input: %s %s\n",
828		    ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
829		goto bad;
830	}
831
832	/* check ICV */
833    {
834	u_char sum0[AH_MAXSUMSIZE] __attribute__((aligned(4)));
835	u_char sum[AH_MAXSUMSIZE] __attribute__((aligned(4)));
836	const struct ah_algorithm *sumalgo;
837	size_t siz;
838
839	sumalgo = ah_algorithm_lookup(sav->alg_auth);
840	if (!sumalgo)
841		goto noreplaycheck;
842	siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1));
843	if (m->m_pkthdr.len < off + ESPMAXLEN + siz) {
844		IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
845		goto bad;
846	}
847	if (AH_MAXSUMSIZE < siz) {
848		ipseclog((LOG_DEBUG,
849		    "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
850		    (u_int32_t)siz));
851		IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
852		goto bad;
853	}
854
855	m_copydata(m, m->m_pkthdr.len - siz, siz, (caddr_t) &sum0[0]);
856
857	if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) {
858		ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n",
859		    ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
860		IPSEC_STAT_INCREMENT(ipsec6stat.in_espauthfail);
861		goto bad;
862	}
863
864	if (bcmp(sum0, sum, siz) != 0) {
865		ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n",
866		    ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
867		IPSEC_STAT_INCREMENT(ipsec6stat.in_espauthfail);
868		goto bad;
869	}
870
871	/* strip off the authentication data */
872	m_adj(m, -siz);
873	ip6 = mtod(m, struct ip6_hdr *);
874	ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - siz);
875
876	m->m_flags |= M_AUTHIPDGM;
877	IPSEC_STAT_INCREMENT(ipsec6stat.in_espauthsucc);
878    }
879
880	/*
881	 * update sequence number.
882	 */
883	if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
884		if (ipsec_updatereplay(seq, sav)) {
885			IPSEC_STAT_INCREMENT(ipsec6stat.in_espreplay);
886			goto bad;
887		}
888	}
889
890noreplaycheck:
891
892	/* process main esp header. */
893	if (sav->flags & SADB_X_EXT_OLD) {
894		/* RFC 1827 */
895		esplen = sizeof(struct esp);
896	} else {
897		/* RFC 2406 */
898		if (sav->flags & SADB_X_EXT_DERIV)
899			esplen = sizeof(struct esp);
900		else
901			esplen = sizeof(struct newesp);
902	}
903
904	if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) {
905		ipseclog((LOG_WARNING,
906		    "IPv6 ESP input: packet too short\n"));
907		IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
908		goto bad;
909	}
910
911#ifndef PULLDOWN_TEST
912	IP6_EXTHDR_CHECK(m, off, esplen + ivlen, return IPPROTO_DONE);	/*XXX*/
913#else
914	IP6_EXTHDR_GET(esp, struct esp *, m, off, esplen + ivlen);
915	if (esp == NULL) {
916		IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
917		m = NULL;
918		goto bad;
919	}
920#endif
921	ip6 = mtod(m, struct ip6_hdr *);	/*set it again just in case*/
922
923	/*
924	 * pre-compute and cache intermediate key
925	 */
926	if (esp_schedule(algo, sav) != 0) {
927		IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
928		goto bad;
929	}
930
931	/*
932	 * decrypt the packet.
933	 */
934	if (!algo->decrypt)
935		panic("internal error: no decrypt function");
936	if ((*algo->decrypt)(m, off, sav, algo, ivlen)) {
937		/* m is already freed */
938		m = NULL;
939		ipseclog((LOG_ERR, "decrypt fail in IPv6 ESP input: %s\n",
940		    ipsec_logsastr(sav)));
941		IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
942		goto bad;
943	}
944	IPSEC_STAT_INCREMENT(ipsec6stat.in_esphist[sav->alg_enc]);
945
946	m->m_flags |= M_DECRYPTED;
947
948	/*
949	 * find the trailer of the ESP.
950	 */
951	m_copydata(m, m->m_pkthdr.len - sizeof(esptail), sizeof(esptail),
952	     (caddr_t)&esptail);
953	nxt = esptail.esp_nxt;
954	taillen = esptail.esp_padlen + sizeof(esptail);
955
956	if (m->m_pkthdr.len < taillen
957	 || m->m_pkthdr.len - taillen < sizeof(struct ip6_hdr)) {	/*?*/
958		ipseclog((LOG_WARNING,
959		    "bad pad length in IPv6 ESP input: %s %s\n",
960		    ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
961		IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
962		goto bad;
963	}
964
965	/* strip off the trailing pad area. */
966	m_adj(m, -taillen);
967	ip6 = mtod(m, struct ip6_hdr *);
968	ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - taillen);
969
970	if (sav->utun_is_keepalive_fn) {
971		if (sav->utun_is_keepalive_fn(sav->utun_pcb, &m, nxt, sav->flags, (off + esplen + ivlen))) {
972			if (m) {
973				// not really bad, we just wanna exit
974				IPSEC_STAT_INCREMENT(ipsec6stat.in_success);
975				m = NULL;
976			}
977			goto bad;
978		}
979	}
980
981	/* was it transmitted over the IPsec tunnel SA? */
982	if (ipsec6_tunnel_validate(m, off + esplen + ivlen, nxt, sav)) {
983		ifaddr_t ifa;
984		struct sockaddr_storage addr;
985
986		/*
987		 * strip off all the headers that precedes ESP header.
988		 *	IP6 xx ESP IP6' payload -> IP6' payload
989		 *
990		 * XXX more sanity checks
991		 * XXX relationship with gif?
992		 */
993		u_int32_t flowinfo;	/*net endian*/
994		flowinfo = ip6->ip6_flow;
995		m_adj(m, off + esplen + ivlen);
996		if (m->m_len < sizeof(*ip6)) {
997#ifndef PULLDOWN_TEST
998			/*
999			 * m_pullup is prohibited in KAME IPv6 input processing
1000			 * but there's no other way!
1001			 */
1002#else
1003			/* okay to pullup in m_pulldown style */
1004#endif
1005			m = m_pullup(m, sizeof(*ip6));
1006			if (!m) {
1007				IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1008				goto bad;
1009			}
1010		}
1011		ip6 = mtod(m, struct ip6_hdr *);
1012		/* ECN consideration. */
1013		ip6_ecn_egress(ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow);
1014		if (!key_checktunnelsanity(sav, AF_INET6,
1015			    (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst)) {
1016			ipseclog((LOG_ERR, "ipsec tunnel address mismatch "
1017			    "in IPv6 ESP input: %s %s\n",
1018			    ipsec6_logpacketstr(ip6, spi),
1019			    ipsec_logsastr(sav)));
1020			IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1021			goto bad;
1022		}
1023
1024		key_sa_recordxfer(sav, m);
1025		if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 ||
1026		    ipsec_addhist(m, IPPROTO_IPV6, 0) != 0) {
1027			IPSEC_STAT_INCREMENT(ipsec6stat.in_nomem);
1028			goto bad;
1029		}
1030
1031		if (ip6_doscopedroute) {
1032			struct sockaddr_in6 *ip6addr;
1033
1034			bzero(&addr, sizeof(addr));
1035			ip6addr = (__typeof__(ip6addr))&addr;
1036			ip6addr->sin6_family = AF_INET6;
1037			ip6addr->sin6_len = sizeof(*ip6addr);
1038			ip6addr->sin6_addr = ip6->ip6_dst;
1039
1040			// update the receiving interface address based on the inner address
1041			ifa = ifa_ifwithaddr((struct sockaddr *)&addr);
1042			if (ifa) {
1043				m->m_pkthdr.rcvif = ifa->ifa_ifp;
1044				IFA_REMREF(ifa);
1045			}
1046		}
1047
1048		if (sav->utun_in_fn) {
1049			if (!(sav->utun_in_fn(sav->utun_pcb, &m, PF_INET6))) {
1050				m = NULL;
1051				// we just wanna exit since packet has been completely processed
1052				goto bad;
1053			}
1054		}
1055
1056		if (proto_input(PF_INET6, m) != 0)
1057			goto bad;
1058		nxt = IPPROTO_DONE;
1059	} else {
1060		/*
1061		 * strip off ESP header and IV.
1062		 * even in m_pulldown case, we need to strip off ESP so that
1063		 * we can always compute checksum for AH correctly.
1064		 */
1065		size_t stripsiz;
1066		char *prvnxtp;
1067
1068		/*
1069		 * Set the next header field of the previous header correctly.
1070		 */
1071		prvnxtp = ip6_get_prevhdr(m, off); /* XXX */
1072		*prvnxtp = nxt;
1073
1074		stripsiz = esplen + ivlen;
1075
1076		ip6 = mtod(m, struct ip6_hdr *);
1077		if (m->m_len >= stripsiz + off) {
1078			ovbcopy((caddr_t)ip6, ((caddr_t)ip6) + stripsiz, off);
1079			m->m_data += stripsiz;
1080			m->m_len -= stripsiz;
1081			m->m_pkthdr.len -= stripsiz;
1082		} else {
1083			/*
1084			 * this comes with no copy if the boundary is on
1085			 * cluster
1086			 */
1087			struct mbuf *n;
1088
1089			n = m_split(m, off, M_DONTWAIT);
1090			if (n == NULL) {
1091				/* m is retained by m_split */
1092				goto bad;
1093			}
1094			m_adj(n, stripsiz);
1095			/* m_cat does not update m_pkthdr.len */
1096			m->m_pkthdr.len += n->m_pkthdr.len;
1097			m_cat(m, n);
1098		}
1099
1100#ifndef PULLDOWN_TEST
1101		/*
1102		 * KAME requires that the packet to be contiguous on the
1103		 * mbuf.  We need to make that sure.
1104		 * this kind of code should be avoided.
1105		 * XXX other conditions to avoid running this part?
1106		 */
1107		if (m->m_len != m->m_pkthdr.len) {
1108			struct mbuf *n = NULL;
1109			int maxlen;
1110
1111			MGETHDR(n, M_DONTWAIT, MT_HEADER);	/* MAC-OK */
1112			maxlen = MHLEN;
1113			if (n)
1114				M_COPY_PKTHDR(n, m);
1115			if (n && m->m_pkthdr.len > maxlen) {
1116				MCLGET(n, M_DONTWAIT);
1117				maxlen = MCLBYTES;
1118				if ((n->m_flags & M_EXT) == 0) {
1119					m_free(n);
1120					n = NULL;
1121				}
1122			}
1123			if (!n) {
1124				printf("esp6_input: mbuf allocation failed\n");
1125				goto bad;
1126			}
1127
1128			if (m->m_pkthdr.len <= maxlen) {
1129				m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t));
1130				n->m_len = m->m_pkthdr.len;
1131				n->m_pkthdr.len = m->m_pkthdr.len;
1132				n->m_next = NULL;
1133				m_freem(m);
1134			} else {
1135				m_copydata(m, 0, maxlen, mtod(n, caddr_t));
1136				n->m_len = maxlen;
1137				n->m_pkthdr.len = m->m_pkthdr.len;
1138				n->m_next = m;
1139				m_adj(m, maxlen);
1140				m->m_flags &= ~M_PKTHDR;
1141			}
1142			m = n;
1143		}
1144#endif
1145
1146		ip6 = mtod(m, struct ip6_hdr *);
1147		ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - stripsiz);
1148
1149		key_sa_recordxfer(sav, m);
1150		if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) {
1151			IPSEC_STAT_INCREMENT(ipsec6stat.in_nomem);
1152			goto bad;
1153		}
1154
1155		if (sav->utun_in_fn) {
1156			if (!(sav->utun_in_fn(sav->utun_pcb, &m, PF_INET6))) {
1157				m = NULL;
1158				// we just wanna exit since packet has been completely processed
1159				goto bad;
1160			}
1161		}
1162	}
1163
1164	*offp = off;
1165	*mp = m;
1166
1167	if (sav) {
1168		KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
1169			printf("DP esp6_input call free SA:%p\n", sav));
1170		key_freesav(sav, KEY_SADB_UNLOCKED);
1171	}
1172	IPSEC_STAT_INCREMENT(ipsec6stat.in_success);
1173	return nxt;
1174
1175bad:
1176	if (sav) {
1177		KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
1178			printf("DP esp6_input call free SA:%p\n", sav));
1179		key_freesav(sav, KEY_SADB_UNLOCKED);
1180	}
1181	if (m)
1182		m_freem(m);
1183	return IPPROTO_DONE;
1184}
1185
1186void
1187esp6_ctlinput(cmd, sa, d)
1188	int cmd;
1189	struct sockaddr *sa;
1190	void *d;
1191{
1192	const struct newesp *espp;
1193	struct newesp esp;
1194	struct ip6ctlparam *ip6cp = NULL, ip6cp1;
1195	struct secasvar *sav;
1196	struct ip6_hdr *ip6;
1197	struct mbuf *m;
1198	int off;
1199	struct sockaddr_in6 *sa6_src, *sa6_dst;
1200
1201	if (sa->sa_family != AF_INET6 ||
1202	    sa->sa_len != sizeof(struct sockaddr_in6))
1203		return;
1204	if ((unsigned)cmd >= PRC_NCMDS)
1205		return;
1206
1207	/* if the parameter is from icmp6, decode it. */
1208	if (d != NULL) {
1209		ip6cp = (struct ip6ctlparam *)d;
1210		m = ip6cp->ip6c_m;
1211		ip6 = ip6cp->ip6c_ip6;
1212		off = ip6cp->ip6c_off;
1213	} else {
1214		m = NULL;
1215		ip6 = NULL;
1216	}
1217
1218	if (ip6) {
1219		/*
1220		 * Notify the error to all possible sockets via pfctlinput2.
1221		 * Since the upper layer information (such as protocol type,
1222		 * source and destination ports) is embedded in the encrypted
1223		 * data and might have been cut, we can't directly call
1224		 * an upper layer ctlinput function. However, the pcbnotify
1225		 * function will consider source and destination addresses
1226		 * as well as the flow info value, and may be able to find
1227		 * some PCB that should be notified.
1228		 * Although pfctlinput2 will call esp6_ctlinput(), there is
1229		 * no possibility of an infinite loop of function calls,
1230		 * because we don't pass the inner IPv6 header.
1231		 */
1232		bzero(&ip6cp1, sizeof(ip6cp1));
1233		ip6cp1.ip6c_src = ip6cp->ip6c_src;
1234		pfctlinput2(cmd, sa, (void *)&ip6cp1);
1235
1236		/*
1237		 * Then go to special cases that need ESP header information.
1238		 * XXX: We assume that when ip6 is non NULL,
1239		 * M and OFF are valid.
1240		 */
1241
1242		/* check if we can safely examine src and dst ports */
1243		if (m->m_pkthdr.len < off + sizeof(esp))
1244			return;
1245
1246		if (m->m_len < off + sizeof(esp)) {
1247			/*
1248			 * this should be rare case,
1249			 * so we compromise on this copy...
1250			 */
1251			m_copydata(m, off, sizeof(esp), (caddr_t)&esp);
1252			espp = &esp;
1253		} else
1254			espp = (struct newesp*)(void *)(mtod(m, caddr_t) + off);
1255
1256		if (cmd == PRC_MSGSIZE) {
1257			int valid = 0;
1258
1259			/*
1260			 * Check to see if we have a valid SA corresponding to
1261			 * the address in the ICMP message payload.
1262			 */
1263			sa6_src = ip6cp->ip6c_src;
1264			sa6_dst = (struct sockaddr_in6 *)(void *)sa;
1265			sav = key_allocsa(AF_INET6,
1266					  (caddr_t)&sa6_src->sin6_addr,
1267					  (caddr_t)&sa6_dst->sin6_addr,
1268					  IPPROTO_ESP, espp->esp_spi);
1269			if (sav) {
1270				if (sav->state == SADB_SASTATE_MATURE ||
1271				    sav->state == SADB_SASTATE_DYING)
1272					valid++;
1273				key_freesav(sav, KEY_SADB_LOCKED);
1274			}
1275
1276			/* XXX Further validation? */
1277
1278			/*
1279			 * Depending on the value of "valid" and routing table
1280			 * size (mtudisc_{hi,lo}wat), we will:
1281			 * - recalcurate the new MTU and create the
1282			 *   corresponding routing entry, or
1283			 * - ignore the MTU change notification.
1284			 */
1285			icmp6_mtudisc_update((struct ip6ctlparam *)d, valid);
1286		}
1287	} else {
1288		/* we normally notify any pcb here */
1289	}
1290}
1291#endif /* INET6 */
1292