]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet6/esp_input.c
xnu-2782.30.5.tar.gz
[apple/xnu.git] / bsd / netinet6 / esp_input.c
CommitLineData
b0d623f7 1/*
39236c6e 2 * Copyright (c) 2008-2013 Apple Inc. All rights reserved.
b0d623f7
A
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
9bccf70c
A
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 $ */
1c79356b
A
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
1c79356b
A
65#include <sys/param.h>
66#include <sys/systm.h>
67#include <sys/malloc.h>
68#include <sys/mbuf.h>
316670eb 69#include <sys/mcache.h>
1c79356b
A
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>
fe8ab488 79#include <net/if_ipsec.h>
1c79356b 80#include <net/route.h>
1c79356b 81#include <kern/cpu_number.h>
91447636 82#include <kern/locks.h>
1c79356b
A
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>
9bccf70c 90#include <netinet/in_pcb.h>
2d21ac55 91#include <netinet/udp.h>
9bccf70c
A
92#if INET6
93#include <netinet6/ip6_ecn.h>
94#endif
1c79356b
A
95
96#if INET6
97#include <netinet/ip6.h>
9bccf70c 98#include <netinet6/in6_pcb.h>
1c79356b
A
99#include <netinet6/ip6_var.h>
100#include <netinet/icmp6.h>
9bccf70c 101#include <netinet6/ip6protosw.h>
1c79356b
A
102#endif
103
104#include <netinet6/ipsec.h>
9bccf70c
A
105#if INET6
106#include <netinet6/ipsec6.h>
107#endif
1c79356b 108#include <netinet6/ah.h>
9bccf70c
A
109#if INET6
110#include <netinet6/ah6.h>
111#endif
1c79356b 112#include <netinet6/esp.h>
9bccf70c
A
113#if INET6
114#include <netinet6/esp6.h>
115#endif
1c79356b
A
116#include <netkey/key.h>
117#include <netkey/keydb.h>
118#include <netkey/key_debug.h>
119
2d21ac55
A
120#include <net/kpi_protocol.h>
121#include <netinet/kpi_ipfilter_var.h>
1c79356b
A
122
123#include <net/net_osdep.h>
6d2010ae 124#include <mach/sdt.h>
1c79356b 125
55e303ae
A
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))
1c79356b
A
131#define IPLEN_FLIPPED
132
2d21ac55
A
133extern lck_mtx_t *sadb_mutex;
134
1c79356b 135#if INET
1c79356b
A
136#define ESPMAXLEN \
137 (sizeof(struct esp) < sizeof(struct newesp) \
138 ? sizeof(struct newesp) : sizeof(struct esp))
139
6d2010ae
A
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
1c79356b
A
158void
159esp4_input(m, off)
160 struct mbuf *m;
161 int off;
162{
163 struct ip *ip;
6d2010ae 164#if INET6
2d21ac55 165 struct ip6_hdr *ip6;
6d2010ae 166#endif /* INET6 */
1c79356b
A
167 struct esp *esp;
168 struct esptail esptail;
169 u_int32_t spi;
6d2010ae 170 u_int32_t seq;
1c79356b
A
171 struct secasvar *sav = NULL;
172 size_t taillen;
173 u_int16_t nxt;
9bccf70c 174 const struct esp_algorithm *algo;
1c79356b
A
175 int ivlen;
176 size_t hlen;
177 size_t esplen;
2d21ac55 178 sa_family_t ifamily;
91447636 179
55e303ae 180 KERNEL_DEBUG(DBG_FNC_ESPIN | DBG_FUNC_START, 0,0,0,0,0);
1c79356b
A
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));
2d21ac55 185 IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
1c79356b
A
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"));
2d21ac55 194 IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
1c79356b
A
195 goto bad;
196 }
197 }
198
316670eb
A
199 /* Expect 32-bit aligned data pointer on strict-align platforms */
200 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
201
1c79356b 202 ip = mtod(m, struct ip *);
6d2010ae
A
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 }
316670eb 211 esp = (struct esp *)(void *)(((u_int8_t *)ip) + off);
1c79356b
A
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)));
2d21ac55 227 IPSEC_STAT_INCREMENT(ipsecstat.in_nosa);
1c79356b
A
228 goto bad;
229 }
230 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
39236c6e
A
231 printf("DP esp4_input called to allocate SA:0x%llx\n",
232 (uint64_t)VM_KERNEL_ADDRPERM(sav)));
1c79356b
A
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)));
2d21ac55 238 IPSEC_STAT_INCREMENT(ipsecstat.in_badspi);
1c79356b
A
239 goto bad;
240 }
9bccf70c
A
241 algo = esp_algorithm_lookup(sav->alg_enc);
242 if (!algo) {
1c79356b 243 ipseclog((LOG_DEBUG, "IPv4 ESP input: "
9bccf70c 244 "unsupported encryption algorithm for spi %u\n",
1c79356b 245 (u_int32_t)ntohl(spi)));
2d21ac55 246 IPSEC_STAT_INCREMENT(ipsecstat.in_badspi);
1c79356b
A
247 goto bad;
248 }
249
1c79356b
A
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)));
2d21ac55 255 IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
1c79356b
A
256 goto bad;
257 }
258
6d2010ae 259 seq = ntohl(((struct newesp *)esp)->esp_seq);
1c79356b
A
260 if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay
261 && (sav->alg_auth && sav->key_auth)))
262 goto noreplaycheck;
263
9bccf70c
A
264 if (sav->alg_auth == SADB_X_AALG_NULL ||
265 sav->alg_auth == SADB_AALG_NONE)
1c79356b
A
266 goto noreplaycheck;
267
268 /*
269 * check for sequence number.
270 */
6d2010ae 271 if (ipsec_chkreplay(seq, sav))
1c79356b
A
272 ; /*okey*/
273 else {
2d21ac55 274 IPSEC_STAT_INCREMENT(ipsecstat.in_espreplay);
1c79356b
A
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 {
316670eb
A
283 u_char sum0[AH_MAXSUMSIZE] __attribute__((aligned(4)));
284 u_char sum[AH_MAXSUMSIZE] __attribute__((aligned(4)));
9bccf70c 285 const struct ah_algorithm *sumalgo;
1c79356b
A
286 size_t siz;
287
9bccf70c
A
288 sumalgo = ah_algorithm_lookup(sav->alg_auth);
289 if (!sumalgo)
290 goto noreplaycheck;
1c79356b 291 siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1));
143cc14e 292 if (m->m_pkthdr.len < off + ESPMAXLEN + siz) {
2d21ac55 293 IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
143cc14e
A
294 goto bad;
295 }
1c79356b
A
296 if (AH_MAXSUMSIZE < siz) {
297 ipseclog((LOG_DEBUG,
298 "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
b0d623f7 299 (u_int32_t)siz));
2d21ac55 300 IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
1c79356b
A
301 goto bad;
302 }
303
b0d623f7 304 m_copydata(m, m->m_pkthdr.len - siz, siz, (caddr_t) &sum0[0]);
1c79356b
A
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)));
2d21ac55 309 IPSEC_STAT_INCREMENT(ipsecstat.in_espauthfail);
1c79356b
A
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)));
2d21ac55 316 IPSEC_STAT_INCREMENT(ipsecstat.in_espauthfail);
1c79356b
A
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;
2d21ac55 329 IPSEC_STAT_INCREMENT(ipsecstat.in_espauthsucc);
1c79356b
A
330 }
331
332 /*
333 * update sequence number.
334 */
335 if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
6d2010ae 336 if (ipsec_updatereplay(seq, sav)) {
2d21ac55 337 IPSEC_STAT_INCREMENT(ipsecstat.in_espreplay);
1c79356b
A
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"));
2d21ac55 359 IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
1c79356b
A
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"));
2d21ac55 368 IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
1c79356b
A
369 goto bad;
370 }
371 }
372
9bccf70c
A
373 /*
374 * pre-compute and cache intermediate key
375 */
376 if (esp_schedule(algo, sav) != 0) {
2d21ac55 377 IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
9bccf70c
A
378 goto bad;
379 }
380
1c79356b
A
381 /*
382 * decrypt the packet.
383 */
384 if (!algo->decrypt)
385 panic("internal error: no decrypt function");
55e303ae 386 KERNEL_DEBUG(DBG_FNC_DECRYPT | DBG_FUNC_START, 0,0,0,0,0);
1c79356b 387 if ((*algo->decrypt)(m, off, sav, algo, ivlen)) {
9bccf70c
A
388 /* m is already freed */
389 m = NULL;
390 ipseclog((LOG_ERR, "decrypt fail in IPv4 ESP input: %s\n",
391 ipsec_logsastr(sav)));
2d21ac55 392 IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
55e303ae 393 KERNEL_DEBUG(DBG_FNC_DECRYPT | DBG_FUNC_END, 1,0,0,0,0);
1c79356b
A
394 goto bad;
395 }
55e303ae 396 KERNEL_DEBUG(DBG_FNC_DECRYPT | DBG_FUNC_END, 2,0,0,0,0);
2d21ac55 397 IPSEC_STAT_INCREMENT(ipsecstat.in_esphist[sav->alg_enc]);
1c79356b
A
398
399 m->m_flags |= M_DECRYPTED;
1c79356b
A
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)));
2d21ac55 414 IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
1c79356b
A
415 goto bad;
416 }
417
418 /* strip off the trailing pad area. */
419 m_adj(m, -taillen);
935ed37a 420 ip = mtod(m, struct ip *);
1c79356b
A
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
6d2010ae
A
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) {
316670eb 445 struct udphdr *encap_uh = (__typeof__(encap_uh))(void *)((caddr_t)ip + off);
6d2010ae 446 if (encap_uh->uh_sport &&
e2d2fc5c
A
447 ntohs(encap_uh->uh_sport) != sav->remote_ike_port) {
448 sav->remote_ike_port = ntohs(encap_uh->uh_sport);
6d2010ae
A
449 }
450 }
451 ip = esp4_input_strip_UDP_encap(m, off);
316670eb
A
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 }
6d2010ae 464 }
1c79356b
A
465
466 /* was it transmitted over the IPsec tunnel SA? */
2d21ac55 467 if (ipsec4_tunnel_validate(m, off + esplen + ivlen, nxt, sav, &ifamily)) {
6d2010ae
A
468 ifaddr_t ifa;
469 struct sockaddr_storage addr;
470
1c79356b
A
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);
2d21ac55 482 if (ifamily == AF_INET) {
6d2010ae
A
483 struct sockaddr_in *ipaddr;
484
2d21ac55
A
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 }
1c79356b 491 }
2d21ac55
A
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,
1c79356b 496 (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst)) {
2d21ac55
A
497 ipseclog((LOG_ERR, "ipsec tunnel address mismatch "
498 "in ESP input: %s %s\n",
1c79356b 499 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
2d21ac55
A
500 IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
501 goto bad;
502 }
6d2010ae
A
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 }
2d21ac55
A
511#if INET6
512 } else if (ifamily == AF_INET6) {
6d2010ae
A
513 struct sockaddr_in6 *ip6addr;
514
2d21ac55
A
515 /*
516 * m_pullup is prohibited in KAME IPv6 input processing
517 * but there's no other way!
518 */
2d21ac55
A
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
316670eb
A
527 /*
528 * Expect 32-bit aligned data pointer on strict-align
529 * platforms.
530 */
531 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
532
2d21ac55
A
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;
6d2010ae
A
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 }
2d21ac55
A
555#endif /* INET6 */
556 } else {
557 ipseclog((LOG_ERR, "ipsec tunnel unsupported address family "
558 "in ESP input\n"));
1c79356b
A
559 goto bad;
560 }
561
1c79356b 562 key_sa_recordxfer(sav, m);
9bccf70c
A
563 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 ||
564 ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) {
2d21ac55 565 IPSEC_STAT_INCREMENT(ipsecstat.in_nomem);
9bccf70c
A
566 goto bad;
567 }
6d2010ae
A
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
55e303ae
A
578 /* Clear the csum flags, they can't be valid for the inner headers */
579 m->m_pkthdr.csum_flags = 0;
316670eb 580
fe8ab488
A
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
316670eb
A
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
6d2010ae
A
599 if (proto_input(ifamily == AF_INET ? PF_INET : PF_INET6, m) != 0)
600 goto bad;
601
1c79356b 602 nxt = IPPROTO_DONE;
55e303ae 603 KERNEL_DEBUG(DBG_FNC_ESPIN | DBG_FUNC_END, 2,0,0,0,0);
1c79356b
A
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);
9bccf70c 629 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) {
2d21ac55 630 IPSEC_STAT_INCREMENT(ipsecstat.in_nomem);
9bccf70c
A
631 goto bad;
632 }
55e303ae
A
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 }
1c79356b 644
9bccf70c
A
645 if (nxt != IPPROTO_DONE) {
646 if ((ip_protox[nxt]->pr_flags & PR_LASTHDR) != 0 &&
647 ipsec4_in_reject(m, NULL)) {
2d21ac55 648 IPSEC_STAT_INCREMENT(ipsecstat.in_polvio);
9bccf70c
A
649 goto bad;
650 }
55e303ae 651 KERNEL_DEBUG(DBG_FNC_ESPIN | DBG_FUNC_END, 3,0,0,0,0);
2d21ac55
A
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 }
316670eb 672 udp = (struct udphdr *)(void *)(((u_int8_t *)ip) + off);
2d21ac55
A
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 }
6d2010ae
A
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
fe8ab488
A
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
316670eb
A
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
91447636 713 ip_proto_dispatch_in(m, off, nxt, 0);
9bccf70c 714 } else
1c79356b
A
715 m_freem(m);
716 m = NULL;
717 }
718
fe8ab488 719done:
1c79356b
A
720 if (sav) {
721 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
39236c6e
A
722 printf("DP esp4_input call free SA:0x%llx\n",
723 (uint64_t)VM_KERNEL_ADDRPERM(sav)));
2d21ac55 724 key_freesav(sav, KEY_SADB_UNLOCKED);
1c79356b 725 }
2d21ac55 726 IPSEC_STAT_INCREMENT(ipsecstat.in_success);
1c79356b
A
727 return;
728
729bad:
730 if (sav) {
731 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
39236c6e
A
732 printf("DP esp4_input call free SA:0x%llx\n",
733 (uint64_t)VM_KERNEL_ADDRPERM(sav)));
2d21ac55 734 key_freesav(sav, KEY_SADB_UNLOCKED);
1c79356b
A
735 }
736 if (m)
737 m_freem(m);
55e303ae 738 KERNEL_DEBUG(DBG_FNC_ESPIN | DBG_FUNC_END, 4,0,0,0,0);
1c79356b
A
739 return;
740}
741#endif /* INET */
742
743#if INET6
744int
6d2010ae 745esp6_input(struct mbuf **mp, int *offp, int proto)
1c79356b 746{
6d2010ae 747#pragma unused(proto)
1c79356b
A
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;
6d2010ae 754 u_int32_t seq;
1c79356b
A
755 struct secasvar *sav = NULL;
756 size_t taillen;
757 u_int16_t nxt;
9bccf70c 758 const struct esp_algorithm *algo;
1c79356b
A
759 int ivlen;
760 size_t esplen;
91447636 761
1c79356b
A
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));
2d21ac55 766 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1c79356b
A
767 goto bad;
768 }
769
770#ifndef PULLDOWN_TEST
2d21ac55 771 IP6_EXTHDR_CHECK(m, off, ESPMAXLEN, {return IPPROTO_DONE;});
316670eb 772 esp = (struct esp *)(void *)(mtod(m, caddr_t) + off);
1c79356b
A
773#else
774 IP6_EXTHDR_GET(esp, struct esp *, m, off, ESPMAXLEN);
775 if (esp == NULL) {
2d21ac55 776 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1c79356b
A
777 return IPPROTO_DONE;
778 }
779#endif
316670eb
A
780 /* Expect 32-bit data aligned pointer on strict-align platforms */
781 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
782
1c79356b
A
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"));
2d21ac55 788 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1c79356b
A
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)));
2d21ac55 801 IPSEC_STAT_INCREMENT(ipsec6stat.in_nosa);
1c79356b
A
802 goto bad;
803 }
804 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
39236c6e
A
805 printf("DP esp6_input called to allocate SA:0x%llx\n",
806 (uint64_t)VM_KERNEL_ADDRPERM(sav)));
1c79356b
A
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)));
2d21ac55 812 IPSEC_STAT_INCREMENT(ipsec6stat.in_badspi);
1c79356b
A
813 goto bad;
814 }
9bccf70c
A
815 algo = esp_algorithm_lookup(sav->alg_enc);
816 if (!algo) {
1c79356b 817 ipseclog((LOG_DEBUG, "IPv6 ESP input: "
9bccf70c 818 "unsupported encryption algorithm for spi %u\n",
1c79356b 819 (u_int32_t)ntohl(spi)));
2d21ac55 820 IPSEC_STAT_INCREMENT(ipsec6stat.in_badspi);
1c79356b
A
821 goto bad;
822 }
823
1c79356b
A
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)));
2d21ac55 829 IPSEC_STAT_INCREMENT(ipsec6stat.in_badspi);
1c79356b
A
830 goto bad;
831 }
832
6d2010ae
A
833 seq = ntohl(((struct newesp *)esp)->esp_seq);
834
1c79356b
A
835 if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay
836 && (sav->alg_auth && sav->key_auth)))
837 goto noreplaycheck;
838
9bccf70c
A
839 if (sav->alg_auth == SADB_X_AALG_NULL ||
840 sav->alg_auth == SADB_AALG_NONE)
1c79356b
A
841 goto noreplaycheck;
842
843 /*
844 * check for sequence number.
845 */
6d2010ae 846 if (ipsec_chkreplay(seq, sav))
1c79356b
A
847 ; /*okey*/
848 else {
2d21ac55 849 IPSEC_STAT_INCREMENT(ipsec6stat.in_espreplay);
1c79356b
A
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 {
316670eb
A
858 u_char sum0[AH_MAXSUMSIZE] __attribute__((aligned(4)));
859 u_char sum[AH_MAXSUMSIZE] __attribute__((aligned(4)));
9bccf70c 860 const struct ah_algorithm *sumalgo;
1c79356b
A
861 size_t siz;
862
9bccf70c
A
863 sumalgo = ah_algorithm_lookup(sav->alg_auth);
864 if (!sumalgo)
865 goto noreplaycheck;
1c79356b 866 siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1));
143cc14e 867 if (m->m_pkthdr.len < off + ESPMAXLEN + siz) {
2d21ac55 868 IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
143cc14e
A
869 goto bad;
870 }
1c79356b
A
871 if (AH_MAXSUMSIZE < siz) {
872 ipseclog((LOG_DEBUG,
873 "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
b0d623f7 874 (u_int32_t)siz));
2d21ac55 875 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1c79356b
A
876 goto bad;
877 }
878
b0d623f7 879 m_copydata(m, m->m_pkthdr.len - siz, siz, (caddr_t) &sum0[0]);
1c79356b
A
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)));
2d21ac55 884 IPSEC_STAT_INCREMENT(ipsec6stat.in_espauthfail);
1c79356b
A
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)));
2d21ac55 891 IPSEC_STAT_INCREMENT(ipsec6stat.in_espauthfail);
1c79356b
A
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;
2d21ac55 901 IPSEC_STAT_INCREMENT(ipsec6stat.in_espauthsucc);
1c79356b
A
902 }
903
904 /*
905 * update sequence number.
906 */
907 if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
6d2010ae 908 if (ipsec_updatereplay(seq, sav)) {
2d21ac55 909 IPSEC_STAT_INCREMENT(ipsec6stat.in_espreplay);
1c79356b
A
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"));
2d21ac55 931 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1c79356b
A
932 goto bad;
933 }
934
935#ifndef PULLDOWN_TEST
91447636 936 IP6_EXTHDR_CHECK(m, off, esplen + ivlen, return IPPROTO_DONE); /*XXX*/
1c79356b
A
937#else
938 IP6_EXTHDR_GET(esp, struct esp *, m, off, esplen + ivlen);
939 if (esp == NULL) {
2d21ac55 940 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1c79356b
A
941 m = NULL;
942 goto bad;
943 }
944#endif
945 ip6 = mtod(m, struct ip6_hdr *); /*set it again just in case*/
946
9bccf70c
A
947 /*
948 * pre-compute and cache intermediate key
949 */
950 if (esp_schedule(algo, sav) != 0) {
2d21ac55 951 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
9bccf70c
A
952 goto bad;
953 }
954
1c79356b
A
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)) {
9bccf70c
A
961 /* m is already freed */
962 m = NULL;
963 ipseclog((LOG_ERR, "decrypt fail in IPv6 ESP input: %s\n",
964 ipsec_logsastr(sav)));
2d21ac55 965 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1c79356b
A
966 goto bad;
967 }
2d21ac55 968 IPSEC_STAT_INCREMENT(ipsec6stat.in_esphist[sav->alg_enc]);
1c79356b
A
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)));
2d21ac55 985 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1c79356b
A
986 goto bad;
987 }
988
989 /* strip off the trailing pad area. */
990 m_adj(m, -taillen);
935ed37a 991 ip6 = mtod(m, struct ip6_hdr *);
1c79356b
A
992 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - taillen);
993
316670eb
A
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
1c79356b 1005 /* was it transmitted over the IPsec tunnel SA? */
9bccf70c 1006 if (ipsec6_tunnel_validate(m, off + esplen + ivlen, nxt, sav)) {
6d2010ae
A
1007 ifaddr_t ifa;
1008 struct sockaddr_storage addr;
1009
1c79356b
A
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) {
2d21ac55 1031 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1c79356b
A
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)));
2d21ac55 1044 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1c79356b
A
1045 goto bad;
1046 }
1047
1c79356b 1048 key_sa_recordxfer(sav, m);
9bccf70c
A
1049 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 ||
1050 ipsec_addhist(m, IPPROTO_IPV6, 0) != 0) {
2d21ac55 1051 IPSEC_STAT_INCREMENT(ipsec6stat.in_nomem);
9bccf70c
A
1052 goto bad;
1053 }
6d2010ae
A
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
fe8ab488
A
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
316670eb
A
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
6d2010ae
A
1091 if (proto_input(PF_INET6, m) != 0)
1092 goto bad;
1c79356b
A
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);
1c79356b
A
1130 /* m_cat does not update m_pkthdr.len */
1131 m->m_pkthdr.len += n->m_pkthdr.len;
55e303ae 1132 m_cat(m, n);
1c79356b
A
1133 }
1134
9bccf70c
A
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
2d21ac55 1146 MGETHDR(n, M_DONTWAIT, MT_HEADER); /* MAC-OK */
9bccf70c
A
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));
9bccf70c
A
1171 n->m_len = maxlen;
1172 n->m_pkthdr.len = m->m_pkthdr.len;
1173 n->m_next = m;
55e303ae 1174 m_adj(m, maxlen);
9bccf70c
A
1175 m->m_flags &= ~M_PKTHDR;
1176 }
1177 m = n;
1178 }
1179#endif
1180
1c79356b
A
1181 ip6 = mtod(m, struct ip6_hdr *);
1182 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - stripsiz);
1183
1184 key_sa_recordxfer(sav, m);
9bccf70c 1185 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) {
2d21ac55 1186 IPSEC_STAT_INCREMENT(ipsec6stat.in_nomem);
9bccf70c
A
1187 goto bad;
1188 }
316670eb 1189
fe8ab488
A
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
316670eb
A
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 }
1c79356b
A
1208 }
1209
fe8ab488 1210done:
1c79356b
A
1211 *offp = off;
1212 *mp = m;
1c79356b
A
1213 if (sav) {
1214 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
39236c6e
A
1215 printf("DP esp6_input call free SA:0x%llx\n",
1216 (uint64_t)VM_KERNEL_ADDRPERM(sav)));
2d21ac55 1217 key_freesav(sav, KEY_SADB_UNLOCKED);
1c79356b 1218 }
2d21ac55 1219 IPSEC_STAT_INCREMENT(ipsec6stat.in_success);
1c79356b
A
1220 return nxt;
1221
1222bad:
1223 if (sav) {
1224 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
39236c6e
A
1225 printf("DP esp6_input call free SA:0x%llx\n",
1226 (uint64_t)VM_KERNEL_ADDRPERM(sav)));
2d21ac55 1227 key_freesav(sav, KEY_SADB_UNLOCKED);
1c79356b
A
1228 }
1229 if (m)
1230 m_freem(m);
1231 return IPPROTO_DONE;
1232}
9bccf70c
A
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;
55e303ae 1247 struct sockaddr_in6 *sa6_src, *sa6_dst;
9bccf70c
A
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
316670eb 1302 espp = (struct newesp*)(void *)(mtod(m, caddr_t) + off);
9bccf70c
A
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 */
55e303ae 1311 sa6_src = ip6cp->ip6c_src;
316670eb 1312 sa6_dst = (struct sockaddr_in6 *)(void *)sa;
9bccf70c 1313 sav = key_allocsa(AF_INET6,
55e303ae
A
1314 (caddr_t)&sa6_src->sin6_addr,
1315 (caddr_t)&sa6_dst->sin6_addr,
1316 IPPROTO_ESP, espp->esp_spi);
9bccf70c
A
1317 if (sav) {
1318 if (sav->state == SADB_SASTATE_MATURE ||
1319 sav->state == SADB_SASTATE_DYING)
1320 valid++;
2d21ac55 1321 key_freesav(sav, KEY_SADB_LOCKED);
9bccf70c
A
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}
1c79356b 1339#endif /* INET6 */