xref: /openbsd-src/sys/netinet/ip_spd.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /* $OpenBSD: ip_spd.c,v 1.38 2001/08/15 09:50:12 niklas Exp $ */
2 /*
3  * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
4  *
5  * Copyright (c) 2000-2001 Angelos D. Keromytis.
6  *
7  * Permission to use, copy, and modify this software with or without fee
8  * is hereby granted, provided that this entire notice is included in
9  * all copies of any software which is or includes a copy or
10  * modification of this software.
11  * You may use this code under the GNU public license if you so wish. Please
12  * contribute changes back to the authors under this freer than GPL license
13  * so that we may further the use of strong encryption without limitations to
14  * all.
15  *
16  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
18  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
19  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
20  * PURPOSE.
21  */
22 
23 #include <sys/param.h>
24 #include <sys/systm.h>
25 #include <sys/mbuf.h>
26 #include <sys/socket.h>
27 #include <sys/kernel.h>
28 
29 #include <net/if.h>
30 #include <net/route.h>
31 #include <net/netisr.h>
32 
33 #ifdef INET
34 #include <netinet/in.h>
35 #include <netinet/in_systm.h>
36 #include <netinet/ip.h>
37 #include <netinet/in_pcb.h>
38 #include <netinet/in_var.h>
39 #endif /* INET */
40 
41 #ifdef INET6
42 #ifndef INET
43 #include <netinet/in.h>
44 #endif
45 #include <netinet6/in6_var.h>
46 #endif /* INET6 */
47 
48 #include <netinet/ip_ipsp.h>
49 #include <net/pfkeyv2.h>
50 
51 #ifdef ENCDEBUG
52 #define	DPRINTF(x)	if (encdebug) printf x
53 #else
54 #define	DPRINTF(x)
55 #endif
56 
57 struct pool ipsec_policy_pool;
58 struct pool ipsec_acquire_pool;
59 int ipsec_policy_pool_initialized = 0;
60 int ipsec_acquire_pool_initialized = 0;
61 
62 /*
63  * Lookup at the SPD based on the headers contained on the mbuf. The second
64  * argument indicates what protocol family the header at the beginning of
65  * the mbuf is. hlen is the the offset of the transport protocol header
66  * in the mbuf.
67  *
68  * Return combinations (of return value and in *error):
69  * - NULL/0 -> no IPsec required on packet
70  * - NULL/-EINVAL -> silently drop the packet
71  * - NULL/errno -> drop packet and return error
72  * or a pointer to a TDB (and 0 in *error).
73  *
74  * In the case of incoming flows, only the first three combinations are
75  * returned.
76  */
77 struct tdb *
78 ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
79     struct tdb *tdbp, struct inpcb *inp)
80 {
81 	struct route_enc re0, *re = &re0;
82 	union sockaddr_union sdst, ssrc;
83 	struct sockaddr_encap *ddst;
84 	struct ipsec_policy *ipo;
85 	int signore = 0, dignore = 0;
86 
87 	/*
88 	 * If there are no flows in place, there's no point
89 	 * continuing with the SPD lookup.
90 	 */
91 	if (!ipsec_in_use && inp == NULL) {
92 		*error = 0;
93 		return NULL;
94 	}
95 
96 	/*
97 	 * If an input packet is destined to a BYPASS socket, just accept it.
98 	 */
99 	if ((inp != NULL) && (direction == IPSP_DIRECTION_IN) &&
100 	    (inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_BYPASS) &&
101 	    (inp->inp_seclevel[SL_ESP_NETWORK] == IPSEC_LEVEL_BYPASS) &&
102 	    (inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_BYPASS)) {
103 		*error = 0;
104 		return NULL;
105 	}
106 
107 	bzero((caddr_t) re, sizeof(struct route_enc));
108 	bzero((caddr_t) &sdst, sizeof(union sockaddr_union));
109 	bzero((caddr_t) &ssrc, sizeof(union sockaddr_union));
110 	ddst = (struct sockaddr_encap *) &re->re_dst;
111 	ddst->sen_family = PF_KEY;
112 	ddst->sen_len = SENT_LEN;
113 
114 	switch (af) {
115 #ifdef INET
116 	case AF_INET:
117 		ddst->sen_direction = direction;
118 		ddst->sen_type = SENT_IP4;
119 
120 		m_copydata(m, offsetof(struct ip, ip_src),
121 		    sizeof(struct in_addr), (caddr_t) &(ddst->sen_ip_src));
122 		m_copydata(m, offsetof(struct ip, ip_dst),
123 		    sizeof(struct in_addr), (caddr_t) &(ddst->sen_ip_dst));
124 		m_copydata(m, offsetof(struct ip, ip_p), sizeof(u_int8_t),
125 		    (caddr_t) &(ddst->sen_proto));
126 
127 		sdst.sin.sin_family = ssrc.sin.sin_family = AF_INET;
128 		sdst.sin.sin_len = ssrc.sin.sin_len =
129 		    sizeof(struct sockaddr_in);
130 		ssrc.sin.sin_addr = ddst->sen_ip_src;
131 		sdst.sin.sin_addr = ddst->sen_ip_dst;
132 
133 		/*
134 		 * If TCP/UDP, extract the port numbers to use in the lookup.
135 		 */
136 		switch (ddst->sen_proto) {
137 		case IPPROTO_UDP:
138 		case IPPROTO_TCP:
139 			/* Make sure there's enough data in the packet. */
140 			if (m->m_pkthdr.len < hlen + 2 * sizeof(u_int16_t)) {
141 				*error = EINVAL;
142 				return NULL;
143 			}
144 
145 			/*
146 			 * Luckily, the offset of the src/dst ports in
147 			 * both the UDP and TCP headers is the same (first
148 			 * two 16-bit values in the respective headers),
149 			 * so we can just copy them.
150 			 */
151 			m_copydata(m, hlen, sizeof(u_int16_t),
152 			    (caddr_t) &(ddst->sen_sport));
153 			m_copydata(m, hlen + sizeof(u_int16_t), sizeof(u_int16_t),
154 			    (caddr_t) &(ddst->sen_dport));
155 			break;
156 
157 		default:
158 			ddst->sen_sport = 0;
159 			ddst->sen_dport = 0;
160 		}
161 
162 		break;
163 #endif /* INET */
164 
165 #ifdef INET6
166 	case AF_INET6:
167 		ddst->sen_type = SENT_IP6;
168 		ddst->sen_ip6_direction = direction;
169 
170 		m_copydata(m, offsetof(struct ip6_hdr, ip6_src),
171 		    sizeof(struct in6_addr),
172 		    (caddr_t) &(ddst->sen_ip6_src));
173 		m_copydata(m, offsetof(struct ip6_hdr, ip6_dst),
174 		    sizeof(struct in6_addr),
175 		    (caddr_t) &(ddst->sen_ip6_dst));
176 		m_copydata(m, offsetof(struct ip6_hdr, ip6_nxt),
177 		    sizeof(u_int8_t),
178 		    (caddr_t) &(ddst->sen_ip6_proto));
179 
180 		sdst.sin6.sin6_family = ssrc.sin6.sin6_family = AF_INET6;
181 		sdst.sin6.sin6_len = ssrc.sin6.sin6_family =
182 		    sizeof(struct sockaddr_in6);
183 		ssrc.sin6.sin6_addr = ddst->sen_ip6_src;
184 		sdst.sin6.sin6_addr = ddst->sen_ip6_dst;
185 
186 		/*
187 		 * If TCP/UDP, extract the port numbers to use in the lookup.
188 		 */
189 		switch (ddst->sen_ip6_proto) {
190 		case IPPROTO_UDP:
191 		case IPPROTO_TCP:
192 			/* Make sure there's enough data in the packet. */
193 			if (m->m_pkthdr.len < hlen + 2 * sizeof(u_int16_t)) {
194 				*error = EINVAL;
195 				return NULL;
196 			}
197 
198 			/*
199 			 * Luckily, the offset of the src/dst ports in
200 			 * both the UDP and TCP headers is the same
201 			 * (first two 16-bit values in the respective
202 			 * headers), so we can just copy them.
203 			 */
204 			m_copydata(m, hlen, sizeof(u_int16_t),
205 			    (caddr_t) &(ddst->sen_ip6_sport));
206 			m_copydata(m, hlen + sizeof(u_int16_t), sizeof(u_int16_t),
207 			    (caddr_t) &(ddst->sen_ip6_dport));
208 			break;
209 
210 		default:
211 			ddst->sen_ip6_sport = 0;
212 			ddst->sen_ip6_dport = 0;
213 		}
214 
215 		break;
216 #endif /* INET6 */
217 
218 	default:
219 		*error = EAFNOSUPPORT;
220 		return NULL;
221 	}
222 
223 	/* Actual SPD lookup. */
224 	rtalloc((struct route *) re);
225 	if (re->re_rt == NULL) {
226 		/*
227 		 * Return whatever the socket requirements are, there are no
228 		 * system-wide policies.
229 		 */
230 		*error = 0;
231 		return ipsp_spd_inp(m, af, hlen, error, direction,
232 		    tdbp, inp, NULL);
233 	}
234 
235 	/* Sanity check. */
236 	if ((re->re_rt->rt_gateway == NULL) ||
237 	    (((struct sockaddr_encap *) re->re_rt->rt_gateway)->sen_type !=
238 		SENT_IPSP)) {
239 		RTFREE(re->re_rt);
240 		*error = EHOSTUNREACH;
241 		return NULL;
242 	}
243 
244 	ipo = ((struct sockaddr_encap *) (re->re_rt->rt_gateway))->sen_ipsp;
245 	RTFREE(re->re_rt);
246 	if (ipo == NULL) {
247 		*error = EHOSTUNREACH;
248 		return NULL;
249 	}
250 
251 	switch (ipo->ipo_type) {
252 	case IPSP_PERMIT:
253 		*error = 0;
254 		return ipsp_spd_inp(m, af, hlen, error, direction, tdbp,
255 		    inp, ipo);
256 
257 	case IPSP_DENY:
258 		*error = EHOSTUNREACH;
259 		return NULL;
260 
261 	case IPSP_IPSEC_USE:
262 	case IPSP_IPSEC_ACQUIRE:
263 	case IPSP_IPSEC_REQUIRE:
264 	case IPSP_IPSEC_DONTACQ:
265 		/* Nothing more needed here. */
266 		break;
267 
268 	default:
269 		*error = EINVAL;
270 		return NULL;
271 	}
272 
273 	/* Check for non-specific destination in the policy. */
274 	switch (ipo->ipo_dst.sa.sa_family) {
275 #ifdef INET
276 	case AF_INET:
277 		if ((ipo->ipo_dst.sin.sin_addr.s_addr == INADDR_ANY) ||
278 		    (ipo->ipo_dst.sin.sin_addr.s_addr == INADDR_BROADCAST))
279 			dignore = 1;
280 		break;
281 #endif /* INET */
282 
283 #ifdef INET6
284 	case AF_INET6:
285 		if ((IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_dst.sin6.sin6_addr)) ||
286 		    (bcmp(&ipo->ipo_dst.sin6.sin6_addr, &in6mask128,
287 			sizeof(in6mask128)) == 0))
288 			dignore = 1;
289 		break;
290 #endif /* INET6 */
291 	}
292 
293 	/* Likewise for source. */
294 	switch (ipo->ipo_src.sa.sa_family) {
295 #ifdef INET
296 	case AF_INET:
297 		if (ipo->ipo_src.sin.sin_addr.s_addr == INADDR_ANY)
298 			signore = 1;
299 		break;
300 #endif /* INET */
301 
302 #ifdef INET6
303 	case AF_INET6:
304 		if (IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_src.sin6.sin6_addr))
305 			signore = 1;
306 		break;
307 #endif /* INET6 */
308 	}
309 
310 	/* Do we have a cached entry ? If so, check if it's still valid. */
311 	if ((ipo->ipo_tdb) && (ipo->ipo_tdb->tdb_flags & TDBF_INVALID)) {
312 		TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
313 		    ipo_tdb_next);
314 		ipo->ipo_tdb = NULL;
315 	}
316 
317 	/* Outgoing packet policy check. */
318 	if (direction == IPSP_DIRECTION_OUT) {
319 		/*
320 		 * If the packet is destined for the policy-specified
321 		 * gateway/endhost, and the socket has the BYPASS
322 		 * option set, skip IPsec processing.
323 		 */
324 		if ((inp != NULL) &&
325 		    (inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_BYPASS) &&
326 		    (inp->inp_seclevel[SL_ESP_NETWORK] ==
327 			IPSEC_LEVEL_BYPASS) &&
328 		    (inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_BYPASS)) {
329 			/* Direct match. */
330 			if (!bcmp(&sdst, &ipo->ipo_dst, sdst.sa.sa_len) ||
331 			    dignore) {
332 				*error = 0;
333 				return ipsp_spd_inp(m, af, hlen, error,
334 				    direction, tdbp, inp, ipo);
335 			}
336 		}
337 
338 		/* Check that the cached TDB (if present), is appropriate. */
339 		if (ipo->ipo_tdb) {
340 			if ((ipo->ipo_last_searched <= ipsec_last_added) ||
341 			    (ipo->ipo_sproto != ipo->ipo_tdb->tdb_sproto) ||
342 			    bcmp(dignore ? &sdst : &ipo->ipo_dst,
343 				&ipo->ipo_tdb->tdb_dst,
344 				ipo->ipo_tdb->tdb_dst.sa.sa_len))
345 				goto nomatchout;
346 
347 			/* Match source ID. */
348 			if (ipo->ipo_srcid) {
349 				if (ipo->ipo_tdb->tdb_srcid == NULL ||
350 				    !ipsp_ref_match(ipo->ipo_srcid,
351 					ipo->ipo_tdb->tdb_srcid))
352 					goto nomatchout;
353 			}
354 
355 			/* Match destination ID. */
356 			if (ipo->ipo_dstid) {
357 				if (ipo->ipo_tdb->tdb_dstid == NULL ||
358 				    !ipsp_ref_match(ipo->ipo_dstid,
359 					ipo->ipo_tdb->tdb_dstid))
360 					goto nomatchout;
361 			}
362 
363 			/* Match local credentials used. */
364 			if (ipo->ipo_local_cred) {
365 				if (ipo->ipo_tdb->tdb_local_cred == NULL ||
366 				    !ipsp_ref_match(ipo->ipo_local_cred,
367 					ipo->ipo_tdb->tdb_local_cred))
368 					goto nomatchout;
369 			}
370 
371 			/* Cached entry is good. */
372 			return ipsp_spd_inp(m, af, hlen, error, direction,
373 			    tdbp, inp, ipo);
374 
375   nomatchout:
376 			/* Cached TDB was not good. */
377 			TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
378 			    ipo_tdb_next);
379 			ipo->ipo_tdb = NULL;
380 			ipo->ipo_last_searched = 0;
381 		}
382 
383 		/*
384 		 * If no SA has been added since the last time we did a
385 		 * lookup, there's no point searching for one. However, if the
386 		 * destination gateway is left unspecified (or is all-1's),
387 		 * always lookup since this is a generic-match rule
388 		 * (otherwise, we can have situations where SAs to some
389 		 * destinations exist but are not used, possibly leading to an
390 		 * explosion in the number of acquired SAs).
391 		 */
392 		if (ipo->ipo_last_searched <= ipsec_last_added)	{
393 			/* "Touch" the entry. */
394 			if (dignore == 0)
395 				ipo->ipo_last_searched = time.tv_sec;
396 
397 			/* Find an appropriate SA from the existing ones. */
398 			ipo->ipo_tdb =
399 			    gettdbbyaddr(dignore ? &sdst : &ipo->ipo_dst,
400 				ipo, m, af);
401 			if (ipo->ipo_tdb) {
402 				TAILQ_INSERT_TAIL(&ipo->ipo_tdb->tdb_policy_head,
403 				    ipo, ipo_tdb_next);
404 				*error = 0;
405 				return ipsp_spd_inp(m, af, hlen, error,
406 				    direction, tdbp, inp, ipo);
407 			}
408 		}
409 
410 		/* So, we don't have an SA -- just a policy. */
411 		switch (ipo->ipo_type) {
412 		case IPSP_IPSEC_REQUIRE:
413 			/* Acquire SA through key management. */
414 			if (ipsp_acquire_sa(ipo,
415 			    dignore ? &sdst : &ipo->ipo_dst,
416 			    signore ? NULL : &ipo->ipo_src, ddst, m) != 0) {
417 				*error = EACCES;
418 				return NULL;
419 			}
420 
421 			/* Fall through */
422 		case IPSP_IPSEC_DONTACQ:
423 			*error = -EINVAL; /* Silently drop packet. */
424 			return NULL;
425 
426 		case IPSP_IPSEC_ACQUIRE:
427 			/* Acquire SA through key management. */
428 			ipsp_acquire_sa(ipo, dignore ? &sdst : &ipo->ipo_dst,
429 			    signore ? NULL : &ipo->ipo_src, ddst, NULL);
430 
431 			/* Fall through */
432 		case IPSP_IPSEC_USE:
433 			*error = 0;
434 			return ipsp_spd_inp(m, af, hlen, error, direction,
435 			    tdbp, inp, ipo);
436 		}
437 	} else { /* IPSP_DIRECTION_IN */
438 		if (tdbp != NULL) {
439 			/* Direct match in the cache. */
440 			if (ipo->ipo_tdb == tdbp) {
441 				*error = 0;
442 				return ipsp_spd_inp(m, af, hlen, error,
443 				    direction, tdbp, inp, ipo);
444 			}
445 
446 			if (bcmp(dignore ? &ssrc : &ipo->ipo_dst,
447 			    &tdbp->tdb_src, tdbp->tdb_src.sa.sa_len) ||
448 			    (ipo->ipo_sproto != tdbp->tdb_sproto))
449 				goto nomatchin;
450 
451 			/* Match source ID. */
452 			if (ipo->ipo_srcid) {
453 				if (tdbp->tdb_dstid == NULL ||
454 				    !ipsp_ref_match(ipo->ipo_srcid,
455 					tdbp->tdb_dstid))
456 					goto nomatchin;
457 			}
458 
459 			/* Match destination ID. */
460 			if (ipo->ipo_dstid) {
461 				if (tdbp->tdb_srcid == NULL ||
462 				    !ipsp_ref_match(ipo->ipo_dstid,
463 					tdbp->tdb_srcid))
464 					goto nomatchin;
465 			}
466 
467 			/* Add it to the cache. */
468 			if (ipo->ipo_tdb)
469 				TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head,
470 				    ipo, ipo_tdb_next);
471 			ipo->ipo_tdb = tdbp;
472 			TAILQ_INSERT_TAIL(&tdbp->tdb_policy_head, ipo,
473 			    ipo_tdb_next);
474 			*error = 0;
475 			return ipsp_spd_inp(m, af, hlen, error, direction,
476 			    tdbp, inp, ipo);
477 
478   nomatchin: /* Nothing needed here, falling through */
479 		}
480 
481 		/* Check whether cached entry applies. */
482 		if (ipo->ipo_tdb) {
483 			/*
484 			 * We only need to check that the correct
485 			 * security protocol and security gateway are
486 			 * set; credentials/IDs will be the same,
487 			 * since the cached entry is linked on this
488 			 * policy.
489 			 */
490 			if (ipo->ipo_sproto == ipo->ipo_tdb->tdb_sproto &&
491 			    !bcmp(&ipo->ipo_tdb->tdb_src,
492 				dignore ? &ssrc : &ipo->ipo_dst,
493 				ipo->ipo_tdb->tdb_src.sa.sa_len))
494 				goto skipinputsearch;
495 
496 			/* Not applicable, unlink. */
497 			TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
498 			    ipo_tdb_next);
499 			ipo->ipo_last_searched = 0;
500 			ipo->ipo_tdb = NULL;
501 		}
502 
503 		/* Find whether there exists an appropriate SA. */
504 		if (ipo->ipo_last_searched <= ipsec_last_added)	{
505 			if (dignore == 0)
506 				ipo->ipo_last_searched = time.tv_sec;
507 
508 			ipo->ipo_tdb =
509 			    gettdbbysrc(dignore ? &ssrc : &ipo->ipo_dst,
510 				ipo, m, af);
511 			if (ipo->ipo_tdb)
512 				TAILQ_INSERT_TAIL(&ipo->ipo_tdb->tdb_policy_head,
513 				    ipo, ipo_tdb_next);
514 		}
515   skipinputsearch:
516 
517 		switch (ipo->ipo_type) {
518 		case IPSP_IPSEC_REQUIRE:
519 			/* If appropriate SA exists, don't acquire another. */
520 			if (ipo->ipo_tdb) {
521 				*error = -EINVAL;
522 				return NULL;
523 			}
524 
525 			/* Acquire SA through key management. */
526 			if ((*error = ipsp_acquire_sa(ipo,
527 			    dignore ? &ssrc : &ipo->ipo_dst,
528 			    signore ? NULL : &ipo->ipo_src, ddst, m)) != 0)
529 				return NULL;
530 
531 			/* Fall through */
532 		case IPSP_IPSEC_DONTACQ:
533 			/* Drop packet. */
534 			*error = -EINVAL;
535 			return NULL;
536 
537 		case IPSP_IPSEC_ACQUIRE:
538 			/* If appropriate SA exists, don't acquire another. */
539 			if (ipo->ipo_tdb) {
540 				*error = 0;
541 				return ipsp_spd_inp(m, af, hlen, error,
542 				    direction, tdbp, inp, ipo);
543 			}
544 
545 			/* Acquire SA through key management. */
546 			ipsp_acquire_sa(ipo, dignore ? &ssrc : &ipo->ipo_dst,
547 			    signore ? NULL : &ipo->ipo_src, ddst, NULL);
548 
549 			/* Fall through */
550 		case IPSP_IPSEC_USE:
551 			*error = 0;
552 			return ipsp_spd_inp(m, af, hlen, error, direction,
553 			    tdbp, inp, ipo);
554 		}
555 	}
556 
557 	/* Shouldn't ever get this far. */
558 	*error = EINVAL;
559 	return NULL;
560 }
561 
562 /*
563  * Delete a policy from the SPD.
564  */
565 int
566 ipsec_delete_policy(struct ipsec_policy *ipo)
567 {
568 	struct ipsec_acquire *ipa;
569 	int err = 0;
570 
571 	/* Delete from SPD. */
572 	if (!(ipo->ipo_flags & IPSP_POLICY_SOCKET))
573 		err = rtrequest(RTM_DELETE, (struct sockaddr *) &ipo->ipo_addr,
574 		    (struct sockaddr *) 0,
575 		    (struct sockaddr *) &ipo->ipo_mask,
576 		    0, (struct rtentry **) 0);
577 
578 	if (ipo->ipo_tdb != NULL)
579 		TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
580 		    ipo_tdb_next);
581 
582 	while ((ipa = TAILQ_FIRST(&ipo->ipo_acquires)) != NULL)
583 		ipsp_delete_acquire(ipa);
584 
585 	TAILQ_REMOVE(&ipsec_policy_head, ipo, ipo_list);
586 
587 	if (ipo->ipo_srcid)
588 		ipsp_reffree(ipo->ipo_srcid);
589 	if (ipo->ipo_dstid)
590 		ipsp_reffree(ipo->ipo_dstid);
591 	if (ipo->ipo_local_cred)
592 		ipsp_reffree(ipo->ipo_local_cred);
593 	if (ipo->ipo_local_auth)
594 		ipsp_reffree(ipo->ipo_local_cred);
595 
596 	pool_put(&ipsec_policy_pool, ipo);
597 
598 	ipsec_in_use--;
599 
600 	return err;
601 }
602 
603 #ifdef notyet
604 /*
605  * Add a policy to the SPD.
606  */
607 struct ipsec_policy *
608 ipsec_add_policy(struct sockaddr_encap *dst, struct sockaddr_encap *mask,
609     union sockaddr_union *sdst, int type, int sproto)
610 {
611 	struct sockaddr_encap encapgw;
612 	struct ipsec_policy *ipon;
613 
614 	if (ipsec_policy_pool_initialized == 0) {
615 		ipsec_policy_pool_initialized = 1;
616 		pool_init(&ipsec_policy_pool, sizeof(struct ipsec_policy),
617 		    0, 0, PR_FREEHEADER, "ipsec policy", 0, NULL, NULL,
618 		    M_IPSEC_POLICY);
619 	}
620 
621 	ipon = pool_get(&ipsec_policy_pool, 0);
622 	if (ipon == NULL)
623 		return NULL;
624 
625 	bzero(ipon, sizeof(struct ipsec_policy));
626 	bzero((caddr_t) &encapgw, sizeof(struct sockaddr_encap));
627 
628 	encapgw.sen_len = SENT_LEN;
629 	encapgw.sen_family = PF_KEY;
630 	encapgw.sen_type = SENT_IPSP;
631 	encapgw.sen_ipsp = ipon;
632 
633 	if (rtrequest(RTM_ADD, (struct sockaddr *) dst,
634 	    (struct sockaddr *) &encapgw, (struct sockaddr *) mask,
635 	    RTF_UP | RTF_GATEWAY | RTF_STATIC, (struct rtentry **) 0) != 0) {
636 		DPRINTF(("ipsec_add_policy: failed to add policy\n"));
637 		pool_put(&ipsec_policy_pool, ipon);
638 		return NULL;
639 	}
640 
641 	ipsec_in_use++;
642 
643 	bcopy(dst, &ipon->ipo_addr, sizeof(struct sockaddr_encap));
644 	bcopy(mask, &ipon->ipo_mask, sizeof(struct sockaddr_encap));
645 	bcopy(sdst, &ipon->ipo_dst, sizeof(union sockaddr_union));
646 	ipon->ipo_sproto = sproto;
647 	ipon->ipo_type = type;
648 
649 	TAILQ_INIT(&ipon->ipo_acquires);
650 	TAILQ_INSERT_HEAD(&ipsec_policy_head, ipon, ipo_list);
651 
652 	return ipon;
653 }
654 #endif
655 
656 /*
657  * Delete a pending IPsec acquire record.
658  */
659 void
660 ipsp_delete_acquire(void *v)
661 {
662 	struct ipsec_acquire *ipa = v;
663 
664 	timeout_del(&ipa->ipa_timeout);
665 	TAILQ_REMOVE(&ipsec_acquire_head, ipa, ipa_next);
666 	if (ipa->ipa_policy != NULL)
667 		TAILQ_REMOVE(&ipa->ipa_policy->ipo_acquires, ipa,
668 		    ipa_ipo_next);
669 	pool_put(&ipsec_acquire_pool, ipa);
670 }
671 
672 /*
673  * Find out if there's an ACQUIRE pending.
674  * XXX Need a better structure.
675  */
676 struct ipsec_acquire *
677 ipsp_pending_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw)
678 {
679 	struct ipsec_acquire *ipa;
680 
681 	TAILQ_FOREACH (ipa, &ipo->ipo_acquires, ipa_ipo_next) {
682 		if (!bcmp(gw, &ipa->ipa_addr, gw->sa.sa_len))
683 			return ipa;
684 	}
685 
686 	return NULL;
687 }
688 
689 /*
690  * Signal key management that we need an SA. If we're given an mbuf, store
691  * it and retransmit the packet if/when we have an SA in place.
692  */
693 int
694 ipsp_acquire_sa(struct ipsec_policy *ipo, union sockaddr_union *gw,
695     union sockaddr_union *laddr, struct sockaddr_encap *ddst, struct mbuf *m)
696 {
697 	struct ipsec_acquire *ipa;
698 #ifdef INET6
699 	int i;
700 #endif
701 
702 	/* Check whether request has been made already. */
703 	if ((ipa = ipsp_pending_acquire(ipo, gw)) != NULL)
704 		return 0;
705 
706 	/* Add request in cache and proceed. */
707 	if (ipsec_acquire_pool_initialized == 0) {
708 		ipsec_acquire_pool_initialized = 1;
709 		pool_init(&ipsec_acquire_pool, sizeof(struct ipsec_acquire),
710 		    0, 0, PR_FREEHEADER, "ipsec acquire", 0, NULL,
711 		    NULL, M_IPSEC_POLICY);
712 	}
713 
714 	ipa = pool_get(&ipsec_acquire_pool, 0);
715 	if (ipa == NULL)
716 		return ENOMEM;
717 
718 	bzero(ipa, sizeof(struct ipsec_acquire));
719 	bcopy(gw, &ipa->ipa_addr, sizeof(union sockaddr_union));
720 
721 	timeout_set(&ipa->ipa_timeout, ipsp_delete_acquire, ipa);
722 
723 	ipa->ipa_info.sen_len = ipa->ipa_mask.sen_len = SENT_LEN;
724 	ipa->ipa_info.sen_family = ipa->ipa_mask.sen_family = PF_KEY;
725 
726 	/* Just copy the right information. */
727 	switch (ipo->ipo_addr.sen_type) {
728 #ifdef INET
729 	case SENT_IP4:
730 		ipa->ipa_info.sen_type = ipa->ipa_mask.sen_type = SENT_IP4;
731 		ipa->ipa_info.sen_direction = ipo->ipo_addr.sen_direction;
732 		ipa->ipa_mask.sen_direction = ipo->ipo_mask.sen_direction;
733 
734 		if (ipo->ipo_mask.sen_ip_src.s_addr == INADDR_ANY ||
735 		    ipo->ipo_addr.sen_ip_src.s_addr == INADDR_ANY ||
736 		    ipsp_is_unspecified(ipo->ipo_dst)) {
737 			ipa->ipa_info.sen_ip_src = ddst->sen_ip_src;
738 			ipa->ipa_mask.sen_ip_src.s_addr = INADDR_BROADCAST;
739 		} else {
740 			ipa->ipa_info.sen_ip_src = ipo->ipo_addr.sen_ip_src;
741 			ipa->ipa_mask.sen_ip_src = ipo->ipo_mask.sen_ip_src;
742 		}
743 
744 		if (ipo->ipo_mask.sen_ip_dst.s_addr == INADDR_ANY ||
745 		    ipo->ipo_addr.sen_ip_dst.s_addr == INADDR_ANY ||
746 		    ipsp_is_unspecified(ipo->ipo_dst)) {
747 			ipa->ipa_info.sen_ip_dst = ddst->sen_ip_dst;
748 			ipa->ipa_mask.sen_ip_dst.s_addr = INADDR_BROADCAST;
749 		} else {
750 			ipa->ipa_info.sen_ip_dst = ipo->ipo_addr.sen_ip_dst;
751 			ipa->ipa_mask.sen_ip_dst = ipo->ipo_mask.sen_ip_dst;
752 		}
753 
754 		ipa->ipa_info.sen_proto = ipo->ipo_addr.sen_proto;
755 		ipa->ipa_mask.sen_proto = ipo->ipo_mask.sen_proto;
756 
757 		if (ipo->ipo_addr.sen_proto) {
758 			ipa->ipa_info.sen_sport = ipo->ipo_addr.sen_sport;
759 			ipa->ipa_mask.sen_sport = ipo->ipo_mask.sen_sport;
760 
761 			ipa->ipa_info.sen_dport = ipo->ipo_addr.sen_dport;
762 			ipa->ipa_mask.sen_dport = ipo->ipo_mask.sen_dport;
763 		}
764 		break;
765 #endif /* INET */
766 
767 #ifdef INET6
768 	case SENT_IP6:
769 		ipa->ipa_info.sen_type = ipa->ipa_mask.sen_type = SENT_IP6;
770 		ipa->ipa_info.sen_ip6_direction =
771 		    ipo->ipo_addr.sen_ip6_direction;
772 		ipa->ipa_mask.sen_ip6_direction =
773 		    ipo->ipo_mask.sen_ip6_direction;
774 
775 		if (IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_mask.sen_ip6_src) ||
776 		    IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_addr.sen_ip6_src) ||
777 		    ipsp_is_unspecified(ipo->ipo_dst)) {
778 			ipa->ipa_info.sen_ip6_src = ddst->sen_ip6_src;
779 			for (i = 0; i < 16; i++)
780 				ipa->ipa_mask.sen_ip6_src.s6_addr8[i] = 0xff;
781 		} else {
782 			ipa->ipa_info.sen_ip6_src = ipo->ipo_addr.sen_ip6_src;
783 			ipa->ipa_mask.sen_ip6_src = ipo->ipo_mask.sen_ip6_src;
784 		}
785 
786 		if (IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_mask.sen_ip6_dst) ||
787 		    IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_addr.sen_ip6_dst) ||
788 		    ipsp_is_unspecified(ipo->ipo_dst)) {
789 			ipa->ipa_info.sen_ip6_dst = ddst->sen_ip6_dst;
790 			for (i = 0; i < 16; i++)
791 				ipa->ipa_mask.sen_ip6_dst.s6_addr8[i] = 0xff;
792 		} else {
793 			ipa->ipa_info.sen_ip6_dst = ipo->ipo_addr.sen_ip6_dst;
794 			ipa->ipa_mask.sen_ip6_dst = ipo->ipo_mask.sen_ip6_dst;
795 		}
796 
797 		ipa->ipa_info.sen_ip6_proto = ipo->ipo_addr.sen_ip6_proto;
798 		ipa->ipa_mask.sen_ip6_proto = ipo->ipo_mask.sen_ip6_proto;
799 
800 		if (ipo->ipo_mask.sen_ip6_proto) {
801 			ipa->ipa_info.sen_ip6_sport =
802 			    ipo->ipo_addr.sen_ip6_sport;
803 			ipa->ipa_mask.sen_ip6_sport =
804 			    ipo->ipo_mask.sen_ip6_sport;
805 			ipa->ipa_info.sen_ip6_dport =
806 			    ipo->ipo_addr.sen_ip6_dport;
807 			ipa->ipa_mask.sen_ip6_dport =
808 			    ipo->ipo_mask.sen_ip6_dport;
809 		}
810 		break;
811 #endif /* INET6 */
812 
813 	default:
814 		pool_put(&ipsec_acquire_pool, ipa);
815 		return 0;
816 	}
817 
818 	timeout_add(&ipa->ipa_timeout, ipsec_expire_acquire * hz);
819 
820 	TAILQ_INSERT_TAIL(&ipsec_acquire_head, ipa, ipa_next);
821 	TAILQ_INSERT_TAIL(&ipo->ipo_acquires, ipa, ipa_ipo_next);
822 	ipa->ipa_policy = ipo;
823 
824 	/* PF_KEYv2 notification message. */
825 	return pfkeyv2_acquire(ipo, gw, laddr, &ipa->ipa_seq, ddst);
826 }
827 
828 /*
829  * Deal with PCB security requirements.
830  */
831 struct tdb *
832 ipsp_spd_inp(struct mbuf *m, int af, int hlen, int *error, int direction,
833     struct tdb *tdbp, struct inpcb *inp, struct ipsec_policy *ipo)
834 {
835 	/* XXX */
836 	if (ipo != NULL)
837 		return ipo->ipo_tdb;
838 	else
839 		return NULL;
840 }
841 
842 /*
843  * Find a pending ACQUIRE record based on its sequence number.
844  * XXX Need to use a better data structure.
845  */
846 struct ipsec_acquire *
847 ipsec_get_acquire(u_int32_t seq)
848 {
849 	struct ipsec_acquire *ipa;
850 
851 	TAILQ_FOREACH (ipa, &ipsec_acquire_head, ipa_ipo_next)
852 		if (ipa->ipa_seq == seq)
853 			return ipa;
854 
855 	return NULL;
856 }
857