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