]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet6/esp_input.c
xnu-2050.48.11.tar.gz
[apple/xnu.git] / bsd / netinet6 / esp_input.c
CommitLineData
b0d623f7 1/*
316670eb 2 * Copyright (c) 2008-2011 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>
79#include <net/route.h>
1c79356b 80#include <kern/cpu_number.h>
91447636 81#include <kern/locks.h>
1c79356b
A
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>
9bccf70c 89#include <netinet/in_pcb.h>
2d21ac55 90#include <netinet/udp.h>
9bccf70c
A
91#if INET6
92#include <netinet6/ip6_ecn.h>
93#endif
1c79356b
A
94
95#if INET6
96#include <netinet/ip6.h>
9bccf70c 97#include <netinet6/in6_pcb.h>
1c79356b
A
98#include <netinet6/ip6_var.h>
99#include <netinet/icmp6.h>
9bccf70c 100#include <netinet6/ip6protosw.h>
1c79356b
A
101#endif
102
103#include <netinet6/ipsec.h>
9bccf70c
A
104#if INET6
105#include <netinet6/ipsec6.h>
106#endif
1c79356b 107#include <netinet6/ah.h>
9bccf70c
A
108#if INET6
109#include <netinet6/ah6.h>
110#endif
1c79356b 111#include <netinet6/esp.h>
9bccf70c
A
112#if INET6
113#include <netinet6/esp6.h>
114#endif
1c79356b
A
115#include <netkey/key.h>
116#include <netkey/keydb.h>
117#include <netkey/key_debug.h>
118
2d21ac55
A
119#include <net/kpi_protocol.h>
120#include <netinet/kpi_ipfilter_var.h>
1c79356b
A
121
122#include <net/net_osdep.h>
6d2010ae 123#include <mach/sdt.h>
1c79356b 124
55e303ae
A
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))
1c79356b
A
130#define IPLEN_FLIPPED
131
2d21ac55
A
132extern lck_mtx_t *sadb_mutex;
133
1c79356b
A
134#if INET
135extern struct protosw inetsw[];
1c79356b
A
136
137#define ESPMAXLEN \
138 (sizeof(struct esp) < sizeof(struct newesp) \
139 ? sizeof(struct newesp) : sizeof(struct esp))
140
6d2010ae
A
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
1c79356b
A
159void
160esp4_input(m, off)
161 struct mbuf *m;
162 int off;
163{
164 struct ip *ip;
6d2010ae 165#if INET6
2d21ac55 166 struct ip6_hdr *ip6;
6d2010ae 167#endif /* INET6 */
1c79356b
A
168 struct esp *esp;
169 struct esptail esptail;
170 u_int32_t spi;
6d2010ae 171 u_int32_t seq;
1c79356b
A
172 struct secasvar *sav = NULL;
173 size_t taillen;
174 u_int16_t nxt;
9bccf70c 175 const struct esp_algorithm *algo;
1c79356b
A
176 int ivlen;
177 size_t hlen;
178 size_t esplen;
2d21ac55 179 sa_family_t ifamily;
91447636 180
55e303ae 181 KERNEL_DEBUG(DBG_FNC_ESPIN | DBG_FUNC_START, 0,0,0,0,0);
1c79356b
A
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));
2d21ac55 186 IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
1c79356b
A
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"));
2d21ac55 195 IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
1c79356b
A
196 goto bad;
197 }
198 }
199
316670eb
A
200 /* Expect 32-bit aligned data pointer on strict-align platforms */
201 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
202
1c79356b 203 ip = mtod(m, struct ip *);
6d2010ae
A
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 }
316670eb 212 esp = (struct esp *)(void *)(((u_int8_t *)ip) + off);
1c79356b
A
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)));
2d21ac55 228 IPSEC_STAT_INCREMENT(ipsecstat.in_nosa);
1c79356b
A
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)));
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#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
316670eb
A
531 /*
532 * Expect 32-bit aligned data pointer on strict-align
533 * platforms.
534 */
535 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
536
2d21ac55
A
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;
6d2010ae
A
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 }
2d21ac55
A
559#endif /* INET6 */
560 } else {
561 ipseclog((LOG_ERR, "ipsec tunnel unsupported address family "
562 "in ESP input\n"));
1c79356b
A
563 goto bad;
564 }
565
1c79356b 566 key_sa_recordxfer(sav, m);
9bccf70c
A
567 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 ||
568 ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) {
2d21ac55 569 IPSEC_STAT_INCREMENT(ipsecstat.in_nomem);
9bccf70c
A
570 goto bad;
571 }
6d2010ae
A
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
55e303ae
A
582 /* Clear the csum flags, they can't be valid for the inner headers */
583 m->m_pkthdr.csum_flags = 0;
316670eb
A
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
6d2010ae
A
593 if (proto_input(ifamily == AF_INET ? PF_INET : PF_INET6, m) != 0)
594 goto bad;
595
1c79356b 596 nxt = IPPROTO_DONE;
55e303ae 597 KERNEL_DEBUG(DBG_FNC_ESPIN | DBG_FUNC_END, 2,0,0,0,0);
1c79356b
A
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);
9bccf70c 623 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) {
2d21ac55 624 IPSEC_STAT_INCREMENT(ipsecstat.in_nomem);
9bccf70c
A
625 goto bad;
626 }
55e303ae
A
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 }
1c79356b 638
9bccf70c
A
639 if (nxt != IPPROTO_DONE) {
640 if ((ip_protox[nxt]->pr_flags & PR_LASTHDR) != 0 &&
641 ipsec4_in_reject(m, NULL)) {
2d21ac55 642 IPSEC_STAT_INCREMENT(ipsecstat.in_polvio);
9bccf70c
A
643 goto bad;
644 }
55e303ae 645 KERNEL_DEBUG(DBG_FNC_ESPIN | DBG_FUNC_END, 3,0,0,0,0);
2d21ac55
A
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 }
316670eb 666 udp = (struct udphdr *)(void *)(((u_int8_t *)ip) + off);
2d21ac55
A
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 }
6d2010ae
A
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
316670eb
A
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
91447636 693 ip_proto_dispatch_in(m, off, nxt, 0);
9bccf70c 694 } else
1c79356b
A
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));
2d21ac55 702 key_freesav(sav, KEY_SADB_UNLOCKED);
1c79356b 703 }
2d21ac55 704 IPSEC_STAT_INCREMENT(ipsecstat.in_success);
1c79356b
A
705 return;
706
707bad:
708 if (sav) {
709 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
710 printf("DP esp4_input call free SA:%p\n", sav));
2d21ac55 711 key_freesav(sav, KEY_SADB_UNLOCKED);
1c79356b
A
712 }
713 if (m)
714 m_freem(m);
55e303ae 715 KERNEL_DEBUG(DBG_FNC_ESPIN | DBG_FUNC_END, 4,0,0,0,0);
1c79356b
A
716 return;
717}
718#endif /* INET */
719
720#if INET6
721int
6d2010ae 722esp6_input(struct mbuf **mp, int *offp, int proto)
1c79356b 723{
6d2010ae 724#pragma unused(proto)
1c79356b
A
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;
6d2010ae 731 u_int32_t seq;
1c79356b
A
732 struct secasvar *sav = NULL;
733 size_t taillen;
734 u_int16_t nxt;
9bccf70c 735 const struct esp_algorithm *algo;
1c79356b
A
736 int ivlen;
737 size_t esplen;
91447636 738
1c79356b
A
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));
2d21ac55 743 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1c79356b
A
744 goto bad;
745 }
746
747#ifndef PULLDOWN_TEST
2d21ac55 748 IP6_EXTHDR_CHECK(m, off, ESPMAXLEN, {return IPPROTO_DONE;});
316670eb 749 esp = (struct esp *)(void *)(mtod(m, caddr_t) + off);
1c79356b
A
750#else
751 IP6_EXTHDR_GET(esp, struct esp *, m, off, ESPMAXLEN);
752 if (esp == NULL) {
2d21ac55 753 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1c79356b
A
754 return IPPROTO_DONE;
755 }
756#endif
316670eb
A
757 /* Expect 32-bit data aligned pointer on strict-align platforms */
758 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
759
1c79356b
A
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"));
2d21ac55 765 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1c79356b
A
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)));
2d21ac55 778 IPSEC_STAT_INCREMENT(ipsec6stat.in_nosa);
1c79356b
A
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)));
2d21ac55 788 IPSEC_STAT_INCREMENT(ipsec6stat.in_badspi);
1c79356b
A
789 goto bad;
790 }
9bccf70c
A
791 algo = esp_algorithm_lookup(sav->alg_enc);
792 if (!algo) {
1c79356b 793 ipseclog((LOG_DEBUG, "IPv6 ESP input: "
9bccf70c 794 "unsupported encryption algorithm for spi %u\n",
1c79356b 795 (u_int32_t)ntohl(spi)));
2d21ac55 796 IPSEC_STAT_INCREMENT(ipsec6stat.in_badspi);
1c79356b
A
797 goto bad;
798 }
799
1c79356b
A
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)));
2d21ac55 805 IPSEC_STAT_INCREMENT(ipsec6stat.in_badspi);
1c79356b
A
806 goto bad;
807 }
808
6d2010ae
A
809 seq = ntohl(((struct newesp *)esp)->esp_seq);
810
1c79356b
A
811 if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay
812 && (sav->alg_auth && sav->key_auth)))
813 goto noreplaycheck;
814
9bccf70c
A
815 if (sav->alg_auth == SADB_X_AALG_NULL ||
816 sav->alg_auth == SADB_AALG_NONE)
1c79356b
A
817 goto noreplaycheck;
818
819 /*
820 * check for sequence number.
821 */
6d2010ae 822 if (ipsec_chkreplay(seq, sav))
1c79356b
A
823 ; /*okey*/
824 else {
2d21ac55 825 IPSEC_STAT_INCREMENT(ipsec6stat.in_espreplay);
1c79356b
A
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 {
316670eb
A
834 u_char sum0[AH_MAXSUMSIZE] __attribute__((aligned(4)));
835 u_char sum[AH_MAXSUMSIZE] __attribute__((aligned(4)));
9bccf70c 836 const struct ah_algorithm *sumalgo;
1c79356b
A
837 size_t siz;
838
9bccf70c
A
839 sumalgo = ah_algorithm_lookup(sav->alg_auth);
840 if (!sumalgo)
841 goto noreplaycheck;
1c79356b 842 siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1));
143cc14e 843 if (m->m_pkthdr.len < off + ESPMAXLEN + siz) {
2d21ac55 844 IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
143cc14e
A
845 goto bad;
846 }
1c79356b
A
847 if (AH_MAXSUMSIZE < siz) {
848 ipseclog((LOG_DEBUG,
849 "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
b0d623f7 850 (u_int32_t)siz));
2d21ac55 851 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1c79356b
A
852 goto bad;
853 }
854
b0d623f7 855 m_copydata(m, m->m_pkthdr.len - siz, siz, (caddr_t) &sum0[0]);
1c79356b
A
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)));
2d21ac55 860 IPSEC_STAT_INCREMENT(ipsec6stat.in_espauthfail);
1c79356b
A
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)));
2d21ac55 867 IPSEC_STAT_INCREMENT(ipsec6stat.in_espauthfail);
1c79356b
A
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;
2d21ac55 877 IPSEC_STAT_INCREMENT(ipsec6stat.in_espauthsucc);
1c79356b
A
878 }
879
880 /*
881 * update sequence number.
882 */
883 if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
6d2010ae 884 if (ipsec_updatereplay(seq, sav)) {
2d21ac55 885 IPSEC_STAT_INCREMENT(ipsec6stat.in_espreplay);
1c79356b
A
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"));
2d21ac55 907 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1c79356b
A
908 goto bad;
909 }
910
911#ifndef PULLDOWN_TEST
91447636 912 IP6_EXTHDR_CHECK(m, off, esplen + ivlen, return IPPROTO_DONE); /*XXX*/
1c79356b
A
913#else
914 IP6_EXTHDR_GET(esp, struct esp *, m, off, esplen + ivlen);
915 if (esp == NULL) {
2d21ac55 916 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1c79356b
A
917 m = NULL;
918 goto bad;
919 }
920#endif
921 ip6 = mtod(m, struct ip6_hdr *); /*set it again just in case*/
922
9bccf70c
A
923 /*
924 * pre-compute and cache intermediate key
925 */
926 if (esp_schedule(algo, sav) != 0) {
2d21ac55 927 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
9bccf70c
A
928 goto bad;
929 }
930
1c79356b
A
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)) {
9bccf70c
A
937 /* m is already freed */
938 m = NULL;
939 ipseclog((LOG_ERR, "decrypt fail in IPv6 ESP input: %s\n",
940 ipsec_logsastr(sav)));
2d21ac55 941 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1c79356b
A
942 goto bad;
943 }
2d21ac55 944 IPSEC_STAT_INCREMENT(ipsec6stat.in_esphist[sav->alg_enc]);
1c79356b
A
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)));
2d21ac55 961 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1c79356b
A
962 goto bad;
963 }
964
965 /* strip off the trailing pad area. */
966 m_adj(m, -taillen);
935ed37a 967 ip6 = mtod(m, struct ip6_hdr *);
1c79356b
A
968 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - taillen);
969
316670eb
A
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
1c79356b 981 /* was it transmitted over the IPsec tunnel SA? */
9bccf70c 982 if (ipsec6_tunnel_validate(m, off + esplen + ivlen, nxt, sav)) {
6d2010ae
A
983 ifaddr_t ifa;
984 struct sockaddr_storage addr;
985
1c79356b
A
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) {
2d21ac55 1007 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1c79356b
A
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)));
2d21ac55 1020 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
1c79356b
A
1021 goto bad;
1022 }
1023
1c79356b 1024 key_sa_recordxfer(sav, m);
9bccf70c
A
1025 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 ||
1026 ipsec_addhist(m, IPPROTO_IPV6, 0) != 0) {
2d21ac55 1027 IPSEC_STAT_INCREMENT(ipsec6stat.in_nomem);
9bccf70c
A
1028 goto bad;
1029 }
6d2010ae
A
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
316670eb
A
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
6d2010ae
A
1056 if (proto_input(PF_INET6, m) != 0)
1057 goto bad;
1c79356b
A
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);
1c79356b
A
1095 /* m_cat does not update m_pkthdr.len */
1096 m->m_pkthdr.len += n->m_pkthdr.len;
55e303ae 1097 m_cat(m, n);
1c79356b
A
1098 }
1099
9bccf70c
A
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
2d21ac55 1111 MGETHDR(n, M_DONTWAIT, MT_HEADER); /* MAC-OK */
9bccf70c
A
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));
9bccf70c
A
1136 n->m_len = maxlen;
1137 n->m_pkthdr.len = m->m_pkthdr.len;
1138 n->m_next = m;
55e303ae 1139 m_adj(m, maxlen);
9bccf70c
A
1140 m->m_flags &= ~M_PKTHDR;
1141 }
1142 m = n;
1143 }
1144#endif
1145
1c79356b
A
1146 ip6 = mtod(m, struct ip6_hdr *);
1147 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - stripsiz);
1148
1149 key_sa_recordxfer(sav, m);
9bccf70c 1150 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) {
2d21ac55 1151 IPSEC_STAT_INCREMENT(ipsec6stat.in_nomem);
9bccf70c
A
1152 goto bad;
1153 }
316670eb
A
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 }
1c79356b
A
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));
2d21ac55 1170 key_freesav(sav, KEY_SADB_UNLOCKED);
1c79356b 1171 }
2d21ac55 1172 IPSEC_STAT_INCREMENT(ipsec6stat.in_success);
1c79356b
A
1173 return nxt;
1174
1175bad:
1176 if (sav) {
1177 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
1178 printf("DP esp6_input call free SA:%p\n", sav));
2d21ac55 1179 key_freesav(sav, KEY_SADB_UNLOCKED);
1c79356b
A
1180 }
1181 if (m)
1182 m_freem(m);
1183 return IPPROTO_DONE;
1184}
9bccf70c
A
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;
55e303ae 1199 struct sockaddr_in6 *sa6_src, *sa6_dst;
9bccf70c
A
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
316670eb 1254 espp = (struct newesp*)(void *)(mtod(m, caddr_t) + off);
9bccf70c
A
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 */
55e303ae 1263 sa6_src = ip6cp->ip6c_src;
316670eb 1264 sa6_dst = (struct sockaddr_in6 *)(void *)sa;
9bccf70c 1265 sav = key_allocsa(AF_INET6,
55e303ae
A
1266 (caddr_t)&sa6_src->sin6_addr,
1267 (caddr_t)&sa6_dst->sin6_addr,
1268 IPPROTO_ESP, espp->esp_spi);
9bccf70c
A
1269 if (sav) {
1270 if (sav->state == SADB_SASTATE_MATURE ||
1271 sav->state == SADB_SASTATE_DYING)
1272 valid++;
2d21ac55 1273 key_freesav(sav, KEY_SADB_LOCKED);
9bccf70c
A
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}
1c79356b 1291#endif /* INET6 */