]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet6/ipsec.c
xnu-2782.30.5.tar.gz
[apple/xnu.git] / bsd / netinet6 / ipsec.c
CommitLineData
b0d623f7 1/*
fe8ab488 2 * Copyright (c) 2008-2014 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/ipsec.c,v 1.3.2.7 2001/07/19 06:37:23 kris Exp $ */
30/* $KAME: ipsec.c,v 1.103 2001/05/24 07:14:18 sakane 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 * IPsec controller part.
63 */
1c79356b
A
64
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/socketvar.h>
74#include <sys/errno.h>
75#include <sys/time.h>
76#include <sys/kernel.h>
77#include <sys/syslog.h>
1c79356b 78#include <sys/sysctl.h>
91447636
A
79#include <kern/locks.h>
80#include <sys/kauth.h>
2d21ac55 81#include <libkern/OSAtomic.h>
1c79356b
A
82
83#include <net/if.h>
84#include <net/route.h>
fe8ab488 85#include <net/if_ipsec.h>
1c79356b
A
86
87#include <netinet/in.h>
88#include <netinet/in_systm.h>
89#include <netinet/ip.h>
90#include <netinet/ip_var.h>
91#include <netinet/in_var.h>
92#include <netinet/udp.h>
93#include <netinet/udp_var.h>
94#include <netinet/ip_ecn.h>
1c79356b 95#if INET6
9bccf70c
A
96#include <netinet6/ip6_ecn.h>
97#endif
98#include <netinet/tcp.h>
99#include <netinet/udp.h>
100
1c79356b 101#include <netinet/ip6.h>
9bccf70c 102#if INET6
1c79356b
A
103#include <netinet6/ip6_var.h>
104#endif
105#include <netinet/in_pcb.h>
106#if INET6
1c79356b
A
107#include <netinet/icmp6.h>
108#endif
109
110#include <netinet6/ipsec.h>
9bccf70c
A
111#if INET6
112#include <netinet6/ipsec6.h>
113#endif
1c79356b 114#include <netinet6/ah.h>
9bccf70c
A
115#if INET6
116#include <netinet6/ah6.h>
117#endif
1c79356b
A
118#if IPSEC_ESP
119#include <netinet6/esp.h>
9bccf70c
A
120#if INET6
121#include <netinet6/esp6.h>
122#endif
1c79356b
A
123#endif
124#include <netinet6/ipcomp.h>
9bccf70c
A
125#if INET6
126#include <netinet6/ipcomp6.h>
127#endif
1c79356b
A
128#include <netkey/key.h>
129#include <netkey/keydb.h>
130#include <netkey/key_debug.h>
131
132#include <net/net_osdep.h>
133
9bccf70c 134#if IPSEC_DEBUG
1c79356b
A
135int ipsec_debug = 1;
136#else
137int ipsec_debug = 0;
138#endif
139
55e303ae
A
140#include <sys/kdebug.h>
141#define DBG_LAYER_BEG NETDBG_CODE(DBG_NETIPSEC, 1)
142#define DBG_LAYER_END NETDBG_CODE(DBG_NETIPSEC, 3)
143#define DBG_FNC_GETPOL_SOCK NETDBG_CODE(DBG_NETIPSEC, (1 << 8))
144#define DBG_FNC_GETPOL_ADDR NETDBG_CODE(DBG_NETIPSEC, (2 << 8))
145#define DBG_FNC_IPSEC_OUT NETDBG_CODE(DBG_NETIPSEC, (3 << 8))
146
91447636 147extern lck_mtx_t *sadb_mutex;
55e303ae 148
1c79356b 149struct ipsecstat ipsecstat;
1c79356b
A
150int ip4_ah_cleartos = 1;
151int ip4_ah_offsetmask = 0; /* maybe IP_DF? */
152int ip4_ipsec_dfbit = 0; /* DF bit on encap. 0: clear 1: set 2: copy */
153int ip4_esp_trans_deflev = IPSEC_LEVEL_USE;
154int ip4_esp_net_deflev = IPSEC_LEVEL_USE;
155int ip4_ah_trans_deflev = IPSEC_LEVEL_USE;
156int ip4_ah_net_deflev = IPSEC_LEVEL_USE;
157struct secpolicy ip4_def_policy;
158int ip4_ipsec_ecn = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */
9bccf70c 159int ip4_esp_randpad = -1;
55e303ae 160int esp_udp_encap_port = 0;
9bccf70c 161static int sysctl_def_policy SYSCTL_HANDLER_ARGS;
b0d623f7 162extern int natt_keepalive_interval;
55e303ae 163extern u_int32_t natt_now;
1c79356b 164
2d21ac55
A
165struct ipsec_tag;
166
1c79356b 167SYSCTL_DECL(_net_inet_ipsec);
9bccf70c
A
168#if INET6
169SYSCTL_DECL(_net_inet6_ipsec6);
170#endif
1c79356b
A
171/* net.inet.ipsec */
172SYSCTL_STRUCT(_net_inet_ipsec, IPSECCTL_STATS,
6d2010ae
A
173 stats, CTLFLAG_RD | CTLFLAG_LOCKED, &ipsecstat, ipsecstat, "");
174SYSCTL_PROC(_net_inet_ipsec, IPSECCTL_DEF_POLICY, def_policy, CTLTYPE_INT|CTLFLAG_RW | CTLFLAG_LOCKED,
9bccf70c 175 &ip4_def_policy.policy, 0, &sysctl_def_policy, "I", "");
1c79356b 176SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev,
6d2010ae 177 CTLFLAG_RW | CTLFLAG_LOCKED, &ip4_esp_trans_deflev, 0, "");
1c79356b 178SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev,
6d2010ae 179 CTLFLAG_RW | CTLFLAG_LOCKED, &ip4_esp_net_deflev, 0, "");
1c79356b 180SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev,
6d2010ae 181 CTLFLAG_RW | CTLFLAG_LOCKED, &ip4_ah_trans_deflev, 0, "");
1c79356b 182SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev,
6d2010ae 183 CTLFLAG_RW | CTLFLAG_LOCKED, &ip4_ah_net_deflev, 0, "");
1c79356b 184SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_CLEARTOS,
6d2010ae 185 ah_cleartos, CTLFLAG_RW | CTLFLAG_LOCKED, &ip4_ah_cleartos, 0, "");
1c79356b 186SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_OFFSETMASK,
6d2010ae 187 ah_offsetmask, CTLFLAG_RW | CTLFLAG_LOCKED, &ip4_ah_offsetmask, 0, "");
1c79356b 188SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DFBIT,
6d2010ae 189 dfbit, CTLFLAG_RW | CTLFLAG_LOCKED, &ip4_ipsec_dfbit, 0, "");
1c79356b 190SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ECN,
6d2010ae 191 ecn, CTLFLAG_RW | CTLFLAG_LOCKED, &ip4_ipsec_ecn, 0, "");
1c79356b 192SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEBUG,
6d2010ae 193 debug, CTLFLAG_RW | CTLFLAG_LOCKED, &ipsec_debug, 0, "");
9bccf70c 194SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ESP_RANDPAD,
6d2010ae 195 esp_randpad, CTLFLAG_RW | CTLFLAG_LOCKED, &ip4_esp_randpad, 0, "");
9bccf70c
A
196
197/* for performance, we bypass ipsec until a security policy is set */
198int ipsec_bypass = 1;
6d2010ae 199SYSCTL_INT(_net_inet_ipsec, OID_AUTO, bypass, CTLFLAG_RD | CTLFLAG_LOCKED, &ipsec_bypass,0, "");
1c79356b 200
55e303ae
A
201/*
202 * NAT Traversal requires a UDP port for encapsulation,
203 * esp_udp_encap_port controls which port is used. Racoon
204 * must set this port to the port racoon is using locally
205 * for nat traversal.
206 */
207SYSCTL_INT(_net_inet_ipsec, OID_AUTO, esp_port,
6d2010ae 208 CTLFLAG_RW | CTLFLAG_LOCKED, &esp_udp_encap_port, 0, "");
55e303ae 209
1c79356b
A
210#if INET6
211struct ipsecstat ipsec6stat;
1c79356b
A
212int ip6_esp_trans_deflev = IPSEC_LEVEL_USE;
213int ip6_esp_net_deflev = IPSEC_LEVEL_USE;
214int ip6_ah_trans_deflev = IPSEC_LEVEL_USE;
215int ip6_ah_net_deflev = IPSEC_LEVEL_USE;
216struct secpolicy ip6_def_policy;
217int ip6_ipsec_ecn = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */
9bccf70c 218int ip6_esp_randpad = -1;
1c79356b 219
1c79356b
A
220/* net.inet6.ipsec6 */
221SYSCTL_STRUCT(_net_inet6_ipsec6, IPSECCTL_STATS,
6d2010ae 222 stats, CTLFLAG_RD | CTLFLAG_LOCKED, &ipsec6stat, ipsecstat, "");
1c79356b 223SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_POLICY,
6d2010ae 224 def_policy, CTLFLAG_RW | CTLFLAG_LOCKED, &ip6_def_policy.policy, 0, "");
1c79356b 225SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev,
6d2010ae 226 CTLFLAG_RW | CTLFLAG_LOCKED, &ip6_esp_trans_deflev, 0, "");
1c79356b 227SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev,
6d2010ae 228 CTLFLAG_RW | CTLFLAG_LOCKED, &ip6_esp_net_deflev, 0, "");
1c79356b 229SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev,
6d2010ae 230 CTLFLAG_RW | CTLFLAG_LOCKED, &ip6_ah_trans_deflev, 0, "");
1c79356b 231SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev,
6d2010ae 232 CTLFLAG_RW | CTLFLAG_LOCKED, &ip6_ah_net_deflev, 0, "");
1c79356b 233SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ECN,
6d2010ae 234 ecn, CTLFLAG_RW | CTLFLAG_LOCKED, &ip6_ipsec_ecn, 0, "");
1c79356b 235SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEBUG,
6d2010ae 236 debug, CTLFLAG_RW | CTLFLAG_LOCKED, &ipsec_debug, 0, "");
9bccf70c 237SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ESP_RANDPAD,
6d2010ae 238 esp_randpad, CTLFLAG_RW | CTLFLAG_LOCKED, &ip6_esp_randpad, 0, "");
1c79356b
A
239#endif /* INET6 */
240
39236c6e
A
241static int ipsec_setspidx_interface(struct secpolicyindex *, u_int, struct mbuf *,
242 int, int, int);
91447636
A
243static int ipsec_setspidx_mbuf(struct secpolicyindex *, u_int, u_int,
244 struct mbuf *, int);
245static int ipsec4_setspidx_inpcb(struct mbuf *, struct inpcb *pcb);
9bccf70c 246#if INET6
91447636 247static int ipsec6_setspidx_in6pcb(struct mbuf *, struct in6pcb *pcb);
9bccf70c 248#endif
39236c6e 249static int ipsec_setspidx(struct mbuf *, struct secpolicyindex *, int, int);
91447636
A
250static void ipsec4_get_ulp(struct mbuf *m, struct secpolicyindex *, int);
251static int ipsec4_setspidx_ipaddr(struct mbuf *, struct secpolicyindex *);
1c79356b 252#if INET6
91447636
A
253static void ipsec6_get_ulp(struct mbuf *m, struct secpolicyindex *, int);
254static int ipsec6_setspidx_ipaddr(struct mbuf *, struct secpolicyindex *);
1c79356b 255#endif
91447636
A
256static struct inpcbpolicy *ipsec_newpcbpolicy(void);
257static void ipsec_delpcbpolicy(struct inpcbpolicy *);
258static struct secpolicy *ipsec_deepcopy_policy(struct secpolicy *src);
259static int ipsec_set_policy(struct secpolicy **pcb_sp,
fe8ab488 260 int optname, caddr_t request, size_t len, int priv);
91447636
A
261static void vshiftl(unsigned char *, int, int);
262static int ipsec_in_reject(struct secpolicy *, struct mbuf *);
1c79356b 263#if INET6
2d21ac55 264static int ipsec64_encapsulate(struct mbuf *, struct secasvar *);
1c79356b 265#endif
2d21ac55
A
266static struct ipsec_tag *ipsec_addaux(struct mbuf *);
267static struct ipsec_tag *ipsec_findaux(struct mbuf *);
268static void ipsec_optaux(struct mbuf *, struct ipsec_tag *);
b0d623f7 269int ipsec_send_natt_keepalive(struct secasvar *sav);
fe8ab488 270bool ipsec_fill_offload_frame(ifnet_t ifp, struct secasvar *sav, struct ipsec_offload_frame *frame, size_t frame_data_offset);
9bccf70c
A
271
272static int
273sysctl_def_policy SYSCTL_HANDLER_ARGS
274{
275 int old_policy = ip4_def_policy.policy;
276 int error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
277
b0d623f7
A
278#pragma unused(arg1, arg2)
279
9bccf70c
A
280 if (ip4_def_policy.policy != IPSEC_POLICY_NONE &&
281 ip4_def_policy.policy != IPSEC_POLICY_DISCARD) {
282 ip4_def_policy.policy = old_policy;
283 return EINVAL;
284 }
285
286 /* Turn off the bypass if the default security policy changes */
287 if (ipsec_bypass != 0 && ip4_def_policy.policy != IPSEC_POLICY_NONE)
288 ipsec_bypass = 0;
289
290 return error;
291}
1c79356b
A
292
293/*
294 * For OUTBOUND packet having a socket. Searching SPD for packet,
295 * and return a pointer to SP.
296 * OUT: NULL: no apropreate SP found, the following value is set to error.
297 * 0 : bypass
298 * EACCES : discard packet.
299 * ENOENT : ipsec_acquire() in progress, maybe.
91447636 300 * others : error occurred.
1c79356b
A
301 * others: a pointer to SP
302 *
303 * NOTE: IPv6 mapped adddress concern is implemented here.
304 */
305struct secpolicy *
fe8ab488
A
306ipsec4_getpolicybysock(struct mbuf *m,
307 u_int dir,
308 struct socket *so,
309 int *error)
1c79356b
A
310{
311 struct inpcbpolicy *pcbsp = NULL;
312 struct secpolicy *currsp = NULL; /* policy on socket */
313 struct secpolicy *kernsp = NULL; /* policy on kernel */
fe8ab488 314
2d21ac55 315 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
1c79356b
A
316 /* sanity check */
317 if (m == NULL || so == NULL || error == NULL)
318 panic("ipsec4_getpolicybysock: NULL pointer was passed.\n");
fe8ab488
A
319
320 if (so->so_pcb == NULL) {
321 printf("ipsec4_getpolicybysock: so->so_pcb == NULL\n");
322 return ipsec4_getpolicybyaddr(m, dir, 0, error);
323 }
9bccf70c 324
39236c6e 325 switch (SOCK_DOM(so)) {
fe8ab488
A
326 case PF_INET:
327 pcbsp = sotoinpcb(so)->inp_sp;
328 break;
9bccf70c 329#if INET6
fe8ab488
A
330 case PF_INET6:
331 pcbsp = sotoin6pcb(so)->in6p_sp;
332 break;
9bccf70c
A
333#endif
334 }
335
336 if (!pcbsp){
337 /* Socket has not specified an IPSEC policy */
338 return ipsec4_getpolicybyaddr(m, dir, 0, error);
339 }
fe8ab488 340
55e303ae 341 KERNEL_DEBUG(DBG_FNC_GETPOL_SOCK | DBG_FUNC_START, 0,0,0,0,0);
fe8ab488 342
39236c6e 343 switch (SOCK_DOM(so)) {
fe8ab488
A
344 case PF_INET:
345 /* set spidx in pcb */
346 *error = ipsec4_setspidx_inpcb(m, sotoinpcb(so));
347 break;
1c79356b 348#if INET6
fe8ab488
A
349 case PF_INET6:
350 /* set spidx in pcb */
351 *error = ipsec6_setspidx_in6pcb(m, sotoin6pcb(so));
352 break;
1c79356b 353#endif
fe8ab488
A
354 default:
355 panic("ipsec4_getpolicybysock: unsupported address family\n");
1c79356b 356 }
55e303ae
A
357 if (*error) {
358 KERNEL_DEBUG(DBG_FNC_GETPOL_SOCK | DBG_FUNC_END, 1,*error,0,0,0);
9bccf70c 359 return NULL;
55e303ae 360 }
fe8ab488 361
1c79356b
A
362 /* sanity check */
363 if (pcbsp == NULL)
364 panic("ipsec4_getpolicybysock: pcbsp is NULL.\n");
fe8ab488
A
365
366 switch (dir) {
367 case IPSEC_DIR_INBOUND:
368 currsp = pcbsp->sp_in;
369 break;
370 case IPSEC_DIR_OUTBOUND:
371 currsp = pcbsp->sp_out;
372 break;
373 default:
374 panic("ipsec4_getpolicybysock: illegal direction.\n");
375 }
376
1c79356b
A
377 /* sanity check */
378 if (currsp == NULL)
379 panic("ipsec4_getpolicybysock: currsp is NULL.\n");
fe8ab488 380
1c79356b 381 /* when privilieged socket */
fe8ab488
A
382 if (pcbsp->priv) {
383 switch (currsp->policy) {
384 case IPSEC_POLICY_BYPASS:
385 lck_mtx_lock(sadb_mutex);
386 currsp->refcnt++;
387 lck_mtx_unlock(sadb_mutex);
388 *error = 0;
389 KERNEL_DEBUG(DBG_FNC_GETPOL_SOCK | DBG_FUNC_END, 2,*error,0,0,0);
390 return currsp;
391
392 case IPSEC_POLICY_ENTRUST:
393 /* look for a policy in SPD */
394 kernsp = key_allocsp(&currsp->spidx, dir);
395
396 /* SP found */
397 if (kernsp != NULL) {
398 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
399 printf("DP ipsec4_getpolicybysock called "
400 "to allocate SP:0x%llx\n",
401 (uint64_t)VM_KERNEL_ADDRPERM(kernsp)));
402 *error = 0;
403 KERNEL_DEBUG(DBG_FNC_GETPOL_SOCK | DBG_FUNC_END, 3,*error,0,0,0);
404 return kernsp;
405 }
406
407 /* no SP found */
408 lck_mtx_lock(sadb_mutex);
409 if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD
410 && ip4_def_policy.policy != IPSEC_POLICY_NONE) {
411 ipseclog((LOG_INFO,
412 "fixed system default policy: %d->%d\n",
413 ip4_def_policy.policy, IPSEC_POLICY_NONE));
414 ip4_def_policy.policy = IPSEC_POLICY_NONE;
415 }
416 ip4_def_policy.refcnt++;
417 lck_mtx_unlock(sadb_mutex);
418 *error = 0;
419 KERNEL_DEBUG(DBG_FNC_GETPOL_SOCK | DBG_FUNC_END, 4,*error,0,0,0);
420 return &ip4_def_policy;
421
422 case IPSEC_POLICY_IPSEC:
423 lck_mtx_lock(sadb_mutex);
424 currsp->refcnt++;
425 lck_mtx_unlock(sadb_mutex);
426 *error = 0;
427 KERNEL_DEBUG(DBG_FNC_GETPOL_SOCK | DBG_FUNC_END, 5,*error,0,0,0);
428 return currsp;
429
430 default:
431 ipseclog((LOG_ERR, "ipsec4_getpolicybysock: "
432 "Invalid policy for PCB %d\n", currsp->policy));
433 *error = EINVAL;
434 KERNEL_DEBUG(DBG_FNC_GETPOL_SOCK | DBG_FUNC_END, 6,*error,0,0,0);
435 return NULL;
436 }
437 /* NOTREACHED */
438 }
439
440 /* when non-privilieged socket */
441 /* look for a policy in SPD */
442 kernsp = key_allocsp(&currsp->spidx, dir);
443
444 /* SP found */
445 if (kernsp != NULL) {
446 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
447 printf("DP ipsec4_getpolicybysock called "
448 "to allocate SP:0x%llx\n",
449 (uint64_t)VM_KERNEL_ADDRPERM(kernsp)));
450 *error = 0;
451 KERNEL_DEBUG(DBG_FNC_GETPOL_SOCK | DBG_FUNC_END, 7,*error,0,0,0);
452 return kernsp;
453 }
454
455 /* no SP found */
456 switch (currsp->policy) {
1c79356b 457 case IPSEC_POLICY_BYPASS:
fe8ab488
A
458 ipseclog((LOG_ERR, "ipsec4_getpolicybysock: "
459 "Illegal policy for non-priviliged defined %d\n",
460 currsp->policy));
461 *error = EINVAL;
462 KERNEL_DEBUG(DBG_FNC_GETPOL_SOCK | DBG_FUNC_END, 8,*error,0,0,0);
463 return NULL;
464
1c79356b 465 case IPSEC_POLICY_ENTRUST:
2d21ac55 466 lck_mtx_lock(sadb_mutex);
1c79356b 467 if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD
fe8ab488 468 && ip4_def_policy.policy != IPSEC_POLICY_NONE) {
1c79356b 469 ipseclog((LOG_INFO,
fe8ab488
A
470 "fixed system default policy: %d->%d\n",
471 ip4_def_policy.policy, IPSEC_POLICY_NONE));
1c79356b
A
472 ip4_def_policy.policy = IPSEC_POLICY_NONE;
473 }
474 ip4_def_policy.refcnt++;
2d21ac55 475 lck_mtx_unlock(sadb_mutex);
1c79356b 476 *error = 0;
fe8ab488 477 KERNEL_DEBUG(DBG_FNC_GETPOL_SOCK | DBG_FUNC_END, 9,*error,0,0,0);
1c79356b
A
478 return &ip4_def_policy;
479
480 case IPSEC_POLICY_IPSEC:
2d21ac55 481 lck_mtx_lock(sadb_mutex);
1c79356b 482 currsp->refcnt++;
2d21ac55 483 lck_mtx_unlock(sadb_mutex);
1c79356b 484 *error = 0;
fe8ab488 485 KERNEL_DEBUG(DBG_FNC_GETPOL_SOCK | DBG_FUNC_END, 10,*error,0,0,0);
1c79356b 486 return currsp;
fe8ab488 487
1c79356b
A
488 default:
489 ipseclog((LOG_ERR, "ipsec4_getpolicybysock: "
fe8ab488 490 "Invalid policy for PCB %d\n", currsp->policy));
1c79356b 491 *error = EINVAL;
fe8ab488 492 KERNEL_DEBUG(DBG_FNC_GETPOL_SOCK | DBG_FUNC_END, 11,*error,0,0,0);
1c79356b 493 return NULL;
1c79356b
A
494 }
495 /* NOTREACHED */
496}
497
498/*
499 * For FORWADING packet or OUTBOUND without a socket. Searching SPD for packet,
500 * and return a pointer to SP.
501 * OUT: positive: a pointer to the entry for security policy leaf matched.
502 * NULL: no apropreate SP found, the following value is set to error.
503 * 0 : bypass
504 * EACCES : discard packet.
505 * ENOENT : ipsec_acquire() in progress, maybe.
91447636 506 * others : error occurred.
1c79356b
A
507 */
508struct secpolicy *
39236c6e
A
509ipsec4_getpolicybyaddr(struct mbuf *m,
510 u_int dir,
511 int flag,
512 int *error)
1c79356b
A
513{
514 struct secpolicy *sp = NULL;
39236c6e 515
9bccf70c
A
516 if (ipsec_bypass != 0)
517 return 0;
518
2d21ac55
A
519 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
520
1c79356b
A
521 /* sanity check */
522 if (m == NULL || error == NULL)
523 panic("ipsec4_getpolicybyaddr: NULL pointer was passed.\n");
39236c6e
A
524 {
525 struct secpolicyindex spidx;
1c79356b 526
39236c6e
A
527 KERNEL_DEBUG(DBG_FNC_GETPOL_ADDR | DBG_FUNC_START, 0,0,0,0,0);
528 bzero(&spidx, sizeof(spidx));
1c79356b 529
39236c6e
A
530 /* make a index to look for a policy */
531 *error = ipsec_setspidx_mbuf(&spidx, dir, AF_INET, m,
532 (flag & IP_FORWARDING) ? 0 : 1);
1c79356b 533
39236c6e
A
534 if (*error != 0) {
535 KERNEL_DEBUG(DBG_FNC_GETPOL_ADDR | DBG_FUNC_END, 1,*error,0,0,0);
536 return NULL;
537 }
1c79356b 538
39236c6e 539 sp = key_allocsp(&spidx, dir);
55e303ae 540 }
1c79356b 541
1c79356b
A
542 /* SP found */
543 if (sp != NULL) {
544 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
39236c6e
A
545 printf("DP ipsec4_getpolicybyaddr called "
546 "to allocate SP:0x%llx\n",
547 (uint64_t)VM_KERNEL_ADDRPERM(sp)));
1c79356b 548 *error = 0;
55e303ae 549 KERNEL_DEBUG(DBG_FNC_GETPOL_ADDR | DBG_FUNC_END, 2,*error,0,0,0);
1c79356b
A
550 return sp;
551 }
552
553 /* no SP found */
2d21ac55 554 lck_mtx_lock(sadb_mutex);
1c79356b
A
555 if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD
556 && ip4_def_policy.policy != IPSEC_POLICY_NONE) {
557 ipseclog((LOG_INFO, "fixed system default policy:%d->%d\n",
558 ip4_def_policy.policy,
559 IPSEC_POLICY_NONE));
560 ip4_def_policy.policy = IPSEC_POLICY_NONE;
561 }
562 ip4_def_policy.refcnt++;
2d21ac55 563 lck_mtx_unlock(sadb_mutex);
1c79356b 564 *error = 0;
55e303ae 565 KERNEL_DEBUG(DBG_FNC_GETPOL_ADDR | DBG_FUNC_END, 3,*error,0,0,0);
1c79356b
A
566 return &ip4_def_policy;
567}
568
39236c6e
A
569/* Match with bound interface rather than src addr.
570 * Unlike getpolicybyaddr, do not set the default policy.
571 * Return 0 if should continue processing, or -1 if packet
572 * should be dropped.
573 */
574int
575ipsec4_getpolicybyinterface(struct mbuf *m,
576 u_int dir,
577 int *flags,
578 struct ip_out_args *ipoa,
579 struct secpolicy **sp)
580{
581 struct secpolicyindex spidx;
582 int error = 0;
583
584 if (ipsec_bypass != 0)
585 return 0;
586
587 /* Sanity check */
588 if (m == NULL || ipoa == NULL || sp == NULL)
589 panic("ipsec4_getpolicybyinterface: NULL pointer was passed.\n");
590
591 if (ipoa->ipoa_boundif == IFSCOPE_NONE)
592 return 0;
593
594 KERNEL_DEBUG(DBG_FNC_GETPOL_ADDR | DBG_FUNC_START, 0,0,0,0,0);
595 bzero(&spidx, sizeof(spidx));
596
597 /* make a index to look for a policy */
598 error = ipsec_setspidx_interface(&spidx, dir, m, (*flags & IP_FORWARDING) ? 0 : 1,
599 ipoa->ipoa_boundif, 4);
600
601 if (error != 0) {
602 KERNEL_DEBUG(DBG_FNC_GETPOL_ADDR | DBG_FUNC_END, 1,error,0,0,0);
603 return 0;
604 }
605
606 *sp = key_allocsp(&spidx, dir);
607
608 /* Return SP, whether NULL or not */
609 if (*sp != NULL && (*sp)->policy == IPSEC_POLICY_IPSEC) {
610 if ((*sp)->ipsec_if == NULL) {
611 /* Invalid to capture on an interface without redirect */
612 key_freesp(*sp, KEY_SADB_UNLOCKED);
613 *sp = NULL;
614 return -1;
615 } else if ((*sp)->disabled) {
616 /* Disabled policies go in the clear */
617 key_freesp(*sp, KEY_SADB_UNLOCKED);
618 *sp = NULL;
619 *flags |= IP_NOIPSEC; /* Avoid later IPSec check */
620 } else {
621 /* If policy is enabled, redirect to ipsec interface */
622 ipoa->ipoa_boundif = (*sp)->ipsec_if->if_index;
623 }
624 }
625
626 KERNEL_DEBUG(DBG_FNC_GETPOL_ADDR | DBG_FUNC_END, 2,error,0,0,0);
627
628 return 0;
629}
630
631
1c79356b
A
632#if INET6
633/*
634 * For OUTBOUND packet having a socket. Searching SPD for packet,
635 * and return a pointer to SP.
636 * OUT: NULL: no apropreate SP found, the following value is set to error.
637 * 0 : bypass
638 * EACCES : discard packet.
639 * ENOENT : ipsec_acquire() in progress, maybe.
91447636 640 * others : error occurred.
1c79356b
A
641 * others: a pointer to SP
642 */
643struct secpolicy *
fe8ab488
A
644ipsec6_getpolicybysock(struct mbuf *m,
645 u_int dir,
646 struct socket *so,
647 int *error)
1c79356b
A
648{
649 struct inpcbpolicy *pcbsp = NULL;
650 struct secpolicy *currsp = NULL; /* policy on socket */
651 struct secpolicy *kernsp = NULL; /* policy on kernel */
fe8ab488 652
2d21ac55
A
653 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
654
1c79356b
A
655 /* sanity check */
656 if (m == NULL || so == NULL || error == NULL)
657 panic("ipsec6_getpolicybysock: NULL pointer was passed.\n");
fe8ab488 658
9bccf70c 659#if DIAGNOSTIC
fe8ab488
A
660 if (SOCK_DOM(so) != PF_INET6)
661 panic("ipsec6_getpolicybysock: socket domain != inet6\n");
9bccf70c 662#endif
fe8ab488
A
663
664 pcbsp = sotoin6pcb(so)->in6p_sp;
665
666 if (!pcbsp){
667 return ipsec6_getpolicybyaddr(m, dir, 0, error);
668 }
9bccf70c 669
9bccf70c
A
670 /* set spidx in pcb */
671 ipsec6_setspidx_in6pcb(m, sotoin6pcb(so));
fe8ab488 672
1c79356b
A
673 /* sanity check */
674 if (pcbsp == NULL)
675 panic("ipsec6_getpolicybysock: pcbsp is NULL.\n");
fe8ab488
A
676
677 switch (dir) {
678 case IPSEC_DIR_INBOUND:
679 currsp = pcbsp->sp_in;
680 break;
681 case IPSEC_DIR_OUTBOUND:
682 currsp = pcbsp->sp_out;
683 break;
684 default:
685 panic("ipsec6_getpolicybysock: illegal direction.\n");
686 }
687
1c79356b
A
688 /* sanity check */
689 if (currsp == NULL)
690 panic("ipsec6_getpolicybysock: currsp is NULL.\n");
fe8ab488 691
1c79356b 692 /* when privilieged socket */
fe8ab488
A
693 if (pcbsp->priv) {
694 switch (currsp->policy) {
695 case IPSEC_POLICY_BYPASS:
696 lck_mtx_lock(sadb_mutex);
697 currsp->refcnt++;
698 lck_mtx_unlock(sadb_mutex);
699 *error = 0;
700 return currsp;
701
702 case IPSEC_POLICY_ENTRUST:
703 /* look for a policy in SPD */
704 kernsp = key_allocsp(&currsp->spidx, dir);
705
706 /* SP found */
707 if (kernsp != NULL) {
708 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
709 printf("DP ipsec6_getpolicybysock called "
710 "to allocate SP:0x%llx\n",
711 (uint64_t)VM_KERNEL_ADDRPERM(kernsp)));
712 *error = 0;
713 return kernsp;
714 }
715
716 /* no SP found */
717 lck_mtx_lock(sadb_mutex);
718 if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD
719 && ip6_def_policy.policy != IPSEC_POLICY_NONE) {
720 ipseclog((LOG_INFO,
721 "fixed system default policy: %d->%d\n",
722 ip6_def_policy.policy, IPSEC_POLICY_NONE));
723 ip6_def_policy.policy = IPSEC_POLICY_NONE;
724 }
725 ip6_def_policy.refcnt++;
726 lck_mtx_unlock(sadb_mutex);
727 *error = 0;
728 return &ip6_def_policy;
729
730 case IPSEC_POLICY_IPSEC:
731 lck_mtx_lock(sadb_mutex);
732 currsp->refcnt++;
733 lck_mtx_unlock(sadb_mutex);
734 *error = 0;
735 return currsp;
736
737 default:
738 ipseclog((LOG_ERR, "ipsec6_getpolicybysock: "
739 "Invalid policy for PCB %d\n", currsp->policy));
740 *error = EINVAL;
741 return NULL;
742 }
743 /* NOTREACHED */
744 }
745
746 /* when non-privilieged socket */
747 /* look for a policy in SPD */
748 kernsp = key_allocsp(&currsp->spidx, dir);
749
750 /* SP found */
751 if (kernsp != NULL) {
752 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
753 printf("DP ipsec6_getpolicybysock called "
754 "to allocate SP:0x%llx\n",
755 (uint64_t)VM_KERNEL_ADDRPERM(kernsp)));
756 *error = 0;
757 return kernsp;
758 }
759
760 /* no SP found */
761 switch (currsp->policy) {
1c79356b 762 case IPSEC_POLICY_BYPASS:
fe8ab488
A
763 ipseclog((LOG_ERR, "ipsec6_getpolicybysock: "
764 "Illegal policy for non-priviliged defined %d\n",
765 currsp->policy));
766 *error = EINVAL;
767 return NULL;
768
1c79356b 769 case IPSEC_POLICY_ENTRUST:
2d21ac55 770 lck_mtx_lock(sadb_mutex);
1c79356b 771 if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD
fe8ab488 772 && ip6_def_policy.policy != IPSEC_POLICY_NONE) {
1c79356b 773 ipseclog((LOG_INFO,
fe8ab488
A
774 "fixed system default policy: %d->%d\n",
775 ip6_def_policy.policy, IPSEC_POLICY_NONE));
1c79356b
A
776 ip6_def_policy.policy = IPSEC_POLICY_NONE;
777 }
778 ip6_def_policy.refcnt++;
2d21ac55 779 lck_mtx_unlock(sadb_mutex);
1c79356b
A
780 *error = 0;
781 return &ip6_def_policy;
782
783 case IPSEC_POLICY_IPSEC:
2d21ac55 784 lck_mtx_lock(sadb_mutex);
1c79356b 785 currsp->refcnt++;
2d21ac55 786 lck_mtx_unlock(sadb_mutex);
1c79356b
A
787 *error = 0;
788 return currsp;
fe8ab488 789
1c79356b 790 default:
fe8ab488
A
791 ipseclog((LOG_ERR,
792 "ipsec6_policybysock: Invalid policy for PCB %d\n",
793 currsp->policy));
1c79356b
A
794 *error = EINVAL;
795 return NULL;
1c79356b
A
796 }
797 /* NOTREACHED */
798}
799
800/*
801 * For FORWADING packet or OUTBOUND without a socket. Searching SPD for packet,
802 * and return a pointer to SP.
803 * `flag' means that packet is to be forwarded whether or not.
804 * flag = 1: forwad
805 * OUT: positive: a pointer to the entry for security policy leaf matched.
806 * NULL: no apropreate SP found, the following value is set to error.
807 * 0 : bypass
808 * EACCES : discard packet.
809 * ENOENT : ipsec_acquire() in progress, maybe.
91447636 810 * others : error occurred.
1c79356b
A
811 */
812#ifndef IP_FORWARDING
813#define IP_FORWARDING 1
814#endif
815
816struct secpolicy *
39236c6e
A
817ipsec6_getpolicybyaddr(struct mbuf *m,
818 u_int dir,
819 int flag,
820 int *error)
1c79356b
A
821{
822 struct secpolicy *sp = NULL;
823
2d21ac55
A
824 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
825
1c79356b
A
826 /* sanity check */
827 if (m == NULL || error == NULL)
828 panic("ipsec6_getpolicybyaddr: NULL pointer was passed.\n");
829
830 {
831 struct secpolicyindex spidx;
832
833 bzero(&spidx, sizeof(spidx));
834
835 /* make a index to look for a policy */
9bccf70c
A
836 *error = ipsec_setspidx_mbuf(&spidx, dir, AF_INET6, m,
837 (flag & IP_FORWARDING) ? 0 : 1);
1c79356b
A
838
839 if (*error != 0)
840 return NULL;
841
842 sp = key_allocsp(&spidx, dir);
843 }
844
845 /* SP found */
846 if (sp != NULL) {
847 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
39236c6e
A
848 printf("DP ipsec6_getpolicybyaddr called "
849 "to allocate SP:0x%llx\n",
850 (uint64_t)VM_KERNEL_ADDRPERM(sp)));
1c79356b
A
851 *error = 0;
852 return sp;
853 }
854
855 /* no SP found */
2d21ac55 856 lck_mtx_lock(sadb_mutex);
1c79356b
A
857 if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD
858 && ip6_def_policy.policy != IPSEC_POLICY_NONE) {
859 ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n",
860 ip6_def_policy.policy, IPSEC_POLICY_NONE));
861 ip6_def_policy.policy = IPSEC_POLICY_NONE;
862 }
863 ip6_def_policy.refcnt++;
2d21ac55 864 lck_mtx_unlock(sadb_mutex);
1c79356b
A
865 *error = 0;
866 return &ip6_def_policy;
867}
39236c6e
A
868
869/* Match with bound interface rather than src addr.
870 * Unlike getpolicybyaddr, do not set the default policy.
871 * Return 0 if should continue processing, or -1 if packet
872 * should be dropped.
873 */
874int
875ipsec6_getpolicybyinterface(struct mbuf *m,
876 u_int dir,
877 int flag,
878 struct ip6_out_args *ip6oap,
879 int *noipsec,
880 struct secpolicy **sp)
881{
882 struct secpolicyindex spidx;
883 int error = 0;
884
885 if (ipsec_bypass != 0)
886 return 0;
887
888 /* Sanity check */
889 if (m == NULL || sp == NULL || noipsec == NULL || ip6oap == NULL)
890 panic("ipsec6_getpolicybyinterface: NULL pointer was passed.\n");
891
892 *noipsec = 0;
893
894 if (ip6oap->ip6oa_boundif == IFSCOPE_NONE)
895 return 0;
896
897 KERNEL_DEBUG(DBG_FNC_GETPOL_ADDR | DBG_FUNC_START, 0,0,0,0,0);
898 bzero(&spidx, sizeof(spidx));
899
900 /* make a index to look for a policy */
901 error = ipsec_setspidx_interface(&spidx, dir, m, (flag & IP_FORWARDING) ? 0 : 1,
902 ip6oap->ip6oa_boundif, 6);
903
904 if (error != 0) {
905 KERNEL_DEBUG(DBG_FNC_GETPOL_ADDR | DBG_FUNC_END, 1,error,0,0,0);
906 return 0;
907 }
908
909 *sp = key_allocsp(&spidx, dir);
910
911 /* Return SP, whether NULL or not */
912 if (*sp != NULL && (*sp)->policy == IPSEC_POLICY_IPSEC) {
913 if ((*sp)->ipsec_if == NULL) {
914 /* Invalid to capture on an interface without redirect */
915 key_freesp(*sp, KEY_SADB_UNLOCKED);
916 *sp = NULL;
917 return -1;
918 } else if ((*sp)->disabled) {
919 /* Disabled policies go in the clear */
920 key_freesp(*sp, KEY_SADB_UNLOCKED);
921 *sp = NULL;
922 *noipsec = 1; /* Avoid later IPSec check */
923 } else {
924 /* If policy is enabled, redirect to ipsec interface */
925 ip6oap->ip6oa_boundif = (*sp)->ipsec_if->if_index;
926 }
927 }
928
929 KERNEL_DEBUG(DBG_FNC_GETPOL_ADDR | DBG_FUNC_END, 2,*error,0,0,0);
930
931 return 0;
932}
1c79356b
A
933#endif /* INET6 */
934
935/*
936 * set IP address into spidx from mbuf.
937 * When Forwarding packet and ICMP echo reply, this function is used.
938 *
939 * IN: get the followings from mbuf.
940 * protocol family, src, dst, next protocol
941 * OUT:
942 * 0: success.
943 * other: failure, and set errno.
944 */
39236c6e 945static int
2d21ac55
A
946ipsec_setspidx_mbuf(
947 struct secpolicyindex *spidx,
948 u_int dir,
949 __unused u_int family,
950 struct mbuf *m,
951 int needport)
1c79356b 952{
9bccf70c 953 int error;
1c79356b
A
954
955 /* sanity check */
956 if (spidx == NULL || m == NULL)
957 panic("ipsec_setspidx_mbuf: NULL pointer was passed.\n");
958
1c79356b
A
959 bzero(spidx, sizeof(*spidx));
960
39236c6e 961 error = ipsec_setspidx(m, spidx, needport, 0);
9bccf70c
A
962 if (error)
963 goto bad;
1c79356b 964 spidx->dir = dir;
1c79356b 965
9bccf70c 966 return 0;
1c79356b 967
9bccf70c
A
968 bad:
969 /* XXX initialize */
970 bzero(spidx, sizeof(*spidx));
971 return EINVAL;
972}
1c79356b 973
39236c6e
A
974static int
975ipsec_setspidx_interface(
976 struct secpolicyindex *spidx,
977 u_int dir,
978 struct mbuf *m,
979 int needport,
980 int ifindex,
981 int ip_version)
982{
983 int error;
984
985 /* sanity check */
986 if (spidx == NULL || m == NULL)
987 panic("ipsec_setspidx_interface: NULL pointer was passed.\n");
988
989 bzero(spidx, sizeof(*spidx));
990
991 error = ipsec_setspidx(m, spidx, needport, ip_version);
992 if (error)
993 goto bad;
994 spidx->dir = dir;
995
996 if (ifindex != 0) {
997 ifnet_head_lock_shared();
998 spidx->internal_if = ifindex2ifnet[ifindex];
999 ifnet_head_done();
1000 } else {
1001 spidx->internal_if = NULL;
1002 }
1003
1004 return 0;
1005
1006bad:
1007 return EINVAL;
1008}
1009
9bccf70c
A
1010static int
1011ipsec4_setspidx_inpcb(m, pcb)
fe8ab488
A
1012struct mbuf *m;
1013struct inpcb *pcb;
9bccf70c
A
1014{
1015 struct secpolicyindex *spidx;
1016 int error;
fe8ab488 1017
9bccf70c
A
1018 if (ipsec_bypass != 0)
1019 return 0;
fe8ab488 1020
9bccf70c
A
1021 /* sanity check */
1022 if (pcb == NULL)
1023 panic("ipsec4_setspidx_inpcb: no PCB found.\n");
fe8ab488
A
1024 if (pcb->inp_sp == NULL)
1025 panic("ipsec4_setspidx_inpcb: no inp_sp found.\n");
1026 if (pcb->inp_sp->sp_out == NULL || pcb->inp_sp->sp_in == NULL)
1027 panic("ipsec4_setspidx_inpcb: no sp_in/out found.\n");
1028
1029 bzero(&pcb->inp_sp->sp_in->spidx, sizeof(*spidx));
1030 bzero(&pcb->inp_sp->sp_out->spidx, sizeof(*spidx));
1031
1032 spidx = &pcb->inp_sp->sp_in->spidx;
1033 error = ipsec_setspidx(m, spidx, 1, 0);
1034 if (error)
1035 goto bad;
9bccf70c 1036 spidx->dir = IPSEC_DIR_INBOUND;
fe8ab488 1037
9bccf70c 1038 spidx = &pcb->inp_sp->sp_out->spidx;
39236c6e 1039 error = ipsec_setspidx(m, spidx, 1, 0);
9bccf70c
A
1040 if (error)
1041 goto bad;
1042 spidx->dir = IPSEC_DIR_OUTBOUND;
fe8ab488 1043
9bccf70c 1044 return 0;
fe8ab488 1045
9bccf70c
A
1046bad:
1047 bzero(&pcb->inp_sp->sp_in->spidx, sizeof(*spidx));
1048 bzero(&pcb->inp_sp->sp_out->spidx, sizeof(*spidx));
1049 return error;
1050}
1c79356b 1051
9bccf70c
A
1052#if INET6
1053static int
1054ipsec6_setspidx_in6pcb(m, pcb)
fe8ab488
A
1055struct mbuf *m;
1056struct in6pcb *pcb;
9bccf70c
A
1057{
1058 struct secpolicyindex *spidx;
1059 int error;
fe8ab488 1060
9bccf70c
A
1061 /* sanity check */
1062 if (pcb == NULL)
1063 panic("ipsec6_setspidx_in6pcb: no PCB found.\n");
fe8ab488
A
1064 if (pcb->in6p_sp == NULL)
1065 panic("ipsec6_setspidx_in6pcb: no in6p_sp found.\n");
1066 if (pcb->in6p_sp->sp_out == NULL || pcb->in6p_sp->sp_in == NULL)
1067 panic("ipsec6_setspidx_in6pcb: no sp_in/out found.\n");
1068
1069 bzero(&pcb->in6p_sp->sp_in->spidx, sizeof(*spidx));
1070 bzero(&pcb->in6p_sp->sp_out->spidx, sizeof(*spidx));
1071
1072 spidx = &pcb->in6p_sp->sp_in->spidx;
1073 error = ipsec_setspidx(m, spidx, 1, 0);
1074 if (error)
1075 goto bad;
1076 spidx->dir = IPSEC_DIR_INBOUND;
1077
1078 spidx = &pcb->in6p_sp->sp_out->spidx;
39236c6e 1079 error = ipsec_setspidx(m, spidx, 1, 0);
55e303ae
A
1080 if (error)
1081 goto bad;
1082 spidx->dir = IPSEC_DIR_OUTBOUND;
fe8ab488 1083
1c79356b 1084 return 0;
fe8ab488 1085
9bccf70c
A
1086bad:
1087 bzero(&pcb->in6p_sp->sp_in->spidx, sizeof(*spidx));
1088 bzero(&pcb->in6p_sp->sp_out->spidx, sizeof(*spidx));
1089 return error;
1c79356b 1090}
9bccf70c 1091#endif
1c79356b 1092
1c79356b 1093/*
9bccf70c
A
1094 * configure security policy index (src/dst/proto/sport/dport)
1095 * by looking at the content of mbuf.
1096 * the caller is responsible for error recovery (like clearing up spidx).
1c79356b 1097 */
9bccf70c 1098static int
39236c6e
A
1099ipsec_setspidx(struct mbuf *m,
1100 struct secpolicyindex *spidx,
1101 int needport,
1102 int force_ip_version)
1c79356b 1103{
9bccf70c
A
1104 struct ip *ip = NULL;
1105 struct ip ipbuf;
1106 u_int v;
1107 struct mbuf *n;
1108 int len;
1109 int error;
39236c6e 1110
1c79356b 1111 if (m == NULL)
9bccf70c 1112 panic("ipsec_setspidx: m == 0 passed.\n");
39236c6e 1113
9bccf70c
A
1114 /*
1115 * validate m->m_pkthdr.len. we see incorrect length if we
1116 * mistakenly call this function with inconsistent mbuf chain
1117 * (like 4.4BSD tcp/udp processing). XXX should we panic here?
1118 */
1119 len = 0;
1120 for (n = m; n; n = n->m_next)
1121 len += n->m_len;
1122 if (m->m_pkthdr.len != len) {
1123 KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
1124 printf("ipsec_setspidx: "
1125 "total of m_len(%d) != pkthdr.len(%d), "
1126 "ignored.\n",
1127 len, m->m_pkthdr.len));
1128 return EINVAL;
1129 }
1c79356b 1130
9bccf70c
A
1131 if (m->m_pkthdr.len < sizeof(struct ip)) {
1132 KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
1133 printf("ipsec_setspidx: "
1134 "pkthdr.len(%d) < sizeof(struct ip), ignored.\n",
1135 m->m_pkthdr.len));
1136 return EINVAL;
1137 }
1c79356b 1138
9bccf70c
A
1139 if (m->m_len >= sizeof(*ip))
1140 ip = mtod(m, struct ip *);
1141 else {
1142 m_copydata(m, 0, sizeof(ipbuf), (caddr_t)&ipbuf);
1143 ip = &ipbuf;
1144 }
39236c6e
A
1145
1146 if (force_ip_version) {
1147 v = force_ip_version;
1148 } else {
9bccf70c 1149#ifdef _IP_VHL
39236c6e 1150 v = _IP_VHL_V(ip->ip_vhl);
9bccf70c 1151#else
39236c6e 1152 v = ip->ip_v;
9bccf70c 1153#endif
39236c6e 1154 }
9bccf70c
A
1155 switch (v) {
1156 case 4:
1157 error = ipsec4_setspidx_ipaddr(m, spidx);
1158 if (error)
1159 return error;
1160 ipsec4_get_ulp(m, spidx, needport);
1161 return 0;
2d21ac55 1162#if INET6
9bccf70c
A
1163 case 6:
1164 if (m->m_pkthdr.len < sizeof(struct ip6_hdr)) {
1165 KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
1166 printf("ipsec_setspidx: "
1167 "pkthdr.len(%d) < sizeof(struct ip6_hdr), "
1168 "ignored.\n", m->m_pkthdr.len));
1169 return EINVAL;
1c79356b 1170 }
9bccf70c
A
1171 error = ipsec6_setspidx_ipaddr(m, spidx);
1172 if (error)
1173 return error;
1174 ipsec6_get_ulp(m, spidx, needport);
1175 return 0;
1176#endif
1c79356b 1177 default:
9bccf70c
A
1178 KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
1179 printf("ipsec_setspidx: "
1180 "unknown IP version %u, ignored.\n", v));
1181 return EINVAL;
1c79356b
A
1182 }
1183}
1c79356b
A
1184
1185static void
9bccf70c 1186ipsec4_get_ulp(m, spidx, needport)
1c79356b 1187 struct mbuf *m;
1c79356b 1188 struct secpolicyindex *spidx;
9bccf70c
A
1189 int needport;
1190{
1191 struct ip ip;
1192 struct ip6_ext ip6e;
1193 u_int8_t nxt;
1194 int off;
1195 struct tcphdr th;
1196 struct udphdr uh;
1c79356b
A
1197
1198 /* sanity check */
9bccf70c
A
1199 if (m == NULL)
1200 panic("ipsec4_get_ulp: NULL pointer was passed.\n");
1201 if (m->m_pkthdr.len < sizeof(ip))
1202 panic("ipsec4_get_ulp: too short\n");
1c79356b 1203
9bccf70c
A
1204 /* set default */
1205 spidx->ul_proto = IPSEC_ULPROTO_ANY;
1206 ((struct sockaddr_in *)&spidx->src)->sin_port = IPSEC_PORT_ANY;
1207 ((struct sockaddr_in *)&spidx->dst)->sin_port = IPSEC_PORT_ANY;
1c79356b 1208
9bccf70c
A
1209 m_copydata(m, 0, sizeof(ip), (caddr_t)&ip);
1210 /* ip_input() flips it into host endian XXX need more checking */
1211 if (ip.ip_off & (IP_MF | IP_OFFMASK))
1212 return;
1c79356b 1213
9bccf70c
A
1214 nxt = ip.ip_p;
1215#ifdef _IP_VHL
1216 off = _IP_VHL_HL(ip->ip_vhl) << 2;
1217#else
1218 off = ip.ip_hl << 2;
1219#endif
1220 while (off < m->m_pkthdr.len) {
1221 switch (nxt) {
1222 case IPPROTO_TCP:
1223 spidx->ul_proto = nxt;
1224 if (!needport)
1225 return;
1226 if (off + sizeof(struct tcphdr) > m->m_pkthdr.len)
1227 return;
1228 m_copydata(m, off, sizeof(th), (caddr_t)&th);
1229 ((struct sockaddr_in *)&spidx->src)->sin_port =
1230 th.th_sport;
1231 ((struct sockaddr_in *)&spidx->dst)->sin_port =
1232 th.th_dport;
1233 return;
1234 case IPPROTO_UDP:
1235 spidx->ul_proto = nxt;
1236 if (!needport)
1237 return;
1238 if (off + sizeof(struct udphdr) > m->m_pkthdr.len)
1239 return;
1240 m_copydata(m, off, sizeof(uh), (caddr_t)&uh);
1241 ((struct sockaddr_in *)&spidx->src)->sin_port =
1242 uh.uh_sport;
1243 ((struct sockaddr_in *)&spidx->dst)->sin_port =
1244 uh.uh_dport;
1245 return;
1246 case IPPROTO_AH:
91447636 1247 if (off + sizeof(ip6e) > m->m_pkthdr.len)
9bccf70c
A
1248 return;
1249 m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
1250 off += (ip6e.ip6e_len + 2) << 2;
1251 nxt = ip6e.ip6e_nxt;
1252 break;
1253 case IPPROTO_ICMP:
1254 default:
1255 /* XXX intermediate headers??? */
1256 spidx->ul_proto = nxt;
1257 return;
1258 }
1259 }
1c79356b
A
1260}
1261
9bccf70c
A
1262/* assumes that m is sane */
1263static int
1c79356b
A
1264ipsec4_setspidx_ipaddr(m, spidx)
1265 struct mbuf *m;
1266 struct secpolicyindex *spidx;
1267{
1268 struct ip *ip = NULL;
1269 struct ip ipbuf;
9bccf70c 1270 struct sockaddr_in *sin;
1c79356b 1271
9bccf70c 1272 if (m->m_len >= sizeof(*ip))
1c79356b
A
1273 ip = mtod(m, struct ip *);
1274 else {
1275 m_copydata(m, 0, sizeof(ipbuf), (caddr_t)&ipbuf);
1276 ip = &ipbuf;
1277 }
1278
9bccf70c
A
1279 sin = (struct sockaddr_in *)&spidx->src;
1280 bzero(sin, sizeof(*sin));
1281 sin->sin_family = AF_INET;
1282 sin->sin_len = sizeof(struct sockaddr_in);
1283 bcopy(&ip->ip_src, &sin->sin_addr, sizeof(ip->ip_src));
1284 spidx->prefs = sizeof(struct in_addr) << 3;
1c79356b 1285
9bccf70c
A
1286 sin = (struct sockaddr_in *)&spidx->dst;
1287 bzero(sin, sizeof(*sin));
1288 sin->sin_family = AF_INET;
1289 sin->sin_len = sizeof(struct sockaddr_in);
1290 bcopy(&ip->ip_dst, &sin->sin_addr, sizeof(ip->ip_dst));
1291 spidx->prefd = sizeof(struct in_addr) << 3;
39236c6e 1292
9bccf70c 1293 return 0;
1c79356b
A
1294}
1295
1296#if INET6
1297static void
fe8ab488
A
1298ipsec6_get_ulp(struct mbuf *m,
1299 struct secpolicyindex *spidx,
1300 int needport)
9bccf70c
A
1301{
1302 int off, nxt;
1303 struct tcphdr th;
1304 struct udphdr uh;
1c79356b
A
1305
1306 /* sanity check */
9bccf70c
A
1307 if (m == NULL)
1308 panic("ipsec6_get_ulp: NULL pointer was passed.\n");
1c79356b 1309
9bccf70c
A
1310 KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
1311 printf("ipsec6_get_ulp:\n"); kdebug_mbuf(m));
1c79356b 1312
9bccf70c
A
1313 /* set default */
1314 spidx->ul_proto = IPSEC_ULPROTO_ANY;
1315 ((struct sockaddr_in6 *)&spidx->src)->sin6_port = IPSEC_PORT_ANY;
1316 ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = IPSEC_PORT_ANY;
1c79356b 1317
9bccf70c
A
1318 nxt = -1;
1319 off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);
1320 if (off < 0 || m->m_pkthdr.len < off)
1321 return;
1322
1323 switch (nxt) {
1324 case IPPROTO_TCP:
1325 spidx->ul_proto = nxt;
1326 if (!needport)
1327 break;
1328 if (off + sizeof(struct tcphdr) > m->m_pkthdr.len)
1329 break;
1330 m_copydata(m, off, sizeof(th), (caddr_t)&th);
1331 ((struct sockaddr_in6 *)&spidx->src)->sin6_port = th.th_sport;
1332 ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = th.th_dport;
1333 break;
1334 case IPPROTO_UDP:
1335 spidx->ul_proto = nxt;
1336 if (!needport)
1337 break;
1338 if (off + sizeof(struct udphdr) > m->m_pkthdr.len)
1339 break;
1340 m_copydata(m, off, sizeof(uh), (caddr_t)&uh);
1341 ((struct sockaddr_in6 *)&spidx->src)->sin6_port = uh.uh_sport;
1342 ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = uh.uh_dport;
1343 break;
1344 case IPPROTO_ICMPV6:
1345 default:
1346 /* XXX intermediate headers??? */
1347 spidx->ul_proto = nxt;
1348 break;
1349 }
1c79356b
A
1350}
1351
9bccf70c
A
1352/* assumes that m is sane */
1353static int
fe8ab488
A
1354ipsec6_setspidx_ipaddr(struct mbuf *m,
1355 struct secpolicyindex *spidx)
1c79356b
A
1356{
1357 struct ip6_hdr *ip6 = NULL;
1358 struct ip6_hdr ip6buf;
9bccf70c 1359 struct sockaddr_in6 *sin6;
1c79356b
A
1360
1361 if (m->m_len >= sizeof(*ip6))
1362 ip6 = mtod(m, struct ip6_hdr *);
1363 else {
1364 m_copydata(m, 0, sizeof(ip6buf), (caddr_t)&ip6buf);
1365 ip6 = &ip6buf;
1366 }
1367
9bccf70c
A
1368 sin6 = (struct sockaddr_in6 *)&spidx->src;
1369 bzero(sin6, sizeof(*sin6));
1370 sin6->sin6_family = AF_INET6;
1371 sin6->sin6_len = sizeof(struct sockaddr_in6);
1372 bcopy(&ip6->ip6_src, &sin6->sin6_addr, sizeof(ip6->ip6_src));
1373 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) {
1374 sin6->sin6_addr.s6_addr16[1] = 0;
1375 sin6->sin6_scope_id = ntohs(ip6->ip6_src.s6_addr16[1]);
1c79356b 1376 }
9bccf70c 1377 spidx->prefs = sizeof(struct in6_addr) << 3;
1c79356b 1378
9bccf70c
A
1379 sin6 = (struct sockaddr_in6 *)&spidx->dst;
1380 bzero(sin6, sizeof(*sin6));
1381 sin6->sin6_family = AF_INET6;
1382 sin6->sin6_len = sizeof(struct sockaddr_in6);
1383 bcopy(&ip6->ip6_dst, &sin6->sin6_addr, sizeof(ip6->ip6_dst));
1384 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) {
1385 sin6->sin6_addr.s6_addr16[1] = 0;
1386 sin6->sin6_scope_id = ntohs(ip6->ip6_dst.s6_addr16[1]);
1387 }
1388 spidx->prefd = sizeof(struct in6_addr) << 3;
1c79356b 1389
9bccf70c 1390 return 0;
1c79356b
A
1391}
1392#endif
1393
1394static struct inpcbpolicy *
1395ipsec_newpcbpolicy()
1396{
1397 struct inpcbpolicy *p;
fe8ab488 1398
0b4e3aa0 1399 p = (struct inpcbpolicy *)_MALLOC(sizeof(*p), M_SECA, M_WAITOK);
1c79356b
A
1400 return p;
1401}
1402
1403static void
fe8ab488 1404ipsec_delpcbpolicy(struct inpcbpolicy *p)
1c79356b 1405{
9bccf70c 1406 FREE(p, M_SECA);
1c79356b
A
1407}
1408
1409/* initialize policy in PCB */
1410int
fe8ab488
A
1411ipsec_init_policy(struct socket *so,
1412 struct inpcbpolicy **pcb_sp)
1c79356b
A
1413{
1414 struct inpcbpolicy *new;
fe8ab488 1415
1c79356b
A
1416 /* sanity check. */
1417 if (so == NULL || pcb_sp == NULL)
1418 panic("ipsec_init_policy: NULL pointer was passed.\n");
fe8ab488
A
1419
1420 new = ipsec_newpcbpolicy();
1421 if (new == NULL) {
1422 ipseclog((LOG_DEBUG, "ipsec_init_policy: No more memory.\n"));
1423 return ENOBUFS;
1424 }
9bccf70c 1425 bzero(new, sizeof(*new));
fe8ab488 1426
9bccf70c 1427#ifdef __APPLE__
316670eb 1428 if (kauth_cred_issuser(so->so_cred))
9bccf70c 1429#else
fe8ab488 1430 if (so->so_cred != 0 && !suser(so->so_cred->pc_ucred, NULL))
9bccf70c 1431#endif
fe8ab488
A
1432 new->priv = 1;
1433 else
1434 new->priv = 0;
1435
1436 if ((new->sp_in = key_newsp()) == NULL) {
1437 ipsec_delpcbpolicy(new);
1438 return ENOBUFS;
1439 }
1c79356b
A
1440 new->sp_in->state = IPSEC_SPSTATE_ALIVE;
1441 new->sp_in->policy = IPSEC_POLICY_ENTRUST;
fe8ab488 1442
1c79356b 1443 if ((new->sp_out = key_newsp()) == NULL) {
2d21ac55 1444 key_freesp(new->sp_in, KEY_SADB_UNLOCKED);
1c79356b
A
1445 ipsec_delpcbpolicy(new);
1446 return ENOBUFS;
1447 }
1448 new->sp_out->state = IPSEC_SPSTATE_ALIVE;
1449 new->sp_out->policy = IPSEC_POLICY_ENTRUST;
fe8ab488 1450
1c79356b 1451 *pcb_sp = new;
fe8ab488 1452
1c79356b
A
1453 return 0;
1454}
1455
1456/* copy old ipsec policy into new */
1457int
fe8ab488
A
1458ipsec_copy_policy(struct inpcbpolicy *old,
1459 struct inpcbpolicy *new)
1c79356b
A
1460{
1461 struct secpolicy *sp;
fe8ab488 1462
9bccf70c
A
1463 if (ipsec_bypass != 0)
1464 return 0;
fe8ab488 1465
1c79356b
A
1466 sp = ipsec_deepcopy_policy(old->sp_in);
1467 if (sp) {
2d21ac55 1468 key_freesp(new->sp_in, KEY_SADB_UNLOCKED);
1c79356b
A
1469 new->sp_in = sp;
1470 } else
1471 return ENOBUFS;
fe8ab488 1472
1c79356b
A
1473 sp = ipsec_deepcopy_policy(old->sp_out);
1474 if (sp) {
2d21ac55 1475 key_freesp(new->sp_out, KEY_SADB_UNLOCKED);
1c79356b
A
1476 new->sp_out = sp;
1477 } else
1478 return ENOBUFS;
fe8ab488 1479
1c79356b 1480 new->priv = old->priv;
fe8ab488 1481
1c79356b
A
1482 return 0;
1483}
1484
1485/* deep-copy a policy in PCB */
1486static struct secpolicy *
fe8ab488 1487ipsec_deepcopy_policy(struct secpolicy *src)
1c79356b
A
1488{
1489 struct ipsecrequest *newchain = NULL;
1490 struct ipsecrequest *p;
1491 struct ipsecrequest **q;
1492 struct ipsecrequest *r;
1493 struct secpolicy *dst;
fe8ab488 1494
2d21ac55
A
1495 if (src == NULL)
1496 return NULL;
1c79356b 1497 dst = key_newsp();
2d21ac55 1498 if (dst == NULL)
1c79356b 1499 return NULL;
fe8ab488 1500
1c79356b
A
1501 /*
1502 * deep-copy IPsec request chain. This is required since struct
1503 * ipsecrequest is not reference counted.
1504 */
1505 q = &newchain;
1506 for (p = src->req; p; p = p->next) {
1507 *q = (struct ipsecrequest *)_MALLOC(sizeof(struct ipsecrequest),
fe8ab488 1508 M_SECA, M_WAITOK);
1c79356b
A
1509 if (*q == NULL)
1510 goto fail;
1511 bzero(*q, sizeof(**q));
1512 (*q)->next = NULL;
fe8ab488 1513
1c79356b
A
1514 (*q)->saidx.proto = p->saidx.proto;
1515 (*q)->saidx.mode = p->saidx.mode;
1516 (*q)->level = p->level;
1517 (*q)->saidx.reqid = p->saidx.reqid;
fe8ab488 1518
1c79356b
A
1519 bcopy(&p->saidx.src, &(*q)->saidx.src, sizeof((*q)->saidx.src));
1520 bcopy(&p->saidx.dst, &(*q)->saidx.dst, sizeof((*q)->saidx.dst));
fe8ab488 1521
1c79356b 1522 (*q)->sp = dst;
fe8ab488 1523
1c79356b
A
1524 q = &((*q)->next);
1525 }
fe8ab488 1526
1c79356b
A
1527 dst->req = newchain;
1528 dst->state = src->state;
1529 dst->policy = src->policy;
1530 /* do not touch the refcnt fields */
fe8ab488 1531
1c79356b 1532 return dst;
fe8ab488 1533
1c79356b
A
1534fail:
1535 for (p = newchain; p; p = r) {
1536 r = p->next;
9bccf70c 1537 FREE(p, M_SECA);
1c79356b
A
1538 p = NULL;
1539 }
2d21ac55 1540 key_freesp(dst, KEY_SADB_UNLOCKED);
1c79356b
A
1541 return NULL;
1542}
1543
1544/* set policy and ipsec request if present. */
1545static int
fe8ab488
A
1546ipsec_set_policy(struct secpolicy **pcb_sp,
1547 __unused int optname,
1548 caddr_t request,
1549 size_t len,
1550 int priv)
1c79356b
A
1551{
1552 struct sadb_x_policy *xpl;
1553 struct secpolicy *newsp = NULL;
1554 int error;
fe8ab488 1555
1c79356b
A
1556 /* sanity check. */
1557 if (pcb_sp == NULL || *pcb_sp == NULL || request == NULL)
1558 return EINVAL;
1559 if (len < sizeof(*xpl))
1560 return EINVAL;
316670eb 1561 xpl = (struct sadb_x_policy *)(void *)request;
fe8ab488 1562
1c79356b 1563 KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
fe8ab488
A
1564 printf("ipsec_set_policy: passed policy\n");
1565 kdebug_sadb_x_policy((struct sadb_ext *)xpl));
1566
1c79356b
A
1567 /* check policy type */
1568 /* ipsec_set_policy() accepts IPSEC, ENTRUST and BYPASS. */
1569 if (xpl->sadb_x_policy_type == IPSEC_POLICY_DISCARD
1570 || xpl->sadb_x_policy_type == IPSEC_POLICY_NONE)
1571 return EINVAL;
fe8ab488 1572
1c79356b
A
1573 /* check privileged socket */
1574 if (priv == 0 && xpl->sadb_x_policy_type == IPSEC_POLICY_BYPASS)
1575 return EACCES;
fe8ab488 1576
1c79356b
A
1577 /* allocation new SP entry */
1578 if ((newsp = key_msg2sp(xpl, len, &error)) == NULL)
1579 return error;
fe8ab488 1580
1c79356b 1581 newsp->state = IPSEC_SPSTATE_ALIVE;
fe8ab488 1582
1c79356b 1583 /* clear old SP and set new SP */
2d21ac55 1584 key_freesp(*pcb_sp, KEY_SADB_UNLOCKED);
1c79356b
A
1585 *pcb_sp = newsp;
1586 KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
fe8ab488
A
1587 printf("ipsec_set_policy: new policy\n");
1588 kdebug_secpolicy(newsp));
1589
1c79356b
A
1590 return 0;
1591}
1592
1593int
fe8ab488
A
1594ipsec4_set_policy(struct inpcb *inp,
1595 int optname,
1596 caddr_t request,
1597 size_t len,
1598 int priv)
1c79356b
A
1599{
1600 struct sadb_x_policy *xpl;
1601 struct secpolicy **pcb_sp;
9bccf70c 1602 int error = 0;
316670eb
A
1603 struct sadb_x_policy xpl_aligned_buf;
1604 u_int8_t *xpl_unaligned;
fe8ab488 1605
1c79356b
A
1606 /* sanity check. */
1607 if (inp == NULL || request == NULL)
1608 return EINVAL;
1609 if (len < sizeof(*xpl))
1610 return EINVAL;
316670eb 1611 xpl = (struct sadb_x_policy *)(void *)request;
fe8ab488 1612
316670eb
A
1613 /* This is a new mbuf allocated by soopt_getm() */
1614 if (IPSEC_IS_P2ALIGNED(xpl)) {
1615 xpl_unaligned = NULL;
1616 } else {
1617 xpl_unaligned = (__typeof__(xpl_unaligned))xpl;
1618 memcpy(&xpl_aligned_buf, xpl, sizeof(xpl_aligned_buf));
1619 xpl = (__typeof__(xpl))&xpl_aligned_buf;
1620 }
fe8ab488 1621
9bccf70c
A
1622 if (inp->inp_sp == NULL) {
1623 error = ipsec_init_policy(inp->inp_socket, &inp->inp_sp);
1624 if (error)
1625 return error;
1626 }
fe8ab488 1627
1c79356b
A
1628 /* select direction */
1629 switch (xpl->sadb_x_policy_dir) {
fe8ab488
A
1630 case IPSEC_DIR_INBOUND:
1631 pcb_sp = &inp->inp_sp->sp_in;
1632 break;
1633 case IPSEC_DIR_OUTBOUND:
1634 pcb_sp = &inp->inp_sp->sp_out;
1635 break;
1636 default:
1637 ipseclog((LOG_ERR, "ipsec4_set_policy: invalid direction=%u\n",
1638 xpl->sadb_x_policy_dir));
1639 return EINVAL;
1c79356b 1640 }
fe8ab488 1641
9bccf70c
A
1642 /* turn bypass off */
1643 if (ipsec_bypass != 0)
1644 ipsec_bypass = 0;
fe8ab488 1645
1c79356b
A
1646 return ipsec_set_policy(pcb_sp, optname, request, len, priv);
1647}
1648
1c79356b
A
1649/* delete policy in PCB */
1650int
fe8ab488 1651ipsec4_delete_pcbpolicy(struct inpcb *inp)
1c79356b 1652{
fe8ab488 1653
1c79356b
A
1654 /* sanity check. */
1655 if (inp == NULL)
1656 panic("ipsec4_delete_pcbpolicy: NULL pointer was passed.\n");
fe8ab488
A
1657
1658 if (inp->inp_sp == NULL)
1659 return 0;
1660
1c79356b 1661 if (inp->inp_sp->sp_in != NULL) {
2d21ac55 1662 key_freesp(inp->inp_sp->sp_in, KEY_SADB_UNLOCKED);
1c79356b
A
1663 inp->inp_sp->sp_in = NULL;
1664 }
fe8ab488 1665
1c79356b 1666 if (inp->inp_sp->sp_out != NULL) {
2d21ac55 1667 key_freesp(inp->inp_sp->sp_out, KEY_SADB_UNLOCKED);
1c79356b
A
1668 inp->inp_sp->sp_out = NULL;
1669 }
fe8ab488 1670
1c79356b
A
1671 ipsec_delpcbpolicy(inp->inp_sp);
1672 inp->inp_sp = NULL;
fe8ab488 1673
1c79356b
A
1674 return 0;
1675}
1676
1677#if INET6
1678int
fe8ab488
A
1679ipsec6_set_policy(struct in6pcb *in6p,
1680 int optname,
1681 caddr_t request,
1682 size_t len,
1683 int priv)
1c79356b
A
1684{
1685 struct sadb_x_policy *xpl;
1686 struct secpolicy **pcb_sp;
9bccf70c 1687 int error = 0;
316670eb
A
1688 struct sadb_x_policy xpl_aligned_buf;
1689 u_int8_t *xpl_unaligned;
fe8ab488 1690
1c79356b
A
1691 /* sanity check. */
1692 if (in6p == NULL || request == NULL)
1693 return EINVAL;
1694 if (len < sizeof(*xpl))
1695 return EINVAL;
316670eb 1696 xpl = (struct sadb_x_policy *)(void *)request;
fe8ab488 1697
316670eb
A
1698 /* This is a new mbuf allocated by soopt_getm() */
1699 if (IPSEC_IS_P2ALIGNED(xpl)) {
1700 xpl_unaligned = NULL;
1701 } else {
1702 xpl_unaligned = (__typeof__(xpl_unaligned))xpl;
1703 memcpy(&xpl_aligned_buf, xpl, sizeof(xpl_aligned_buf));
1704 xpl = (__typeof__(xpl))&xpl_aligned_buf;
1705 }
fe8ab488 1706
9bccf70c
A
1707 if (in6p->in6p_sp == NULL) {
1708 error = ipsec_init_policy(in6p->inp_socket, &in6p->in6p_sp);
1709 if (error)
1710 return error;
1711 }
fe8ab488 1712
1c79356b
A
1713 /* select direction */
1714 switch (xpl->sadb_x_policy_dir) {
fe8ab488
A
1715 case IPSEC_DIR_INBOUND:
1716 pcb_sp = &in6p->in6p_sp->sp_in;
1717 break;
1718 case IPSEC_DIR_OUTBOUND:
1719 pcb_sp = &in6p->in6p_sp->sp_out;
1720 break;
1721 default:
1722 ipseclog((LOG_ERR, "ipsec6_set_policy: invalid direction=%u\n",
1723 xpl->sadb_x_policy_dir));
1724 return EINVAL;
1c79356b
A
1725 }
1726
1727 return ipsec_set_policy(pcb_sp, optname, request, len, priv);
1728}
1729
1730int
fe8ab488 1731ipsec6_delete_pcbpolicy(struct in6pcb *in6p)
1c79356b 1732{
fe8ab488 1733
1c79356b
A
1734 /* sanity check. */
1735 if (in6p == NULL)
1736 panic("ipsec6_delete_pcbpolicy: NULL pointer was passed.\n");
fe8ab488
A
1737
1738 if (in6p->in6p_sp == NULL)
1739 return 0;
1740
1c79356b 1741 if (in6p->in6p_sp->sp_in != NULL) {
2d21ac55 1742 key_freesp(in6p->in6p_sp->sp_in, KEY_SADB_UNLOCKED);
1c79356b
A
1743 in6p->in6p_sp->sp_in = NULL;
1744 }
fe8ab488 1745
1c79356b 1746 if (in6p->in6p_sp->sp_out != NULL) {
2d21ac55 1747 key_freesp(in6p->in6p_sp->sp_out, KEY_SADB_UNLOCKED);
1c79356b
A
1748 in6p->in6p_sp->sp_out = NULL;
1749 }
fe8ab488 1750
1c79356b
A
1751 ipsec_delpcbpolicy(in6p->in6p_sp);
1752 in6p->in6p_sp = NULL;
fe8ab488 1753
1c79356b
A
1754 return 0;
1755}
1756#endif
1757
1758/*
1759 * return current level.
1760 * Either IPSEC_LEVEL_USE or IPSEC_LEVEL_REQUIRE are always returned.
1761 */
1762u_int
1763ipsec_get_reqlevel(isr)
1764 struct ipsecrequest *isr;
1765{
1766 u_int level = 0;
2d21ac55 1767 u_int esp_trans_deflev = 0, esp_net_deflev = 0, ah_trans_deflev = 0, ah_net_deflev = 0;
91447636 1768
1c79356b
A
1769 /* sanity check */
1770 if (isr == NULL || isr->sp == NULL)
1771 panic("ipsec_get_reqlevel: NULL pointer is passed.\n");
1772 if (((struct sockaddr *)&isr->sp->spidx.src)->sa_family
1773 != ((struct sockaddr *)&isr->sp->spidx.dst)->sa_family)
1774 panic("ipsec_get_reqlevel: family mismatched.\n");
1775
1776/* XXX note that we have ipseclog() expanded here - code sync issue */
1777#define IPSEC_CHECK_DEFAULT(lev) \
1778 (((lev) != IPSEC_LEVEL_USE && (lev) != IPSEC_LEVEL_REQUIRE \
1779 && (lev) != IPSEC_LEVEL_UNIQUE) \
1780 ? (ipsec_debug \
1781 ? log(LOG_INFO, "fixed system default level " #lev ":%d->%d\n",\
1782 (lev), IPSEC_LEVEL_REQUIRE) \
6d2010ae 1783 : (void)0), \
1c79356b
A
1784 (lev) = IPSEC_LEVEL_REQUIRE, \
1785 (lev) \
1786 : (lev))
1787
1788 /* set default level */
1789 switch (((struct sockaddr *)&isr->sp->spidx.src)->sa_family) {
1790#if INET
1791 case AF_INET:
1792 esp_trans_deflev = IPSEC_CHECK_DEFAULT(ip4_esp_trans_deflev);
1793 esp_net_deflev = IPSEC_CHECK_DEFAULT(ip4_esp_net_deflev);
1794 ah_trans_deflev = IPSEC_CHECK_DEFAULT(ip4_ah_trans_deflev);
1795 ah_net_deflev = IPSEC_CHECK_DEFAULT(ip4_ah_net_deflev);
1796 break;
1797#endif
1798#if INET6
1799 case AF_INET6:
1800 esp_trans_deflev = IPSEC_CHECK_DEFAULT(ip6_esp_trans_deflev);
1801 esp_net_deflev = IPSEC_CHECK_DEFAULT(ip6_esp_net_deflev);
1802 ah_trans_deflev = IPSEC_CHECK_DEFAULT(ip6_ah_trans_deflev);
1803 ah_net_deflev = IPSEC_CHECK_DEFAULT(ip6_ah_net_deflev);
1804 break;
1805#endif /* INET6 */
1806 default:
1807 panic("key_get_reqlevel: Unknown family. %d\n",
1808 ((struct sockaddr *)&isr->sp->spidx.src)->sa_family);
1809 }
1810
9bccf70c 1811#undef IPSEC_CHECK_DEFAULT
1c79356b
A
1812
1813 /* set level */
1814 switch (isr->level) {
1815 case IPSEC_LEVEL_DEFAULT:
1816 switch (isr->saidx.proto) {
1817 case IPPROTO_ESP:
1818 if (isr->saidx.mode == IPSEC_MODE_TUNNEL)
1819 level = esp_net_deflev;
1820 else
1821 level = esp_trans_deflev;
1822 break;
1823 case IPPROTO_AH:
1824 if (isr->saidx.mode == IPSEC_MODE_TUNNEL)
1825 level = ah_net_deflev;
1826 else
1827 level = ah_trans_deflev;
91447636 1828 break;
1c79356b
A
1829 case IPPROTO_IPCOMP:
1830 /*
1831 * we don't really care, as IPcomp document says that
1832 * we shouldn't compress small packets
1833 */
1834 level = IPSEC_LEVEL_USE;
1835 break;
1836 default:
1837 panic("ipsec_get_reqlevel: "
1838 "Illegal protocol defined %u\n",
1839 isr->saidx.proto);
1840 }
1841 break;
1842
1843 case IPSEC_LEVEL_USE:
1844 case IPSEC_LEVEL_REQUIRE:
1845 level = isr->level;
1846 break;
1847 case IPSEC_LEVEL_UNIQUE:
1848 level = IPSEC_LEVEL_REQUIRE;
1849 break;
1850
1851 default:
1852 panic("ipsec_get_reqlevel: Illegal IPsec level %u\n",
1853 isr->level);
1854 }
1855
1856 return level;
1857}
1858
1859/*
1860 * Check AH/ESP integrity.
1861 * OUT:
1862 * 0: valid
1863 * 1: invalid
1864 */
1865static int
1866ipsec_in_reject(sp, m)
1867 struct secpolicy *sp;
1868 struct mbuf *m;
1869{
1870 struct ipsecrequest *isr;
1871 u_int level;
1872 int need_auth, need_conf, need_icv;
1873
1874 KEYDEBUG(KEYDEBUG_IPSEC_DATA,
1875 printf("ipsec_in_reject: using SP\n");
1876 kdebug_secpolicy(sp));
1877
1878 /* check policy */
1879 switch (sp->policy) {
1880 case IPSEC_POLICY_DISCARD:
2d21ac55 1881 case IPSEC_POLICY_GENERATE:
1c79356b
A
1882 return 1;
1883 case IPSEC_POLICY_BYPASS:
1884 case IPSEC_POLICY_NONE:
1885 return 0;
1886
1887 case IPSEC_POLICY_IPSEC:
1888 break;
1889
1890 case IPSEC_POLICY_ENTRUST:
1891 default:
1892 panic("ipsec_hdrsiz: Invalid policy found. %d\n", sp->policy);
1893 }
1894
1895 need_auth = 0;
1896 need_conf = 0;
1897 need_icv = 0;
1898
9bccf70c
A
1899 /* XXX should compare policy against ipsec header history */
1900
1c79356b
A
1901 for (isr = sp->req; isr != NULL; isr = isr->next) {
1902
1903 /* get current level */
1904 level = ipsec_get_reqlevel(isr);
1905
1906 switch (isr->saidx.proto) {
1907 case IPPROTO_ESP:
1908 if (level == IPSEC_LEVEL_REQUIRE) {
1909 need_conf++;
1910
2d21ac55
A
1911#if 0
1912 /* this won't work with multiple input threads - isr->sav would change
1913 * with every packet and is not necessarily related to the current packet
1914 * being processed. If ESP processing is required - the esp code should
1915 * make sure that the integrity check is present and correct. I don't see
1916 * why it would be necessary to check for the presence of the integrity
1917 * check value here. I think this is just wrong.
1918 * isr->sav has been removed.
1919 * %%%%%% this needs to be re-worked at some point but I think the code below can
1920 * be ignored for now.
1921 */
1c79356b
A
1922 if (isr->sav != NULL
1923 && isr->sav->flags == SADB_X_EXT_NONE
1924 && isr->sav->alg_auth != SADB_AALG_NONE)
1925 need_icv++;
2d21ac55 1926#endif
1c79356b
A
1927 }
1928 break;
1929 case IPPROTO_AH:
1930 if (level == IPSEC_LEVEL_REQUIRE) {
1931 need_auth++;
1932 need_icv++;
1933 }
1934 break;
1935 case IPPROTO_IPCOMP:
1936 /*
1937 * we don't really care, as IPcomp document says that
9bccf70c
A
1938 * we shouldn't compress small packets, IPComp policy
1939 * should always be treated as being in "use" level.
1c79356b
A
1940 */
1941 break;
1942 }
1943 }
1944
1945 KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
1946 printf("ipsec_in_reject: auth:%d conf:%d icv:%d m_flags:%x\n",
1947 need_auth, need_conf, need_icv, m->m_flags));
1948
1949 if ((need_conf && !(m->m_flags & M_DECRYPTED))
1950 || (!need_auth && need_icv && !(m->m_flags & M_AUTHIPDGM))
1951 || (need_auth && !(m->m_flags & M_AUTHIPHDR)))
1952 return 1;
1953
1954 return 0;
1955}
1956
1957/*
1958 * Check AH/ESP integrity.
1959 * This function is called from tcp_input(), udp_input(),
1960 * and {ah,esp}4_input for tunnel mode
1961 */
1962int
1963ipsec4_in_reject_so(m, so)
1964 struct mbuf *m;
1965 struct socket *so;
1966{
1967 struct secpolicy *sp = NULL;
1968 int error;
1969 int result;
1970
2d21ac55 1971 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
1c79356b
A
1972 /* sanity check */
1973 if (m == NULL)
1974 return 0; /* XXX should be panic ? */
1975
1976 /* get SP for this packet.
1977 * When we are called from ip_forward(), we call
1978 * ipsec4_getpolicybyaddr() with IP_FORWARDING flag.
1979 */
1980 if (so == NULL)
1981 sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error);
1982 else
fe8ab488 1983 sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_INBOUND, 0, &error);
1c79356b
A
1984
1985 if (sp == NULL)
1986 return 0; /* XXX should be panic ?
1987 * -> No, there may be error. */
1988
1989 result = ipsec_in_reject(sp, m);
1990 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
39236c6e
A
1991 printf("DP ipsec4_in_reject_so call free SP:0x%llx\n",
1992 (uint64_t)VM_KERNEL_ADDRPERM(sp)));
2d21ac55 1993 key_freesp(sp, KEY_SADB_UNLOCKED);
1c79356b
A
1994
1995 return result;
1996}
1997
1998int
1999ipsec4_in_reject(m, inp)
2000 struct mbuf *m;
2001 struct inpcb *inp;
2002{
2d21ac55
A
2003
2004 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
1c79356b
A
2005 if (inp == NULL)
2006 return ipsec4_in_reject_so(m, NULL);
9bccf70c
A
2007 if (inp->inp_socket)
2008 return ipsec4_in_reject_so(m, inp->inp_socket);
2009 else
2010 panic("ipsec4_in_reject: invalid inpcb/socket");
91447636
A
2011
2012 /* NOTREACHED */
2013 return 0;
1c79356b
A
2014}
2015
2016#if INET6
2017/*
2018 * Check AH/ESP integrity.
2019 * This function is called from tcp6_input(), udp6_input(),
2020 * and {ah,esp}6_input for tunnel mode
2021 */
2022int
2023ipsec6_in_reject_so(m, so)
2024 struct mbuf *m;
2025 struct socket *so;
2026{
2027 struct secpolicy *sp = NULL;
2028 int error;
2029 int result;
2030
2d21ac55 2031 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
1c79356b
A
2032 /* sanity check */
2033 if (m == NULL)
2034 return 0; /* XXX should be panic ? */
2035
2036 /* get SP for this packet.
2037 * When we are called from ip_forward(), we call
2038 * ipsec6_getpolicybyaddr() with IP_FORWARDING flag.
2039 */
2040 if (so == NULL)
2041 sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error);
2042 else
fe8ab488 2043 sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_INBOUND, 0, &error);
1c79356b
A
2044
2045 if (sp == NULL)
2046 return 0; /* XXX should be panic ? */
2047
2048 result = ipsec_in_reject(sp, m);
2049 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
39236c6e
A
2050 printf("DP ipsec6_in_reject_so call free SP:0x%llx\n",
2051 (uint64_t)VM_KERNEL_ADDRPERM(sp)));
2d21ac55 2052 key_freesp(sp, KEY_SADB_UNLOCKED);
1c79356b
A
2053
2054 return result;
2055}
2056
2057int
2058ipsec6_in_reject(m, in6p)
2059 struct mbuf *m;
2060 struct in6pcb *in6p;
2061{
91447636 2062
2d21ac55 2063 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
1c79356b
A
2064 if (in6p == NULL)
2065 return ipsec6_in_reject_so(m, NULL);
9bccf70c
A
2066 if (in6p->in6p_socket)
2067 return ipsec6_in_reject_so(m, in6p->in6p_socket);
2068 else
2069 panic("ipsec6_in_reject: invalid in6p/socket");
91447636
A
2070
2071 /* NOTREACHED */
2072 return 0;
1c79356b
A
2073}
2074#endif
2075
2076/*
2077 * compute the byte size to be occupied by IPsec header.
2078 * in case it is tunneled, it includes the size of outer IP header.
2079 * NOTE: SP passed is free in this function.
2080 */
2d21ac55 2081size_t
1c79356b
A
2082ipsec_hdrsiz(sp)
2083 struct secpolicy *sp;
2084{
2085 struct ipsecrequest *isr;
2086 size_t siz, clen;
2087
2d21ac55 2088 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
1c79356b 2089 KEYDEBUG(KEYDEBUG_IPSEC_DATA,
55e303ae 2090 printf("ipsec_hdrsiz: using SP\n");
1c79356b
A
2091 kdebug_secpolicy(sp));
2092
2093 /* check policy */
2094 switch (sp->policy) {
2095 case IPSEC_POLICY_DISCARD:
2d21ac55 2096 case IPSEC_POLICY_GENERATE:
1c79356b
A
2097 case IPSEC_POLICY_BYPASS:
2098 case IPSEC_POLICY_NONE:
2099 return 0;
2100
2101 case IPSEC_POLICY_IPSEC:
2102 break;
2103
2104 case IPSEC_POLICY_ENTRUST:
2105 default:
2106 panic("ipsec_hdrsiz: Invalid policy found. %d\n", sp->policy);
2107 }
2108
2109 siz = 0;
2110
2111 for (isr = sp->req; isr != NULL; isr = isr->next) {
2112
2113 clen = 0;
2114
2115 switch (isr->saidx.proto) {
2116 case IPPROTO_ESP:
2117#if IPSEC_ESP
2118 clen = esp_hdrsiz(isr);
2119#else
2120 clen = 0; /*XXX*/
2121#endif
2122 break;
2123 case IPPROTO_AH:
2124 clen = ah_hdrsiz(isr);
2125 break;
2126 case IPPROTO_IPCOMP:
2127 clen = sizeof(struct ipcomp);
2128 break;
2129 }
2130
2131 if (isr->saidx.mode == IPSEC_MODE_TUNNEL) {
2132 switch (((struct sockaddr *)&isr->saidx.dst)->sa_family) {
2133 case AF_INET:
2134 clen += sizeof(struct ip);
2135 break;
2136#if INET6
2137 case AF_INET6:
2138 clen += sizeof(struct ip6_hdr);
2139 break;
2140#endif
2141 default:
2142 ipseclog((LOG_ERR, "ipsec_hdrsiz: "
2143 "unknown AF %d in IPsec tunnel SA\n",
2144 ((struct sockaddr *)&isr->saidx.dst)->sa_family));
2145 break;
2146 }
2147 }
2148 siz += clen;
2149 }
2150
2151 return siz;
2152}
2153
2154/* This function is called from ip_forward() and ipsec4_hdrsize_tcp(). */
2155size_t
2156ipsec4_hdrsiz(m, dir, inp)
2157 struct mbuf *m;
2158 u_int dir;
2159 struct inpcb *inp;
2160{
2161 struct secpolicy *sp = NULL;
2162 int error;
2163 size_t size;
2164
2d21ac55 2165 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
1c79356b
A
2166 /* sanity check */
2167 if (m == NULL)
2168 return 0; /* XXX should be panic ? */
2169 if (inp != NULL && inp->inp_socket == NULL)
2170 panic("ipsec4_hdrsize: why is socket NULL but there is PCB.");
2171
2172 /* get SP for this packet.
2173 * When we are called from ip_forward(), we call
2174 * ipsec4_getpolicybyaddr() with IP_FORWARDING flag.
2175 */
2176 if (inp == NULL)
2177 sp = ipsec4_getpolicybyaddr(m, dir, IP_FORWARDING, &error);
2178 else
fe8ab488 2179 sp = ipsec4_getpolicybyaddr(m, dir, 0, &error);
1c79356b
A
2180
2181 if (sp == NULL)
2182 return 0; /* XXX should be panic ? */
2183
2184 size = ipsec_hdrsiz(sp);
2185 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
39236c6e
A
2186 printf("DP ipsec4_hdrsiz call free SP:0x%llx\n",
2187 (uint64_t)VM_KERNEL_ADDRPERM(sp)));
1c79356b 2188 KEYDEBUG(KEYDEBUG_IPSEC_DATA,
b0d623f7 2189 printf("ipsec4_hdrsiz: size:%lu.\n", (u_int32_t)size));
2d21ac55 2190 key_freesp(sp, KEY_SADB_UNLOCKED);
1c79356b
A
2191
2192 return size;
2193}
2194
2195#if INET6
2196/* This function is called from ipsec6_hdrsize_tcp(),
2197 * and maybe from ip6_forward.()
2198 */
2199size_t
2200ipsec6_hdrsiz(m, dir, in6p)
2201 struct mbuf *m;
2202 u_int dir;
2203 struct in6pcb *in6p;
2204{
2205 struct secpolicy *sp = NULL;
2206 int error;
2207 size_t size;
2208
2d21ac55 2209 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
1c79356b
A
2210 /* sanity check */
2211 if (m == NULL)
2212 return 0; /* XXX shoud be panic ? */
2213 if (in6p != NULL && in6p->in6p_socket == NULL)
2214 panic("ipsec6_hdrsize: why is socket NULL but there is PCB.");
2215
2216 /* get SP for this packet */
2217 /* XXX Is it right to call with IP_FORWARDING. */
2218 if (in6p == NULL)
2219 sp = ipsec6_getpolicybyaddr(m, dir, IP_FORWARDING, &error);
2220 else
fe8ab488 2221 sp = ipsec6_getpolicybyaddr(m, dir, 0, &error);
1c79356b
A
2222
2223 if (sp == NULL)
2224 return 0;
2225 size = ipsec_hdrsiz(sp);
2226 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
39236c6e
A
2227 printf("DP ipsec6_hdrsiz call free SP:0x%llx\n",
2228 (uint64_t)VM_KERNEL_ADDRPERM(sp)));
1c79356b 2229 KEYDEBUG(KEYDEBUG_IPSEC_DATA,
b0d623f7 2230 printf("ipsec6_hdrsiz: size:%lu.\n", (u_int32_t)size));
2d21ac55 2231 key_freesp(sp, KEY_SADB_UNLOCKED);
1c79356b
A
2232
2233 return size;
2234}
2235#endif /*INET6*/
2236
2237#if INET
2238/*
2239 * encapsulate for ipsec tunnel.
2240 * ip->ip_src must be fixed later on.
2241 */
316670eb 2242int
1c79356b
A
2243ipsec4_encapsulate(m, sav)
2244 struct mbuf *m;
2245 struct secasvar *sav;
2246{
2247 struct ip *oip;
2248 struct ip *ip;
2249 size_t hlen;
2250 size_t plen;
2251
2252 /* can't tunnel between different AFs */
2253 if (((struct sockaddr *)&sav->sah->saidx.src)->sa_family
2254 != ((struct sockaddr *)&sav->sah->saidx.dst)->sa_family
2255 || ((struct sockaddr *)&sav->sah->saidx.src)->sa_family != AF_INET) {
2256 m_freem(m);
2257 return EINVAL;
2258 }
2259#if 0
2260 /* XXX if the dst is myself, perform nothing. */
9bccf70c 2261 if (key_ismyaddr((struct sockaddr *)&sav->sah->saidx.dst)) {
1c79356b
A
2262 m_freem(m);
2263 return EINVAL;
2264 }
2265#endif
2266
2267 if (m->m_len < sizeof(*ip))
2268 panic("ipsec4_encapsulate: assumption failed (first mbuf length)");
2269
2270 ip = mtod(m, struct ip *);
2271#ifdef _IP_VHL
9bccf70c 2272 hlen = _IP_VHL_HL(ip->ip_vhl) << 2;
1c79356b
A
2273#else
2274 hlen = ip->ip_hl << 2;
2275#endif
2276
2277 if (m->m_len != hlen)
2278 panic("ipsec4_encapsulate: assumption failed (first mbuf length)");
2279
2280 /* generate header checksum */
2281 ip->ip_sum = 0;
2282#ifdef _IP_VHL
2283 ip->ip_sum = in_cksum(m, hlen);
2284#else
2285 ip->ip_sum = in_cksum(m, hlen);
2286#endif
2287
2288 plen = m->m_pkthdr.len;
2289
2290 /*
2291 * grow the mbuf to accomodate the new IPv4 header.
2292 * NOTE: IPv4 options will never be copied.
2293 */
2294 if (M_LEADINGSPACE(m->m_next) < hlen) {
2295 struct mbuf *n;
2296 MGET(n, M_DONTWAIT, MT_DATA);
2297 if (!n) {
2298 m_freem(m);
2299 return ENOBUFS;
2300 }
2301 n->m_len = hlen;
2302 n->m_next = m->m_next;
2303 m->m_next = n;
2304 m->m_pkthdr.len += hlen;
2305 oip = mtod(n, struct ip *);
2306 } else {
2307 m->m_next->m_len += hlen;
2308 m->m_next->m_data -= hlen;
2309 m->m_pkthdr.len += hlen;
2310 oip = mtod(m->m_next, struct ip *);
2311 }
2312 ip = mtod(m, struct ip *);
2313 ovbcopy((caddr_t)ip, (caddr_t)oip, hlen);
2314 m->m_len = sizeof(struct ip);
2315 m->m_pkthdr.len -= (hlen - sizeof(struct ip));
2316
2317 /* construct new IPv4 header. see RFC 2401 5.1.2.1 */
2318 /* ECN consideration. */
2319 ip_ecn_ingress(ip4_ipsec_ecn, &ip->ip_tos, &oip->ip_tos);
2320#ifdef _IP_VHL
2321 ip->ip_vhl = IP_MAKE_VHL(IPVERSION, sizeof(struct ip) >> 2);
2322#else
2323 ip->ip_hl = sizeof(struct ip) >> 2;
2324#endif
2325 ip->ip_off &= htons(~IP_OFFMASK);
2326 ip->ip_off &= htons(~IP_MF);
2327 switch (ip4_ipsec_dfbit) {
55e303ae 2328 case 0: /* clear DF bit */
1c79356b
A
2329 ip->ip_off &= htons(~IP_DF);
2330 break;
55e303ae 2331 case 1: /* set DF bit */
1c79356b
A
2332 ip->ip_off |= htons(IP_DF);
2333 break;
55e303ae 2334 default: /* copy DF bit */
1c79356b
A
2335 break;
2336 }
2337 ip->ip_p = IPPROTO_IPIP;
2338 if (plen + sizeof(struct ip) < IP_MAXPACKET)
2339 ip->ip_len = htons(plen + sizeof(struct ip));
2340 else {
2341 ipseclog((LOG_ERR, "IPv4 ipsec: size exceeds limit: "
2342 "leave ip_len as is (invalid packet)\n"));
2343 }
9bccf70c 2344 ip->ip_id = ip_randomid();
1c79356b
A
2345 bcopy(&((struct sockaddr_in *)&sav->sah->saidx.src)->sin_addr,
2346 &ip->ip_src, sizeof(ip->ip_src));
2347 bcopy(&((struct sockaddr_in *)&sav->sah->saidx.dst)->sin_addr,
2348 &ip->ip_dst, sizeof(ip->ip_dst));
9bccf70c 2349 ip->ip_ttl = IPDEFTTL;
1c79356b
A
2350
2351 /* XXX Should ip_src be updated later ? */
2352
2353 return 0;
2354}
316670eb
A
2355
2356/*
2357 * encapsulate for ipsec tunnel.
2358 * ip->ip_src must be fixed later on.
2359 */
2360int
2361ipsec4_encapsulate_utun_esp_keepalive(m_ptr, sav)
2362 struct mbuf **m_ptr;
2363 struct secasvar *sav;
2364{
2365 struct ip *ip;
2366 size_t plen;
2367 struct mbuf *m = *m_ptr;
2368
2369 /* can't tunnel between different AFs */
2370 if (((struct sockaddr *)&sav->sah->saidx.src)->sa_family
2371 != ((struct sockaddr *)&sav->sah->saidx.dst)->sa_family
2372 || ((struct sockaddr *)&sav->sah->saidx.src)->sa_family != AF_INET) {
2373 m_freem(m);
2374 *m_ptr = NULL;
2375 return EINVAL;
2376 }
2377
2378 plen = m->m_pkthdr.len;
2379
2380 /*
2381 * grow the mbuf to accomodate the new IPv4 header.
2382 * NOTE: IPv4 options will never be copied.
2383 */
2384 {
2385 struct mbuf *n;
2386 MGETHDR(n, M_DONTWAIT, MT_HEADER); /* MAC-OK */
2387 if (!n) {
2388 m_freem(m);
2389 *m_ptr = NULL;
2390 return ENOBUFS;
2391 }
2392 if (m->m_flags & M_PKTHDR) {
2393 M_COPY_PKTHDR(n, m);
2394 m->m_flags &= ~M_PKTHDR;
2395 }
2396 MH_ALIGN(n, sizeof(*ip));
2397 n->m_len = sizeof(*ip);
2398 n->m_next = m;
2399 n->m_pkthdr.len = (plen + n->m_len);
2400 m_fixhdr(m);
2401 m = n;
2402 *m_ptr = m;
2403 plen = m->m_pkthdr.len;
2404 }
2405 ip = mtod(m, __typeof__(ip));
2406
2407 /* construct new IPv4 header. see RFC 2401 5.1.2.1 */
2408 // ip_ecn_ingress(ip4_ipsec_ecn, &ip->ip_tos, &oip->ip_tos);
2409#ifdef _IP_VHL
2410 ip->ip_vhl = IP_MAKE_VHL(IPVERSION, sizeof(*ip) >> 2);
2411#else
2412 ip->ip_hl = sizeof(*ip) >> 2;
2413#endif
2414 ip->ip_off &= htons(~IP_OFFMASK);
2415 ip->ip_off &= htons(~IP_MF);
2416 switch (ip4_ipsec_dfbit) {
2417 case 0: /* clear DF bit */
2418 ip->ip_off &= htons(~IP_DF);
2419 break;
2420 case 1: /* set DF bit */
2421 ip->ip_off |= htons(IP_DF);
2422 break;
2423 default: /* copy DF bit */
2424 break;
2425 }
2426 ip->ip_p = IPPROTO_IPIP;
2427 if (plen < IP_MAXPACKET)
2428 ip->ip_len = htons(plen);
2429 else {
2430 ipseclog((LOG_ERR, "IPv4 ipsec: size exceeds limit: "
2431 "leave ip_len as is (invalid packet)\n"));
2432 }
316670eb 2433 ip->ip_id = ip_randomid();
316670eb
A
2434 bcopy(&((struct sockaddr_in *)&sav->sah->saidx.src)->sin_addr,
2435 &ip->ip_src, sizeof(ip->ip_src));
2436 bcopy(&((struct sockaddr_in *)&sav->sah->saidx.dst)->sin_addr,
2437 &ip->ip_dst, sizeof(ip->ip_dst));
2438 ip->ip_ttl = IPDEFTTL;
2439
2440 /* XXX Should ip_src be updated later ? */
2441
2442 return 0;
2443}
1c79356b
A
2444#endif /*INET*/
2445
2446#if INET6
316670eb 2447int
1c79356b
A
2448ipsec6_encapsulate(m, sav)
2449 struct mbuf *m;
2450 struct secasvar *sav;
2451{
2452 struct ip6_hdr *oip6;
2453 struct ip6_hdr *ip6;
2454 size_t plen;
2455
2456 /* can't tunnel between different AFs */
2457 if (((struct sockaddr *)&sav->sah->saidx.src)->sa_family
2458 != ((struct sockaddr *)&sav->sah->saidx.dst)->sa_family
2459 || ((struct sockaddr *)&sav->sah->saidx.src)->sa_family != AF_INET6) {
2460 m_freem(m);
2461 return EINVAL;
2462 }
2463#if 0
2464 /* XXX if the dst is myself, perform nothing. */
9bccf70c 2465 if (key_ismyaddr((struct sockaddr *)&sav->sah->saidx.dst)) {
1c79356b
A
2466 m_freem(m);
2467 return EINVAL;
2468 }
2469#endif
2470
2471 plen = m->m_pkthdr.len;
2472
2473 /*
2474 * grow the mbuf to accomodate the new IPv6 header.
2475 */
2476 if (m->m_len != sizeof(struct ip6_hdr))
2477 panic("ipsec6_encapsulate: assumption failed (first mbuf length)");
2478 if (M_LEADINGSPACE(m->m_next) < sizeof(struct ip6_hdr)) {
2479 struct mbuf *n;
2480 MGET(n, M_DONTWAIT, MT_DATA);
2481 if (!n) {
2482 m_freem(m);
2483 return ENOBUFS;
2484 }
2485 n->m_len = sizeof(struct ip6_hdr);
2486 n->m_next = m->m_next;
2487 m->m_next = n;
2488 m->m_pkthdr.len += sizeof(struct ip6_hdr);
2489 oip6 = mtod(n, struct ip6_hdr *);
2490 } else {
2491 m->m_next->m_len += sizeof(struct ip6_hdr);
2492 m->m_next->m_data -= sizeof(struct ip6_hdr);
2493 m->m_pkthdr.len += sizeof(struct ip6_hdr);
2494 oip6 = mtod(m->m_next, struct ip6_hdr *);
2495 }
2496 ip6 = mtod(m, struct ip6_hdr *);
2497 ovbcopy((caddr_t)ip6, (caddr_t)oip6, sizeof(struct ip6_hdr));
2498
2499 /* Fake link-local scope-class addresses */
2500 if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_src))
2501 oip6->ip6_src.s6_addr16[1] = 0;
2502 if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_dst))
2503 oip6->ip6_dst.s6_addr16[1] = 0;
2504
2505 /* construct new IPv6 header. see RFC 2401 5.1.2.2 */
2506 /* ECN consideration. */
2507 ip6_ecn_ingress(ip6_ipsec_ecn, &ip6->ip6_flow, &oip6->ip6_flow);
2508 if (plen < IPV6_MAXPACKET - sizeof(struct ip6_hdr))
2509 ip6->ip6_plen = htons(plen);
2510 else {
2511 /* ip6->ip6_plen will be updated in ip6_output() */
2512 }
2513 ip6->ip6_nxt = IPPROTO_IPV6;
2514 bcopy(&((struct sockaddr_in6 *)&sav->sah->saidx.src)->sin6_addr,
2515 &ip6->ip6_src, sizeof(ip6->ip6_src));
2516 bcopy(&((struct sockaddr_in6 *)&sav->sah->saidx.dst)->sin6_addr,
2517 &ip6->ip6_dst, sizeof(ip6->ip6_dst));
9bccf70c 2518 ip6->ip6_hlim = IPV6_DEFHLIM;
1c79356b
A
2519
2520 /* XXX Should ip6_src be updated later ? */
2521
2522 return 0;
2523}
2d21ac55
A
2524
2525static int
2526ipsec64_encapsulate(m, sav)
2527 struct mbuf *m;
2528 struct secasvar *sav;
2529{
2530 struct ip6_hdr *ip6, *ip6i;
2531 struct ip *ip;
2532 size_t plen;
2533 u_int8_t hlim;
2534
2535 /* tunneling over IPv4 */
2536 if (((struct sockaddr *)&sav->sah->saidx.src)->sa_family
2537 != ((struct sockaddr *)&sav->sah->saidx.dst)->sa_family
2538 || ((struct sockaddr *)&sav->sah->saidx.src)->sa_family != AF_INET) {
2539 m_freem(m);
2540 return EINVAL;
2541 }
2542#if 0
2543 /* XXX if the dst is myself, perform nothing. */
2544 if (key_ismyaddr((struct sockaddr *)&sav->sah->saidx.dst)) {
2545 m_freem(m);
2546 return EINVAL;
2547 }
2548#endif
2549
2550 plen = m->m_pkthdr.len;
2551 ip6 = mtod(m, struct ip6_hdr *);
2552 hlim = ip6->ip6_hlim;
2553 /*
2554 * grow the mbuf to accomodate the new IPv4 header.
2555 */
2556 if (m->m_len != sizeof(struct ip6_hdr))
2557 panic("ipsec6_encapsulate: assumption failed (first mbuf length)");
2558 if (M_LEADINGSPACE(m->m_next) < sizeof(struct ip6_hdr)) {
2559 struct mbuf *n;
2560 MGET(n, M_DONTWAIT, MT_DATA);
2561 if (!n) {
2562 m_freem(m);
2563 return ENOBUFS;
2564 }
2565 n->m_len = sizeof(struct ip6_hdr);
2566 n->m_next = m->m_next;
2567 m->m_next = n;
2568 m->m_pkthdr.len += sizeof(struct ip);
2569 ip6i = mtod(n, struct ip6_hdr *);
2570 } else {
2571 m->m_next->m_len += sizeof(struct ip6_hdr);
2572 m->m_next->m_data -= sizeof(struct ip6_hdr);
2573 m->m_pkthdr.len += sizeof(struct ip);
2574 ip6i = mtod(m->m_next, struct ip6_hdr *);
2575 }
2576 /* construct new IPv4 header. see RFC 2401 5.1.2.1 */
2577 /* ECN consideration. */
2578 /* XXX To be fixed later if needed */
2579 // ip_ecn_ingress(ip4_ipsec_ecn, &ip->ip_tos, &oip->ip_tos);
2580
2581 bcopy(ip6, ip6i, sizeof(struct ip6_hdr));
2582 ip = mtod(m, struct ip *);
2583 m->m_len = sizeof(struct ip);
2584 /*
2585 * Fill in some of the IPv4 fields - we don't need all of them
2586 * because the rest will be filled in by ip_output
2587 */
2588 ip->ip_v = IPVERSION;
2589 ip->ip_hl = sizeof(struct ip) >> 2;
2590 ip->ip_id = 0;
2591 ip->ip_sum = 0;
2592 ip->ip_tos = 0;
2593 ip->ip_off = 0;
2594 ip->ip_ttl = hlim;
2595 ip->ip_p = IPPROTO_IPV6;
2596 if (plen + sizeof(struct ip) < IP_MAXPACKET)
2597 ip->ip_len = htons(plen + sizeof(struct ip));
2598 else {
2599 ip->ip_len = htons(plen);
2600 ipseclog((LOG_ERR, "IPv4 ipsec: size exceeds limit: "
2601 "leave ip_len as is (invalid packet)\n"));
2602 }
2603 bcopy(&((struct sockaddr_in *)&sav->sah->saidx.src)->sin_addr,
2604 &ip->ip_src, sizeof(ip->ip_src));
2605 bcopy(&((struct sockaddr_in *)&sav->sah->saidx.dst)->sin_addr,
2606 &ip->ip_dst, sizeof(ip->ip_dst));
2607
2608 return 0;
2609}
316670eb
A
2610
2611int
2612ipsec6_encapsulate_utun_esp_keepalive(m_ptr, sav)
2613 struct mbuf **m_ptr;
2614 struct secasvar *sav;
2615{
2616 struct ip6_hdr *ip6;
2617 size_t plen;
2618 struct mbuf *m = *m_ptr;
2619
2620 /* can't tunnel between different AFs */
2621 if (((struct sockaddr *)&sav->sah->saidx.src)->sa_family
2622 != ((struct sockaddr *)&sav->sah->saidx.dst)->sa_family
2623 || ((struct sockaddr *)&sav->sah->saidx.src)->sa_family != AF_INET6) {
2624 m_freem(m);
2625 *m_ptr = NULL;
2626 return EINVAL;
2627 }
2628
2629 plen = m->m_pkthdr.len;
2630
2631 /*
2632 * grow the mbuf to accomodate the new IPv6 header.
2633 */
2634 {
2635 struct mbuf *n;
2636 MGETHDR(n, M_DONTWAIT, MT_HEADER); /* MAC-OK */
2637 if (!n) {
2638 m_freem(m);
2639 *m_ptr = NULL;
2640 return ENOBUFS;
2641 }
2642 if (m->m_flags & M_PKTHDR) {
2643 M_COPY_PKTHDR(n, m);
2644 m->m_flags &= ~M_PKTHDR;
2645 }
2646 MH_ALIGN(n, sizeof(*ip6));
2647 n->m_len = sizeof(*ip6);
2648 n->m_next = m;
2649 n->m_pkthdr.len = (plen + n->m_len);
2650 m_fixhdr(m);
2651 m = n;
2652 *m_ptr = m;
2653 plen = m->m_pkthdr.len;
2654 }
2655 ip6 = mtod(m, __typeof__(ip6));
2656
2657 /* construct new IPv6 header. see RFC 2401 5.1.2.2 */
2658 if (plen < IPV6_MAXPACKET)
2659 ip6->ip6_plen = htons(plen);
2660 else {
2661 /* ip6->ip6_plen will be updated in ip6_output() */
2662 }
2663 ip6->ip6_nxt = IPPROTO_IPV6;
2664 bcopy(&((struct sockaddr_in6 *)&sav->sah->saidx.src)->sin6_addr,
2665 &ip6->ip6_src, sizeof(ip6->ip6_src));
2666 bcopy(&((struct sockaddr_in6 *)&sav->sah->saidx.dst)->sin6_addr,
2667 &ip6->ip6_dst, sizeof(ip6->ip6_dst));
2668 ip6->ip6_hlim = IPV6_DEFHLIM;
2669
2670 /* XXX Should ip6_src be updated later ? */
2671
2672 return 0;
2673}
1c79356b
A
2674#endif /*INET6*/
2675
2676/*
2677 * Check the variable replay window.
2678 * ipsec_chkreplay() performs replay check before ICV verification.
2679 * ipsec_updatereplay() updates replay bitmap. This must be called after
2680 * ICV verification (it also performs replay check, which is usually done
2681 * beforehand).
2682 * 0 (zero) is returned if packet disallowed, 1 if packet permitted.
2683 *
2684 * based on RFC 2401.
2685 */
2686int
2687ipsec_chkreplay(seq, sav)
2688 u_int32_t seq;
2689 struct secasvar *sav;
2690{
2691 const struct secreplay *replay;
2692 u_int32_t diff;
2693 int fr;
2694 u_int32_t wsizeb; /* constant: bits of window size */
2695 int frlast; /* constant: last frame */
2696
2d21ac55 2697
1c79356b
A
2698 /* sanity check */
2699 if (sav == NULL)
2700 panic("ipsec_chkreplay: NULL pointer was passed.\n");
2701
2d21ac55 2702 lck_mtx_lock(sadb_mutex);
1c79356b
A
2703 replay = sav->replay;
2704
2d21ac55
A
2705 if (replay->wsize == 0) {
2706 lck_mtx_unlock(sadb_mutex);
1c79356b 2707 return 1; /* no need to check replay. */
2d21ac55 2708 }
1c79356b
A
2709
2710 /* constant */
2711 frlast = replay->wsize - 1;
2712 wsizeb = replay->wsize << 3;
2713
2714 /* sequence number of 0 is invalid */
2d21ac55
A
2715 if (seq == 0) {
2716 lck_mtx_unlock(sadb_mutex);
1c79356b 2717 return 0;
2d21ac55 2718 }
1c79356b
A
2719
2720 /* first time is always okay */
2d21ac55
A
2721 if (replay->count == 0) {
2722 lck_mtx_unlock(sadb_mutex);
1c79356b 2723 return 1;
2d21ac55 2724 }
1c79356b
A
2725
2726 if (seq > replay->lastseq) {
2727 /* larger sequences are okay */
2d21ac55 2728 lck_mtx_unlock(sadb_mutex);
1c79356b
A
2729 return 1;
2730 } else {
2731 /* seq is equal or less than lastseq. */
2732 diff = replay->lastseq - seq;
2733
2734 /* over range to check, i.e. too old or wrapped */
2d21ac55
A
2735 if (diff >= wsizeb) {
2736 lck_mtx_unlock(sadb_mutex);
1c79356b 2737 return 0;
2d21ac55 2738 }
1c79356b
A
2739
2740 fr = frlast - diff / 8;
2741
2742 /* this packet already seen ? */
2d21ac55
A
2743 if ((replay->bitmap)[fr] & (1 << (diff % 8))) {
2744 lck_mtx_unlock(sadb_mutex);
1c79356b 2745 return 0;
2d21ac55 2746 }
1c79356b
A
2747
2748 /* out of order but good */
2d21ac55 2749 lck_mtx_unlock(sadb_mutex);
1c79356b
A
2750 return 1;
2751 }
2752}
2753
2754/*
2755 * check replay counter whether to update or not.
2756 * OUT: 0: OK
2757 * 1: NG
2758 */
2759int
2760ipsec_updatereplay(seq, sav)
2761 u_int32_t seq;
2762 struct secasvar *sav;
2763{
2764 struct secreplay *replay;
2765 u_int32_t diff;
2766 int fr;
2767 u_int32_t wsizeb; /* constant: bits of window size */
2768 int frlast; /* constant: last frame */
2d21ac55 2769
1c79356b
A
2770 /* sanity check */
2771 if (sav == NULL)
2772 panic("ipsec_chkreplay: NULL pointer was passed.\n");
2773
2d21ac55 2774 lck_mtx_lock(sadb_mutex);
1c79356b
A
2775 replay = sav->replay;
2776
2777 if (replay->wsize == 0)
2778 goto ok; /* no need to check replay. */
2779
2780 /* constant */
2781 frlast = replay->wsize - 1;
2782 wsizeb = replay->wsize << 3;
2783
2784 /* sequence number of 0 is invalid */
2785 if (seq == 0)
2786 return 1;
2787
2788 /* first time */
2789 if (replay->count == 0) {
2790 replay->lastseq = seq;
2791 bzero(replay->bitmap, replay->wsize);
2792 (replay->bitmap)[frlast] = 1;
2793 goto ok;
2794 }
2795
2796 if (seq > replay->lastseq) {
2797 /* seq is larger than lastseq. */
2798 diff = seq - replay->lastseq;
2799
2800 /* new larger sequence number */
2801 if (diff < wsizeb) {
2802 /* In window */
2803 /* set bit for this packet */
2d21ac55 2804 vshiftl((unsigned char *) replay->bitmap, diff, replay->wsize);
1c79356b
A
2805 (replay->bitmap)[frlast] |= 1;
2806 } else {
2807 /* this packet has a "way larger" */
2808 bzero(replay->bitmap, replay->wsize);
2809 (replay->bitmap)[frlast] = 1;
2810 }
2811 replay->lastseq = seq;
2812
2813 /* larger is good */
2814 } else {
2815 /* seq is equal or less than lastseq. */
2816 diff = replay->lastseq - seq;
2817
2818 /* over range to check, i.e. too old or wrapped */
2d21ac55
A
2819 if (diff >= wsizeb) {
2820 lck_mtx_unlock(sadb_mutex);
1c79356b 2821 return 1;
2d21ac55 2822 }
1c79356b
A
2823
2824 fr = frlast - diff / 8;
2825
2826 /* this packet already seen ? */
2d21ac55
A
2827 if ((replay->bitmap)[fr] & (1 << (diff % 8))) {
2828 lck_mtx_unlock(sadb_mutex);
1c79356b 2829 return 1;
2d21ac55 2830 }
1c79356b
A
2831
2832 /* mark as seen */
2833 (replay->bitmap)[fr] |= (1 << (diff % 8));
2834
2835 /* out of order but good */
2836 }
2837
2838ok:
2839 if (replay->count == ~0) {
2840
2841 /* set overflow flag */
2842 replay->overflow++;
2843
2844 /* don't increment, no more packets accepted */
2d21ac55
A
2845 if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0) {
2846 lck_mtx_unlock(sadb_mutex);
1c79356b 2847 return 1;
2d21ac55 2848 }
1c79356b
A
2849
2850 ipseclog((LOG_WARNING, "replay counter made %d cycle. %s\n",
2851 replay->overflow, ipsec_logsastr(sav)));
2852 }
2853
2854 replay->count++;
2d21ac55
A
2855
2856 lck_mtx_unlock(sadb_mutex);
1c79356b
A
2857 return 0;
2858}
2859
2860/*
55e303ae 2861 * shift variable length buffer to left.
1c79356b
A
2862 * IN: bitmap: pointer to the buffer
2863 * nbit: the number of to shift.
2864 * wsize: buffer size (bytes).
2865 */
2866static void
2867vshiftl(bitmap, nbit, wsize)
2868 unsigned char *bitmap;
2869 int nbit, wsize;
2870{
2871 int s, j, i;
2872 unsigned char over;
2873
2874 for (j = 0; j < nbit; j += 8) {
2875 s = (nbit - j < 8) ? (nbit - j): 8;
2876 bitmap[0] <<= s;
2877 for (i = 1; i < wsize; i++) {
2878 over = (bitmap[i] >> (8 - s));
2879 bitmap[i] <<= s;
2880 bitmap[i-1] |= over;
2881 }
2882 }
2883
2884 return;
2885}
2886
2887const char *
2888ipsec4_logpacketstr(ip, spi)
2889 struct ip *ip;
2890 u_int32_t spi;
2891{
316670eb 2892 static char buf[256] __attribute__((aligned(4)));
1c79356b
A
2893 char *p;
2894 u_int8_t *s, *d;
2895
2896 s = (u_int8_t *)(&ip->ip_src);
2897 d = (u_int8_t *)(&ip->ip_dst);
2898
2899 p = buf;
2900 snprintf(buf, sizeof(buf), "packet(SPI=%u ", (u_int32_t)ntohl(spi));
2901 while (p && *p)
2902 p++;
9bccf70c 2903 snprintf(p, sizeof(buf) - (p - buf), "src=%u.%u.%u.%u",
1c79356b
A
2904 s[0], s[1], s[2], s[3]);
2905 while (p && *p)
2906 p++;
9bccf70c 2907 snprintf(p, sizeof(buf) - (p - buf), " dst=%u.%u.%u.%u",
1c79356b
A
2908 d[0], d[1], d[2], d[3]);
2909 while (p && *p)
2910 p++;
2911 snprintf(p, sizeof(buf) - (p - buf), ")");
2912
2913 return buf;
2914}
2915
2916#if INET6
2917const char *
2918ipsec6_logpacketstr(ip6, spi)
2919 struct ip6_hdr *ip6;
2920 u_int32_t spi;
2921{
316670eb 2922 static char buf[256] __attribute__((aligned(4)));
1c79356b
A
2923 char *p;
2924
2925 p = buf;
2926 snprintf(buf, sizeof(buf), "packet(SPI=%u ", (u_int32_t)ntohl(spi));
2927 while (p && *p)
2928 p++;
2929 snprintf(p, sizeof(buf) - (p - buf), "src=%s",
2930 ip6_sprintf(&ip6->ip6_src));
2931 while (p && *p)
2932 p++;
2933 snprintf(p, sizeof(buf) - (p - buf), " dst=%s",
2934 ip6_sprintf(&ip6->ip6_dst));
2935 while (p && *p)
2936 p++;
2937 snprintf(p, sizeof(buf) - (p - buf), ")");
2938
2939 return buf;
2940}
2941#endif /*INET6*/
2942
2943const char *
2944ipsec_logsastr(sav)
2945 struct secasvar *sav;
2946{
316670eb 2947 static char buf[256] __attribute__((aligned(4)));
1c79356b
A
2948 char *p;
2949 struct secasindex *saidx = &sav->sah->saidx;
2950
2951 /* validity check */
2952 if (((struct sockaddr *)&sav->sah->saidx.src)->sa_family
2953 != ((struct sockaddr *)&sav->sah->saidx.dst)->sa_family)
2954 panic("ipsec_logsastr: family mismatched.\n");
2955
2956 p = buf;
2957 snprintf(buf, sizeof(buf), "SA(SPI=%u ", (u_int32_t)ntohl(sav->spi));
2958 while (p && *p)
2959 p++;
2960 if (((struct sockaddr *)&saidx->src)->sa_family == AF_INET) {
2961 u_int8_t *s, *d;
2962 s = (u_int8_t *)&((struct sockaddr_in *)&saidx->src)->sin_addr;
2963 d = (u_int8_t *)&((struct sockaddr_in *)&saidx->dst)->sin_addr;
2964 snprintf(p, sizeof(buf) - (p - buf),
2965 "src=%d.%d.%d.%d dst=%d.%d.%d.%d",
2966 s[0], s[1], s[2], s[3], d[0], d[1], d[2], d[3]);
2967 }
2968#if INET6
2969 else if (((struct sockaddr *)&saidx->src)->sa_family == AF_INET6) {
2970 snprintf(p, sizeof(buf) - (p - buf),
2971 "src=%s",
2972 ip6_sprintf(&((struct sockaddr_in6 *)&saidx->src)->sin6_addr));
2973 while (p && *p)
2974 p++;
2975 snprintf(p, sizeof(buf) - (p - buf),
2976 " dst=%s",
2977 ip6_sprintf(&((struct sockaddr_in6 *)&saidx->dst)->sin6_addr));
2978 }
2979#endif
2980 while (p && *p)
2981 p++;
2982 snprintf(p, sizeof(buf) - (p - buf), ")");
2983
2984 return buf;
2985}
2986
2987void
2988ipsec_dumpmbuf(m)
2989 struct mbuf *m;
2990{
2991 int totlen;
2992 int i;
2993 u_char *p;
2994
2995 totlen = 0;
2996 printf("---\n");
2997 while (m) {
2998 p = mtod(m, u_char *);
2999 for (i = 0; i < m->m_len; i++) {
3000 printf("%02x ", p[i]);
3001 totlen++;
3002 if (totlen % 16 == 0)
3003 printf("\n");
3004 }
3005 m = m->m_next;
3006 }
3007 if (totlen % 16 != 0)
3008 printf("\n");
3009 printf("---\n");
3010}
3011
9bccf70c 3012#if INET
1c79356b
A
3013/*
3014 * IPsec output logic for IPv4.
3015 */
fe8ab488
A
3016static int
3017ipsec4_output_internal(struct ipsec_output_state *state, struct secasvar *sav)
1c79356b
A
3018{
3019 struct ip *ip = NULL;
2d21ac55 3020 int error = 0;
1c79356b 3021 struct sockaddr_in *dst4;
ebb1b9f4 3022 struct route *ro4;
1c79356b 3023
fe8ab488
A
3024 /* validity check */
3025 if (sav == NULL || sav->sah == NULL) {
3026 error = EINVAL;
3027 goto bad;
3028 }
3029
3030 /*
3031 * If there is no valid SA, we give up to process any
3032 * more. In such a case, the SA's status is changed
3033 * from DYING to DEAD after allocating. If a packet
3034 * send to the receiver by dead SA, the receiver can
3035 * not decode a packet because SA has been dead.
3036 */
3037 if (sav->state != SADB_SASTATE_MATURE
3038 && sav->state != SADB_SASTATE_DYING) {
3039 IPSEC_STAT_INCREMENT(ipsecstat.out_nosa);
3040 error = EINVAL;
3041 goto bad;
3042 }
3043
3044 state->outgoing_if = sav->sah->outgoing_if;
3045
3046 /*
3047 * There may be the case that SA status will be changed when
3048 * we are refering to one. So calling splsoftnet().
3049 */
3050
3051 if (sav->sah->saidx.mode == IPSEC_MODE_TUNNEL) {
3052 /*
3053 * build IPsec tunnel.
3054 */
3055 /* XXX should be processed with other familiy */
3056 if (((struct sockaddr *)&sav->sah->saidx.src)->sa_family != AF_INET) {
3057 ipseclog((LOG_ERR, "ipsec4_output: "
3058 "family mismatched between inner and outer spi=%u\n",
3059 (u_int32_t)ntohl(sav->spi)));
3060 error = EAFNOSUPPORT;
3061 goto bad;
3062 }
3063
3064 state->m = ipsec4_splithdr(state->m);
3065 if (!state->m) {
3066 error = ENOMEM;
3067 goto bad;
3068 }
3069 error = ipsec4_encapsulate(state->m, sav);
3070 if (error) {
3071 state->m = NULL;
3072 goto bad;
3073 }
3074 ip = mtod(state->m, struct ip *);
3075
3076 // grab sadb_mutex, before updating sah's route cache
3077 lck_mtx_lock(sadb_mutex);
3078 ro4= &sav->sah->sa_route;
3079 dst4 = (struct sockaddr_in *)(void *)&ro4->ro_dst;
3080 if (ro4->ro_rt != NULL) {
3081 RT_LOCK(ro4->ro_rt);
3082 }
3083 if (ROUTE_UNUSABLE(ro4) ||
3084 dst4->sin_addr.s_addr != ip->ip_dst.s_addr) {
3085 if (ro4->ro_rt != NULL)
3086 RT_UNLOCK(ro4->ro_rt);
3087 ROUTE_RELEASE(ro4);
3088 }
3089 if (ro4->ro_rt == 0) {
3090 dst4->sin_family = AF_INET;
3091 dst4->sin_len = sizeof(*dst4);
3092 dst4->sin_addr = ip->ip_dst;
3093 rtalloc(ro4);
3094 if (ro4->ro_rt == 0) {
3095 OSAddAtomic(1, &ipstat.ips_noroute);
3096 error = EHOSTUNREACH;
3097 // release sadb_mutex, after updating sah's route cache
3098 lck_mtx_unlock(sadb_mutex);
3099 goto bad;
3100 }
3101 RT_LOCK(ro4->ro_rt);
3102 }
3103
3104 /*
3105 * adjust state->dst if tunnel endpoint is offlink
3106 *
3107 * XXX: caching rt_gateway value in the state is
3108 * not really good, since it may point elsewhere
3109 * when the gateway gets modified to a larger
3110 * sockaddr via rt_setgate(). This is currently
3111 * addressed by SA_SIZE roundup in that routine.
3112 */
3113 if (ro4->ro_rt->rt_flags & RTF_GATEWAY)
3114 dst4 = (struct sockaddr_in *)(void *)ro4->ro_rt->rt_gateway;
3115 RT_UNLOCK(ro4->ro_rt);
3116 ROUTE_RELEASE(&state->ro);
3117 route_copyout(&state->ro, ro4, sizeof(state->ro));
3118 state->dst = (struct sockaddr *)dst4;
3119 state->tunneled = 4;
3120 // release sadb_mutex, after updating sah's route cache
3121 lck_mtx_unlock(sadb_mutex);
3122 }
3123
3124 state->m = ipsec4_splithdr(state->m);
3125 if (!state->m) {
3126 error = ENOMEM;
3127 goto bad;
3128 }
3129 switch (sav->sah->saidx.proto) {
3130 case IPPROTO_ESP:
3131#if IPSEC_ESP
3132 if ((error = esp4_output(state->m, sav)) != 0) {
3133 state->m = NULL;
3134 goto bad;
3135 }
3136 break;
3137#else
3138 m_freem(state->m);
3139 state->m = NULL;
3140 error = EINVAL;
3141 goto bad;
3142#endif
3143 case IPPROTO_AH:
3144 if ((error = ah4_output(state->m, sav)) != 0) {
3145 state->m = NULL;
3146 goto bad;
3147 }
3148 break;
3149 case IPPROTO_IPCOMP:
3150 if ((error = ipcomp4_output(state->m, sav)) != 0) {
3151 state->m = NULL;
3152 goto bad;
3153 }
3154 break;
3155 default:
3156 ipseclog((LOG_ERR,
3157 "ipsec4_output: unknown ipsec protocol %d\n",
3158 sav->sah->saidx.proto));
3159 m_freem(state->m);
3160 state->m = NULL;
3161 error = EINVAL;
3162 goto bad;
3163 }
3164
3165 if (state->m == 0) {
3166 error = ENOMEM;
3167 goto bad;
3168 }
3169
3170 return 0;
3171
3172bad:
3173 return error;
3174}
3175
3176int
3177ipsec4_interface_output(struct ipsec_output_state *state, ifnet_t interface)
3178{
3179 int error = 0;
3180 struct secasvar *sav = NULL;
3181
2d21ac55
A
3182 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
3183
1c79356b
A
3184 if (!state)
3185 panic("state == NULL in ipsec4_output");
3186 if (!state->m)
3187 panic("state->m == NULL in ipsec4_output");
1c79356b
A
3188 if (!state->dst)
3189 panic("state->dst == NULL in ipsec4_output");
fe8ab488
A
3190
3191 sav = key_alloc_outbound_sav_for_interface(interface, AF_INET);
3192 if (sav == NULL) {
3193 goto bad;
3194 }
3195
3196 if ((error = ipsec4_output_internal(state, sav)) != 0) {
3197 goto bad;
3198 }
3199
3200 KERNEL_DEBUG(DBG_FNC_IPSEC_OUT | DBG_FUNC_END, 0,0,0,0,0);
3201 if (sav)
3202 key_freesav(sav, KEY_SADB_UNLOCKED);
3203 return 0;
3204
3205bad:
3206 if (sav)
3207 key_freesav(sav, KEY_SADB_UNLOCKED);
3208 m_freem(state->m);
3209 state->m = NULL;
3210 KERNEL_DEBUG(DBG_FNC_IPSEC_OUT | DBG_FUNC_END, error,0,0,0,0);
3211 return error;
3212}
1c79356b 3213
fe8ab488
A
3214int
3215ipsec4_output(struct ipsec_output_state *state, struct secpolicy *sp, __unused int flags)
3216{
3217 struct ip *ip = NULL;
3218 struct ipsecrequest *isr = NULL;
3219 struct secasindex saidx;
3220 struct secasvar *sav = NULL;
3221 int error = 0;
3222 struct sockaddr_in *sin;
3223
3224 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
3225
3226 if (!state)
3227 panic("state == NULL in ipsec4_output");
3228 if (!state->m)
3229 panic("state->m == NULL in ipsec4_output");
3230 if (!state->dst)
3231 panic("state->dst == NULL in ipsec4_output");
3232
55e303ae 3233 KERNEL_DEBUG(DBG_FNC_IPSEC_OUT | DBG_FUNC_START, 0,0,0,0,0);
fe8ab488 3234
1c79356b 3235 KEYDEBUG(KEYDEBUG_IPSEC_DATA,
fe8ab488
A
3236 printf("ipsec4_output: applied SP\n");
3237 kdebug_secpolicy(sp));
3238
1c79356b 3239 for (isr = sp->req; isr != NULL; isr = isr->next) {
1c79356b
A
3240 /* make SA index for search proper SA */
3241 ip = mtod(state->m, struct ip *);
3242 bcopy(&isr->saidx, &saidx, sizeof(saidx));
9bccf70c
A
3243 saidx.mode = isr->saidx.mode;
3244 saidx.reqid = isr->saidx.reqid;
3245 sin = (struct sockaddr_in *)&saidx.src;
3246 if (sin->sin_len == 0) {
3247 sin->sin_len = sizeof(*sin);
3248 sin->sin_family = AF_INET;
3249 sin->sin_port = IPSEC_PORT_ANY;
3250 bcopy(&ip->ip_src, &sin->sin_addr,
fe8ab488 3251 sizeof(sin->sin_addr));
1c79356b 3252 }
9bccf70c
A
3253 sin = (struct sockaddr_in *)&saidx.dst;
3254 if (sin->sin_len == 0) {
3255 sin->sin_len = sizeof(*sin);
3256 sin->sin_family = AF_INET;
3257 sin->sin_port = IPSEC_PORT_ANY;
fe8ab488
A
3258 /*
3259 * Get port from packet if upper layer is UDP and nat traversal
3260 * is enabled and transport mode.
3261 */
3262
2d21ac55 3263 if ((esp_udp_encap_port & 0xFFFF) != 0 &&
fe8ab488 3264 isr->saidx.mode == IPSEC_MODE_TRANSPORT) {
2d21ac55
A
3265
3266 if (ip->ip_p == IPPROTO_UDP) {
3267 struct udphdr *udp;
3268 size_t hlen;
3269#ifdef _IP_VHL
3270 hlen = IP_VHL_HL(ip->ip_vhl) << 2;
3271#else
3272 hlen = ip->ip_hl << 2;
3273#endif
3274 if (state->m->m_len < hlen + sizeof(struct udphdr)) {
3275 state->m = m_pullup(state->m, hlen + sizeof(struct udphdr));
3276 if (!state->m) {
fe8ab488 3277 ipseclog((LOG_DEBUG, "IPv4 output: can't pullup UDP header\n"));
2d21ac55
A
3278 IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
3279 goto bad;
3280 }
3281 ip = mtod(state->m, struct ip *);
3282 }
316670eb 3283 udp = (struct udphdr *)(void *)(((u_int8_t *)ip) + hlen);
2d21ac55
A
3284 sin->sin_port = udp->uh_dport;
3285 }
3286 }
fe8ab488 3287
9bccf70c 3288 bcopy(&ip->ip_dst, &sin->sin_addr,
fe8ab488 3289 sizeof(sin->sin_addr));
1c79356b 3290 }
fe8ab488 3291
2d21ac55 3292 if ((error = key_checkrequest(isr, &saidx, &sav)) != 0) {
1c79356b
A
3293 /*
3294 * IPsec processing is required, but no SA found.
3295 * I assume that key_acquire() had been called
3296 * to get/establish the SA. Here I discard
3297 * this packet because it is responsibility for
3298 * upper layer to retransmit the packet.
3299 */
2d21ac55 3300 IPSEC_STAT_INCREMENT(ipsecstat.out_nosa);
1c79356b
A
3301 goto bad;
3302 }
fe8ab488 3303
1c79356b 3304 /* validity check */
2d21ac55 3305 if (sav == NULL) {
1c79356b 3306 switch (ipsec_get_reqlevel(isr)) {
fe8ab488
A
3307 case IPSEC_LEVEL_USE:
3308 continue;
3309 case IPSEC_LEVEL_REQUIRE:
3310 /* must be not reached here. */
3311 panic("ipsec4_output: no SA found, but required.");
1c79356b 3312 }
1c79356b 3313 }
fe8ab488
A
3314
3315 if ((error = ipsec4_output_internal(state, sav)) != 0) {
1c79356b
A
3316 goto bad;
3317 }
1c79356b 3318 }
fe8ab488 3319
55e303ae 3320 KERNEL_DEBUG(DBG_FNC_IPSEC_OUT | DBG_FUNC_END, 0,0,0,0,0);
2d21ac55
A
3321 if (sav)
3322 key_freesav(sav, KEY_SADB_UNLOCKED);
1c79356b 3323 return 0;
fe8ab488 3324
1c79356b 3325bad:
2d21ac55
A
3326 if (sav)
3327 key_freesav(sav, KEY_SADB_UNLOCKED);
1c79356b
A
3328 m_freem(state->m);
3329 state->m = NULL;
55e303ae 3330 KERNEL_DEBUG(DBG_FNC_IPSEC_OUT | DBG_FUNC_END, error,0,0,0,0);
1c79356b
A
3331 return error;
3332}
fe8ab488 3333
9bccf70c 3334#endif
1c79356b
A
3335
3336#if INET6
3337/*
3338 * IPsec output logic for IPv6, transport mode.
3339 */
fe8ab488
A
3340static int
3341ipsec6_output_trans_internal(
2d21ac55 3342 struct ipsec_output_state *state,
fe8ab488 3343 struct secasvar *sav,
2d21ac55 3344 u_char *nexthdrp,
fe8ab488
A
3345 struct mbuf *mprev)
3346{
3347 struct ip6_hdr *ip6;
3348 int error = 0;
3349 int plen;
3350
3351 /* validity check */
3352 if (sav == NULL || sav->sah == NULL) {
3353 error = EINVAL;
3354 goto bad;
3355 }
3356
3357 /*
3358 * If there is no valid SA, we give up to process.
3359 * see same place at ipsec4_output().
3360 */
3361 if (sav->state != SADB_SASTATE_MATURE
3362 && sav->state != SADB_SASTATE_DYING) {
3363 IPSEC_STAT_INCREMENT(ipsec6stat.out_nosa);
3364 error = EINVAL;
3365 goto bad;
3366 }
3367
3368 state->outgoing_if = sav->sah->outgoing_if;
3369
3370 switch (sav->sah->saidx.proto) {
3371 case IPPROTO_ESP:
3372#if IPSEC_ESP
3373 error = esp6_output(state->m, nexthdrp, mprev->m_next, sav);
3374#else
3375 m_freem(state->m);
3376 error = EINVAL;
3377#endif
3378 break;
3379 case IPPROTO_AH:
3380 error = ah6_output(state->m, nexthdrp, mprev->m_next, sav);
3381 break;
3382 case IPPROTO_IPCOMP:
3383 error = ipcomp6_output(state->m, nexthdrp, mprev->m_next, sav);
3384 break;
3385 default:
3386 ipseclog((LOG_ERR, "ipsec6_output_trans: "
3387 "unknown ipsec protocol %d\n", sav->sah->saidx.proto));
3388 m_freem(state->m);
3389 IPSEC_STAT_INCREMENT(ipsec6stat.out_inval);
3390 error = EINVAL;
3391 break;
3392 }
3393 if (error) {
3394 state->m = NULL;
3395 goto bad;
3396 }
3397 plen = state->m->m_pkthdr.len - sizeof(struct ip6_hdr);
3398 if (plen > IPV6_MAXPACKET) {
3399 ipseclog((LOG_ERR, "ipsec6_output_trans: "
3400 "IPsec with IPv6 jumbogram is not supported\n"));
3401 IPSEC_STAT_INCREMENT(ipsec6stat.out_inval);
3402 error = EINVAL; /*XXX*/
3403 goto bad;
3404 }
3405 ip6 = mtod(state->m, struct ip6_hdr *);
3406 ip6->ip6_plen = htons(plen);
3407
3408 return 0;
3409bad:
3410 return error;
3411}
3412
3413int
3414ipsec6_output_trans(
3415 struct ipsec_output_state *state,
3416 u_char *nexthdrp,
3417 struct mbuf *mprev,
3418 struct secpolicy *sp,
3419 __unused int flags,
3420 int *tun)
1c79356b
A
3421{
3422 struct ip6_hdr *ip6;
3423 struct ipsecrequest *isr = NULL;
3424 struct secasindex saidx;
3425 int error = 0;
9bccf70c 3426 struct sockaddr_in6 *sin6;
2d21ac55 3427 struct secasvar *sav = NULL;
fe8ab488 3428
2d21ac55
A
3429 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
3430
1c79356b 3431 if (!state)
55e303ae 3432 panic("state == NULL in ipsec6_output_trans");
1c79356b 3433 if (!state->m)
55e303ae 3434 panic("state->m == NULL in ipsec6_output_trans");
1c79356b 3435 if (!nexthdrp)
55e303ae 3436 panic("nexthdrp == NULL in ipsec6_output_trans");
1c79356b 3437 if (!mprev)
55e303ae 3438 panic("mprev == NULL in ipsec6_output_trans");
1c79356b 3439 if (!sp)
55e303ae 3440 panic("sp == NULL in ipsec6_output_trans");
1c79356b 3441 if (!tun)
55e303ae 3442 panic("tun == NULL in ipsec6_output_trans");
fe8ab488 3443
1c79356b 3444 KEYDEBUG(KEYDEBUG_IPSEC_DATA,
fe8ab488
A
3445 printf("ipsec6_output_trans: applyed SP\n");
3446 kdebug_secpolicy(sp));
91447636 3447
1c79356b
A
3448 *tun = 0;
3449 for (isr = sp->req; isr; isr = isr->next) {
3450 if (isr->saidx.mode == IPSEC_MODE_TUNNEL) {
3451 /* the rest will be handled by ipsec6_output_tunnel() */
3452 break;
3453 }
fe8ab488 3454
1c79356b
A
3455 /* make SA index for search proper SA */
3456 ip6 = mtod(state->m, struct ip6_hdr *);
3457 bcopy(&isr->saidx, &saidx, sizeof(saidx));
9bccf70c
A
3458 saidx.mode = isr->saidx.mode;
3459 saidx.reqid = isr->saidx.reqid;
3460 sin6 = (struct sockaddr_in6 *)&saidx.src;
3461 if (sin6->sin6_len == 0) {
3462 sin6->sin6_len = sizeof(*sin6);
3463 sin6->sin6_family = AF_INET6;
3464 sin6->sin6_port = IPSEC_PORT_ANY;
3465 bcopy(&ip6->ip6_src, &sin6->sin6_addr,
fe8ab488 3466 sizeof(ip6->ip6_src));
9bccf70c
A
3467 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) {
3468 /* fix scope id for comparing SPD */
3469 sin6->sin6_addr.s6_addr16[1] = 0;
3470 sin6->sin6_scope_id = ntohs(ip6->ip6_src.s6_addr16[1]);
3471 }
1c79356b 3472 }
9bccf70c
A
3473 sin6 = (struct sockaddr_in6 *)&saidx.dst;
3474 if (sin6->sin6_len == 0) {
3475 sin6->sin6_len = sizeof(*sin6);
3476 sin6->sin6_family = AF_INET6;
3477 sin6->sin6_port = IPSEC_PORT_ANY;
3478 bcopy(&ip6->ip6_dst, &sin6->sin6_addr,
fe8ab488 3479 sizeof(ip6->ip6_dst));
9bccf70c
A
3480 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) {
3481 /* fix scope id for comparing SPD */
3482 sin6->sin6_addr.s6_addr16[1] = 0;
3483 sin6->sin6_scope_id = ntohs(ip6->ip6_dst.s6_addr16[1]);
3484 }
1c79356b 3485 }
fe8ab488 3486
2d21ac55 3487 if (key_checkrequest(isr, &saidx, &sav) == ENOENT) {
1c79356b
A
3488 /*
3489 * IPsec processing is required, but no SA found.
3490 * I assume that key_acquire() had been called
3491 * to get/establish the SA. Here I discard
3492 * this packet because it is responsibility for
3493 * upper layer to retransmit the packet.
3494 */
2d21ac55 3495 IPSEC_STAT_INCREMENT(ipsec6stat.out_nosa);
1c79356b 3496 error = ENOENT;
fe8ab488 3497
9bccf70c
A
3498 /*
3499 * Notify the fact that the packet is discarded
3500 * to ourselves. I believe this is better than
3501 * just silently discarding. (jinmei@kame.net)
3502 * XXX: should we restrict the error to TCP packets?
3503 * XXX: should we directly notify sockets via
3504 * pfctlinputs?
3505 */
3506 icmp6_error(state->m, ICMP6_DST_UNREACH,
fe8ab488 3507 ICMP6_DST_UNREACH_ADMIN, 0);
9bccf70c 3508 state->m = NULL; /* icmp6_error freed the mbuf */
1c79356b
A
3509 goto bad;
3510 }
fe8ab488 3511
1c79356b 3512 /* validity check */
2d21ac55 3513 if (sav == NULL) {
1c79356b 3514 switch (ipsec_get_reqlevel(isr)) {
fe8ab488
A
3515 case IPSEC_LEVEL_USE:
3516 continue;
3517 case IPSEC_LEVEL_REQUIRE:
3518 /* must be not reached here. */
3519 panic("ipsec6_output_trans: no SA found, but required.");
1c79356b
A
3520 }
3521 }
fe8ab488
A
3522
3523 if ((error = ipsec6_output_trans_internal(state, sav, nexthdrp, mprev)) != 0) {
3524 goto bad;
3525 }
3526 }
3527
3528 /* if we have more to go, we need a tunnel mode processing */
3529 if (isr != NULL)
3530 *tun = 1;
3531
3532 if (sav)
3533 key_freesav(sav, KEY_SADB_UNLOCKED);
3534 return 0;
3535
3536bad:
3537 if (sav)
3538 key_freesav(sav, KEY_SADB_UNLOCKED);
3539 m_freem(state->m);
3540 state->m = NULL;
3541 return error;
3542}
1c79356b 3543
fe8ab488
A
3544/*
3545 * IPsec output logic for IPv6, tunnel mode.
3546 */
3547static int
3548ipsec6_output_tunnel_internal(struct ipsec_output_state *state, struct secasvar *sav, int *must_be_last)
3549{
3550 struct ip6_hdr *ip6;
3551 int error = 0;
3552 int plen;
3553 struct sockaddr_in6* dst6;
3554 struct route *ro6;
3555
3556 /* validity check */
3557 if (sav == NULL || sav->sah == NULL || sav->sah->saidx.mode != IPSEC_MODE_TUNNEL) {
3558 error = EINVAL;
3559 goto bad;
3560 }
3561
3562 /*
3563 * If there is no valid SA, we give up to process.
3564 * see same place at ipsec4_output().
3565 */
3566 if (sav->state != SADB_SASTATE_MATURE
3567 && sav->state != SADB_SASTATE_DYING) {
3568 IPSEC_STAT_INCREMENT(ipsec6stat.out_nosa);
3569 error = EINVAL;
3570 goto bad;
3571 }
3572
3573 state->outgoing_if = sav->sah->outgoing_if;
3574
3575 if (sav->sah->saidx.mode == IPSEC_MODE_TUNNEL) {
1c79356b 3576 /*
fe8ab488 3577 * build IPsec tunnel.
1c79356b 3578 */
fe8ab488
A
3579 state->m = ipsec6_splithdr(state->m);
3580 if (!state->m) {
3581 IPSEC_STAT_INCREMENT(ipsec6stat.out_nomem);
3582 error = ENOMEM;
3583 goto bad;
3584 }
3585
3586 if (((struct sockaddr *)&sav->sah->saidx.src)->sa_family == AF_INET6) {
3587 error = ipsec6_encapsulate(state->m, sav);
3588 if (error) {
3589 state->m = 0;
3590 goto bad;
3591 }
3592 ip6 = mtod(state->m, struct ip6_hdr *);
3593 } else if (((struct sockaddr *)&sav->sah->saidx.src)->sa_family == AF_INET) {
3594
3595 struct ip *ip;
3596 struct sockaddr_in* dst4;
3597 struct route *ro4 = NULL;
3598 struct route ro4_copy;
3599 struct ip_out_args ipoa = { IFSCOPE_NONE, { 0 },
3600 IPOAF_SELECT_SRCIF, 0 };
3601
3602 if (must_be_last)
3603 *must_be_last = 1;
3604
3605 state->tunneled = 4; /* must not process any further in ip6_output */
3606 error = ipsec64_encapsulate(state->m, sav);
3607 if (error) {
3608 state->m = 0;
3609 goto bad;
3610 }
3611 /* Now we have an IPv4 packet */
3612 ip = mtod(state->m, struct ip *);
3613
3614 // grab sadb_mutex, to update sah's route cache and get a local copy of it
3615 lck_mtx_lock(sadb_mutex);
3616 ro4 = &sav->sah->sa_route;
3617 dst4 = (struct sockaddr_in *)(void *)&ro4->ro_dst;
3618 if (ro4->ro_rt) {
3619 RT_LOCK(ro4->ro_rt);
3620 }
3621 if (ROUTE_UNUSABLE(ro4) ||
3622 dst4->sin_addr.s_addr != ip->ip_dst.s_addr) {
3623 if (ro4->ro_rt != NULL)
3624 RT_UNLOCK(ro4->ro_rt);
3625 ROUTE_RELEASE(ro4);
3626 }
3627 if (ro4->ro_rt == NULL) {
3628 dst4->sin_family = AF_INET;
3629 dst4->sin_len = sizeof(*dst4);
3630 dst4->sin_addr = ip->ip_dst;
3631 } else {
3632 RT_UNLOCK(ro4->ro_rt);
3633 }
3634 route_copyout(&ro4_copy, ro4, sizeof(ro4_copy));
3635 // release sadb_mutex, after updating sah's route cache and getting a local copy
3636 lck_mtx_unlock(sadb_mutex);
3637 state->m = ipsec4_splithdr(state->m);
3638 if (!state->m) {
3639 error = ENOMEM;
3640 ROUTE_RELEASE(&ro4_copy);
3641 goto bad;
3642 }
3643 switch (sav->sah->saidx.proto) {
3644 case IPPROTO_ESP:
3645#if IPSEC_ESP
3646 if ((error = esp4_output(state->m, sav)) != 0) {
3647 state->m = NULL;
3648 ROUTE_RELEASE(&ro4_copy);
3649 goto bad;
3650 }
3651 break;
3652
3653#else
3654 m_freem(state->m);
3655 state->m = NULL;
3656 error = EINVAL;
3657 ROUTE_RELEASE(&ro4_copy);
3658 goto bad;
3659#endif
3660 case IPPROTO_AH:
3661 if ((error = ah4_output(state->m, sav)) != 0) {
3662 state->m = NULL;
3663 ROUTE_RELEASE(&ro4_copy);
3664 goto bad;
3665 }
3666 break;
3667 case IPPROTO_IPCOMP:
3668 if ((error = ipcomp4_output(state->m, sav)) != 0) {
3669 state->m = NULL;
3670 ROUTE_RELEASE(&ro4_copy);
3671 goto bad;
3672 }
3673 break;
3674 default:
3675 ipseclog((LOG_ERR,
3676 "ipsec4_output: unknown ipsec protocol %d\n",
3677 sav->sah->saidx.proto));
3678 m_freem(state->m);
3679 state->m = NULL;
3680 error = EINVAL;
3681 ROUTE_RELEASE(&ro4_copy);
3682 goto bad;
3683 }
3684
3685 if (state->m == 0) {
3686 error = ENOMEM;
3687 ROUTE_RELEASE(&ro4_copy);
3688 goto bad;
3689 }
3690 ipsec_set_pkthdr_for_interface(sav->sah->ipsec_if, state->m, AF_INET);
3691 ip = mtod(state->m, struct ip *);
3692 ip->ip_len = ntohs(ip->ip_len); /* flip len field before calling ip_output */
3693 error = ip_output(state->m, NULL, &ro4_copy, IP_OUTARGS, NULL, &ipoa);
3694 state->m = NULL;
3695 // grab sadb_mutex, to synchronize the sah's route cache with the local copy
3696 lck_mtx_lock(sadb_mutex);
3697 route_copyin(&ro4_copy, ro4, sizeof(ro4_copy));
3698 lck_mtx_unlock(sadb_mutex);
3699 if (error != 0)
3700 goto bad;
3701 goto done;
3702 } else {
3703 ipseclog((LOG_ERR, "ipsec6_output_tunnel: "
3704 "unsupported inner family, spi=%u\n",
3705 (u_int32_t)ntohl(sav->spi)));
3706 IPSEC_STAT_INCREMENT(ipsec6stat.out_inval);
3707 error = EAFNOSUPPORT;
3708 goto bad;
3709 }
3710
3711 // grab sadb_mutex, before updating sah's route cache
3712 lck_mtx_lock(sadb_mutex);
3713 ro6 = &sav->sah->sa_route;
3714 dst6 = (struct sockaddr_in6 *)(void *)&ro6->ro_dst;
3715 if (ro6->ro_rt) {
3716 RT_LOCK(ro6->ro_rt);
3717 }
3718 if (ROUTE_UNUSABLE(ro6) ||
3719 !IN6_ARE_ADDR_EQUAL(&dst6->sin6_addr, &ip6->ip6_dst)) {
3720 if (ro6->ro_rt != NULL)
3721 RT_UNLOCK(ro6->ro_rt);
3722 ROUTE_RELEASE(ro6);
3723 }
3724 if (ro6->ro_rt == 0) {
3725 bzero(dst6, sizeof(*dst6));
3726 dst6->sin6_family = AF_INET6;
3727 dst6->sin6_len = sizeof(*dst6);
3728 dst6->sin6_addr = ip6->ip6_dst;
3729 rtalloc(ro6);
3730 if (ro6->ro_rt) {
3731 RT_LOCK(ro6->ro_rt);
3732 }
3733 }
3734 if (ro6->ro_rt == 0) {
3735 ip6stat.ip6s_noroute++;
3736 IPSEC_STAT_INCREMENT(ipsec6stat.out_noroute);
3737 error = EHOSTUNREACH;
3738 // release sadb_mutex, after updating sah's route cache
3739 lck_mtx_unlock(sadb_mutex);
1c79356b
A
3740 goto bad;
3741 }
fe8ab488
A
3742
3743 /*
3744 * adjust state->dst if tunnel endpoint is offlink
3745 *
3746 * XXX: caching rt_gateway value in the state is
3747 * not really good, since it may point elsewhere
3748 * when the gateway gets modified to a larger
3749 * sockaddr via rt_setgate(). This is currently
3750 * addressed by SA_SIZE roundup in that routine.
3751 */
3752 if (ro6->ro_rt->rt_flags & RTF_GATEWAY)
3753 dst6 = (struct sockaddr_in6 *)(void *)ro6->ro_rt->rt_gateway;
3754 RT_UNLOCK(ro6->ro_rt);
3755 ROUTE_RELEASE(&state->ro);
3756 route_copyout(&state->ro, ro6, sizeof(state->ro));
3757 state->dst = (struct sockaddr *)dst6;
3758 state->tunneled = 6;
3759 // release sadb_mutex, after updating sah's route cache
3760 lck_mtx_unlock(sadb_mutex);
3761 }
3762
3763 state->m = ipsec6_splithdr(state->m);
3764 if (!state->m) {
3765 IPSEC_STAT_INCREMENT(ipsec6stat.out_nomem);
3766 error = ENOMEM;
3767 goto bad;
3768 }
3769 ip6 = mtod(state->m, struct ip6_hdr *);
3770 switch (sav->sah->saidx.proto) {
1c79356b
A
3771 case IPPROTO_ESP:
3772#if IPSEC_ESP
fe8ab488 3773 error = esp6_output(state->m, &ip6->ip6_nxt, state->m->m_next, sav);
1c79356b
A
3774#else
3775 m_freem(state->m);
3776 error = EINVAL;
3777#endif
3778 break;
3779 case IPPROTO_AH:
fe8ab488 3780 error = ah6_output(state->m, &ip6->ip6_nxt, state->m->m_next, sav);
1c79356b
A
3781 break;
3782 case IPPROTO_IPCOMP:
fe8ab488
A
3783 /* XXX code should be here */
3784 /*FALLTHROUGH*/
1c79356b 3785 default:
fe8ab488
A
3786 ipseclog((LOG_ERR, "ipsec6_output_tunnel: "
3787 "unknown ipsec protocol %d\n", sav->sah->saidx.proto));
1c79356b 3788 m_freem(state->m);
2d21ac55 3789 IPSEC_STAT_INCREMENT(ipsec6stat.out_inval);
1c79356b
A
3790 error = EINVAL;
3791 break;
1c79356b 3792 }
fe8ab488
A
3793 if (error) {
3794 state->m = NULL;
3795 goto bad;
3796 }
3797 plen = state->m->m_pkthdr.len - sizeof(struct ip6_hdr);
3798 if (plen > IPV6_MAXPACKET) {
3799 ipseclog((LOG_ERR, "ipsec6_output_tunnel: "
3800 "IPsec with IPv6 jumbogram is not supported\n"));
3801 IPSEC_STAT_INCREMENT(ipsec6stat.out_inval);
3802 error = EINVAL; /*XXX*/
3803 goto bad;
3804 }
3805 ip6 = mtod(state->m, struct ip6_hdr *);
3806 ip6->ip6_plen = htons(plen);
3807done:
1c79356b 3808 return 0;
fe8ab488 3809
1c79356b 3810bad:
1c79356b
A
3811 return error;
3812}
3813
1c79356b 3814int
2d21ac55
A
3815ipsec6_output_tunnel(
3816 struct ipsec_output_state *state,
3817 struct secpolicy *sp,
ebb1b9f4 3818 __unused int flags)
1c79356b
A
3819{
3820 struct ip6_hdr *ip6;
3821 struct ipsecrequest *isr = NULL;
3822 struct secasindex saidx;
2d21ac55 3823 struct secasvar *sav = NULL;
1c79356b 3824 int error = 0;
1c79356b 3825
2d21ac55
A
3826 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
3827
1c79356b 3828 if (!state)
55e303ae 3829 panic("state == NULL in ipsec6_output_tunnel");
1c79356b 3830 if (!state->m)
55e303ae 3831 panic("state->m == NULL in ipsec6_output_tunnel");
1c79356b 3832 if (!sp)
55e303ae 3833 panic("sp == NULL in ipsec6_output_tunnel");
1c79356b
A
3834
3835 KEYDEBUG(KEYDEBUG_IPSEC_DATA,
3836 printf("ipsec6_output_tunnel: applyed SP\n");
3837 kdebug_secpolicy(sp));
3838
3839 /*
3840 * transport mode ipsec (before the 1st tunnel mode) is already
3841 * processed by ipsec6_output_trans().
3842 */
3843 for (isr = sp->req; isr; isr = isr->next) {
3844 if (isr->saidx.mode == IPSEC_MODE_TUNNEL)
3845 break;
3846 }
3847
55e303ae
A
3848 for (/* already initialized */; isr; isr = isr->next) {
3849 if (isr->saidx.mode == IPSEC_MODE_TUNNEL) {
3850 /* When tunnel mode, SA peers must be specified. */
3851 bcopy(&isr->saidx, &saidx, sizeof(saidx));
3852 } else {
3853 /* make SA index to look for a proper SA */
3854 struct sockaddr_in6 *sin6;
3855
3856 bzero(&saidx, sizeof(saidx));
3857 saidx.proto = isr->saidx.proto;
3858 saidx.mode = isr->saidx.mode;
3859 saidx.reqid = isr->saidx.reqid;
3860
3861 ip6 = mtod(state->m, struct ip6_hdr *);
3862 sin6 = (struct sockaddr_in6 *)&saidx.src;
3863 if (sin6->sin6_len == 0) {
3864 sin6->sin6_len = sizeof(*sin6);
3865 sin6->sin6_family = AF_INET6;
3866 sin6->sin6_port = IPSEC_PORT_ANY;
3867 bcopy(&ip6->ip6_src, &sin6->sin6_addr,
3868 sizeof(ip6->ip6_src));
3869 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) {
3870 /* fix scope id for comparing SPD */
3871 sin6->sin6_addr.s6_addr16[1] = 0;
3872 sin6->sin6_scope_id = ntohs(ip6->ip6_src.s6_addr16[1]);
3873 }
3874 }
3875 sin6 = (struct sockaddr_in6 *)&saidx.dst;
3876 if (sin6->sin6_len == 0) {
3877 sin6->sin6_len = sizeof(*sin6);
3878 sin6->sin6_family = AF_INET6;
3879 sin6->sin6_port = IPSEC_PORT_ANY;
3880 bcopy(&ip6->ip6_dst, &sin6->sin6_addr,
3881 sizeof(ip6->ip6_dst));
3882 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) {
3883 /* fix scope id for comparing SPD */
3884 sin6->sin6_addr.s6_addr16[1] = 0;
3885 sin6->sin6_scope_id = ntohs(ip6->ip6_dst.s6_addr16[1]);
3886 }
3887 }
3888 }
3889
2d21ac55 3890 if (key_checkrequest(isr, &saidx, &sav) == ENOENT) {
1c79356b
A
3891 /*
3892 * IPsec processing is required, but no SA found.
3893 * I assume that key_acquire() had been called
3894 * to get/establish the SA. Here I discard
3895 * this packet because it is responsibility for
3896 * upper layer to retransmit the packet.
3897 */
2d21ac55 3898 IPSEC_STAT_INCREMENT(ipsec6stat.out_nosa);
1c79356b
A
3899 error = ENOENT;
3900 goto bad;
3901 }
3902
3903 /* validity check */
2d21ac55 3904 if (sav == NULL) {
1c79356b
A
3905 switch (ipsec_get_reqlevel(isr)) {
3906 case IPSEC_LEVEL_USE:
3907 continue;
3908 case IPSEC_LEVEL_REQUIRE:
3909 /* must be not reached here. */
3910 panic("ipsec6_output_tunnel: no SA found, but required.");
3911 }
3912 }
3913
3914 /*
3915 * If there is no valid SA, we give up to process.
3916 * see same place at ipsec4_output().
3917 */
2d21ac55
A
3918 if (sav->state != SADB_SASTATE_MATURE
3919 && sav->state != SADB_SASTATE_DYING) {
3920 IPSEC_STAT_INCREMENT(ipsec6stat.out_nosa);
1c79356b
A
3921 error = EINVAL;
3922 goto bad;
3923 }
2d21ac55 3924
fe8ab488
A
3925 int must_be_last = 0;
3926
3927 if ((error = ipsec6_output_tunnel_internal(state, sav, &must_be_last)) != 0) {
1c79356b
A
3928 goto bad;
3929 }
fe8ab488
A
3930
3931 if (must_be_last && isr->next) {
1c79356b 3932 ipseclog((LOG_ERR, "ipsec6_output_tunnel: "
fe8ab488
A
3933 "IPv4 must be outer layer, spi=%u\n",
3934 (u_int32_t)ntohl(sav->spi)));
1c79356b 3935 error = EINVAL;
1c79356b
A
3936 goto bad;
3937 }
1c79356b 3938 }
fe8ab488 3939
2d21ac55
A
3940 if (sav)
3941 key_freesav(sav, KEY_SADB_UNLOCKED);
1c79356b
A
3942 return 0;
3943
3944bad:
2d21ac55
A
3945 if (sav)
3946 key_freesav(sav, KEY_SADB_UNLOCKED);
3947 if (state->m)
3948 m_freem(state->m);
1c79356b
A
3949 state->m = NULL;
3950 return error;
3951}
fe8ab488
A
3952
3953int
3954ipsec6_interface_output(struct ipsec_output_state *state, ifnet_t interface, u_char *nexthdrp, struct mbuf *mprev)
3955{
3956 int error = 0;
3957 struct secasvar *sav = NULL;
3958
3959 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
3960
3961 if (!state)
3962 panic("state == NULL in ipsec6_output");
3963 if (!state->m)
3964 panic("state->m == NULL in ipsec6_output");
3965 if (!nexthdrp)
3966 panic("nexthdrp == NULL in ipsec6_output");
3967 if (!mprev)
3968 panic("mprev == NULL in ipsec6_output");
3969
3970 sav = key_alloc_outbound_sav_for_interface(interface, AF_INET6);
3971 if (sav == NULL) {
3972 goto bad;
3973 }
3974
3975 if (sav->sah && sav->sah->saidx.mode == IPSEC_MODE_TUNNEL) {
3976 if ((error = ipsec6_output_tunnel_internal(state, sav, NULL)) != 0) {
3977 goto bad;
3978 }
3979 }
3980 else {
3981 if ((error = ipsec6_output_trans_internal(state, sav, nexthdrp, mprev)) != 0) {
3982 goto bad;
3983 }
3984 }
3985
3986 if (sav)
3987 key_freesav(sav, KEY_SADB_UNLOCKED);
3988 return 0;
3989
3990bad:
3991 if (sav)
3992 key_freesav(sav, KEY_SADB_UNLOCKED);
3993 m_freem(state->m);
3994 state->m = NULL;
3995 return error;
3996}
1c79356b
A
3997#endif /*INET6*/
3998
9bccf70c 3999#if INET
1c79356b
A
4000/*
4001 * Chop IP header and option off from the payload.
4002 */
316670eb 4003struct mbuf *
1c79356b
A
4004ipsec4_splithdr(m)
4005 struct mbuf *m;
4006{
4007 struct mbuf *mh;
4008 struct ip *ip;
4009 int hlen;
4010
4011 if (m->m_len < sizeof(struct ip))
316670eb 4012 panic("ipsec4_splithdr: first mbuf too short, m_len %d, pkt_len %d, m_flag %x", m->m_len, m->m_pkthdr.len, m->m_flags);
1c79356b
A
4013 ip = mtod(m, struct ip *);
4014#ifdef _IP_VHL
9bccf70c 4015 hlen = _IP_VHL_HL(ip->ip_vhl) << 2;
1c79356b
A
4016#else
4017 hlen = ip->ip_hl << 2;
4018#endif
4019 if (m->m_len > hlen) {
2d21ac55 4020 MGETHDR(mh, M_DONTWAIT, MT_HEADER); /* MAC-OK */
1c79356b
A
4021 if (!mh) {
4022 m_freem(m);
4023 return NULL;
4024 }
4025 M_COPY_PKTHDR(mh, m);
4026 MH_ALIGN(mh, hlen);
4027 m->m_flags &= ~M_PKTHDR;
2d21ac55 4028 m_mchtype(m, MT_DATA);
1c79356b
A
4029 m->m_len -= hlen;
4030 m->m_data += hlen;
4031 mh->m_next = m;
4032 m = mh;
4033 m->m_len = hlen;
4034 bcopy((caddr_t)ip, mtod(m, caddr_t), hlen);
4035 } else if (m->m_len < hlen) {
4036 m = m_pullup(m, hlen);
4037 if (!m)
4038 return NULL;
4039 }
4040 return m;
4041}
9bccf70c 4042#endif
1c79356b
A
4043
4044#if INET6
316670eb 4045struct mbuf *
1c79356b
A
4046ipsec6_splithdr(m)
4047 struct mbuf *m;
4048{
4049 struct mbuf *mh;
4050 struct ip6_hdr *ip6;
4051 int hlen;
4052
4053 if (m->m_len < sizeof(struct ip6_hdr))
4054 panic("ipsec6_splithdr: first mbuf too short");
4055 ip6 = mtod(m, struct ip6_hdr *);
4056 hlen = sizeof(struct ip6_hdr);
4057 if (m->m_len > hlen) {
2d21ac55 4058 MGETHDR(mh, M_DONTWAIT, MT_HEADER); /* MAC-OK */
1c79356b
A
4059 if (!mh) {
4060 m_freem(m);
4061 return NULL;
4062 }
4063 M_COPY_PKTHDR(mh, m);
4064 MH_ALIGN(mh, hlen);
4065 m->m_flags &= ~M_PKTHDR;
2d21ac55 4066 m_mchtype(m, MT_DATA);
1c79356b
A
4067 m->m_len -= hlen;
4068 m->m_data += hlen;
4069 mh->m_next = m;
4070 m = mh;
4071 m->m_len = hlen;
4072 bcopy((caddr_t)ip6, mtod(m, caddr_t), hlen);
4073 } else if (m->m_len < hlen) {
4074 m = m_pullup(m, hlen);
4075 if (!m)
4076 return NULL;
4077 }
4078 return m;
4079}
4080#endif
4081
4082/* validate inbound IPsec tunnel packet. */
4083int
2d21ac55 4084ipsec4_tunnel_validate(m, off, nxt0, sav, ifamily)
9bccf70c
A
4085 struct mbuf *m; /* no pullup permitted, m->m_len >= ip */
4086 int off;
1c79356b
A
4087 u_int nxt0;
4088 struct secasvar *sav;
2d21ac55 4089 sa_family_t *ifamily;
1c79356b
A
4090{
4091 u_int8_t nxt = nxt0 & 0xff;
4092 struct sockaddr_in *sin;
2d21ac55
A
4093 struct sockaddr_in osrc, odst, i4src, i4dst;
4094 struct sockaddr_in6 i6src, i6dst;
1c79356b 4095 int hlen;
9bccf70c
A
4096 struct secpolicy *sp;
4097 struct ip *oip;
1c79356b 4098
2d21ac55 4099 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
91447636 4100
9bccf70c
A
4101#if DIAGNOSTIC
4102 if (m->m_len < sizeof(struct ip))
4103 panic("too short mbuf on ipsec4_tunnel_validate");
4104#endif
2d21ac55 4105 if (nxt != IPPROTO_IPV4 && nxt != IPPROTO_IPV6)
1c79356b 4106 return 0;
9bccf70c
A
4107 if (m->m_pkthdr.len < off + sizeof(struct ip))
4108 return 0;
4109 /* do not decapsulate if the SA is for transport mode only */
4110 if (sav->sah->saidx.mode == IPSEC_MODE_TRANSPORT)
4111 return 0;
4112
4113 oip = mtod(m, struct ip *);
1c79356b 4114#ifdef _IP_VHL
9bccf70c 4115 hlen = _IP_VHL_HL(oip->ip_vhl) << 2;
1c79356b 4116#else
9bccf70c 4117 hlen = oip->ip_hl << 2;
1c79356b
A
4118#endif
4119 if (hlen != sizeof(struct ip))
4120 return 0;
9bccf70c 4121
9bccf70c
A
4122 sin = (struct sockaddr_in *)&sav->sah->saidx.dst;
4123 if (sin->sin_family != AF_INET)
1c79356b 4124 return 0;
9bccf70c
A
4125 if (bcmp(&oip->ip_dst, &sin->sin_addr, sizeof(oip->ip_dst)) != 0)
4126 return 0;
4127
fe8ab488
A
4128 if (sav->utun_in_fn ||
4129 sav->sah->ipsec_if != NULL) {
4130 // the ipsec/utun interface SAs don't have a policies.
316670eb
A
4131 if (nxt == IPPROTO_IPV4) {
4132 *ifamily = AF_INET;
4133 } else if (nxt == IPPROTO_IPV6) {
4134 *ifamily = AF_INET6;
4135 } else {
4136 return 0;
4137 }
4138 return 1;
4139 }
4140
9bccf70c
A
4141 /* XXX slow */
4142 bzero(&osrc, sizeof(osrc));
4143 bzero(&odst, sizeof(odst));
2d21ac55
A
4144 osrc.sin_family = odst.sin_family = AF_INET;
4145 osrc.sin_len = odst.sin_len = sizeof(struct sockaddr_in);
9bccf70c
A
4146 osrc.sin_addr = oip->ip_src;
4147 odst.sin_addr = oip->ip_dst;
9bccf70c
A
4148 /*
4149 * RFC2401 5.2.1 (b): (assume that we are using tunnel mode)
4150 * - if the inner destination is multicast address, there can be
4151 * multiple permissible inner source address. implementation
4152 * may want to skip verification of inner source address against
4153 * SPD selector.
4154 * - if the inner protocol is ICMP, the packet may be an error report
4155 * from routers on the other side of the VPN cloud (R in the
4156 * following diagram). in this case, we cannot verify inner source
4157 * address against SPD selector.
4158 * me -- gw === gw -- R -- you
4159 *
4160 * we consider the first bullet to be users responsibility on SPD entry
4161 * configuration (if you need to encrypt multicast traffic, set
4162 * the source range of SPD selector to 0.0.0.0/0, or have explicit
4163 * address ranges for possible senders).
4164 * the second bullet is not taken care of (yet).
4165 *
4166 * therefore, we do not do anything special about inner source.
4167 */
2d21ac55
A
4168 if (nxt == IPPROTO_IPV4) {
4169 bzero(&i4src, sizeof(struct sockaddr_in));
4170 bzero(&i4dst, sizeof(struct sockaddr_in));
4171 i4src.sin_family = i4dst.sin_family = *ifamily = AF_INET;
4172 i4src.sin_len = i4dst.sin_len = sizeof(struct sockaddr_in);
4173 m_copydata(m, off + offsetof(struct ip, ip_src), sizeof(i4src.sin_addr),
4174 (caddr_t)&i4src.sin_addr);
4175 m_copydata(m, off + offsetof(struct ip, ip_dst), sizeof(i4dst.sin_addr),
4176 (caddr_t)&i4dst.sin_addr);
4177 sp = key_gettunnel((struct sockaddr *)&osrc, (struct sockaddr *)&odst,
4178 (struct sockaddr *)&i4src, (struct sockaddr *)&i4dst);
4179 } else if (nxt == IPPROTO_IPV6) {
4180 bzero(&i6src, sizeof(struct sockaddr_in6));
4181 bzero(&i6dst, sizeof(struct sockaddr_in6));
4182 i6src.sin6_family = i6dst.sin6_family = *ifamily = AF_INET6;
4183 i6src.sin6_len = i6dst.sin6_len = sizeof(struct sockaddr_in6);
4184 m_copydata(m, off + offsetof(struct ip6_hdr, ip6_src), sizeof(i6src.sin6_addr),
4185 (caddr_t)&i6src.sin6_addr);
4186 m_copydata(m, off + offsetof(struct ip6_hdr, ip6_dst), sizeof(i6dst.sin6_addr),
4187 (caddr_t)&i6dst.sin6_addr);
4188 sp = key_gettunnel((struct sockaddr *)&osrc, (struct sockaddr *)&odst,
4189 (struct sockaddr *)&i6src, (struct sockaddr *)&i6dst);
4190 } else
4191 return 0; /* unsupported family */
4192
4193 if (!sp)
9bccf70c 4194 return 0;
2d21ac55
A
4195
4196 key_freesp(sp, KEY_SADB_UNLOCKED);
1c79356b
A
4197
4198 return 1;
4199}
4200
4201#if INET6
4202/* validate inbound IPsec tunnel packet. */
4203int
9bccf70c
A
4204ipsec6_tunnel_validate(m, off, nxt0, sav)
4205 struct mbuf *m; /* no pullup permitted, m->m_len >= ip */
4206 int off;
1c79356b
A
4207 u_int nxt0;
4208 struct secasvar *sav;
4209{
4210 u_int8_t nxt = nxt0 & 0xff;
4211 struct sockaddr_in6 *sin6;
9bccf70c
A
4212 struct sockaddr_in6 osrc, odst, isrc, idst;
4213 struct secpolicy *sp;
4214 struct ip6_hdr *oip6;
1c79356b 4215
2d21ac55
A
4216 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
4217
9bccf70c
A
4218#if DIAGNOSTIC
4219 if (m->m_len < sizeof(struct ip6_hdr))
4220 panic("too short mbuf on ipsec6_tunnel_validate");
4221#endif
1c79356b
A
4222 if (nxt != IPPROTO_IPV6)
4223 return 0;
9bccf70c
A
4224 if (m->m_pkthdr.len < off + sizeof(struct ip6_hdr))
4225 return 0;
4226 /* do not decapsulate if the SA is for transport mode only */
4227 if (sav->sah->saidx.mode == IPSEC_MODE_TRANSPORT)
4228 return 0;
4229
4230 oip6 = mtod(m, struct ip6_hdr *);
4231 /* AF_INET should be supported, but at this moment we don't. */
4232 sin6 = (struct sockaddr_in6 *)&sav->sah->saidx.dst;
4233 if (sin6->sin6_family != AF_INET6)
4234 return 0;
4235 if (!IN6_ARE_ADDR_EQUAL(&oip6->ip6_dst, &sin6->sin6_addr))
1c79356b 4236 return 0;
9bccf70c 4237
316670eb
A
4238 if (sav->utun_in_fn) {
4239 // the utun SAs don't have a policy (yet).
4240 return 1;
4241 }
4242
9bccf70c
A
4243 /* XXX slow */
4244 bzero(&osrc, sizeof(osrc));
4245 bzero(&odst, sizeof(odst));
4246 bzero(&isrc, sizeof(isrc));
4247 bzero(&idst, sizeof(idst));
4248 osrc.sin6_family = odst.sin6_family = isrc.sin6_family =
4249 idst.sin6_family = AF_INET6;
4250 osrc.sin6_len = odst.sin6_len = isrc.sin6_len = idst.sin6_len =
4251 sizeof(struct sockaddr_in6);
4252 osrc.sin6_addr = oip6->ip6_src;
4253 odst.sin6_addr = oip6->ip6_dst;
4254 m_copydata(m, off + offsetof(struct ip6_hdr, ip6_src),
4255 sizeof(isrc.sin6_addr), (caddr_t)&isrc.sin6_addr);
4256 m_copydata(m, off + offsetof(struct ip6_hdr, ip6_dst),
4257 sizeof(idst.sin6_addr), (caddr_t)&idst.sin6_addr);
4258
4259 /*
4260 * regarding to inner source address validation, see a long comment
4261 * in ipsec4_tunnel_validate.
4262 */
4263
4264 sp = key_gettunnel((struct sockaddr *)&osrc, (struct sockaddr *)&odst,
4265 (struct sockaddr *)&isrc, (struct sockaddr *)&idst);
55e303ae
A
4266 /*
4267 * when there is no suitable inbound policy for the packet of the ipsec
4268 * tunnel mode, the kernel never decapsulate the tunneled packet
4269 * as the ipsec tunnel mode even when the system wide policy is "none".
4270 * then the kernel leaves the generic tunnel module to process this
4271 * packet. if there is no rule of the generic tunnel, the packet
4272 * is rejected and the statistics will be counted up.
4273 */
9bccf70c
A
4274 if (!sp)
4275 return 0;
2d21ac55 4276 key_freesp(sp, KEY_SADB_UNLOCKED);
1c79356b
A
4277
4278 return 1;
4279}
4280#endif
4281
4282/*
4283 * Make a mbuf chain for encryption.
4284 * If the original mbuf chain contains a mbuf with a cluster,
4285 * allocate a new cluster and copy the data to the new cluster.
4286 * XXX: this hack is inefficient, but is necessary to handle cases
4287 * of TCP retransmission...
4288 */
4289struct mbuf *
4290ipsec_copypkt(m)
4291 struct mbuf *m;
4292{
4293 struct mbuf *n, **mpp, *mnew;
4294
4295 for (n = m, mpp = &m; n; n = n->m_next) {
4296 if (n->m_flags & M_EXT) {
4297 /*
4298 * Make a copy only if there are more than one references
4299 * to the cluster.
4300 * XXX: is this approach effective?
4301 */
4302 if (
1c79356b 4303 n->m_ext.ext_free ||
d12e1678 4304 m_mclhasreference(n)
1c79356b
A
4305 )
4306 {
4307 int remain, copied;
4308 struct mbuf *mm;
4309
4310 if (n->m_flags & M_PKTHDR) {
2d21ac55 4311 MGETHDR(mnew, M_DONTWAIT, MT_HEADER); /* MAC-OK */
1c79356b
A
4312 if (mnew == NULL)
4313 goto fail;
1c79356b 4314 M_COPY_PKTHDR(mnew, n);
1c79356b
A
4315 }
4316 else {
4317 MGET(mnew, M_DONTWAIT, MT_DATA);
4318 if (mnew == NULL)
4319 goto fail;
4320 }
4321 mnew->m_len = 0;
4322 mm = mnew;
4323
4324 /*
4325 * Copy data. If we don't have enough space to
4326 * store the whole data, allocate a cluster
4327 * or additional mbufs.
4328 * XXX: we don't use m_copyback(), since the
4329 * function does not use clusters and thus is
4330 * inefficient.
4331 */
4332 remain = n->m_len;
4333 copied = 0;
9bccf70c 4334 while (1) {
1c79356b
A
4335 int len;
4336 struct mbuf *mn;
4337
4338 if (remain <= (mm->m_flags & M_PKTHDR ? MHLEN : MLEN))
4339 len = remain;
4340 else { /* allocate a cluster */
4341 MCLGET(mm, M_DONTWAIT);
4342 if (!(mm->m_flags & M_EXT)) {
4343 m_free(mm);
4344 goto fail;
4345 }
4346 len = remain < MCLBYTES ?
4347 remain : MCLBYTES;
4348 }
4349
4350 bcopy(n->m_data + copied, mm->m_data,
4351 len);
4352
4353 copied += len;
4354 remain -= len;
4355 mm->m_len = len;
4356
4357 if (remain <= 0) /* completed? */
4358 break;
4359
4360 /* need another mbuf */
2d21ac55 4361 MGETHDR(mn, M_DONTWAIT, MT_HEADER); /* XXXMAC: tags copied next time in loop? */
1c79356b
A
4362 if (mn == NULL)
4363 goto fail;
9bccf70c 4364 mn->m_pkthdr.rcvif = NULL;
1c79356b
A
4365 mm->m_next = mn;
4366 mm = mn;
4367 }
4368
4369 /* adjust chain */
4370 mm->m_next = m_free(n);
4371 n = mm;
4372 *mpp = mnew;
4373 mpp = &n->m_next;
4374
4375 continue;
4376 }
4377 }
4378 *mpp = n;
4379 mpp = &n->m_next;
4380 }
4381
4382 return(m);
4383 fail:
4384 m_freem(m);
4385 return(NULL);
4386}
4387
2d21ac55
A
4388/*
4389 * Tags are allocated as mbufs for now, since our minimum size is MLEN, we
4390 * should make use of up to that much space.
4391 */
4392#define IPSEC_TAG_HEADER \
4393
4394struct ipsec_tag {
4395 struct socket *socket;
4396 u_int32_t history_count;
4397 struct ipsec_history history[];
4398};
4399
4400#define IPSEC_TAG_SIZE (MLEN - sizeof(struct m_tag))
4401#define IPSEC_TAG_HDR_SIZE (offsetof(struct ipsec_tag, history[0]))
4402#define IPSEC_HISTORY_MAX ((IPSEC_TAG_SIZE - IPSEC_TAG_HDR_SIZE) / \
4403 sizeof(struct ipsec_history))
4404
4405static struct ipsec_tag *
4406ipsec_addaux(
4407 struct mbuf *m)
1c79356b 4408{
2d21ac55
A
4409 struct m_tag *tag;
4410
4411 /* Check if the tag already exists */
4412 tag = m_tag_locate(m, KERNEL_MODULE_TAG_ID, KERNEL_TAG_TYPE_IPSEC, NULL);
4413
4414 if (tag == NULL) {
4415 struct ipsec_tag *itag;
4416
4417 /* Allocate a tag */
6d2010ae
A
4418 tag = m_tag_create(KERNEL_MODULE_TAG_ID, KERNEL_TAG_TYPE_IPSEC,
4419 IPSEC_TAG_SIZE, M_DONTWAIT, m);
2d21ac55
A
4420
4421 if (tag) {
4422 itag = (struct ipsec_tag*)(tag + 1);
4423 itag->socket = 0;
4424 itag->history_count = 0;
4425
4426 m_tag_prepend(m, tag);
4427 }
4428 }
4429
4430 return tag ? (struct ipsec_tag*)(tag + 1) : NULL;
1c79356b
A
4431}
4432
2d21ac55
A
4433static struct ipsec_tag *
4434ipsec_findaux(
4435 struct mbuf *m)
1c79356b 4436{
2d21ac55
A
4437 struct m_tag *tag;
4438
4439 tag = m_tag_locate(m, KERNEL_MODULE_TAG_ID, KERNEL_TAG_TYPE_IPSEC, NULL);
4440
4441 return tag ? (struct ipsec_tag*)(tag + 1) : NULL;
1c79356b
A
4442}
4443
9bccf70c 4444void
2d21ac55
A
4445ipsec_delaux(
4446 struct mbuf *m)
1c79356b 4447{
2d21ac55
A
4448 struct m_tag *tag;
4449
4450 tag = m_tag_locate(m, KERNEL_MODULE_TAG_ID, KERNEL_TAG_TYPE_IPSEC, NULL);
4451
4452 if (tag) {
4453 m_tag_delete(m, tag);
4454 }
1c79356b
A
4455}
4456
9bccf70c
A
4457/* if the aux buffer is unnecessary, nuke it. */
4458static void
2d21ac55
A
4459ipsec_optaux(
4460 struct mbuf *m,
4461 struct ipsec_tag *itag)
9bccf70c 4462{
2d21ac55
A
4463 if (itag && itag->socket == NULL && itag->history_count == 0) {
4464 m_tag_delete(m, ((struct m_tag*)itag) - 1);
4465 }
9bccf70c 4466}
1c79356b
A
4467
4468int
fe8ab488 4469ipsec_setsocket(struct mbuf *m, struct socket *so)
1c79356b 4470{
2d21ac55 4471 struct ipsec_tag *tag;
fe8ab488 4472
9bccf70c
A
4473 /* if so == NULL, don't insist on getting the aux mbuf */
4474 if (so) {
2d21ac55
A
4475 tag = ipsec_addaux(m);
4476 if (!tag)
9bccf70c
A
4477 return ENOBUFS;
4478 } else
2d21ac55
A
4479 tag = ipsec_findaux(m);
4480 if (tag) {
4481 tag->socket = so;
4482 ipsec_optaux(m, tag);
4483 }
9bccf70c
A
4484 return 0;
4485}
1c79356b 4486
9bccf70c 4487struct socket *
fe8ab488 4488ipsec_getsocket(struct mbuf *m)
9bccf70c 4489{
2d21ac55
A
4490 struct ipsec_tag *itag;
4491
4492 itag = ipsec_findaux(m);
4493 if (itag)
4494 return itag->socket;
9bccf70c
A
4495 else
4496 return NULL;
4497}
1c79356b
A
4498
4499int
2d21ac55
A
4500ipsec_addhist(
4501 struct mbuf *m,
4502 int proto,
4503 u_int32_t spi)
1c79356b 4504{
2d21ac55
A
4505 struct ipsec_tag *itag;
4506 struct ipsec_history *p;
4507 itag = ipsec_addaux(m);
4508 if (!itag)
9bccf70c 4509 return ENOBUFS;
2d21ac55 4510 if (itag->history_count == IPSEC_HISTORY_MAX)
55e303ae 4511 return ENOSPC; /* XXX */
2d21ac55
A
4512
4513 p = &itag->history[itag->history_count];
4514 itag->history_count++;
4515
9bccf70c
A
4516 bzero(p, sizeof(*p));
4517 p->ih_proto = proto;
4518 p->ih_spi = spi;
2d21ac55 4519
9bccf70c 4520 return 0;
1c79356b
A
4521}
4522
9bccf70c 4523struct ipsec_history *
2d21ac55
A
4524ipsec_gethist(
4525 struct mbuf *m,
4526 int *lenp)
9bccf70c 4527{
2d21ac55
A
4528 struct ipsec_tag *itag;
4529
4530 itag = ipsec_findaux(m);
4531 if (!itag)
9bccf70c 4532 return NULL;
2d21ac55 4533 if (itag->history_count == 0)
9bccf70c 4534 return NULL;
9bccf70c 4535 if (lenp)
2d21ac55
A
4536 *lenp = (int)(itag->history_count * sizeof(struct ipsec_history));
4537 return itag->history;
9bccf70c 4538}
1c79356b 4539
9bccf70c 4540void
2d21ac55
A
4541ipsec_clearhist(
4542 struct mbuf *m)
1c79356b 4543{
2d21ac55
A
4544 struct ipsec_tag *itag;
4545
4546 itag = ipsec_findaux(m);
4547 if (itag) {
4548 itag->history_count = 0;
4549 }
4550 ipsec_optaux(m, itag);
1c79356b 4551}
55e303ae 4552
b0d623f7 4553__private_extern__ int
55e303ae
A
4554ipsec_send_natt_keepalive(
4555 struct secasvar *sav)
4556{
316670eb
A
4557 struct mbuf *m;
4558 struct ip *ip;
4559 int error;
39236c6e
A
4560 struct ip_out_args ipoa =
4561 { IFSCOPE_NONE, { 0 }, IPOAF_SELECT_SRCIF, 0 };
316670eb 4562 struct route ro;
fe8ab488 4563 int keepalive_interval = natt_keepalive_interval;
91447636 4564
2d21ac55 4565 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
316670eb 4566
b0d623f7
A
4567 if ((esp_udp_encap_port & 0xFFFF) == 0 || sav->remote_ike_port == 0) return FALSE;
4568
fe8ab488
A
4569 if (sav->natt_interval != 0) {
4570 keepalive_interval = (int)sav->natt_interval;
4571 }
4572
b0d623f7 4573 // natt timestamp may have changed... reverify
fe8ab488 4574 if ((natt_now - sav->natt_last_activity) < keepalive_interval) return FALSE;
b0d623f7 4575
316670eb
A
4576 if (sav->flags & SADB_X_EXT_ESP_KEEPALIVE) return FALSE; // don't send these from the kernel
4577
55e303ae 4578 m = m_gethdr(M_NOWAIT, MT_DATA);
b0d623f7 4579 if (m == NULL) return FALSE;
316670eb
A
4580
4581 ip = (__typeof__(ip))m_mtod(m);
4582
4583 // this sends one type of NATT keepalives (Type 1, ESP keepalives, aren't sent by kernel)
4584 if ((sav->flags & SADB_X_EXT_ESP_KEEPALIVE) == 0) {
4585 struct udphdr *uh;
4586
4587 /*
4588 * Type 2: a UDP packet complete with IP header.
4589 * We must do this because UDP output requires
4590 * an inpcb which we don't have. UDP packet
4591 * contains one byte payload. The byte is set
4592 * to 0xFF.
4593 */
4594 uh = (__typeof__(uh))(void *)((char *)m_mtod(m) + sizeof(*ip));
4595 m->m_len = sizeof(struct udpiphdr) + 1;
4596 bzero(m_mtod(m), m->m_len);
4597 m->m_pkthdr.len = m->m_len;
4598
4599 ip->ip_len = m->m_len;
4600 ip->ip_ttl = ip_defttl;
4601 ip->ip_p = IPPROTO_UDP;
4602 if (sav->sah->dir != IPSEC_DIR_INBOUND) {
4603 ip->ip_src = ((struct sockaddr_in*)&sav->sah->saidx.src)->sin_addr;
4604 ip->ip_dst = ((struct sockaddr_in*)&sav->sah->saidx.dst)->sin_addr;
4605 } else {
4606 ip->ip_src = ((struct sockaddr_in*)&sav->sah->saidx.dst)->sin_addr;
4607 ip->ip_dst = ((struct sockaddr_in*)&sav->sah->saidx.src)->sin_addr;
4608 }
4609 uh->uh_sport = htons((u_short)esp_udp_encap_port);
4610 uh->uh_dport = htons(sav->remote_ike_port);
4611 uh->uh_ulen = htons(1 + sizeof(*uh));
4612 uh->uh_sum = 0;
4613 *(u_int8_t*)((char*)m_mtod(m) + sizeof(*ip) + sizeof(*uh)) = 0xFF;
b0d623f7 4614 }
6d2010ae
A
4615
4616 // grab sadb_mutex, to get a local copy of sah's route cache
4617 lck_mtx_lock(sadb_mutex);
39236c6e
A
4618 if (ROUTE_UNUSABLE(&sav->sah->sa_route) ||
4619 rt_key(sav->sah->sa_route.ro_rt)->sa_family != AF_INET)
4620 ROUTE_RELEASE(&sav->sah->sa_route);
4621
6d2010ae
A
4622 route_copyout(&ro, &sav->sah->sa_route, sizeof(ro));
4623 lck_mtx_unlock(sadb_mutex);
fe8ab488
A
4624
4625 necp_mark_packet_as_keepalive(m, TRUE);
6d2010ae
A
4626
4627 error = ip_output(m, NULL, &ro, IP_OUTARGS | IP_NOIPSEC, NULL, &ipoa);
4628
4629 // grab sadb_mutex, to synchronize the sah's route cache with the local copy
4630 lck_mtx_lock(sadb_mutex);
4631 route_copyin(&ro, &sav->sah->sa_route, sizeof(ro));
4632 lck_mtx_unlock(sadb_mutex);
b0d623f7 4633 if (error == 0) {
55e303ae 4634 sav->natt_last_activity = natt_now;
b0d623f7
A
4635 return TRUE;
4636 }
4637 return FALSE;
55e303ae 4638}
fe8ab488
A
4639
4640__private_extern__ bool
4641ipsec_fill_offload_frame(ifnet_t ifp,
4642 struct secasvar *sav,
4643 struct ipsec_offload_frame *frame,
4644 size_t frame_data_offset)
4645{
4646 u_int8_t *data = NULL;
4647 struct ip *ip = NULL;
4648 struct udphdr *uh = NULL;
4649
4650 if (sav == NULL || sav->sah == NULL || frame == NULL ||
4651 (ifp != NULL && ifp->if_index != sav->sah->outgoing_if) ||
4652 sav->sah->saidx.dst.ss_family != AF_INET ||
4653 !(sav->flags & SADB_X_EXT_NATT) ||
4654 !(sav->flags & SADB_X_EXT_NATT_KEEPALIVE) ||
4655 !(sav->flags & SADB_X_EXT_NATT_KEEPALIVE_OFFLOAD) ||
4656 sav->flags & SADB_X_EXT_ESP_KEEPALIVE ||
4657 (esp_udp_encap_port & 0xFFFF) == 0 ||
4658 sav->remote_ike_port == 0 ||
4659 (natt_keepalive_interval == 0 && sav->natt_interval == 0)) {
4660 /* SA is not eligible for keepalive offload on this interface */
4661 return (FALSE);
4662 }
4663
4664 if (frame_data_offset + sizeof(struct udpiphdr) + 1 > IPSEC_OFFLOAD_FRAME_DATA_SIZE) {
4665 /* Not enough room in this data frame */
4666 return (FALSE);
4667 }
4668
4669 data = frame->data;
4670 ip = (__typeof__(ip))(void *)(data + frame_data_offset);
4671 uh = (__typeof__(uh))(void *)(data + frame_data_offset + sizeof(*ip));
4672
4673 frame->length = frame_data_offset + sizeof(struct udpiphdr) + 1;
4674 bzero(data, IPSEC_OFFLOAD_FRAME_DATA_SIZE);
4675
4676 ip->ip_v = IPVERSION;
4677 ip->ip_hl = sizeof(struct ip) >> 2;
4678 ip->ip_off &= htons(~IP_OFFMASK);
4679 ip->ip_off &= htons(~IP_MF);
4680 switch (ip4_ipsec_dfbit) {
4681 case 0: /* clear DF bit */
4682 ip->ip_off &= htons(~IP_DF);
4683 break;
4684 case 1: /* set DF bit */
4685 ip->ip_off |= htons(IP_DF);
4686 break;
4687 default: /* copy DF bit */
4688 break;
4689 }
4690 ip->ip_len = htons(sizeof(struct udpiphdr) + 1);
4691 ip->ip_id = ip_randomid();
4692 ip->ip_ttl = ip_defttl;
4693 ip->ip_p = IPPROTO_UDP;
4694 ip->ip_sum = 0;
4695 if (sav->sah->dir != IPSEC_DIR_INBOUND) {
4696 ip->ip_src = ((struct sockaddr_in*)&sav->sah->saidx.src)->sin_addr;
4697 ip->ip_dst = ((struct sockaddr_in*)&sav->sah->saidx.dst)->sin_addr;
4698 } else {
4699 ip->ip_src = ((struct sockaddr_in*)&sav->sah->saidx.dst)->sin_addr;
4700 ip->ip_dst = ((struct sockaddr_in*)&sav->sah->saidx.src)->sin_addr;
4701 }
4702 ip->ip_sum = in_cksum_hdr_opt(ip);
4703 uh->uh_sport = htons((u_short)esp_udp_encap_port);
4704 uh->uh_dport = htons(sav->remote_ike_port);
4705 uh->uh_ulen = htons(1 + sizeof(*uh));
4706 uh->uh_sum = 0;
4707 *(u_int8_t*)(data + frame_data_offset + sizeof(*ip) + sizeof(*uh)) = 0xFF;
4708
4709 if (sav->natt_interval != 0) {
4710 frame->interval = sav->natt_interval;
4711 } else {
4712 frame->interval = natt_keepalive_interval;
4713 }
4714 return (TRUE);
4715}