xref: /openbsd-src/sys/net/pfkeyv2.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /* $OpenBSD: pfkeyv2.c,v 1.148 2016/09/15 02:00:18 dlg Exp $ */
2 
3 /*
4  *	@(#)COPYRIGHT	1.1 (NRL) 17 January 1995
5  *
6  * NRL grants permission for redistribution and use in source and binary
7  * forms, with or without modification, of the software and documentation
8  * created at NRL provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgements:
17  * 	This product includes software developed by the University of
18  * 	California, Berkeley and its contributors.
19  * 	This product includes software developed at the Information
20  * 	Technology Division, US Naval Research Laboratory.
21  * 4. Neither the name of the NRL nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS
26  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
28  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL NRL OR
29  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  *
37  * The views and conclusions contained in the software and documentation
38  * are those of the authors and should not be interpreted as representing
39  * official policies, either expressed or implied, of the US Naval
40  * Research Laboratory (NRL).
41  */
42 
43 /*
44  * Copyright (c) 1995, 1996, 1997, 1998, 1999 Craig Metz. All rights reserved.
45  *
46  * Redistribution and use in source and binary forms, with or without
47  * modification, are permitted provided that the following conditions
48  * are met:
49  * 1. Redistributions of source code must retain the above copyright
50  *    notice, this list of conditions and the following disclaimer.
51  * 2. Redistributions in binary form must reproduce the above copyright
52  *    notice, this list of conditions and the following disclaimer in the
53  *    documentation and/or other materials provided with the distribution.
54  * 3. Neither the name of the author nor the names of any contributors
55  *    may be used to endorse or promote products derived from this software
56  *    without specific prior written permission.
57  *
58  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68  * SUCH DAMAGE.
69  */
70 
71 #include "pf.h"
72 
73 #include <sys/types.h>
74 #include <sys/param.h>
75 #include <sys/socket.h>
76 #include <sys/systm.h>
77 #include <sys/mbuf.h>
78 #include <sys/kernel.h>
79 #include <sys/proc.h>
80 #include <sys/pool.h>
81 #include <net/route.h>
82 #include <netinet/ip_ipsp.h>
83 #include <net/pfkeyv2.h>
84 #include <net/radix.h>
85 #include <netinet/ip_ah.h>
86 #include <netinet/ip_esp.h>
87 #include <netinet/ip_ipcomp.h>
88 #include <crypto/blf.h>
89 
90 #if NPF > 0
91 #include <net/if.h>
92 #include <net/pfvar.h>
93 #endif
94 
95 #define PFKEYV2_PROTOCOL 2
96 
97 /* Static globals */
98 static struct pfkeyv2_socket *pfkeyv2_sockets = NULL;
99 static struct pfkey_version pfkeyv2_version;
100 static uint32_t pfkeyv2_seq = 1;
101 static int nregistered = 0;
102 static int npromisc = 0;
103 
104 static const struct sadb_alg ealgs[] = {
105 	{ SADB_EALG_NULL, 0, 0, 0 },
106 	{ SADB_EALG_3DESCBC, 64, 192, 192 },
107 	{ SADB_X_EALG_BLF, 64, 40, BLF_MAXKEYLEN * 8},
108 	{ SADB_X_EALG_CAST, 64, 40, 128},
109 	{ SADB_X_EALG_AES, 128, 128, 256},
110 	{ SADB_X_EALG_AESCTR, 128, 128 + 32, 256 + 32}
111 };
112 
113 static const struct sadb_alg aalgs[] = {
114 	{ SADB_AALG_SHA1HMAC, 0, 160, 160 },
115 	{ SADB_AALG_MD5HMAC, 0, 128, 128 },
116 	{ SADB_X_AALG_RIPEMD160HMAC, 0, 160, 160 },
117 	{ SADB_X_AALG_SHA2_256, 0, 256, 256 },
118 	{ SADB_X_AALG_SHA2_384, 0, 384, 384 },
119 	{ SADB_X_AALG_SHA2_512, 0, 512, 512 }
120 };
121 
122 static const struct sadb_alg calgs[] = {
123 	{ SADB_X_CALG_DEFLATE, 0, 0, 0},
124 	{ SADB_X_CALG_LZS, 0, 0, 0}
125 };
126 
127 extern uint64_t sadb_exts_allowed_out[SADB_MAX+1];
128 extern uint64_t sadb_exts_required_out[SADB_MAX+1];
129 
130 extern struct pool ipsec_policy_pool;
131 
132 extern struct radix_node_head **spd_tables;
133 
134 /*
135  * Wrapper around m_devget(); copy data from contiguous buffer to mbuf
136  * chain.
137  */
138 int
139 pfdatatopacket(void *data, int len, struct mbuf **packet)
140 {
141 	if (!(*packet = m_devget(data, len, 0)))
142 		return (ENOMEM);
143 
144 	/* Make sure, all data gets zeroized on free */
145 	(*packet)->m_flags |= M_ZEROIZE;
146 
147 	return (0);
148 }
149 
150 /*
151  * Create a new PF_KEYv2 socket.
152  */
153 int
154 pfkeyv2_create(struct socket *socket)
155 {
156 	struct pfkeyv2_socket *pfkeyv2_socket;
157 
158 	if (!(pfkeyv2_socket = malloc(sizeof(struct pfkeyv2_socket),
159 	    M_PFKEY, M_NOWAIT | M_ZERO)))
160 		return (ENOMEM);
161 
162 	pfkeyv2_socket->next = pfkeyv2_sockets;
163 	pfkeyv2_socket->socket = socket;
164 	pfkeyv2_socket->pid = curproc->p_p->ps_pid;
165 
166 	/*
167 	 * XXX we should get this from the socket instead but
168 	 * XXX rawcb doesn't store the rdomain like inpcb does.
169 	 */
170 	pfkeyv2_socket->rdomain = rtable_l2(curproc->p_p->ps_rtableid);
171 
172 	pfkeyv2_sockets = pfkeyv2_socket;
173 
174 	return (0);
175 }
176 
177 /*
178  * Close a PF_KEYv2 socket.
179  */
180 int
181 pfkeyv2_release(struct socket *socket)
182 {
183 	struct pfkeyv2_socket **pp;
184 
185 	for (pp = &pfkeyv2_sockets; *pp && ((*pp)->socket != socket);
186 	    pp = &((*pp)->next))
187 		/*EMPTY*/;
188 
189 	if (*pp) {
190 		struct pfkeyv2_socket *pfkeyv2_socket;
191 
192 		pfkeyv2_socket = *pp;
193 		*pp = (*pp)->next;
194 
195 		if (pfkeyv2_socket->flags & PFKEYV2_SOCKETFLAGS_REGISTERED)
196 			nregistered--;
197 
198 		if (pfkeyv2_socket->flags & PFKEYV2_SOCKETFLAGS_PROMISC)
199 			npromisc--;
200 
201 		free(pfkeyv2_socket, M_PFKEY, 0);
202 	}
203 
204 	return (0);
205 }
206 
207 /*
208  * Send a PFKEYv2 message, possibly to many receivers, based on the
209  * satype of the socket (which is set by the REGISTER message), and the
210  * third argument.
211  */
212 int
213 pfkeyv2_sendmessage(void **headers, int mode, struct socket *socket,
214     u_int8_t satype, int count, u_int rdomain)
215 {
216 	int i, j, rval;
217 	void *p, *buffer = NULL;
218 	struct mbuf *packet;
219 	struct pfkeyv2_socket *s;
220 	struct sadb_msg *smsg;
221 
222 	/* Find out how much space we'll need... */
223 	j = sizeof(struct sadb_msg);
224 
225 	for (i = 1; i <= SADB_EXT_MAX; i++)
226 		if (headers[i])
227 			j += ((struct sadb_ext *)headers[i])->sadb_ext_len *
228 			    sizeof(uint64_t);
229 
230 	/* ...and allocate it */
231 	if (!(buffer = malloc(j + sizeof(struct sadb_msg), M_PFKEY,
232 	    M_NOWAIT))) {
233 		rval = ENOMEM;
234 		goto ret;
235 	}
236 
237 	p = buffer + sizeof(struct sadb_msg);
238 	bcopy(headers[0], p, sizeof(struct sadb_msg));
239 	((struct sadb_msg *) p)->sadb_msg_len = j / sizeof(uint64_t);
240 	p += sizeof(struct sadb_msg);
241 
242 	/* Copy payloads in the packet */
243 	for (i = 1; i <= SADB_EXT_MAX; i++)
244 		if (headers[i]) {
245 			((struct sadb_ext *) headers[i])->sadb_ext_type = i;
246 			bcopy(headers[i], p, EXTLEN(headers[i]));
247 			p += EXTLEN(headers[i]);
248 		}
249 
250 	if ((rval = pfdatatopacket(buffer + sizeof(struct sadb_msg),
251 	    j, &packet)) != 0)
252 		goto ret;
253 
254 	switch (mode) {
255 	case PFKEYV2_SENDMESSAGE_UNICAST:
256 		/*
257 		 * Send message to the specified socket, plus all
258 		 * promiscuous listeners.
259 		 */
260 		pfkey_sendup(socket, packet, 0);
261 
262 		/*
263 		 * Promiscuous messages contain the original message
264 		 * encapsulated in another sadb_msg header.
265 		 */
266 		bzero(buffer, sizeof(struct sadb_msg));
267 		smsg = (struct sadb_msg *) buffer;
268 		smsg->sadb_msg_version = PF_KEY_V2;
269 		smsg->sadb_msg_type = SADB_X_PROMISC;
270 		smsg->sadb_msg_len = (sizeof(struct sadb_msg) + j) /
271 		    sizeof(uint64_t);
272 		smsg->sadb_msg_seq = 0;
273 
274 		/* Copy to mbuf chain */
275 		if ((rval = pfdatatopacket(buffer, sizeof(struct sadb_msg) + j,
276 		    &packet)) != 0)
277 			goto ret;
278 
279 		/*
280 		 * Search for promiscuous listeners, skipping the
281 		 * original destination.
282 		 */
283 		for (s = pfkeyv2_sockets; s; s = s->next)
284 			if ((s->flags & PFKEYV2_SOCKETFLAGS_PROMISC) &&
285 			    (s->socket != socket) &&
286 			    (s->rdomain == rdomain))
287 				pfkey_sendup(s->socket, packet, 1);
288 
289 		m_freem(packet);
290 		break;
291 
292 	case PFKEYV2_SENDMESSAGE_REGISTERED:
293 		/*
294 		 * Send the message to all registered sockets that match
295 		 * the specified satype (e.g., all IPSEC-ESP negotiators)
296 		 */
297 		for (s = pfkeyv2_sockets; s; s = s->next)
298 			if ((s->flags & PFKEYV2_SOCKETFLAGS_REGISTERED) &&
299 			    (s->rdomain == rdomain)) {
300 				if (!satype)    /* Just send to everyone registered */
301 					pfkey_sendup(s->socket, packet, 1);
302 				else {
303 					/* Check for specified satype */
304 					if ((1 << satype) & s->registration)
305 						pfkey_sendup(s->socket, packet, 1);
306 				}
307 			}
308 
309 		/* Free last/original copy of the packet */
310 		m_freem(packet);
311 
312 		/* Encapsulate the original message "inside" an sadb_msg header */
313 		bzero(buffer, sizeof(struct sadb_msg));
314 		smsg = (struct sadb_msg *) buffer;
315 		smsg->sadb_msg_version = PF_KEY_V2;
316 		smsg->sadb_msg_type = SADB_X_PROMISC;
317 		smsg->sadb_msg_len = (sizeof(struct sadb_msg) + j) /
318 		    sizeof(uint64_t);
319 		smsg->sadb_msg_seq = 0;
320 
321 		/* Convert to mbuf chain */
322 		if ((rval = pfdatatopacket(buffer, sizeof(struct sadb_msg) + j,
323 		    &packet)) != 0)
324 			goto ret;
325 
326 		/* Send to all registered promiscuous listeners */
327 		for (s = pfkeyv2_sockets; s; s = s->next)
328 			if ((s->flags & PFKEYV2_SOCKETFLAGS_PROMISC) &&
329 			    !(s->flags & PFKEYV2_SOCKETFLAGS_REGISTERED) &&
330 			    (s->rdomain == rdomain))
331 				pfkey_sendup(s->socket, packet, 1);
332 
333 		m_freem(packet);
334 		break;
335 
336 	case PFKEYV2_SENDMESSAGE_BROADCAST:
337 		/* Send message to all sockets */
338 		for (s = pfkeyv2_sockets; s; s = s->next) {
339 			if (s->rdomain == rdomain)
340 				pfkey_sendup(s->socket, packet, 1);
341 		}
342 		m_freem(packet);
343 		break;
344 	}
345 
346 ret:
347 	if (buffer != NULL) {
348 		bzero(buffer, j + sizeof(struct sadb_msg));
349 		free(buffer, M_PFKEY, 0);
350 	}
351 
352 	return (rval);
353 }
354 
355 /*
356  * Get SPD information for an ACQUIRE. We setup the message such that
357  * the SRC/DST payloads are relative to us (regardless of whether the
358  * SPD rule was for incoming or outgoing packets).
359  */
360 int
361 pfkeyv2_policy(struct ipsec_acquire *ipa, void **headers, void **buffer)
362 {
363 	union sockaddr_union sunion;
364 	struct sadb_protocol *sp;
365 	int rval, i, dir;
366 	void *p;
367 
368 	/* Find out how big a buffer we need */
369 	i = 4 * sizeof(struct sadb_address) + sizeof(struct sadb_protocol);
370 	bzero(&sunion, sizeof(union sockaddr_union));
371 
372 	switch (ipa->ipa_info.sen_type) {
373 	case SENT_IP4:
374 		i += 4 * PADUP(sizeof(struct sockaddr_in));
375 		sunion.sa.sa_family = AF_INET;
376 		sunion.sa.sa_len = sizeof(struct sockaddr_in);
377 		dir = ipa->ipa_info.sen_direction;
378 		break;
379 
380 #ifdef INET6
381 	case SENT_IP6:
382 		i += 4 * PADUP(sizeof(struct sockaddr_in6));
383 		sunion.sa.sa_family = AF_INET6;
384 		sunion.sa.sa_len = sizeof(struct sockaddr_in6);
385 		dir = ipa->ipa_info.sen_ip6_direction;
386 		break;
387 #endif /* INET6 */
388 
389 	default:
390 		return (EINVAL);
391 	}
392 
393 	if (!(p = malloc(i, M_PFKEY, M_NOWAIT | M_ZERO))) {
394 		rval = ENOMEM;
395 		goto ret;
396 	} else
397 		*buffer = p;
398 
399 	if (dir == IPSP_DIRECTION_OUT)
400 		headers[SADB_X_EXT_SRC_FLOW] = p;
401 	else
402 		headers[SADB_X_EXT_DST_FLOW] = p;
403 	switch (sunion.sa.sa_family) {
404 	case AF_INET:
405 		sunion.sin.sin_addr = ipa->ipa_info.sen_ip_src;
406 		sunion.sin.sin_port = ipa->ipa_info.sen_sport;
407 		break;
408 
409 #ifdef INET6
410 	case AF_INET6:
411 		sunion.sin6.sin6_addr = ipa->ipa_info.sen_ip6_src;
412 		sunion.sin6.sin6_port = ipa->ipa_info.sen_ip6_sport;
413 		break;
414 #endif /* INET6 */
415 	}
416 	export_address(&p, (struct sockaddr *) &sunion);
417 
418 	if (dir == IPSP_DIRECTION_OUT)
419 		headers[SADB_X_EXT_SRC_MASK] = p;
420 	else
421 		headers[SADB_X_EXT_DST_MASK] = p;
422 	switch (sunion.sa.sa_family) {
423 	case AF_INET:
424 		sunion.sin.sin_addr = ipa->ipa_mask.sen_ip_src;
425 		sunion.sin.sin_port = ipa->ipa_mask.sen_sport;
426 		break;
427 
428 #ifdef INET6
429 	case AF_INET6:
430 		sunion.sin6.sin6_addr = ipa->ipa_mask.sen_ip6_src;
431 		sunion.sin6.sin6_port = ipa->ipa_mask.sen_ip6_sport;
432 		break;
433 #endif /* INET6 */
434 	}
435 	export_address(&p, (struct sockaddr *) &sunion);
436 
437 	if (dir == IPSP_DIRECTION_OUT)
438 		headers[SADB_X_EXT_DST_FLOW] = p;
439 	else
440 		headers[SADB_X_EXT_SRC_FLOW] = p;
441 	switch (sunion.sa.sa_family) {
442 	case AF_INET:
443 		sunion.sin.sin_addr = ipa->ipa_info.sen_ip_dst;
444 		sunion.sin.sin_port = ipa->ipa_info.sen_dport;
445 		break;
446 
447 #ifdef INET6
448 	case AF_INET6:
449 		sunion.sin6.sin6_addr = ipa->ipa_info.sen_ip6_dst;
450 		sunion.sin6.sin6_port = ipa->ipa_info.sen_ip6_dport;
451 		break;
452 #endif /* INET6 */
453 	}
454 	export_address(&p, (struct sockaddr *) &sunion);
455 
456 	if (dir == IPSP_DIRECTION_OUT)
457 		headers[SADB_X_EXT_DST_MASK] = p;
458 	else
459 		headers[SADB_X_EXT_SRC_MASK] = p;
460 	switch (sunion.sa.sa_family) {
461 	case AF_INET:
462 		sunion.sin.sin_addr = ipa->ipa_mask.sen_ip_dst;
463 		sunion.sin.sin_port = ipa->ipa_mask.sen_dport;
464 		break;
465 
466 #ifdef INET6
467 	case AF_INET6:
468 		sunion.sin6.sin6_addr = ipa->ipa_mask.sen_ip6_dst;
469 		sunion.sin6.sin6_port = ipa->ipa_mask.sen_ip6_dport;
470 		break;
471 #endif /* INET6 */
472 	}
473 	export_address(&p, (struct sockaddr *) &sunion);
474 
475 	headers[SADB_X_EXT_FLOW_TYPE] = p;
476 	sp = p;
477 	sp->sadb_protocol_len = sizeof(struct sadb_protocol) /
478 	    sizeof(u_int64_t);
479 	switch (sunion.sa.sa_family) {
480 	case AF_INET:
481 		if (ipa->ipa_mask.sen_proto)
482 			sp->sadb_protocol_proto = ipa->ipa_info.sen_proto;
483 		sp->sadb_protocol_direction = ipa->ipa_info.sen_direction;
484 		break;
485 
486 #ifdef INET6
487 	case AF_INET6:
488 		if (ipa->ipa_mask.sen_ip6_proto)
489 			sp->sadb_protocol_proto = ipa->ipa_info.sen_ip6_proto;
490 		sp->sadb_protocol_direction = ipa->ipa_info.sen_ip6_direction;
491 		break;
492 #endif /* INET6 */
493 	}
494 
495 	rval = 0;
496 
497 ret:
498 	return (rval);
499 }
500 
501 /*
502  * Get all the information contained in an SA to a PFKEYV2 message.
503  */
504 int
505 pfkeyv2_get(struct tdb *sa, void **headers, void **buffer, int *lenp)
506 {
507 	int rval, i;
508 	void *p;
509 
510 	/* Find how much space we need */
511 	i = sizeof(struct sadb_sa) + sizeof(struct sadb_lifetime);
512 
513 	if (sa->tdb_soft_allocations || sa->tdb_soft_bytes ||
514 	    sa->tdb_soft_timeout || sa->tdb_soft_first_use)
515 		i += sizeof(struct sadb_lifetime);
516 
517 	if (sa->tdb_exp_allocations || sa->tdb_exp_bytes ||
518 	    sa->tdb_exp_timeout || sa->tdb_exp_first_use)
519 		i += sizeof(struct sadb_lifetime);
520 
521 	if (sa->tdb_last_used)
522 		i += sizeof(struct sadb_lifetime);
523 
524 	i += sizeof(struct sadb_address) + PADUP(SA_LEN(&sa->tdb_src.sa));
525 	i += sizeof(struct sadb_address) + PADUP(SA_LEN(&sa->tdb_dst.sa));
526 
527 	if (sa->tdb_ids) {
528 		i += sizeof(struct sadb_ident) + PADUP(sa->tdb_ids->id_local->len);
529 		i += sizeof(struct sadb_ident) + PADUP(sa->tdb_ids->id_remote->len);
530 	}
531 
532 	if (sa->tdb_amxkey)
533 		i += sizeof(struct sadb_key) + PADUP(sa->tdb_amxkeylen);
534 
535 	if (sa->tdb_emxkey)
536 		i += sizeof(struct sadb_key) + PADUP(sa->tdb_emxkeylen);
537 
538 	if (sa->tdb_filter.sen_type) {
539 		i += 2 * sizeof(struct sadb_protocol);
540 
541 		/* We'll need four of them: src, src mask, dst, dst mask. */
542 		switch (sa->tdb_filter.sen_type) {
543 		case SENT_IP4:
544 			i += 4 * PADUP(sizeof(struct sockaddr_in));
545 			i += 4 * sizeof(struct sadb_address);
546 			break;
547 #ifdef INET6
548 		case SENT_IP6:
549 			i += 4 * PADUP(sizeof(struct sockaddr_in6));
550 			i += 4 * sizeof(struct sadb_address);
551 			break;
552 #endif /* INET6 */
553 		default:
554 			rval = EINVAL;
555 			goto ret;
556 		}
557 	}
558 
559 	if (sa->tdb_udpencap_port)
560 		i += sizeof(struct sadb_x_udpencap);
561 
562 #if NPF > 0
563 	if (sa->tdb_tag)
564 		i += sizeof(struct sadb_x_tag) + PADUP(PF_TAG_NAME_SIZE);
565 	if (sa->tdb_tap)
566 		i += sizeof(struct sadb_x_tap);
567 #endif
568 
569 	if (lenp)
570 		*lenp = i;
571 
572 	if (buffer == NULL) {
573 		rval = 0;
574 		goto ret;
575 	}
576 
577 	if (!(p = malloc(i, M_PFKEY, M_NOWAIT | M_ZERO))) {
578 		rval = ENOMEM;
579 		goto ret;
580 	} else
581 		*buffer = p;
582 
583 	headers[SADB_EXT_SA] = p;
584 
585 	export_sa(&p, sa);  /* Export SA information (mostly flags) */
586 
587 	/* Export lifetimes where applicable */
588 	headers[SADB_EXT_LIFETIME_CURRENT] = p;
589 	export_lifetime(&p, sa, PFKEYV2_LIFETIME_CURRENT);
590 
591 	if (sa->tdb_soft_allocations || sa->tdb_soft_bytes ||
592 	    sa->tdb_soft_first_use || sa->tdb_soft_timeout) {
593 		headers[SADB_EXT_LIFETIME_SOFT] = p;
594 		export_lifetime(&p, sa, PFKEYV2_LIFETIME_SOFT);
595 	}
596 
597 	if (sa->tdb_exp_allocations || sa->tdb_exp_bytes ||
598 	    sa->tdb_exp_first_use || sa->tdb_exp_timeout) {
599 		headers[SADB_EXT_LIFETIME_HARD] = p;
600 		export_lifetime(&p, sa, PFKEYV2_LIFETIME_HARD);
601 	}
602 
603 	if (sa->tdb_last_used) {
604 		headers[SADB_X_EXT_LIFETIME_LASTUSE] = p;
605 		export_lifetime(&p, sa, PFKEYV2_LIFETIME_LASTUSE);
606 	}
607 
608 	/* Export TDB source address */
609 	headers[SADB_EXT_ADDRESS_SRC] = p;
610 	export_address(&p, (struct sockaddr *) &sa->tdb_src);
611 
612 	/* Export TDB destination address */
613 	headers[SADB_EXT_ADDRESS_DST] = p;
614 	export_address(&p, (struct sockaddr *) &sa->tdb_dst);
615 
616 	/* Export source/destination identities, if present */
617 	if (sa->tdb_ids)
618 		export_identities(&p, sa->tdb_ids, sa->tdb_ids_swapped, headers);
619 
620 	/* Export authentication key, if present */
621 	if (sa->tdb_amxkey) {
622 		headers[SADB_EXT_KEY_AUTH] = p;
623 		export_key(&p, sa, PFKEYV2_AUTHENTICATION_KEY);
624 	}
625 
626 	/* Export encryption key, if present */
627 	if (sa->tdb_emxkey) {
628 		headers[SADB_EXT_KEY_ENCRYPT] = p;
629 		export_key(&p, sa, PFKEYV2_ENCRYPTION_KEY);
630 	}
631 
632 	/* Export flow/filter, if present */
633 	if (sa->tdb_filter.sen_type)
634 		export_flow(&p, IPSP_IPSEC_USE, &sa->tdb_filter,
635 		    &sa->tdb_filtermask, headers);
636 
637 	/* Export UDP encapsulation port, if present */
638 	if (sa->tdb_udpencap_port) {
639 		headers[SADB_X_EXT_UDPENCAP] = p;
640 		export_udpencap(&p, sa);
641 	}
642 
643 #if NPF > 0
644 	/* Export tag information, if present */
645 	if (sa->tdb_tag) {
646 		headers[SADB_X_EXT_TAG] = p;
647 		export_tag(&p, sa);
648 	}
649 
650 	/* Export tap enc(4) device information, if present */
651 	if (sa->tdb_tap) {
652 		headers[SADB_X_EXT_TAP] = p;
653 		export_tap(&p, sa);
654 	}
655 #endif
656 
657 	rval = 0;
658 
659  ret:
660 	return (rval);
661 }
662 
663 /*
664  * Dump a TDB.
665  */
666 int
667 pfkeyv2_dump_walker(struct tdb *sa, void *state, int last)
668 {
669 	struct dump_state *dump_state = (struct dump_state *) state;
670 	void *headers[SADB_EXT_MAX+1], *buffer;
671 	int rval;
672 
673 	/* If not satype was specified, dump all TDBs */
674 	if (!dump_state->sadb_msg->sadb_msg_satype ||
675 	    (sa->tdb_satype == dump_state->sadb_msg->sadb_msg_satype)) {
676 		bzero(headers, sizeof(headers));
677 		headers[0] = (void *) dump_state->sadb_msg;
678 
679 		/* Get the information from the TDB to a PFKEYv2 message */
680 		if ((rval = pfkeyv2_get(sa, headers, &buffer, NULL)) != 0)
681 			return (rval);
682 
683 		if (last)
684 			((struct sadb_msg *)headers[0])->sadb_msg_seq = 0;
685 
686 		/* Send the message to the specified socket */
687 		rval = pfkeyv2_sendmessage(headers,
688 		    PFKEYV2_SENDMESSAGE_UNICAST, dump_state->socket, 0, 0,
689 		    sa->tdb_rdomain);
690 
691 		free(buffer, M_PFKEY, 0);
692 		if (rval)
693 			return (rval);
694 	}
695 
696 	return (0);
697 }
698 
699 /*
700  * Delete an SA.
701  */
702 int
703 pfkeyv2_flush_walker(struct tdb *sa, void *satype_vp, int last)
704 {
705 	if (!(*((u_int8_t *) satype_vp)) ||
706 	    sa->tdb_satype == *((u_int8_t *) satype_vp))
707 		tdb_delete(sa);
708 	return (0);
709 }
710 
711 /*
712  * Convert between SATYPEs and IPsec protocols, taking into consideration
713  * sysctl variables enabling/disabling ESP/AH and the presence of the old
714  * IPsec transforms.
715  */
716 int
717 pfkeyv2_get_proto_alg(u_int8_t satype, u_int8_t *sproto, int *alg)
718 {
719 	switch (satype) {
720 #ifdef IPSEC
721 	case SADB_SATYPE_AH:
722 		if (!ah_enable)
723 			return (EOPNOTSUPP);
724 
725 		*sproto = IPPROTO_AH;
726 
727 		if(alg != NULL)
728 			*alg = satype = XF_AH;
729 
730 		break;
731 
732 	case SADB_SATYPE_ESP:
733 		if (!esp_enable)
734 			return (EOPNOTSUPP);
735 
736 		*sproto = IPPROTO_ESP;
737 
738 		if(alg != NULL)
739 			*alg = satype = XF_ESP;
740 
741 		break;
742 
743 	case SADB_X_SATYPE_IPIP:
744 		*sproto = IPPROTO_IPIP;
745 
746 		if (alg != NULL)
747 			*alg = XF_IP4;
748 
749 		break;
750 
751 	case SADB_X_SATYPE_IPCOMP:
752 		if (!ipcomp_enable)
753 			return (EOPNOTSUPP);
754 
755 		*sproto = IPPROTO_IPCOMP;
756 
757 		if(alg != NULL)
758 			*alg = satype = XF_IPCOMP;
759 
760 		break;
761 #endif /* IPSEC */
762 #ifdef TCP_SIGNATURE
763 	case SADB_X_SATYPE_TCPSIGNATURE:
764 		*sproto = IPPROTO_TCP;
765 
766 		if (alg != NULL)
767 			*alg = XF_TCPSIGNATURE;
768 
769 		break;
770 #endif /* TCP_SIGNATURE */
771 
772 	default: /* Nothing else supported */
773 		return (EOPNOTSUPP);
774 	}
775 
776 	return (0);
777 }
778 
779 /*
780  * Handle all messages from userland to kernel.
781  */
782 int
783 pfkeyv2_send(struct socket *socket, void *message, int len)
784 {
785 	int i, j, rval = 0, mode = PFKEYV2_SENDMESSAGE_BROADCAST;
786 	int delflag = 0, s;
787 	struct sockaddr_encap encapdst, encapnetmask;
788 	struct ipsec_policy *ipo, *tmpipo;
789 	struct ipsec_acquire *ipa;
790 	struct radix_node_head *rnh;
791 	struct radix_node *rn = NULL;
792 
793 	struct pfkeyv2_socket *pfkeyv2_socket, *so = NULL;
794 
795 	void *freeme = NULL, *bckptr = NULL;
796 	void *headers[SADB_EXT_MAX + 1];
797 
798 	union sockaddr_union *sunionp;
799 
800 	struct tdb *sa1 = NULL, *sa2 = NULL;
801 
802 	struct sadb_msg *smsg;
803 	struct sadb_spirange *sprng;
804 	struct sadb_sa *ssa;
805 	struct sadb_supported *ssup;
806 	struct sadb_ident *sid, *did;
807 
808 	u_int rdomain;
809 
810 	/* Verify that we received this over a legitimate pfkeyv2 socket */
811 	bzero(headers, sizeof(headers));
812 
813 	for (pfkeyv2_socket = pfkeyv2_sockets; pfkeyv2_socket;
814 	    pfkeyv2_socket = pfkeyv2_socket->next)
815 		if (pfkeyv2_socket->socket == socket)
816 			break;
817 
818 	if (!pfkeyv2_socket) {
819 		rval = EINVAL;
820 		goto ret;
821 	}
822 
823 	rdomain = pfkeyv2_socket->rdomain;
824 
825 	/* If we have any promiscuous listeners, send them a copy of the message */
826 	if (npromisc) {
827 		struct mbuf *packet;
828 
829 		if (!(freeme = malloc(sizeof(struct sadb_msg) + len, M_PFKEY,
830 		    M_NOWAIT))) {
831 			rval = ENOMEM;
832 			goto ret;
833 		}
834 
835 		/* Initialize encapsulating header */
836 		bzero(freeme, sizeof(struct sadb_msg));
837 		smsg = (struct sadb_msg *) freeme;
838 		smsg->sadb_msg_version = PF_KEY_V2;
839 		smsg->sadb_msg_type = SADB_X_PROMISC;
840 		smsg->sadb_msg_len = (sizeof(struct sadb_msg) + len) /
841 		    sizeof(uint64_t);
842 		smsg->sadb_msg_seq = curproc->p_p->ps_pid;
843 
844 		bcopy(message, freeme + sizeof(struct sadb_msg), len);
845 
846 		/* Convert to mbuf chain */
847 		if ((rval = pfdatatopacket(freeme,
848 		    sizeof(struct sadb_msg) + len, &packet)) != 0)
849 			goto ret;
850 
851 		/* Send to all promiscuous listeners */
852 		for (so = pfkeyv2_sockets; so; so = so->next) {
853 			if ((so->flags & PFKEYV2_SOCKETFLAGS_PROMISC) &&
854 			    (so->rdomain == rdomain))
855 				pfkey_sendup(so->socket, packet, 1);
856 		}
857 
858 		m_freem(packet);
859 
860 		/* Paranoid */
861 		explicit_bzero(freeme, sizeof(struct sadb_msg) + len);
862 		free(freeme, M_PFKEY, 0);
863 		freeme = NULL;
864 	}
865 
866 	/* Validate message format */
867 	if ((rval = pfkeyv2_parsemessage(message, len, headers)) != 0)
868 		goto ret;
869 
870 	smsg = (struct sadb_msg *) headers[0];
871 	switch (smsg->sadb_msg_type) {
872 	case SADB_GETSPI:  /* Reserve an SPI */
873 		sa1 = malloc(sizeof (*sa1), M_PFKEY, M_NOWAIT | M_ZERO);
874 		if (sa1 == NULL) {
875 			rval = ENOMEM;
876 			goto ret;
877 		}
878 
879 		sa1->tdb_satype = smsg->sadb_msg_satype;
880 		if ((rval = pfkeyv2_get_proto_alg(sa1->tdb_satype,
881 		    &sa1->tdb_sproto, 0)))
882 			goto ret;
883 
884 		import_address((struct sockaddr *) &sa1->tdb_src,
885 		    headers[SADB_EXT_ADDRESS_SRC]);
886 		import_address((struct sockaddr *) &sa1->tdb_dst,
887 		    headers[SADB_EXT_ADDRESS_DST]);
888 
889 		/* Find an unused SA identifier */
890 		sprng = (struct sadb_spirange *) headers[SADB_EXT_SPIRANGE];
891 		sa1->tdb_spi = reserve_spi(rdomain,
892 		    sprng->sadb_spirange_min, sprng->sadb_spirange_max,
893 		    &sa1->tdb_src, &sa1->tdb_dst, sa1->tdb_sproto, &rval);
894 		if (sa1->tdb_spi == 0)
895 			goto ret;
896 
897 		/* Send a message back telling what the SA (the SPI really) is */
898 		if (!(freeme = malloc(sizeof(struct sadb_sa), M_PFKEY,
899 		    M_NOWAIT | M_ZERO))) {
900 			rval = ENOMEM;
901 			goto ret;
902 		}
903 
904 		headers[SADB_EXT_SPIRANGE] = NULL;
905 		headers[SADB_EXT_SA] = freeme;
906 		bckptr = freeme;
907 
908 		/* We really only care about the SPI, but we'll export the SA */
909 		export_sa((void **) &bckptr, sa1);
910 		break;
911 
912 	case SADB_UPDATE:
913 		ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
914 		sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] +
915 		    sizeof(struct sadb_address));
916 
917 		/* Either all or none of the flow must be included */
918 		if ((headers[SADB_X_EXT_SRC_FLOW] ||
919 		    headers[SADB_X_EXT_PROTOCOL] ||
920 		    headers[SADB_X_EXT_FLOW_TYPE] ||
921 		    headers[SADB_X_EXT_DST_FLOW] ||
922 		    headers[SADB_X_EXT_SRC_MASK] ||
923 		    headers[SADB_X_EXT_DST_MASK]) &&
924 		    !(headers[SADB_X_EXT_SRC_FLOW] &&
925 		    headers[SADB_X_EXT_PROTOCOL] &&
926 		    headers[SADB_X_EXT_FLOW_TYPE] &&
927 		    headers[SADB_X_EXT_DST_FLOW] &&
928 		    headers[SADB_X_EXT_SRC_MASK] &&
929 		    headers[SADB_X_EXT_DST_MASK])) {
930 			rval = EINVAL;
931 			goto ret;
932 		}
933 #ifdef IPSEC
934 		/* UDP encap has to be enabled and is only supported for ESP */
935 		if (headers[SADB_X_EXT_UDPENCAP] &&
936 		    (!udpencap_enable ||
937 		    smsg->sadb_msg_satype != SADB_SATYPE_ESP)) {
938 			rval = EINVAL;
939 			goto ret;
940 		}
941 #endif /* IPSEC */
942 
943 		s = splsoftnet();
944 
945 		/* Find TDB */
946 		sa2 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp,
947 		    SADB_X_GETSPROTO(smsg->sadb_msg_satype));
948 
949 		/* If there's no such SA, we're done */
950 		if (sa2 == NULL) {
951 			rval = ESRCH;
952 			goto splxret;
953 		}
954 
955 		/* If this is a reserved SA */
956 		if (sa2->tdb_flags & TDBF_INVALID) {
957 			struct tdb *newsa;
958 			struct ipsecinit ii;
959 			int alg;
960 
961 			/* Create new TDB */
962 			freeme = tdb_alloc(rdomain);
963 			bzero(&ii, sizeof(struct ipsecinit));
964 
965 			newsa = (struct tdb *) freeme;
966 			newsa->tdb_satype = smsg->sadb_msg_satype;
967 
968 			if ((rval = pfkeyv2_get_proto_alg(newsa->tdb_satype,
969 			    &newsa->tdb_sproto, &alg))) {
970 				tdb_free(freeme);
971 				freeme = NULL;
972 				goto splxret;
973 			}
974 
975 			/* Initialize SA */
976 			import_sa(newsa, headers[SADB_EXT_SA], &ii);
977 			import_address((struct sockaddr *) &newsa->tdb_src,
978 			    headers[SADB_EXT_ADDRESS_SRC]);
979 			import_address((struct sockaddr *) &newsa->tdb_dst,
980 			    headers[SADB_EXT_ADDRESS_DST]);
981 			import_lifetime(newsa,
982 			    headers[SADB_EXT_LIFETIME_CURRENT],
983 			    PFKEYV2_LIFETIME_CURRENT);
984 			import_lifetime(newsa, headers[SADB_EXT_LIFETIME_SOFT],
985 			    PFKEYV2_LIFETIME_SOFT);
986 			import_lifetime(newsa, headers[SADB_EXT_LIFETIME_HARD],
987 			    PFKEYV2_LIFETIME_HARD);
988 			import_key(&ii, headers[SADB_EXT_KEY_AUTH],
989 			    PFKEYV2_AUTHENTICATION_KEY);
990 			import_key(&ii, headers[SADB_EXT_KEY_ENCRYPT],
991 			    PFKEYV2_ENCRYPTION_KEY);
992 			newsa->tdb_ids_swapped = 1; /* only on TDB_UPDATE */
993 			import_identities(&newsa->tdb_ids,
994 			    newsa->tdb_ids_swapped,
995 			    headers[SADB_EXT_IDENTITY_SRC],
996 			    headers[SADB_EXT_IDENTITY_DST]);
997 			import_flow(&newsa->tdb_filter, &newsa->tdb_filtermask,
998 			    headers[SADB_X_EXT_SRC_FLOW],
999 			    headers[SADB_X_EXT_SRC_MASK],
1000 			    headers[SADB_X_EXT_DST_FLOW],
1001 			    headers[SADB_X_EXT_DST_MASK],
1002 			    headers[SADB_X_EXT_PROTOCOL],
1003 			    headers[SADB_X_EXT_FLOW_TYPE]);
1004 			import_udpencap(newsa, headers[SADB_X_EXT_UDPENCAP]);
1005 #if NPF > 0
1006 			import_tag(newsa, headers[SADB_X_EXT_TAG]);
1007 			import_tap(newsa, headers[SADB_X_EXT_TAP]);
1008 #endif
1009 
1010 			/* Exclude sensitive data from reply message. */
1011 			headers[SADB_EXT_KEY_AUTH] = NULL;
1012 			headers[SADB_EXT_KEY_ENCRYPT] = NULL;
1013 			headers[SADB_X_EXT_LOCAL_AUTH] = NULL;
1014 			headers[SADB_X_EXT_REMOTE_AUTH] = NULL;
1015 
1016 			newsa->tdb_seq = smsg->sadb_msg_seq;
1017 
1018 			rval = tdb_init(newsa, alg, &ii);
1019 			if (rval) {
1020 				rval = EINVAL;
1021 				tdb_free(freeme);
1022 				freeme = NULL;
1023 				goto splxret;
1024 			}
1025 
1026 			newsa->tdb_cur_allocations = sa2->tdb_cur_allocations;
1027 
1028 			/* Delete old version of the SA, insert new one */
1029 			tdb_delete(sa2);
1030 			puttdb((struct tdb *) freeme);
1031 			sa2 = freeme = NULL;
1032 		} else {
1033 			/*
1034 			 * The SA is already initialized, so we're only allowed to
1035 			 * change lifetimes and some other information; we're
1036 			 * not allowed to change keys, addresses or identities.
1037 			 */
1038 			if (headers[SADB_EXT_KEY_AUTH] ||
1039 			    headers[SADB_EXT_KEY_ENCRYPT] ||
1040 			    headers[SADB_EXT_IDENTITY_SRC] ||
1041 			    headers[SADB_EXT_IDENTITY_DST] ||
1042 			    headers[SADB_EXT_SENSITIVITY]) {
1043 				rval = EINVAL;
1044 				goto splxret;
1045 			}
1046 
1047 			import_sa(sa2, headers[SADB_EXT_SA], NULL);
1048 			import_lifetime(sa2,
1049 			    headers[SADB_EXT_LIFETIME_CURRENT],
1050 			    PFKEYV2_LIFETIME_CURRENT);
1051 			import_lifetime(sa2, headers[SADB_EXT_LIFETIME_SOFT],
1052 			    PFKEYV2_LIFETIME_SOFT);
1053 			import_lifetime(sa2, headers[SADB_EXT_LIFETIME_HARD],
1054 			    PFKEYV2_LIFETIME_HARD);
1055 			import_udpencap(sa2, headers[SADB_X_EXT_UDPENCAP]);
1056 #if NPF > 0
1057 			import_tag(sa2, headers[SADB_X_EXT_TAG]);
1058 			import_tap(sa2, headers[SADB_X_EXT_TAP]);
1059 #endif
1060 		}
1061 
1062 		splx(s);
1063 		break;
1064 	case SADB_ADD:
1065 		ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
1066 		sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] +
1067 		    sizeof(struct sadb_address));
1068 
1069 		/* Either all or none of the flow must be included */
1070 		if ((headers[SADB_X_EXT_SRC_FLOW] ||
1071 		    headers[SADB_X_EXT_PROTOCOL] ||
1072 		    headers[SADB_X_EXT_FLOW_TYPE] ||
1073 		    headers[SADB_X_EXT_DST_FLOW] ||
1074 		    headers[SADB_X_EXT_SRC_MASK] ||
1075 		    headers[SADB_X_EXT_DST_MASK]) &&
1076 		    !(headers[SADB_X_EXT_SRC_FLOW] &&
1077 		    headers[SADB_X_EXT_PROTOCOL] &&
1078 		    headers[SADB_X_EXT_FLOW_TYPE] &&
1079 		    headers[SADB_X_EXT_DST_FLOW] &&
1080 		    headers[SADB_X_EXT_SRC_MASK] &&
1081 		    headers[SADB_X_EXT_DST_MASK])) {
1082 			rval = EINVAL;
1083 			goto ret;
1084 		}
1085 #ifdef IPSEC
1086 		/* UDP encap has to be enabled and is only supported for ESP */
1087 		if (headers[SADB_X_EXT_UDPENCAP] &&
1088 		    (!udpencap_enable ||
1089 		    smsg->sadb_msg_satype != SADB_SATYPE_ESP)) {
1090 			rval = EINVAL;
1091 			goto ret;
1092 		}
1093 #endif /* IPSEC */
1094 
1095 		s = splsoftnet();
1096 
1097 		sa2 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp,
1098 		    SADB_X_GETSPROTO(smsg->sadb_msg_satype));
1099 
1100 		/* We can't add an existing SA! */
1101 		if (sa2 != NULL) {
1102 			rval = EEXIST;
1103 			goto splxret;
1104 		}
1105 
1106 		/* We can only add "mature" SAs */
1107 		if (ssa->sadb_sa_state != SADB_SASTATE_MATURE) {
1108 			rval = EINVAL;
1109 			goto splxret;
1110 		}
1111 
1112 		/* Allocate and initialize new TDB */
1113 		freeme = tdb_alloc(rdomain);
1114 
1115 		{
1116 			struct tdb *newsa = (struct tdb *) freeme;
1117 			struct ipsecinit ii;
1118 			int alg;
1119 
1120 			bzero(&ii, sizeof(struct ipsecinit));
1121 
1122 			newsa->tdb_satype = smsg->sadb_msg_satype;
1123 			if ((rval = pfkeyv2_get_proto_alg(newsa->tdb_satype,
1124 			    &newsa->tdb_sproto, &alg))) {
1125 				tdb_free(freeme);
1126 				freeme = NULL;
1127 				goto splxret;
1128 			}
1129 
1130 			import_sa(newsa, headers[SADB_EXT_SA], &ii);
1131 			import_address((struct sockaddr *) &newsa->tdb_src,
1132 			    headers[SADB_EXT_ADDRESS_SRC]);
1133 			import_address((struct sockaddr *) &newsa->tdb_dst,
1134 			    headers[SADB_EXT_ADDRESS_DST]);
1135 
1136 			import_lifetime(newsa,
1137 			    headers[SADB_EXT_LIFETIME_CURRENT],
1138 			    PFKEYV2_LIFETIME_CURRENT);
1139 			import_lifetime(newsa, headers[SADB_EXT_LIFETIME_SOFT],
1140 			    PFKEYV2_LIFETIME_SOFT);
1141 			import_lifetime(newsa, headers[SADB_EXT_LIFETIME_HARD],
1142 			    PFKEYV2_LIFETIME_HARD);
1143 
1144 			import_key(&ii, headers[SADB_EXT_KEY_AUTH],
1145 			    PFKEYV2_AUTHENTICATION_KEY);
1146 			import_key(&ii, headers[SADB_EXT_KEY_ENCRYPT],
1147 			    PFKEYV2_ENCRYPTION_KEY);
1148 
1149 			import_identities(&newsa->tdb_ids,
1150 			    newsa->tdb_ids_swapped,
1151 			    headers[SADB_EXT_IDENTITY_SRC],
1152 			    headers[SADB_EXT_IDENTITY_DST]);
1153 
1154 			import_flow(&newsa->tdb_filter, &newsa->tdb_filtermask,
1155 			    headers[SADB_X_EXT_SRC_FLOW],
1156 			    headers[SADB_X_EXT_SRC_MASK],
1157 			    headers[SADB_X_EXT_DST_FLOW],
1158 			    headers[SADB_X_EXT_DST_MASK],
1159 			    headers[SADB_X_EXT_PROTOCOL],
1160 			    headers[SADB_X_EXT_FLOW_TYPE]);
1161 			import_udpencap(newsa, headers[SADB_X_EXT_UDPENCAP]);
1162 #if NPF > 0
1163 			import_tag(newsa, headers[SADB_X_EXT_TAG]);
1164 			import_tap(newsa, headers[SADB_X_EXT_TAP]);
1165 #endif
1166 
1167 			/* Exclude sensitive data from reply message. */
1168 			headers[SADB_EXT_KEY_AUTH] = NULL;
1169 			headers[SADB_EXT_KEY_ENCRYPT] = NULL;
1170 			headers[SADB_X_EXT_LOCAL_AUTH] = NULL;
1171 			headers[SADB_X_EXT_REMOTE_AUTH] = NULL;
1172 
1173 			newsa->tdb_seq = smsg->sadb_msg_seq;
1174 
1175 			rval = tdb_init(newsa, alg, &ii);
1176 			if (rval) {
1177 				rval = EINVAL;
1178 				tdb_free(freeme);
1179 				freeme = NULL;
1180 				goto splxret;
1181 			}
1182 		}
1183 
1184 		/* Add TDB in table */
1185 		puttdb((struct tdb *) freeme);
1186 
1187 		splx(s);
1188 
1189 		freeme = NULL;
1190 		break;
1191 
1192 	case SADB_DELETE:
1193 		ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
1194 		sunionp =
1195 		    (union sockaddr_union *)(headers[SADB_EXT_ADDRESS_DST] +
1196 			sizeof(struct sadb_address));
1197 		s = splsoftnet();
1198 
1199 		sa2 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp,
1200 		    SADB_X_GETSPROTO(smsg->sadb_msg_satype));
1201 		if (sa2 == NULL) {
1202 			rval = ESRCH;
1203 			goto splxret;
1204 		}
1205 
1206 		tdb_delete(sa2);
1207 
1208 		splx(s);
1209 
1210 		sa2 = NULL;
1211 		break;
1212 
1213 	case SADB_X_ASKPOLICY:
1214 		/* Get the relevant policy */
1215 		ipa = ipsec_get_acquire(((struct sadb_x_policy *) headers[SADB_X_EXT_POLICY])->sadb_x_policy_seq);
1216 		if (ipa == NULL) {
1217 			rval = ESRCH;
1218 			goto ret;
1219 		}
1220 
1221 		rval = pfkeyv2_policy(ipa, headers, &freeme);
1222 		if (rval)
1223 			mode = PFKEYV2_SENDMESSAGE_UNICAST;
1224 
1225 		break;
1226 
1227 	case SADB_GET:
1228 		ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
1229 		sunionp =
1230 		    (union sockaddr_union *)(headers[SADB_EXT_ADDRESS_DST] +
1231 			sizeof(struct sadb_address));
1232 
1233 		s = splsoftnet();
1234 
1235 		sa2 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp,
1236 		    SADB_X_GETSPROTO(smsg->sadb_msg_satype));
1237 		if (sa2 == NULL) {
1238 			rval = ESRCH;
1239 			goto splxret;
1240 		}
1241 
1242 		rval = pfkeyv2_get(sa2, headers, &freeme, NULL);
1243 		if (rval)
1244 			mode = PFKEYV2_SENDMESSAGE_UNICAST;
1245 
1246 		splx(s);
1247 
1248 		break;
1249 
1250 	case SADB_REGISTER:
1251 		if (!(pfkeyv2_socket->flags & PFKEYV2_SOCKETFLAGS_REGISTERED)) {
1252 			pfkeyv2_socket->flags |= PFKEYV2_SOCKETFLAGS_REGISTERED;
1253 			nregistered++;
1254 		}
1255 
1256 		i = sizeof(struct sadb_supported) + sizeof(ealgs);
1257 
1258 		if (!(freeme = malloc(i, M_PFKEY, M_NOWAIT | M_ZERO))) {
1259 			rval = ENOMEM;
1260 			goto ret;
1261 		}
1262 
1263 		ssup = (struct sadb_supported *) freeme;
1264 		ssup->sadb_supported_len = i / sizeof(uint64_t);
1265 
1266 		{
1267 			void *p = freeme + sizeof(struct sadb_supported);
1268 
1269 			bcopy(&ealgs[0], p, sizeof(ealgs));
1270 		}
1271 
1272 		headers[SADB_EXT_SUPPORTED_ENCRYPT] = freeme;
1273 
1274 		i = sizeof(struct sadb_supported) + sizeof(aalgs);
1275 
1276 		if (!(freeme = malloc(i, M_PFKEY, M_NOWAIT | M_ZERO))) {
1277 			rval = ENOMEM;
1278 			goto ret;
1279 		}
1280 
1281 		/* Keep track what this socket has registered for */
1282 		pfkeyv2_socket->registration |= (1 << ((struct sadb_msg *)message)->sadb_msg_satype);
1283 
1284 		ssup = (struct sadb_supported *) freeme;
1285 		ssup->sadb_supported_len = i / sizeof(uint64_t);
1286 
1287 		{
1288 			void *p = freeme + sizeof(struct sadb_supported);
1289 
1290 			bcopy(&aalgs[0], p, sizeof(aalgs));
1291 		}
1292 
1293 		headers[SADB_EXT_SUPPORTED_AUTH] = freeme;
1294 
1295 		i = sizeof(struct sadb_supported) + sizeof(calgs);
1296 
1297 		if (!(freeme = malloc(i, M_PFKEY, M_NOWAIT | M_ZERO))) {
1298 			rval = ENOMEM;
1299 			goto ret;
1300 		}
1301 
1302 		ssup = (struct sadb_supported *) freeme;
1303 		ssup->sadb_supported_len = i / sizeof(uint64_t);
1304 
1305 		{
1306 			void *p = freeme + sizeof(struct sadb_supported);
1307 
1308 			bcopy(&calgs[0], p, sizeof(calgs));
1309 		}
1310 
1311 		headers[SADB_X_EXT_SUPPORTED_COMP] = freeme;
1312 
1313 		break;
1314 
1315 	case SADB_ACQUIRE:
1316 	case SADB_EXPIRE:
1317 		/* Nothing to handle */
1318 		rval = 0;
1319 		break;
1320 
1321 	case SADB_FLUSH:
1322 		rval = 0;
1323 
1324 		switch (smsg->sadb_msg_satype) {
1325 		case SADB_SATYPE_UNSPEC:
1326 			s = splsoftnet();
1327 
1328 			for (ipo = TAILQ_FIRST(&ipsec_policy_head);
1329 			    ipo != NULL; ipo = tmpipo) {
1330 				tmpipo = TAILQ_NEXT(ipo, ipo_list);
1331 				if (ipo->ipo_rdomain == rdomain)
1332 					ipsec_delete_policy(ipo);
1333 			}
1334 			splx(s);
1335 			/* FALLTHROUGH */
1336 		case SADB_SATYPE_AH:
1337 		case SADB_SATYPE_ESP:
1338 		case SADB_X_SATYPE_IPIP:
1339 		case SADB_X_SATYPE_IPCOMP:
1340 #ifdef TCP_SIGNATURE
1341 		case SADB_X_SATYPE_TCPSIGNATURE:
1342 #endif /* TCP_SIGNATURE */
1343 			s = splsoftnet();
1344 
1345 			tdb_walk(rdomain, pfkeyv2_flush_walker,
1346 			    (u_int8_t *) &(smsg->sadb_msg_satype));
1347 
1348 			splx(s);
1349 			break;
1350 
1351 		default:
1352 			rval = EINVAL; /* Unknown/unsupported type */
1353 		}
1354 
1355 		break;
1356 
1357 	case SADB_DUMP:
1358 	{
1359 		struct dump_state dump_state;
1360 		dump_state.sadb_msg = (struct sadb_msg *) headers[0];
1361 		dump_state.socket = socket;
1362 
1363 		s = splsoftnet();
1364 		rval = tdb_walk(rdomain, pfkeyv2_dump_walker, &dump_state);
1365 		splx(s);
1366 
1367 		if (!rval)
1368 			goto realret;
1369 
1370 		if ((rval == ENOMEM) || (rval == ENOBUFS))
1371 			rval = 0;
1372 	}
1373 	break;
1374 
1375 	case SADB_X_GRPSPIS:
1376 	{
1377 		struct tdb *tdb1, *tdb2, *tdb3;
1378 		struct sadb_protocol *sa_proto;
1379 
1380 		ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
1381 		sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] +
1382 		    sizeof(struct sadb_address));
1383 
1384 		s = splsoftnet();
1385 
1386 		tdb1 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp,
1387 		    SADB_X_GETSPROTO(smsg->sadb_msg_satype));
1388 		if (tdb1 == NULL) {
1389 			rval = ESRCH;
1390 			goto splxret;
1391 		}
1392 
1393 		ssa = (struct sadb_sa *) headers[SADB_X_EXT_SA2];
1394 		sunionp = (union sockaddr_union *) (headers[SADB_X_EXT_DST2] +
1395 		    sizeof(struct sadb_address));
1396 		sa_proto = ((struct sadb_protocol *) headers[SADB_X_EXT_PROTOCOL]);
1397 
1398 		tdb2 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp,
1399 		    SADB_X_GETSPROTO(sa_proto->sadb_protocol_proto));
1400 		if (tdb2 == NULL) {
1401 			rval = ESRCH;
1402 			goto splxret;
1403 		}
1404 
1405 		/* Detect cycles */
1406 		for (tdb3 = tdb2; tdb3; tdb3 = tdb3->tdb_onext)
1407 			if (tdb3 == tdb1) {
1408 				rval = ESRCH;
1409 				goto splxret;
1410 			}
1411 
1412 		/* Maintenance */
1413 		if ((tdb1->tdb_onext) &&
1414 		    (tdb1->tdb_onext->tdb_inext == tdb1))
1415 			tdb1->tdb_onext->tdb_inext = NULL;
1416 
1417 		if ((tdb2->tdb_inext) &&
1418 		    (tdb2->tdb_inext->tdb_onext == tdb2))
1419 			tdb2->tdb_inext->tdb_onext = NULL;
1420 
1421 		/* Link them */
1422 		tdb1->tdb_onext = tdb2;
1423 		tdb2->tdb_inext = tdb1;
1424 
1425 		splx(s);
1426 	}
1427 	break;
1428 
1429 	case SADB_X_DELFLOW:
1430 		delflag = 1;
1431 		/*FALLTHROUGH*/
1432 	case SADB_X_ADDFLOW:
1433 	{
1434 		struct sadb_protocol *sab;
1435 		union sockaddr_union *ssrc;
1436 		int exists = 0;
1437 
1438 		if ((rnh = spd_table_add(rdomain)) == NULL) {
1439 			rval = ENOMEM;
1440 			goto ret;
1441 		}
1442 
1443 		sab = (struct sadb_protocol *) headers[SADB_X_EXT_FLOW_TYPE];
1444 
1445 		if ((sab->sadb_protocol_direction != IPSP_DIRECTION_IN) &&
1446 		    (sab->sadb_protocol_direction != IPSP_DIRECTION_OUT)) {
1447 			rval = EINVAL;
1448 			goto ret;
1449 		}
1450 
1451 		/* If the security protocol wasn't specified, pretend it was ESP */
1452 		if (smsg->sadb_msg_satype == 0)
1453 			smsg->sadb_msg_satype = SADB_SATYPE_ESP;
1454 
1455 		if (headers[SADB_EXT_ADDRESS_DST])
1456 			sunionp = (union sockaddr_union *)
1457 			    (headers[SADB_EXT_ADDRESS_DST] +
1458 				sizeof(struct sadb_address));
1459 		else
1460 			sunionp = NULL;
1461 
1462 		if (headers[SADB_EXT_ADDRESS_SRC])
1463 			ssrc = (union sockaddr_union *)
1464 			    (headers[SADB_EXT_ADDRESS_SRC] +
1465 				sizeof(struct sadb_address));
1466 		else
1467 			ssrc = NULL;
1468 
1469 		import_flow(&encapdst, &encapnetmask,
1470 		    headers[SADB_X_EXT_SRC_FLOW], headers[SADB_X_EXT_SRC_MASK],
1471 		    headers[SADB_X_EXT_DST_FLOW], headers[SADB_X_EXT_DST_MASK],
1472 		    headers[SADB_X_EXT_PROTOCOL], headers[SADB_X_EXT_FLOW_TYPE]);
1473 
1474 		/* Determine whether the exact same SPD entry already exists. */
1475 		s = splsoftnet();
1476 		if ((rn = rn_match(&encapdst, rnh)) != NULL) {
1477 			ipo = (struct ipsec_policy *)rn;
1478 
1479 			/* Verify that the entry is identical */
1480 			if (bcmp(&ipo->ipo_addr, &encapdst,
1481 				sizeof(struct sockaddr_encap)) ||
1482 			    bcmp(&ipo->ipo_mask, &encapnetmask,
1483 				sizeof(struct sockaddr_encap)))
1484 				ipo = NULL; /* Fall through */
1485 			else
1486 				exists = 1;
1487 		} else
1488 			ipo = NULL;
1489 
1490 		/*
1491 		 * If the existing policy is static, only delete or update
1492 		 * it if the new one is also static.
1493 		 */
1494 		if (exists && (ipo->ipo_flags & IPSP_POLICY_STATIC)) {
1495 			if (!(sab->sadb_protocol_flags &
1496 				SADB_X_POLICYFLAGS_POLICY)) {
1497 				splx(s);
1498 				goto ret;
1499 			}
1500 		}
1501 
1502 		/* Delete ? */
1503 		if (delflag) {
1504 			if (exists) {
1505 				rval = ipsec_delete_policy(ipo);
1506 				splx(s);
1507 				goto ret;
1508 			}
1509 
1510 			/* If we were asked to delete something non-existent, error. */
1511 			splx(s);
1512 			rval = ESRCH;
1513 			break;
1514 		}
1515 
1516 		if (!exists) {
1517 			if (ipsec_policy_pool_initialized == 0) {
1518 				ipsec_policy_pool_initialized = 1;
1519 				pool_init(&ipsec_policy_pool,
1520 				    sizeof(struct ipsec_policy), 0,
1521 				    IPL_NONE, 0, "ipsec policy", NULL);
1522 			}
1523 
1524 			/* Allocate policy entry */
1525 			ipo = pool_get(&ipsec_policy_pool, PR_NOWAIT|PR_ZERO);
1526 			if (ipo == NULL) {
1527 				splx(s);
1528 				rval = ENOMEM;
1529 				goto ret;
1530 			}
1531 		}
1532 
1533 		switch (sab->sadb_protocol_proto) {
1534 		case SADB_X_FLOW_TYPE_USE:
1535 			ipo->ipo_type = IPSP_IPSEC_USE;
1536 			break;
1537 
1538 		case SADB_X_FLOW_TYPE_ACQUIRE:
1539 			ipo->ipo_type = IPSP_IPSEC_ACQUIRE;
1540 			break;
1541 
1542 		case SADB_X_FLOW_TYPE_REQUIRE:
1543 			ipo->ipo_type = IPSP_IPSEC_REQUIRE;
1544 			break;
1545 
1546 		case SADB_X_FLOW_TYPE_DENY:
1547 			ipo->ipo_type = IPSP_DENY;
1548 			break;
1549 
1550 		case SADB_X_FLOW_TYPE_BYPASS:
1551 			ipo->ipo_type = IPSP_PERMIT;
1552 			break;
1553 
1554 		case SADB_X_FLOW_TYPE_DONTACQ:
1555 			ipo->ipo_type = IPSP_IPSEC_DONTACQ;
1556 			break;
1557 
1558 		default:
1559 			if (!exists)
1560 				pool_put(&ipsec_policy_pool, ipo);
1561 			else
1562 				ipsec_delete_policy(ipo);
1563 
1564 			splx(s);
1565 			rval = EINVAL;
1566 			goto ret;
1567 		}
1568 
1569 		if (sab->sadb_protocol_flags & SADB_X_POLICYFLAGS_POLICY)
1570 			ipo->ipo_flags |= IPSP_POLICY_STATIC;
1571 
1572 		if (sunionp)
1573 			bcopy(sunionp, &ipo->ipo_dst,
1574 			    sizeof(union sockaddr_union));
1575 		else
1576 			bzero(&ipo->ipo_dst, sizeof(union sockaddr_union));
1577 
1578 		if (ssrc)
1579 			bcopy(ssrc, &ipo->ipo_src,
1580 			    sizeof(union sockaddr_union));
1581 		else
1582 			bzero(&ipo->ipo_src, sizeof(union sockaddr_union));
1583 
1584 		ipo->ipo_sproto = SADB_X_GETSPROTO(smsg->sadb_msg_satype);
1585 
1586 		if (ipo->ipo_ids) {
1587 			ipsp_ids_free(ipo->ipo_ids);
1588 			ipo->ipo_ids = NULL;
1589 		}
1590 
1591 		if ((sid = headers[SADB_EXT_IDENTITY_SRC]) != NULL &&
1592 		    (did = headers[SADB_EXT_IDENTITY_DST]) != NULL) {
1593 			import_identities(&ipo->ipo_ids, 0, sid, did);
1594 			if (ipo->ipo_ids == NULL) {
1595 				if (exists)
1596 					ipsec_delete_policy(ipo);
1597 				else
1598 					pool_put(&ipsec_policy_pool, ipo);
1599 				splx(s);
1600 				rval = ENOBUFS;
1601 				goto ret;
1602 			}
1603 		}
1604 
1605 		/* Flow type */
1606 		if (!exists) {
1607 			/* Initialize policy entry */
1608 			bcopy(&encapdst, &ipo->ipo_addr,
1609 			    sizeof(struct sockaddr_encap));
1610 			bcopy(&encapnetmask, &ipo->ipo_mask,
1611 			    sizeof(struct sockaddr_encap));
1612 
1613 			TAILQ_INIT(&ipo->ipo_acquires);
1614 			ipo->ipo_rdomain = rdomain;
1615 			ipo->ipo_ref_count = 1;
1616 
1617 			/* Add SPD entry */
1618 			if ((rnh = spd_table_get(rdomain)) == NULL ||
1619 			    (rn = rn_addroute((caddr_t)&ipo->ipo_addr,
1620 				(caddr_t)&ipo->ipo_mask, rnh,
1621 				ipo->ipo_nodes, 0)) == NULL) {
1622 				/* Remove from linked list of policies on TDB */
1623 				if (ipo->ipo_tdb)
1624 					TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head,
1625 					    ipo, ipo_tdb_next);
1626 
1627 				if (ipo->ipo_ids)
1628 					ipsp_ids_free(ipo->ipo_ids);
1629 				pool_put(&ipsec_policy_pool, ipo);
1630 
1631 				splx(s);
1632 				goto ret;
1633 			}
1634 			TAILQ_INSERT_HEAD(&ipsec_policy_head, ipo, ipo_list);
1635 			ipsec_in_use++;
1636 		} else {
1637 			ipo->ipo_last_searched = ipo->ipo_flags = 0;
1638 		}
1639 
1640 		splx(s);
1641 	}
1642 	break;
1643 
1644 	case SADB_X_PROMISC:
1645 		if (len >= 2 * sizeof(struct sadb_msg)) {
1646 			struct mbuf *packet;
1647 
1648 			if ((rval = pfdatatopacket(message, len, &packet)) != 0)
1649 				goto ret;
1650 
1651 			for (so = pfkeyv2_sockets; so; so = so->next)
1652 				if ((so != pfkeyv2_socket) &&
1653 				    (so->rdomain == rdomain) &&
1654 				    (!smsg->sadb_msg_seq ||
1655 				    (smsg->sadb_msg_seq == pfkeyv2_socket->pid)))
1656 					pfkey_sendup(so->socket, packet, 1);
1657 
1658 			m_freem(packet);
1659 		} else {
1660 			if (len != sizeof(struct sadb_msg)) {
1661 				rval = EINVAL;
1662 				goto ret;
1663 			}
1664 
1665 			i = (pfkeyv2_socket->flags &
1666 			    PFKEYV2_SOCKETFLAGS_PROMISC) ? 1 : 0;
1667 			j = smsg->sadb_msg_satype ? 1 : 0;
1668 
1669 			if (i ^ j) {
1670 				if (j) {
1671 					pfkeyv2_socket->flags |=
1672 					    PFKEYV2_SOCKETFLAGS_PROMISC;
1673 					npromisc++;
1674 				} else {
1675 					pfkeyv2_socket->flags &=
1676 					    ~PFKEYV2_SOCKETFLAGS_PROMISC;
1677 					npromisc--;
1678 				}
1679 			}
1680 		}
1681 
1682 
1683 		break;
1684 
1685 	default:
1686 		rval = EINVAL;
1687 		goto ret;
1688 	}
1689 
1690 ret:
1691 	if (rval) {
1692 		if ((rval == EINVAL) || (rval == ENOMEM) || (rval == ENOBUFS))
1693 			goto realret;
1694 
1695 		for (i = 1; i <= SADB_EXT_MAX; i++)
1696 			headers[i] = NULL;
1697 
1698 		smsg->sadb_msg_errno = abs(rval);
1699 	} else {
1700 		uint64_t seen = 0LL;
1701 
1702 		for (i = 1; i <= SADB_EXT_MAX; i++)
1703 			if (headers[i])
1704 				seen |= (1LL << i);
1705 
1706 		if ((seen & sadb_exts_allowed_out[smsg->sadb_msg_type])
1707 		    != seen)
1708 			goto realret;
1709 
1710 		if ((seen & sadb_exts_required_out[smsg->sadb_msg_type]) !=
1711 		    sadb_exts_required_out[smsg->sadb_msg_type])
1712 			goto realret;
1713 	}
1714 
1715 	rval = pfkeyv2_sendmessage(headers, mode, socket, 0, 0, rdomain);
1716 
1717 realret:
1718 	if (freeme)
1719 		free(freeme, M_PFKEY, 0);
1720 
1721 	explicit_bzero(message, len);
1722 	free(message, M_PFKEY, 0);
1723 
1724 	if (sa1)
1725 		free(sa1, M_PFKEY, 0);
1726 
1727 	return (rval);
1728 
1729 splxret:
1730 	splx(s);
1731 	goto ret;
1732 }
1733 
1734 /*
1735  * Send an ACQUIRE message to key management, to get a new SA.
1736  */
1737 int
1738 pfkeyv2_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw,
1739     union sockaddr_union *laddr, u_int32_t *seq, struct sockaddr_encap *ddst)
1740 {
1741 	void *p, *headers[SADB_EXT_MAX + 1], *buffer = NULL;
1742 	struct sadb_comb *sadb_comb;
1743 	struct sadb_address *sadd;
1744 	struct sadb_prop *sa_prop;
1745 	struct sadb_msg *smsg;
1746 	int rval = 0;
1747 	int i, j;
1748 
1749 	*seq = pfkeyv2_seq++;
1750 
1751 	if (!nregistered) {
1752 		rval = ESRCH;
1753 		goto ret;
1754 	}
1755 
1756 	/* How large a buffer do we need... XXX we only do one proposal for now */
1757 	i = sizeof(struct sadb_msg) +
1758 	    (laddr == NULL ? 0 : sizeof(struct sadb_address) +
1759 		PADUP(SA_LEN(&ipo->ipo_src.sa))) +
1760 	    sizeof(struct sadb_address) + PADUP(SA_LEN(&gw->sa)) +
1761 	    sizeof(struct sadb_prop) + 1 * sizeof(struct sadb_comb);
1762 
1763 	if (ipo->ipo_ids) {
1764 		i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_ids->id_local->len);
1765 		i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_ids->id_remote->len);
1766 	}
1767 
1768 	/* Allocate */
1769 	if (!(p = malloc(i, M_PFKEY, M_NOWAIT | M_ZERO))) {
1770 		rval = ENOMEM;
1771 		goto ret;
1772 	}
1773 
1774 	bzero(headers, sizeof(headers));
1775 
1776 	buffer = p;
1777 
1778 	headers[0] = p;
1779 	p += sizeof(struct sadb_msg);
1780 
1781 	smsg = (struct sadb_msg *) headers[0];
1782 	smsg->sadb_msg_version = PF_KEY_V2;
1783 	smsg->sadb_msg_type = SADB_ACQUIRE;
1784 	smsg->sadb_msg_len = i / sizeof(uint64_t);
1785 	smsg->sadb_msg_seq = *seq;
1786 
1787 	if (ipo->ipo_sproto == IPPROTO_ESP)
1788 		smsg->sadb_msg_satype = SADB_SATYPE_ESP;
1789 	else if (ipo->ipo_sproto == IPPROTO_AH)
1790 		smsg->sadb_msg_satype = SADB_SATYPE_AH;
1791 	else if (ipo->ipo_sproto == IPPROTO_IPCOMP)
1792 		smsg->sadb_msg_satype = SADB_X_SATYPE_IPCOMP;
1793 
1794 	if (laddr) {
1795 		headers[SADB_EXT_ADDRESS_SRC] = p;
1796 		p += sizeof(struct sadb_address) + PADUP(SA_LEN(&laddr->sa));
1797 		sadd = (struct sadb_address *) headers[SADB_EXT_ADDRESS_SRC];
1798 		sadd->sadb_address_len = (sizeof(struct sadb_address) +
1799 		    SA_LEN(&laddr->sa) + sizeof(uint64_t) - 1) /
1800 		    sizeof(uint64_t);
1801 		bcopy(laddr, headers[SADB_EXT_ADDRESS_SRC] +
1802 		    sizeof(struct sadb_address), SA_LEN(&laddr->sa));
1803 	}
1804 
1805 	headers[SADB_EXT_ADDRESS_DST] = p;
1806 	p += sizeof(struct sadb_address) + PADUP(SA_LEN(&gw->sa));
1807 	sadd = (struct sadb_address *) headers[SADB_EXT_ADDRESS_DST];
1808 	sadd->sadb_address_len = (sizeof(struct sadb_address) +
1809 	    SA_LEN(&gw->sa) + sizeof(uint64_t) - 1) / sizeof(uint64_t);
1810 	bcopy(gw, headers[SADB_EXT_ADDRESS_DST] + sizeof(struct sadb_address),
1811 	    SA_LEN(&gw->sa));
1812 
1813 	if (ipo->ipo_ids)
1814 		export_identities(&p, ipo->ipo_ids, 0, headers);
1815 
1816 	headers[SADB_EXT_PROPOSAL] = p;
1817 	p += sizeof(struct sadb_prop);
1818 	sa_prop = (struct sadb_prop *) headers[SADB_EXT_PROPOSAL];
1819 	sa_prop->sadb_prop_num = 1; /* XXX One proposal only */
1820 	sa_prop->sadb_prop_len = (sizeof(struct sadb_prop) +
1821 	    (sizeof(struct sadb_comb) * sa_prop->sadb_prop_num)) /
1822 	    sizeof(uint64_t);
1823 
1824 	sadb_comb = p;
1825 
1826 	/* XXX Should actually ask the crypto layer what's supported */
1827 	for (j = 0; j < sa_prop->sadb_prop_num; j++) {
1828 		sadb_comb->sadb_comb_flags = 0;
1829 
1830 		if (ipsec_require_pfs)
1831 			sadb_comb->sadb_comb_flags |= SADB_SAFLAGS_PFS;
1832 
1833 		/* Set the encryption algorithm */
1834 		if (ipo->ipo_sproto == IPPROTO_ESP) {
1835 			if (!strncasecmp(ipsec_def_enc, "aes",
1836 			    sizeof("aes"))) {
1837 				sadb_comb->sadb_comb_encrypt = SADB_X_EALG_AES;
1838 				sadb_comb->sadb_comb_encrypt_minbits = 128;
1839 				sadb_comb->sadb_comb_encrypt_maxbits = 256;
1840 			} else if (!strncasecmp(ipsec_def_enc, "aesctr",
1841 			    sizeof("aesctr"))) {
1842 				sadb_comb->sadb_comb_encrypt = SADB_X_EALG_AESCTR;
1843 				sadb_comb->sadb_comb_encrypt_minbits = 128+32;
1844 				sadb_comb->sadb_comb_encrypt_maxbits = 256+32;
1845 			} else if (!strncasecmp(ipsec_def_enc, "3des",
1846 			    sizeof("3des"))) {
1847 				sadb_comb->sadb_comb_encrypt = SADB_EALG_3DESCBC;
1848 				sadb_comb->sadb_comb_encrypt_minbits = 192;
1849 				sadb_comb->sadb_comb_encrypt_maxbits = 192;
1850 			} else if (!strncasecmp(ipsec_def_enc, "blowfish",
1851 			    sizeof("blowfish"))) {
1852 				sadb_comb->sadb_comb_encrypt = SADB_X_EALG_BLF;
1853 				sadb_comb->sadb_comb_encrypt_minbits = 40;
1854 				sadb_comb->sadb_comb_encrypt_maxbits = BLF_MAXKEYLEN * 8;
1855 			} else if (!strncasecmp(ipsec_def_enc, "cast128",
1856 			    sizeof("cast128"))) {
1857 				sadb_comb->sadb_comb_encrypt = SADB_X_EALG_CAST;
1858 				sadb_comb->sadb_comb_encrypt_minbits = 40;
1859 				sadb_comb->sadb_comb_encrypt_maxbits = 128;
1860 			}
1861 		} else if (ipo->ipo_sproto == IPPROTO_IPCOMP) {
1862 			/* Set the compression algorithm */
1863 			if (!strncasecmp(ipsec_def_comp, "deflate",
1864 			    sizeof("deflate"))) {
1865 				sadb_comb->sadb_comb_encrypt = SADB_X_CALG_DEFLATE;
1866 				sadb_comb->sadb_comb_encrypt_minbits = 0;
1867 				sadb_comb->sadb_comb_encrypt_maxbits = 0;
1868 			} else if (!strncasecmp(ipsec_def_comp, "lzs",
1869 			    sizeof("lzs"))) {
1870 				sadb_comb->sadb_comb_encrypt = SADB_X_CALG_LZS;
1871 				sadb_comb->sadb_comb_encrypt_minbits = 0;
1872 				sadb_comb->sadb_comb_encrypt_maxbits = 0;
1873 			}
1874 		}
1875 
1876 		/* Set the authentication algorithm */
1877 		if (!strncasecmp(ipsec_def_auth, "hmac-sha1",
1878 		    sizeof("hmac-sha1"))) {
1879 			sadb_comb->sadb_comb_auth = SADB_AALG_SHA1HMAC;
1880 			sadb_comb->sadb_comb_auth_minbits = 160;
1881 			sadb_comb->sadb_comb_auth_maxbits = 160;
1882 		} else if (!strncasecmp(ipsec_def_auth, "hmac-ripemd160",
1883 		    sizeof("hmac_ripemd160"))) {
1884 			sadb_comb->sadb_comb_auth = SADB_X_AALG_RIPEMD160HMAC;
1885 			sadb_comb->sadb_comb_auth_minbits = 160;
1886 			sadb_comb->sadb_comb_auth_maxbits = 160;
1887 		} else if (!strncasecmp(ipsec_def_auth, "hmac-md5",
1888 		    sizeof("hmac-md5"))) {
1889 			sadb_comb->sadb_comb_auth = SADB_AALG_MD5HMAC;
1890 			sadb_comb->sadb_comb_auth_minbits = 128;
1891 			sadb_comb->sadb_comb_auth_maxbits = 128;
1892 		} else if (!strncasecmp(ipsec_def_auth, "hmac-sha2-256",
1893 		    sizeof("hmac-sha2-256"))) {
1894 			sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA2_256;
1895 			sadb_comb->sadb_comb_auth_minbits = 256;
1896 			sadb_comb->sadb_comb_auth_maxbits = 256;
1897 		} else if (!strncasecmp(ipsec_def_auth, "hmac-sha2-384",
1898 		    sizeof("hmac-sha2-384"))) {
1899 			sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA2_384;
1900 			sadb_comb->sadb_comb_auth_minbits = 384;
1901 			sadb_comb->sadb_comb_auth_maxbits = 384;
1902 		} else if (!strncasecmp(ipsec_def_auth, "hmac-sha2-512",
1903 		    sizeof("hmac-sha2-512"))) {
1904 			sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA2_512;
1905 			sadb_comb->sadb_comb_auth_minbits = 512;
1906 			sadb_comb->sadb_comb_auth_maxbits = 512;
1907 		}
1908 
1909 		sadb_comb->sadb_comb_soft_allocations = ipsec_soft_allocations;
1910 		sadb_comb->sadb_comb_hard_allocations = ipsec_exp_allocations;
1911 
1912 		sadb_comb->sadb_comb_soft_bytes = ipsec_soft_bytes;
1913 		sadb_comb->sadb_comb_hard_bytes = ipsec_exp_bytes;
1914 
1915 		sadb_comb->sadb_comb_soft_addtime = ipsec_soft_timeout;
1916 		sadb_comb->sadb_comb_hard_addtime = ipsec_exp_timeout;
1917 
1918 		sadb_comb->sadb_comb_soft_usetime = ipsec_soft_first_use;
1919 		sadb_comb->sadb_comb_hard_usetime = ipsec_exp_first_use;
1920 		sadb_comb++;
1921 	}
1922 
1923 	/* Send the ACQUIRE message to all compliant registered listeners. */
1924 	if ((rval = pfkeyv2_sendmessage(headers,
1925 	    PFKEYV2_SENDMESSAGE_REGISTERED, NULL, smsg->sadb_msg_satype, 0,
1926 	    ipo->ipo_rdomain)) != 0)
1927 		goto ret;
1928 
1929 	rval = 0;
1930 ret:
1931 	if (buffer != NULL) {
1932 		bzero(buffer, i);
1933 		free(buffer, M_PFKEY, 0);
1934 	}
1935 
1936 	return (rval);
1937 }
1938 
1939 /*
1940  * Notify key management that an expiration went off. The second argument
1941  * specifies the type of expiration (soft or hard).
1942  */
1943 int
1944 pfkeyv2_expire(struct tdb *sa, u_int16_t type)
1945 {
1946 	void *p, *headers[SADB_EXT_MAX+1], *buffer = NULL;
1947 	struct sadb_msg *smsg;
1948 	int rval = 0;
1949 	int i;
1950 
1951 	switch (sa->tdb_sproto) {
1952 	case IPPROTO_AH:
1953 	case IPPROTO_ESP:
1954 	case IPPROTO_IPIP:
1955 	case IPPROTO_IPCOMP:
1956 #ifdef TCP_SIGNATURE
1957 	case IPPROTO_TCP:
1958 #endif /* TCP_SIGNATURE */
1959 		break;
1960 
1961 	default:
1962 		rval = EOPNOTSUPP;
1963 		goto ret;
1964 	}
1965 
1966 	i = sizeof(struct sadb_msg) + sizeof(struct sadb_sa) +
1967 	    2 * sizeof(struct sadb_lifetime) +
1968 	    sizeof(struct sadb_address) + PADUP(SA_LEN(&sa->tdb_src.sa)) +
1969 	    sizeof(struct sadb_address) + PADUP(SA_LEN(&sa->tdb_dst.sa));
1970 
1971 	if (!(p = malloc(i, M_PFKEY, M_NOWAIT | M_ZERO))) {
1972 		rval = ENOMEM;
1973 		goto ret;
1974 	}
1975 
1976 	bzero(headers, sizeof(headers));
1977 
1978 	buffer = p;
1979 
1980 	headers[0] = p;
1981 	p += sizeof(struct sadb_msg);
1982 
1983 	smsg = (struct sadb_msg *) headers[0];
1984 	smsg->sadb_msg_version = PF_KEY_V2;
1985 	smsg->sadb_msg_type = SADB_EXPIRE;
1986 	smsg->sadb_msg_satype = sa->tdb_satype;
1987 	smsg->sadb_msg_len = i / sizeof(uint64_t);
1988 	smsg->sadb_msg_seq = pfkeyv2_seq++;
1989 
1990 	headers[SADB_EXT_SA] = p;
1991 	export_sa(&p, sa);
1992 
1993 	headers[SADB_EXT_LIFETIME_CURRENT] = p;
1994 	export_lifetime(&p, sa, 2);
1995 
1996 	headers[type] = p;
1997 	export_lifetime(&p, sa, type == SADB_EXT_LIFETIME_SOFT ?
1998 	    PFKEYV2_LIFETIME_SOFT : PFKEYV2_LIFETIME_HARD);
1999 
2000 	headers[SADB_EXT_ADDRESS_SRC] = p;
2001 	export_address(&p, (struct sockaddr *) &sa->tdb_src);
2002 
2003 	headers[SADB_EXT_ADDRESS_DST] = p;
2004 	export_address(&p, (struct sockaddr *) &sa->tdb_dst);
2005 
2006 	if ((rval = pfkeyv2_sendmessage(headers, PFKEYV2_SENDMESSAGE_BROADCAST,
2007 	    NULL, 0, 0, sa->tdb_rdomain)) != 0)
2008 		goto ret;
2009 
2010 	rval = 0;
2011 
2012  ret:
2013 	if (buffer != NULL) {
2014 		bzero(buffer, i);
2015 		free(buffer, M_PFKEY, 0);
2016 	}
2017 
2018 	return (rval);
2019 }
2020 
2021 struct pfkeyv2_sysctl_walk {
2022 	void		*w_where;
2023 	size_t		 w_len;
2024 	int		 w_op;
2025 	u_int8_t	 w_satype;
2026 };
2027 
2028 int
2029 pfkeyv2_sysctl_walker(struct tdb *sa, void *arg, int last)
2030 {
2031 	struct pfkeyv2_sysctl_walk *w = (struct pfkeyv2_sysctl_walk *)arg;
2032 	void *buffer = NULL;
2033 	int error = 0;
2034 	int buflen, i;
2035 
2036 	if (w->w_satype != SADB_SATYPE_UNSPEC &&
2037 	    w->w_satype != sa->tdb_satype)
2038 		return (0);
2039 
2040 	if (w->w_where) {
2041 		void *headers[SADB_EXT_MAX+1];
2042 		struct sadb_msg msg;
2043 
2044 		bzero(headers, sizeof(headers));
2045 		if ((error = pfkeyv2_get(sa, headers, &buffer, &buflen)) != 0)
2046 			goto done;
2047 		if (w->w_len < sizeof(msg) + buflen) {
2048 			error = ENOMEM;
2049 			goto done;
2050 		}
2051 		/* prepend header */
2052 		bzero(&msg, sizeof(msg));
2053 		msg.sadb_msg_version = PF_KEY_V2;
2054 		msg.sadb_msg_satype = sa->tdb_satype;
2055 		msg.sadb_msg_type = SADB_DUMP;
2056 		msg.sadb_msg_len = (sizeof(msg) + buflen) / sizeof(uint64_t);
2057 		if ((error = copyout(&msg, w->w_where, sizeof(msg))) != 0)
2058 			goto done;
2059 		w->w_where += sizeof(msg);
2060 		w->w_len -= sizeof(msg);
2061 		/* set extension type */
2062 		for (i = 1; i <= SADB_EXT_MAX; i++)
2063 			if (headers[i])
2064 				((struct sadb_ext *)
2065 				    headers[i])->sadb_ext_type = i;
2066 		if ((error = copyout(buffer, w->w_where, buflen)) != 0)
2067 			goto done;
2068 		w->w_where += buflen;
2069 		w->w_len -= buflen;
2070 	} else {
2071 		if ((error = pfkeyv2_get(sa, NULL, NULL, &buflen)) != 0)
2072 			return (error);
2073 		w->w_len += buflen;
2074 		w->w_len += sizeof(struct sadb_msg);
2075 	}
2076 
2077 done:
2078 	if (buffer)
2079 		free(buffer, M_PFKEY, 0);
2080 	return (error);
2081 }
2082 
2083 int
2084 pfkeyv2_dump_policy(struct ipsec_policy *ipo, void **headers, void **buffer,
2085     int *lenp)
2086 {
2087 	int i, rval, perm;
2088 	void *p;
2089 
2090 	/* Find how much space we need. */
2091 	i = 2 * sizeof(struct sadb_protocol);
2092 
2093 	/* We'll need four of them: src, src mask, dst, dst mask. */
2094 	switch (ipo->ipo_addr.sen_type) {
2095 	case SENT_IP4:
2096 		i += 4 * PADUP(sizeof(struct sockaddr_in));
2097 		i += 4 * sizeof(struct sadb_address);
2098 		break;
2099 #ifdef INET6
2100 	case SENT_IP6:
2101 		i += 4 * PADUP(sizeof(struct sockaddr_in6));
2102 		i += 4 * sizeof(struct sadb_address);
2103 		break;
2104 #endif /* INET6 */
2105 	default:
2106 		return (EINVAL);
2107 	}
2108 
2109 	/* Local address, might be zeroed. */
2110 	switch (ipo->ipo_src.sa.sa_family) {
2111 	case 0:
2112 		break;
2113 	case AF_INET:
2114 		i += PADUP(sizeof(struct sockaddr_in));
2115 		i += sizeof(struct sadb_address);
2116 		break;
2117 #ifdef INET6
2118 	case AF_INET6:
2119 		i += PADUP(sizeof(struct sockaddr_in6));
2120 		i += sizeof(struct sadb_address);
2121 		break;
2122 #endif /* INET6 */
2123 	default:
2124 		return (EINVAL);
2125 	}
2126 
2127 	/* Remote address, might be zeroed. XXX ??? */
2128 	switch (ipo->ipo_dst.sa.sa_family) {
2129 	case 0:
2130 		break;
2131 	case AF_INET:
2132 		i += PADUP(sizeof(struct sockaddr_in));
2133 		i += sizeof(struct sadb_address);
2134 		break;
2135 #ifdef INET6
2136 	case AF_INET6:
2137 		i += PADUP(sizeof(struct sockaddr_in6));
2138 		i += sizeof(struct sadb_address);
2139 		break;
2140 #endif /* INET6 */
2141 	default:
2142 		return (EINVAL);
2143 	}
2144 
2145 	if (ipo->ipo_ids) {
2146 		i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_ids->id_local->len);
2147 		i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_ids->id_remote->len);
2148 	}
2149 
2150 	if (lenp)
2151 		*lenp = i;
2152 
2153 	if (buffer == NULL) {
2154 		rval = 0;
2155 		goto ret;
2156 	}
2157 
2158 	if (!(p = malloc(i, M_PFKEY, M_NOWAIT | M_ZERO))) {
2159 		rval = ENOMEM;
2160 		goto ret;
2161 	} else
2162 		*buffer = p;
2163 
2164 	/* Local address. */
2165 	if (ipo->ipo_src.sa.sa_family) {
2166 		headers[SADB_EXT_ADDRESS_SRC] = p;
2167 		export_address(&p, (struct sockaddr *)&ipo->ipo_src);
2168 	}
2169 
2170 	/* Remote address. */
2171 	if (ipo->ipo_dst.sa.sa_family) {
2172 		headers[SADB_EXT_ADDRESS_DST] = p;
2173 		export_address(&p, (struct sockaddr *)&ipo->ipo_dst);
2174 	}
2175 
2176 	/* Get actual flow. */
2177 	export_flow(&p, ipo->ipo_type, &ipo->ipo_addr, &ipo->ipo_mask,
2178 	    headers);
2179 
2180 	/* Add ids only when we are root. */
2181 	perm = suser(curproc, 0);
2182 	if (perm == 0 && ipo->ipo_ids)
2183 		export_identities(&p, ipo->ipo_ids, 0, headers);
2184 
2185 	rval = 0;
2186 ret:
2187 	return (rval);
2188 }
2189 
2190 /*
2191  * Caller is responsible for setting at least splsoftnet().
2192  */
2193 int
2194 pfkeyv2_ipo_walk(u_int rdomain, int (*walker)(struct ipsec_policy *, void *),
2195     void *arg)
2196 {
2197 	int rval = 0;
2198 	struct ipsec_policy *ipo;
2199 
2200 	TAILQ_FOREACH(ipo, &ipsec_policy_head, ipo_list) {
2201 		if (ipo->ipo_rdomain != rdomain)
2202 			continue;
2203 		rval = walker(ipo, (void *)arg);
2204 	}
2205 	return (rval);
2206 }
2207 
2208 int
2209 pfkeyv2_sysctl_policydumper(struct ipsec_policy *ipo, void *arg)
2210 {
2211 	struct pfkeyv2_sysctl_walk *w = (struct pfkeyv2_sysctl_walk *)arg;
2212 	void *buffer = 0;
2213 	int i, buflen, error = 0;
2214 
2215 	if (w->w_where) {
2216 		void *headers[SADB_EXT_MAX + 1];
2217 		struct sadb_msg msg;
2218 
2219 		bzero(headers, sizeof(headers));
2220 		if ((error = pfkeyv2_dump_policy(ipo, headers, &buffer,
2221 		    &buflen)) != 0)
2222 			goto done;
2223 		if (w->w_len < buflen) {
2224 			error = ENOMEM;
2225 			goto done;
2226 		}
2227 		/* prepend header */
2228 		bzero(&msg, sizeof(msg));
2229 		msg.sadb_msg_version = PF_KEY_V2;
2230 		if (ipo->ipo_sproto == IPPROTO_ESP)
2231 			msg.sadb_msg_satype = SADB_SATYPE_ESP;
2232 		else if (ipo->ipo_sproto == IPPROTO_AH)
2233 			msg.sadb_msg_satype = SADB_SATYPE_AH;
2234 		else if (ipo->ipo_sproto == IPPROTO_IPCOMP)
2235 			msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP;
2236 		else if (ipo->ipo_sproto == IPPROTO_IPIP)
2237 			msg.sadb_msg_satype = SADB_X_SATYPE_IPIP;
2238 		msg.sadb_msg_type = SADB_X_SPDDUMP;
2239 		msg.sadb_msg_len = (sizeof(msg) + buflen) / sizeof(uint64_t);
2240 		if ((error = copyout(&msg, w->w_where, sizeof(msg))) != 0)
2241 			goto done;
2242 		w->w_where += sizeof(msg);
2243 		w->w_len -= sizeof(msg);
2244 		/* set extension type */
2245 		for (i = 1; i < SADB_EXT_MAX; i++)
2246 			if (headers[i])
2247 				((struct sadb_ext *)
2248 				    headers[i])->sadb_ext_type = i;
2249 		if ((error = copyout(buffer, w->w_where, buflen)) != 0)
2250 			goto done;
2251 		w->w_where += buflen;
2252 		w->w_len -= buflen;
2253 	} else {
2254 		if ((error = pfkeyv2_dump_policy(ipo, NULL, NULL,
2255 		    &buflen)) != 0)
2256 			goto done;
2257 		w->w_len += buflen;
2258 		w->w_len += sizeof(struct sadb_msg);
2259 	}
2260 
2261 done:
2262 	if (buffer)
2263 		free(buffer, M_PFKEY, 0);
2264 	return (error);
2265 }
2266 
2267 int
2268 pfkeyv2_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
2269     void *new, size_t newlen)
2270 {
2271 	struct pfkeyv2_sysctl_walk w;
2272 	int s, error = EINVAL;
2273 	u_int rdomain;
2274 
2275 	if (new)
2276 		return (EPERM);
2277 	if (namelen < 1)
2278 		return (EINVAL);
2279 	w.w_op = name[0];
2280 	w.w_satype = name[1];
2281 	w.w_where = oldp;
2282 	w.w_len = oldp ? *oldlenp : 0;
2283 
2284 	rdomain = rtable_l2(curproc->p_p->ps_rtableid);
2285 
2286 	switch(w.w_op) {
2287 	case NET_KEY_SADB_DUMP:
2288 		if ((error = suser(curproc, 0)) != 0)
2289 			return (error);
2290 		s = splsoftnet();
2291 		error = tdb_walk(rdomain, pfkeyv2_sysctl_walker, &w);
2292 		splx(s);
2293 		if (oldp)
2294 			*oldlenp = w.w_where - oldp;
2295 		else
2296 			*oldlenp = w.w_len;
2297 		break;
2298 
2299 	case NET_KEY_SPD_DUMP:
2300 		s = splsoftnet();
2301 		error = pfkeyv2_ipo_walk(rdomain,
2302 		    pfkeyv2_sysctl_policydumper, &w);
2303 		splx(s);
2304 		if (oldp)
2305 			*oldlenp = w.w_where - oldp;
2306 		else
2307 			*oldlenp = w.w_len;
2308 		break;
2309 	}
2310 
2311 	return (error);
2312 }
2313 
2314 int
2315 pfkeyv2_init(void)
2316 {
2317 	int rval;
2318 
2319 	bzero(&pfkeyv2_version, sizeof(struct pfkey_version));
2320 	pfkeyv2_version.protocol = PFKEYV2_PROTOCOL;
2321 	pfkeyv2_version.create = &pfkeyv2_create;
2322 	pfkeyv2_version.release = &pfkeyv2_release;
2323 	pfkeyv2_version.send = &pfkeyv2_send;
2324 	pfkeyv2_version.sysctl = &pfkeyv2_sysctl;
2325 
2326 	rval = pfkey_register(&pfkeyv2_version);
2327 	return (rval);
2328 }
2329 
2330 int
2331 pfkeyv2_cleanup(void)
2332 {
2333 	pfkey_unregister(&pfkeyv2_version);
2334 	return (0);
2335 }
2336