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