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