xref: /freebsd/lib/libipsec/pfkey.c (revision eb69d1f144a6fcc765d1b9d44a5ae8082353e70b)
1 /*	$KAME: pfkey.c,v 1.46 2003/08/26 03:37:06 itojun Exp $	*/
2 
3 /*-
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the project nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36 
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/socket.h>
40 #include <net/pfkeyv2.h>
41 #include <netipsec/key_var.h>
42 #include <netinet/in.h>
43 #include <netipsec/ipsec.h>
44 
45 #include <stdlib.h>
46 #include <stdint.h>
47 #include <unistd.h>
48 #include <string.h>
49 #include <errno.h>
50 
51 #include "ipsec_strerror.h"
52 #include "libpfkey.h"
53 
54 #define CALLOC(size, cast) (cast)calloc(1, (size))
55 
56 static int findsupportedmap(int);
57 static int setsupportedmap(struct sadb_supported *);
58 static struct sadb_alg *findsupportedalg(u_int, u_int);
59 static int pfkey_send_x1(int, u_int, u_int, u_int, struct sockaddr *,
60 	struct sockaddr *, u_int32_t, u_int32_t, u_int, caddr_t,
61 	u_int, u_int, u_int, u_int, u_int, u_int32_t, u_int32_t,
62 	u_int32_t, u_int32_t, u_int32_t);
63 static int pfkey_send_x2(int, u_int, u_int, u_int,
64 	struct sockaddr *, struct sockaddr *, u_int32_t);
65 static int pfkey_send_x3(int, u_int, u_int);
66 static int pfkey_send_x4(int, u_int, struct sockaddr *, u_int,
67 	struct sockaddr *, u_int, u_int, u_int64_t, u_int64_t,
68 	char *, int, u_int32_t);
69 static int pfkey_send_x5(int, u_int, u_int32_t);
70 
71 static caddr_t pfkey_setsadbmsg(caddr_t, caddr_t, u_int, u_int,
72 	u_int, u_int32_t, pid_t);
73 static caddr_t pfkey_setsadbsa(caddr_t, caddr_t, u_int32_t, u_int,
74 	u_int, u_int, u_int32_t);
75 static caddr_t pfkey_setsadbxreplay(caddr_t, caddr_t, uint32_t);
76 static caddr_t pfkey_setsadbaddr(caddr_t, caddr_t, u_int,
77 	struct sockaddr *, u_int, u_int);
78 static caddr_t pfkey_setsadbkey(caddr_t, caddr_t, u_int, caddr_t, u_int);
79 static caddr_t pfkey_setsadblifetime(caddr_t, caddr_t, u_int, u_int32_t,
80 	u_int32_t, u_int32_t, u_int32_t);
81 static caddr_t pfkey_setsadbxsa2(caddr_t, caddr_t, u_int32_t, u_int32_t);
82 
83 /*
84  * make and search supported algorithm structure.
85  */
86 static struct sadb_supported *ipsec_supported[] = { NULL, NULL, NULL, NULL };
87 
88 static int supported_map[] = {
89 	SADB_SATYPE_AH,
90 	SADB_SATYPE_ESP,
91 	SADB_X_SATYPE_IPCOMP,
92 	SADB_X_SATYPE_TCPSIGNATURE
93 };
94 
95 static int
96 findsupportedmap(satype)
97 	int satype;
98 {
99 	int i;
100 
101 	for (i = 0; i < sizeof(supported_map)/sizeof(supported_map[0]); i++)
102 		if (supported_map[i] == satype)
103 			return i;
104 	return -1;
105 }
106 
107 static struct sadb_alg *
108 findsupportedalg(satype, alg_id)
109 	u_int satype, alg_id;
110 {
111 	int algno;
112 	int tlen;
113 	caddr_t p;
114 
115 	/* validity check */
116 	algno = findsupportedmap(satype);
117 	if (algno == -1) {
118 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
119 		return NULL;
120 	}
121 	if (ipsec_supported[algno] == NULL) {
122 		__ipsec_errcode = EIPSEC_DO_GET_SUPP_LIST;
123 		return NULL;
124 	}
125 
126 	tlen = ipsec_supported[algno]->sadb_supported_len
127 		- sizeof(struct sadb_supported);
128 	p = (caddr_t)(ipsec_supported[algno] + 1);
129 	while (tlen > 0) {
130 		if (tlen < sizeof(struct sadb_alg)) {
131 			/* invalid format */
132 			break;
133 		}
134 		if (((struct sadb_alg *)p)->sadb_alg_id == alg_id)
135 			return (struct sadb_alg *)p;
136 
137 		tlen -= sizeof(struct sadb_alg);
138 		p += sizeof(struct sadb_alg);
139 	}
140 
141 	__ipsec_errcode = EIPSEC_NOT_SUPPORTED;
142 	return NULL;
143 }
144 
145 static int
146 setsupportedmap(sup)
147 	struct sadb_supported *sup;
148 {
149 	struct sadb_supported **ipsup;
150 
151 	switch (sup->sadb_supported_exttype) {
152 	case SADB_EXT_SUPPORTED_AUTH:
153 		ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_AH)];
154 		break;
155 	case SADB_EXT_SUPPORTED_ENCRYPT:
156 		ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_ESP)];
157 		break;
158 	default:
159 		__ipsec_errcode = EIPSEC_INVAL_SATYPE;
160 		return -1;
161 	}
162 
163 	if (*ipsup)
164 		free(*ipsup);
165 
166 	*ipsup = malloc(sup->sadb_supported_len);
167 	if (!*ipsup) {
168 		__ipsec_set_strerror(strerror(errno));
169 		return -1;
170 	}
171 	memcpy(*ipsup, sup, sup->sadb_supported_len);
172 
173 	return 0;
174 }
175 
176 /*
177  * check key length against algorithm specified.
178  * This function is called with SADB_EXT_SUPPORTED_{AUTH,ENCRYPT} as the
179  * augument, and only calls to ipsec_check_keylen2();
180  * keylen is the unit of bit.
181  * OUT:
182  *	-1: invalid.
183  *	 0: valid.
184  */
185 int
186 ipsec_check_keylen(supported, alg_id, keylen)
187 	u_int supported;
188 	u_int alg_id;
189 	u_int keylen;
190 {
191 	int satype;
192 
193 	/* validity check */
194 	switch (supported) {
195 	case SADB_EXT_SUPPORTED_AUTH:
196 		satype = SADB_SATYPE_AH;
197 		break;
198 	case SADB_EXT_SUPPORTED_ENCRYPT:
199 		satype = SADB_SATYPE_ESP;
200 		break;
201 	default:
202 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
203 		return -1;
204 	}
205 
206 	return ipsec_check_keylen2(satype, alg_id, keylen);
207 }
208 
209 /*
210  * check key length against algorithm specified.
211  * satype is one of satype defined at pfkeyv2.h.
212  * keylen is the unit of bit.
213  * OUT:
214  *	-1: invalid.
215  *	 0: valid.
216  */
217 int
218 ipsec_check_keylen2(satype, alg_id, keylen)
219 	u_int satype;
220 	u_int alg_id;
221 	u_int keylen;
222 {
223 	struct sadb_alg *alg;
224 
225 	alg = findsupportedalg(satype, alg_id);
226 	if (!alg)
227 		return -1;
228 
229 	if (keylen < alg->sadb_alg_minbits || keylen > alg->sadb_alg_maxbits) {
230 		__ipsec_errcode = EIPSEC_INVAL_KEYLEN;
231 		return -1;
232 	}
233 
234 	__ipsec_errcode = EIPSEC_NO_ERROR;
235 	return 0;
236 }
237 
238 /*
239  * get max/min key length against algorithm specified.
240  * satype is one of satype defined at pfkeyv2.h.
241  * keylen is the unit of bit.
242  * OUT:
243  *	-1: invalid.
244  *	 0: valid.
245  */
246 int
247 ipsec_get_keylen(supported, alg_id, alg0)
248 	u_int supported, alg_id;
249 	struct sadb_alg *alg0;
250 {
251 	struct sadb_alg *alg;
252 	u_int satype;
253 
254 	/* validity check */
255 	if (!alg0) {
256 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
257 		return -1;
258 	}
259 
260 	switch (supported) {
261 	case SADB_EXT_SUPPORTED_AUTH:
262 		satype = SADB_SATYPE_AH;
263 		break;
264 	case SADB_EXT_SUPPORTED_ENCRYPT:
265 		satype = SADB_SATYPE_ESP;
266 		break;
267 	default:
268 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
269 		return -1;
270 	}
271 
272 	alg = findsupportedalg(satype, alg_id);
273 	if (!alg)
274 		return -1;
275 
276 	memcpy(alg0, alg, sizeof(*alg0));
277 
278 	__ipsec_errcode = EIPSEC_NO_ERROR;
279 	return 0;
280 }
281 
282 /*
283  * set the rate for SOFT lifetime against HARD one.
284  * If rate is more than 100 or equal to zero, then set to 100.
285  */
286 static u_int soft_lifetime_allocations_rate = PFKEY_SOFT_LIFETIME_RATE;
287 static u_int soft_lifetime_bytes_rate = PFKEY_SOFT_LIFETIME_RATE;
288 static u_int soft_lifetime_addtime_rate = PFKEY_SOFT_LIFETIME_RATE;
289 static u_int soft_lifetime_usetime_rate = PFKEY_SOFT_LIFETIME_RATE;
290 
291 u_int
292 pfkey_set_softrate(type, rate)
293 	u_int type, rate;
294 {
295 	__ipsec_errcode = EIPSEC_NO_ERROR;
296 
297 	if (rate > 100 || rate == 0)
298 		rate = 100;
299 
300 	switch (type) {
301 	case SADB_X_LIFETIME_ALLOCATIONS:
302 		soft_lifetime_allocations_rate = rate;
303 		return 0;
304 	case SADB_X_LIFETIME_BYTES:
305 		soft_lifetime_bytes_rate = rate;
306 		return 0;
307 	case SADB_X_LIFETIME_ADDTIME:
308 		soft_lifetime_addtime_rate = rate;
309 		return 0;
310 	case SADB_X_LIFETIME_USETIME:
311 		soft_lifetime_usetime_rate = rate;
312 		return 0;
313 	}
314 
315 	__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
316 	return 1;
317 }
318 
319 /*
320  * get current rate for SOFT lifetime against HARD one.
321  * ATTENTION: ~0 is returned if invalid type was passed.
322  */
323 u_int
324 pfkey_get_softrate(type)
325 	u_int type;
326 {
327 	switch (type) {
328 	case SADB_X_LIFETIME_ALLOCATIONS:
329 		return soft_lifetime_allocations_rate;
330 	case SADB_X_LIFETIME_BYTES:
331 		return soft_lifetime_bytes_rate;
332 	case SADB_X_LIFETIME_ADDTIME:
333 		return soft_lifetime_addtime_rate;
334 	case SADB_X_LIFETIME_USETIME:
335 		return soft_lifetime_usetime_rate;
336 	}
337 
338 	return ~0;
339 }
340 
341 /*
342  * sending SADB_GETSPI message to the kernel.
343  * OUT:
344  *	positive: success and return length sent.
345  *	-1	: error occured, and set errno.
346  */
347 int
348 pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq)
349 	int so;
350 	u_int satype, mode;
351 	struct sockaddr *src, *dst;
352 	u_int32_t min, max, reqid, seq;
353 {
354 	struct sadb_msg *newmsg;
355 	caddr_t ep;
356 	int len;
357 	int need_spirange = 0;
358 	caddr_t p;
359 	int plen;
360 
361 	/* validity check */
362 	if (src == NULL || dst == NULL) {
363 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
364 		return -1;
365 	}
366 	if (src->sa_family != dst->sa_family) {
367 		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
368 		return -1;
369 	}
370 	if (min > max || (min > 0 && min <= 255)) {
371 		__ipsec_errcode = EIPSEC_INVAL_SPI;
372 		return -1;
373 	}
374 	switch (src->sa_family) {
375 	case AF_INET:
376 		plen = sizeof(struct in_addr) << 3;
377 		break;
378 	case AF_INET6:
379 		plen = sizeof(struct in6_addr) << 3;
380 		break;
381 	default:
382 		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
383 		return -1;
384 	}
385 
386 	/* create new sadb_msg to send. */
387 	len = sizeof(struct sadb_msg)
388 		+ sizeof(struct sadb_x_sa2)
389 		+ sizeof(struct sadb_address)
390 		+ PFKEY_ALIGN8(src->sa_len)
391 		+ sizeof(struct sadb_address)
392 		+ PFKEY_ALIGN8(dst->sa_len);
393 
394 	if (min > 255 && max < ~0) {
395 		need_spirange++;
396 		len += sizeof(struct sadb_spirange);
397 	}
398 
399 	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
400 		__ipsec_set_strerror(strerror(errno));
401 		return -1;
402 	}
403 	ep = ((caddr_t)newmsg) + len;
404 
405 	p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_GETSPI,
406 	    len, satype, seq, getpid());
407 	if (!p) {
408 		free(newmsg);
409 		return -1;
410 	}
411 
412 	p = pfkey_setsadbxsa2(p, ep, mode, reqid);
413 	if (!p) {
414 		free(newmsg);
415 		return -1;
416 	}
417 
418 	/* set sadb_address for source */
419 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen,
420 	    IPSEC_ULPROTO_ANY);
421 	if (!p) {
422 		free(newmsg);
423 		return -1;
424 	}
425 
426 	/* set sadb_address for destination */
427 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen,
428 	    IPSEC_ULPROTO_ANY);
429 	if (!p) {
430 		free(newmsg);
431 		return -1;
432 	}
433 
434 	/* proccessing spi range */
435 	if (need_spirange) {
436 		struct sadb_spirange spirange;
437 
438 		if (p + sizeof(spirange) > ep) {
439 			free(newmsg);
440 			return -1;
441 		}
442 
443 		memset(&spirange, 0, sizeof(spirange));
444 		spirange.sadb_spirange_len = PFKEY_UNIT64(sizeof(spirange));
445 		spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE;
446 		spirange.sadb_spirange_min = min;
447 		spirange.sadb_spirange_max = max;
448 
449 		memcpy(p, &spirange, sizeof(spirange));
450 
451 		p += sizeof(spirange);
452 	}
453 	if (p != ep) {
454 		free(newmsg);
455 		return -1;
456 	}
457 
458 	/* send message */
459 	len = pfkey_send(so, newmsg, len);
460 	free(newmsg);
461 
462 	if (len < 0)
463 		return -1;
464 
465 	__ipsec_errcode = EIPSEC_NO_ERROR;
466 	return len;
467 }
468 
469 /*
470  * sending SADB_UPDATE message to the kernel.
471  * The length of key material is a_keylen + e_keylen.
472  * OUT:
473  *	positive: success and return length sent.
474  *	-1	: error occured, and set errno.
475  */
476 int
477 pfkey_send_update(so, satype, mode, src, dst, spi, reqid, wsize,
478 		keymat, e_type, e_keylen, a_type, a_keylen, flags,
479 		l_alloc, l_bytes, l_addtime, l_usetime, seq)
480 	int so;
481 	u_int satype, mode, wsize;
482 	struct sockaddr *src, *dst;
483 	u_int32_t spi, reqid;
484 	caddr_t keymat;
485 	u_int e_type, e_keylen, a_type, a_keylen, flags;
486 	u_int32_t l_alloc;
487 	u_int64_t l_bytes, l_addtime, l_usetime;
488 	u_int32_t seq;
489 {
490 	int len;
491 	if ((len = pfkey_send_x1(so, SADB_UPDATE, satype, mode, src, dst, spi,
492 			reqid, wsize,
493 			keymat, e_type, e_keylen, a_type, a_keylen, flags,
494 			l_alloc, l_bytes, l_addtime, l_usetime, seq)) < 0)
495 		return -1;
496 
497 	return len;
498 }
499 
500 /*
501  * sending SADB_ADD message to the kernel.
502  * The length of key material is a_keylen + e_keylen.
503  * OUT:
504  *	positive: success and return length sent.
505  *	-1	: error occured, and set errno.
506  */
507 int
508 pfkey_send_add(so, satype, mode, src, dst, spi, reqid, wsize,
509 		keymat, e_type, e_keylen, a_type, a_keylen, flags,
510 		l_alloc, l_bytes, l_addtime, l_usetime, seq)
511 	int so;
512 	u_int satype, mode, wsize;
513 	struct sockaddr *src, *dst;
514 	u_int32_t spi, reqid;
515 	caddr_t keymat;
516 	u_int e_type, e_keylen, a_type, a_keylen, flags;
517 	u_int32_t l_alloc;
518 	u_int64_t l_bytes, l_addtime, l_usetime;
519 	u_int32_t seq;
520 {
521 	int len;
522 	if ((len = pfkey_send_x1(so, SADB_ADD, satype, mode, src, dst, spi,
523 			reqid, wsize,
524 			keymat, e_type, e_keylen, a_type, a_keylen, flags,
525 			l_alloc, l_bytes, l_addtime, l_usetime, seq)) < 0)
526 		return -1;
527 
528 	return len;
529 }
530 
531 /*
532  * sending SADB_DELETE message to the kernel.
533  * OUT:
534  *	positive: success and return length sent.
535  *	-1	: error occured, and set errno.
536  */
537 int
538 pfkey_send_delete(so, satype, mode, src, dst, spi)
539 	int so;
540 	u_int satype, mode;
541 	struct sockaddr *src, *dst;
542 	u_int32_t spi;
543 {
544 	int len;
545 	if ((len = pfkey_send_x2(so, SADB_DELETE, satype, mode, src, dst, spi)) < 0)
546 		return -1;
547 
548 	return len;
549 }
550 
551 /*
552  * sending SADB_DELETE without spi to the kernel.  This is
553  * the "delete all" request (an extension also present in
554  * Solaris).
555  *
556  * OUT:
557  *	positive: success and return length sent
558  *	-1	: error occured, and set errno
559  */
560 int
561 pfkey_send_delete_all(so, satype, mode, src, dst)
562 	int so;
563 	u_int satype, mode;
564 	struct sockaddr *src, *dst;
565 {
566 	struct sadb_msg *newmsg;
567 	int len;
568 	caddr_t p;
569 	int plen;
570 	caddr_t ep;
571 
572 	/* validity check */
573 	if (src == NULL || dst == NULL) {
574 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
575 		return -1;
576 	}
577 	if (src->sa_family != dst->sa_family) {
578 		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
579 		return -1;
580 	}
581 	switch (src->sa_family) {
582 	case AF_INET:
583 		plen = sizeof(struct in_addr) << 3;
584 		break;
585 	case AF_INET6:
586 		plen = sizeof(struct in6_addr) << 3;
587 		break;
588 	default:
589 		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
590 		return -1;
591 	}
592 
593 	/* create new sadb_msg to reply. */
594 	len = sizeof(struct sadb_msg)
595 		+ sizeof(struct sadb_address)
596 		+ PFKEY_ALIGN8(src->sa_len)
597 		+ sizeof(struct sadb_address)
598 		+ PFKEY_ALIGN8(dst->sa_len);
599 
600 	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
601 		__ipsec_set_strerror(strerror(errno));
602 		return -1;
603 	}
604 	ep = ((caddr_t)newmsg) + len;
605 
606 	p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_DELETE, len, satype, 0,
607 	    getpid());
608 	if (!p) {
609 		free(newmsg);
610 		return -1;
611 	}
612 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen,
613 	    IPSEC_ULPROTO_ANY);
614 	if (!p) {
615 		free(newmsg);
616 		return -1;
617 	}
618 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen,
619 	    IPSEC_ULPROTO_ANY);
620 	if (!p || p != ep) {
621 		free(newmsg);
622 		return -1;
623 	}
624 
625 	/* send message */
626 	len = pfkey_send(so, newmsg, len);
627 	free(newmsg);
628 
629 	if (len < 0)
630 		return -1;
631 
632 	__ipsec_errcode = EIPSEC_NO_ERROR;
633 	return len;
634 }
635 
636 /*
637  * sending SADB_GET message to the kernel.
638  * OUT:
639  *	positive: success and return length sent.
640  *	-1	: error occured, and set errno.
641  */
642 int
643 pfkey_send_get(so, satype, mode, src, dst, spi)
644 	int so;
645 	u_int satype, mode;
646 	struct sockaddr *src, *dst;
647 	u_int32_t spi;
648 {
649 	int len;
650 	if ((len = pfkey_send_x2(so, SADB_GET, satype, mode, src, dst, spi)) < 0)
651 		return -1;
652 
653 	return len;
654 }
655 
656 /*
657  * sending SADB_REGISTER message to the kernel.
658  * OUT:
659  *	positive: success and return length sent.
660  *	-1	: error occured, and set errno.
661  */
662 int
663 pfkey_send_register(so, satype)
664 	int so;
665 	u_int satype;
666 {
667 	int len, algno;
668 
669 	if (satype == SADB_SATYPE_UNSPEC) {
670 		for (algno = 0;
671 		     algno < sizeof(supported_map)/sizeof(supported_map[0]);
672 		     algno++) {
673 			if (ipsec_supported[algno]) {
674 				free(ipsec_supported[algno]);
675 				ipsec_supported[algno] = NULL;
676 			}
677 		}
678 	} else {
679 		algno = findsupportedmap(satype);
680 		if (algno == -1) {
681 			__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
682 			return -1;
683 		}
684 
685 		if (ipsec_supported[algno]) {
686 			free(ipsec_supported[algno]);
687 			ipsec_supported[algno] = NULL;
688 		}
689 	}
690 
691 	if ((len = pfkey_send_x3(so, SADB_REGISTER, satype)) < 0)
692 		return -1;
693 
694 	return len;
695 }
696 
697 /*
698  * receiving SADB_REGISTER message from the kernel, and copy buffer for
699  * sadb_supported returned into ipsec_supported.
700  * OUT:
701  *	 0: success and return length sent.
702  *	-1: error occured, and set errno.
703  */
704 int
705 pfkey_recv_register(so)
706 	int so;
707 {
708 	pid_t pid = getpid();
709 	struct sadb_msg *newmsg;
710 	int error = -1;
711 
712 	/* receive message */
713 	for (;;) {
714 		if ((newmsg = pfkey_recv(so)) == NULL)
715 			return -1;
716 		if (newmsg->sadb_msg_type == SADB_REGISTER &&
717 		    newmsg->sadb_msg_pid == pid)
718 			break;
719 		free(newmsg);
720 	}
721 
722 	/* check and fix */
723 	newmsg->sadb_msg_len = PFKEY_UNUNIT64(newmsg->sadb_msg_len);
724 
725 	error = pfkey_set_supported(newmsg, newmsg->sadb_msg_len);
726 	free(newmsg);
727 
728 	if (error == 0)
729 		__ipsec_errcode = EIPSEC_NO_ERROR;
730 
731 	return error;
732 }
733 
734 /*
735  * receiving SADB_REGISTER message from the kernel, and copy buffer for
736  * sadb_supported returned into ipsec_supported.
737  * NOTE: sadb_msg_len must be host order.
738  * IN:
739  *	tlen: msg length, it's to makeing sure.
740  * OUT:
741  *	 0: success and return length sent.
742  *	-1: error occured, and set errno.
743  */
744 int
745 pfkey_set_supported(msg, tlen)
746 	struct sadb_msg *msg;
747 	int tlen;
748 {
749 	struct sadb_supported *sup;
750 	caddr_t p;
751 	caddr_t ep;
752 
753 	/* validity */
754 	if (msg->sadb_msg_len != tlen) {
755 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
756 		return -1;
757 	}
758 
759 	p = (caddr_t)msg;
760 	ep = p + tlen;
761 
762 	p += sizeof(struct sadb_msg);
763 
764 	while (p < ep) {
765 		sup = (struct sadb_supported *)p;
766 		if (ep < p + sizeof(*sup) ||
767 		    PFKEY_EXTLEN(sup) < sizeof(*sup) ||
768 		    ep < p + sup->sadb_supported_len) {
769 			/* invalid format */
770 			break;
771 		}
772 
773 		switch (sup->sadb_supported_exttype) {
774 		case SADB_EXT_SUPPORTED_AUTH:
775 		case SADB_EXT_SUPPORTED_ENCRYPT:
776 			break;
777 		default:
778 			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
779 			return -1;
780 		}
781 
782 		/* fixed length */
783 		sup->sadb_supported_len = PFKEY_EXTLEN(sup);
784 
785 		/* set supported map */
786 		if (setsupportedmap(sup) != 0)
787 			return -1;
788 
789 		p += sup->sadb_supported_len;
790 	}
791 
792 	if (p != ep) {
793 		__ipsec_errcode = EIPSEC_INVAL_SATYPE;
794 		return -1;
795 	}
796 
797 	__ipsec_errcode = EIPSEC_NO_ERROR;
798 
799 	return 0;
800 }
801 
802 /*
803  * sending SADB_FLUSH message to the kernel.
804  * OUT:
805  *	positive: success and return length sent.
806  *	-1	: error occured, and set errno.
807  */
808 int
809 pfkey_send_flush(so, satype)
810 	int so;
811 	u_int satype;
812 {
813 	int len;
814 
815 	if ((len = pfkey_send_x3(so, SADB_FLUSH, satype)) < 0)
816 		return -1;
817 
818 	return len;
819 }
820 
821 /*
822  * sending SADB_DUMP message to the kernel.
823  * OUT:
824  *	positive: success and return length sent.
825  *	-1	: error occured, and set errno.
826  */
827 int
828 pfkey_send_dump(so, satype)
829 	int so;
830 	u_int satype;
831 {
832 	int len;
833 
834 	if ((len = pfkey_send_x3(so, SADB_DUMP, satype)) < 0)
835 		return -1;
836 
837 	return len;
838 }
839 
840 /*
841  * sending SADB_X_PROMISC message to the kernel.
842  * NOTE that this function handles promisc mode toggle only.
843  * IN:
844  *	flag:	set promisc off if zero, set promisc on if non-zero.
845  * OUT:
846  *	positive: success and return length sent.
847  *	-1	: error occured, and set errno.
848  *	0     : error occured, and set errno.
849  *	others: a pointer to new allocated buffer in which supported
850  *	        algorithms is.
851  */
852 int
853 pfkey_send_promisc_toggle(so, flag)
854 	int so;
855 	int flag;
856 {
857 	int len;
858 
859 	if ((len = pfkey_send_x3(so, SADB_X_PROMISC, (flag ? 1 : 0))) < 0)
860 		return -1;
861 
862 	return len;
863 }
864 
865 /*
866  * sending SADB_X_SPDADD message to the kernel.
867  * OUT:
868  *	positive: success and return length sent.
869  *	-1	: error occured, and set errno.
870  */
871 int
872 pfkey_send_spdadd(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
873 	int so;
874 	struct sockaddr *src, *dst;
875 	u_int prefs, prefd, proto;
876 	caddr_t policy;
877 	int policylen;
878 	u_int32_t seq;
879 {
880 	int len;
881 
882 	if ((len = pfkey_send_x4(so, SADB_X_SPDADD,
883 				src, prefs, dst, prefd, proto,
884 				0, 0,
885 				policy, policylen, seq)) < 0)
886 		return -1;
887 
888 	return len;
889 }
890 
891 /*
892  * sending SADB_X_SPDADD message to the kernel.
893  * OUT:
894  *	positive: success and return length sent.
895  *	-1	: error occured, and set errno.
896  */
897 int
898 pfkey_send_spdadd2(so, src, prefs, dst, prefd, proto, ltime, vtime,
899 		policy, policylen, seq)
900 	int so;
901 	struct sockaddr *src, *dst;
902 	u_int prefs, prefd, proto;
903 	u_int64_t ltime, vtime;
904 	caddr_t policy;
905 	int policylen;
906 	u_int32_t seq;
907 {
908 	int len;
909 
910 	if ((len = pfkey_send_x4(so, SADB_X_SPDADD,
911 				src, prefs, dst, prefd, proto,
912 				ltime, vtime,
913 				policy, policylen, seq)) < 0)
914 		return -1;
915 
916 	return len;
917 }
918 
919 /*
920  * sending SADB_X_SPDUPDATE message to the kernel.
921  * OUT:
922  *	positive: success and return length sent.
923  *	-1	: error occured, and set errno.
924  */
925 int
926 pfkey_send_spdupdate(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
927 	int so;
928 	struct sockaddr *src, *dst;
929 	u_int prefs, prefd, proto;
930 	caddr_t policy;
931 	int policylen;
932 	u_int32_t seq;
933 {
934 	int len;
935 
936 	if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE,
937 				src, prefs, dst, prefd, proto,
938 				0, 0,
939 				policy, policylen, seq)) < 0)
940 		return -1;
941 
942 	return len;
943 }
944 
945 /*
946  * sending SADB_X_SPDUPDATE message to the kernel.
947  * OUT:
948  *	positive: success and return length sent.
949  *	-1	: error occured, and set errno.
950  */
951 int
952 pfkey_send_spdupdate2(so, src, prefs, dst, prefd, proto, ltime, vtime,
953 		policy, policylen, seq)
954 	int so;
955 	struct sockaddr *src, *dst;
956 	u_int prefs, prefd, proto;
957 	u_int64_t ltime, vtime;
958 	caddr_t policy;
959 	int policylen;
960 	u_int32_t seq;
961 {
962 	int len;
963 
964 	if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE,
965 				src, prefs, dst, prefd, proto,
966 				ltime, vtime,
967 				policy, policylen, seq)) < 0)
968 		return -1;
969 
970 	return len;
971 }
972 
973 /*
974  * sending SADB_X_SPDDELETE message to the kernel.
975  * OUT:
976  *	positive: success and return length sent.
977  *	-1	: error occured, and set errno.
978  */
979 int
980 pfkey_send_spddelete(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
981 	int so;
982 	struct sockaddr *src, *dst;
983 	u_int prefs, prefd, proto;
984 	caddr_t policy;
985 	int policylen;
986 	u_int32_t seq;
987 {
988 	int len;
989 
990 	if (policylen != sizeof(struct sadb_x_policy)) {
991 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
992 		return -1;
993 	}
994 
995 	if ((len = pfkey_send_x4(so, SADB_X_SPDDELETE,
996 				src, prefs, dst, prefd, proto,
997 				0, 0,
998 				policy, policylen, seq)) < 0)
999 		return -1;
1000 
1001 	return len;
1002 }
1003 
1004 /*
1005  * sending SADB_X_SPDDELETE message to the kernel.
1006  * OUT:
1007  *	positive: success and return length sent.
1008  *	-1	: error occured, and set errno.
1009  */
1010 int
1011 pfkey_send_spddelete2(so, spid)
1012 	int so;
1013 	u_int32_t spid;
1014 {
1015 	int len;
1016 
1017 	if ((len = pfkey_send_x5(so, SADB_X_SPDDELETE2, spid)) < 0)
1018 		return -1;
1019 
1020 	return len;
1021 }
1022 
1023 /*
1024  * sending SADB_X_SPDGET message to the kernel.
1025  * OUT:
1026  *	positive: success and return length sent.
1027  *	-1	: error occured, and set errno.
1028  */
1029 int
1030 pfkey_send_spdget(so, spid)
1031 	int so;
1032 	u_int32_t spid;
1033 {
1034 	int len;
1035 
1036 	if ((len = pfkey_send_x5(so, SADB_X_SPDGET, spid)) < 0)
1037 		return -1;
1038 
1039 	return len;
1040 }
1041 
1042 /*
1043  * sending SADB_X_SPDSETIDX message to the kernel.
1044  * OUT:
1045  *	positive: success and return length sent.
1046  *	-1	: error occured, and set errno.
1047  */
1048 int
1049 pfkey_send_spdsetidx(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
1050 	int so;
1051 	struct sockaddr *src, *dst;
1052 	u_int prefs, prefd, proto;
1053 	caddr_t policy;
1054 	int policylen;
1055 	u_int32_t seq;
1056 {
1057 	int len;
1058 
1059 	if (policylen != sizeof(struct sadb_x_policy)) {
1060 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1061 		return -1;
1062 	}
1063 
1064 	if ((len = pfkey_send_x4(so, SADB_X_SPDSETIDX,
1065 				src, prefs, dst, prefd, proto,
1066 				0, 0,
1067 				policy, policylen, seq)) < 0)
1068 		return -1;
1069 
1070 	return len;
1071 }
1072 
1073 /*
1074  * sending SADB_SPDFLUSH message to the kernel.
1075  * OUT:
1076  *	positive: success and return length sent.
1077  *	-1	: error occured, and set errno.
1078  */
1079 int
1080 pfkey_send_spdflush(so)
1081 	int so;
1082 {
1083 	int len;
1084 
1085 	if ((len = pfkey_send_x3(so, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC)) < 0)
1086 		return -1;
1087 
1088 	return len;
1089 }
1090 
1091 /*
1092  * sending SADB_SPDDUMP message to the kernel.
1093  * OUT:
1094  *	positive: success and return length sent.
1095  *	-1	: error occured, and set errno.
1096  */
1097 int
1098 pfkey_send_spddump(so)
1099 	int so;
1100 {
1101 	int len;
1102 
1103 	if ((len = pfkey_send_x3(so, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC)) < 0)
1104 		return -1;
1105 
1106 	return len;
1107 }
1108 
1109 /* sending SADB_ADD or SADB_UPDATE message to the kernel */
1110 static int
1111 pfkey_send_x1(so, type, satype, mode, src, dst, spi, reqid, wsize,
1112 		keymat, e_type, e_keylen, a_type, a_keylen, flags,
1113 		l_alloc, l_bytes, l_addtime, l_usetime, seq)
1114 	int so;
1115 	u_int type, satype, mode;
1116 	struct sockaddr *src, *dst;
1117 	u_int32_t spi, reqid;
1118 	u_int wsize;
1119 	caddr_t keymat;
1120 	u_int e_type, e_keylen, a_type, a_keylen, flags;
1121 	u_int32_t l_alloc, l_bytes, l_addtime, l_usetime, seq;
1122 {
1123 	struct sadb_msg *newmsg;
1124 	int len;
1125 	caddr_t p;
1126 	int plen;
1127 	caddr_t ep;
1128 
1129 	/* validity check */
1130 	if (src == NULL || dst == NULL) {
1131 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1132 		return -1;
1133 	}
1134 	if (src->sa_family != dst->sa_family) {
1135 		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1136 		return -1;
1137 	}
1138 	switch (src->sa_family) {
1139 	case AF_INET:
1140 		plen = sizeof(struct in_addr) << 3;
1141 		break;
1142 	case AF_INET6:
1143 		plen = sizeof(struct in6_addr) << 3;
1144 		break;
1145 	default:
1146 		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
1147 		return -1;
1148 	}
1149 
1150 	switch (satype) {
1151 	case SADB_SATYPE_ESP:
1152 		if (e_type == SADB_EALG_NONE) {
1153 			__ipsec_errcode = EIPSEC_NO_ALGS;
1154 			return -1;
1155 		}
1156 		break;
1157 	case SADB_SATYPE_AH:
1158 		if (e_type != SADB_EALG_NONE) {
1159 			__ipsec_errcode = EIPSEC_INVAL_ALGS;
1160 			return -1;
1161 		}
1162 		if (a_type == SADB_AALG_NONE) {
1163 			__ipsec_errcode = EIPSEC_NO_ALGS;
1164 			return -1;
1165 		}
1166 		break;
1167 	case SADB_X_SATYPE_IPCOMP:
1168 		if (e_type == SADB_X_CALG_NONE) {
1169 			__ipsec_errcode = EIPSEC_INVAL_ALGS;
1170 			return -1;
1171 		}
1172 		if (a_type != SADB_AALG_NONE) {
1173 			__ipsec_errcode = EIPSEC_NO_ALGS;
1174 			return -1;
1175 		}
1176 		break;
1177 	case SADB_X_SATYPE_TCPSIGNATURE:
1178 		if (e_type != SADB_EALG_NONE) {
1179 			__ipsec_errcode = EIPSEC_INVAL_ALGS;
1180 			return -1;
1181 		}
1182 		if (a_type != SADB_X_AALG_TCP_MD5) {
1183 			__ipsec_errcode = EIPSEC_INVAL_ALGS;
1184 			return -1;
1185 		}
1186 		break;
1187 	default:
1188 		__ipsec_errcode = EIPSEC_INVAL_SATYPE;
1189 		return -1;
1190 	}
1191 
1192 	/* create new sadb_msg to reply. */
1193 	len = sizeof(struct sadb_msg)
1194 		+ sizeof(struct sadb_sa)
1195 		+ sizeof(struct sadb_x_sa2)
1196 		+ sizeof(struct sadb_address)
1197 		+ PFKEY_ALIGN8(src->sa_len)
1198 		+ sizeof(struct sadb_address)
1199 		+ PFKEY_ALIGN8(dst->sa_len)
1200 		+ sizeof(struct sadb_lifetime)
1201 		+ sizeof(struct sadb_lifetime);
1202 
1203 	if (wsize > UINT8_MAX) {
1204 		if (wsize > (UINT32_MAX - 32) >> 3) {
1205 			__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1206 			return (-1);
1207 		}
1208 		len += sizeof(struct sadb_x_sa_replay);
1209 	}
1210 	if (e_type != SADB_EALG_NONE)
1211 		len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(e_keylen));
1212 	if (a_type != SADB_AALG_NONE)
1213 		len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(a_keylen));
1214 
1215 	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
1216 		__ipsec_set_strerror(strerror(errno));
1217 		return -1;
1218 	}
1219 	ep = ((caddr_t)newmsg) + len;
1220 
1221 	p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len,
1222 	                     satype, seq, getpid());
1223 	if (!p) {
1224 		free(newmsg);
1225 		return -1;
1226 	}
1227 	p = pfkey_setsadbsa(p, ep, spi, wsize, a_type, e_type, flags);
1228 	if (!p) {
1229 		free(newmsg);
1230 		return -1;
1231 	}
1232 	p = pfkey_setsadbxsa2(p, ep, mode, reqid);
1233 	if (!p) {
1234 		free(newmsg);
1235 		return -1;
1236 	}
1237 	if (wsize > UINT8_MAX) {
1238 		p = pfkey_setsadbxreplay(p, ep, wsize);
1239 		if (!p) {
1240 			free(newmsg);
1241 			return (-1);
1242 		}
1243 	}
1244 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen,
1245 	    IPSEC_ULPROTO_ANY);
1246 	if (!p) {
1247 		free(newmsg);
1248 		return -1;
1249 	}
1250 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen,
1251 	    IPSEC_ULPROTO_ANY);
1252 	if (!p) {
1253 		free(newmsg);
1254 		return -1;
1255 	}
1256 
1257 	if (e_type != SADB_EALG_NONE) {
1258 		p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_ENCRYPT,
1259 		                   keymat, e_keylen);
1260 		if (!p) {
1261 			free(newmsg);
1262 			return -1;
1263 		}
1264 	}
1265 	if (a_type != SADB_AALG_NONE) {
1266 		p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_AUTH,
1267 		                   keymat + e_keylen, a_keylen);
1268 		if (!p) {
1269 			free(newmsg);
1270 			return -1;
1271 		}
1272 	}
1273 
1274 	/* set sadb_lifetime for destination */
1275 	p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD,
1276 			l_alloc, l_bytes, l_addtime, l_usetime);
1277 	if (!p) {
1278 		free(newmsg);
1279 		return -1;
1280 	}
1281 	p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_SOFT,
1282 			l_alloc, l_bytes, l_addtime, l_usetime);
1283 	if (!p || p != ep) {
1284 		free(newmsg);
1285 		return -1;
1286 	}
1287 
1288 	/* send message */
1289 	len = pfkey_send(so, newmsg, len);
1290 	free(newmsg);
1291 
1292 	if (len < 0)
1293 		return -1;
1294 
1295 	__ipsec_errcode = EIPSEC_NO_ERROR;
1296 	return len;
1297 }
1298 
1299 /* sending SADB_DELETE or SADB_GET message to the kernel */
1300 static int
1301 pfkey_send_x2(so, type, satype, mode, src, dst, spi)
1302 	int so;
1303 	u_int type, satype, mode;
1304 	struct sockaddr *src, *dst;
1305 	u_int32_t spi;
1306 {
1307 	struct sadb_msg *newmsg;
1308 	int len;
1309 	caddr_t p;
1310 	int plen;
1311 	caddr_t ep;
1312 
1313 	/* validity check */
1314 	if (src == NULL || dst == NULL) {
1315 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1316 		return -1;
1317 	}
1318 	if (src->sa_family != dst->sa_family) {
1319 		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1320 		return -1;
1321 	}
1322 	switch (src->sa_family) {
1323 	case AF_INET:
1324 		plen = sizeof(struct in_addr) << 3;
1325 		break;
1326 	case AF_INET6:
1327 		plen = sizeof(struct in6_addr) << 3;
1328 		break;
1329 	default:
1330 		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
1331 		return -1;
1332 	}
1333 
1334 	/* create new sadb_msg to reply. */
1335 	len = sizeof(struct sadb_msg)
1336 		+ sizeof(struct sadb_sa)
1337 		+ sizeof(struct sadb_address)
1338 		+ PFKEY_ALIGN8(src->sa_len)
1339 		+ sizeof(struct sadb_address)
1340 		+ PFKEY_ALIGN8(dst->sa_len);
1341 
1342 	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
1343 		__ipsec_set_strerror(strerror(errno));
1344 		return -1;
1345 	}
1346 	ep = ((caddr_t)newmsg) + len;
1347 
1348 	p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, 0,
1349 	    getpid());
1350 	if (!p) {
1351 		free(newmsg);
1352 		return -1;
1353 	}
1354 	p = pfkey_setsadbsa(p, ep, spi, 0, 0, 0, 0);
1355 	if (!p) {
1356 		free(newmsg);
1357 		return -1;
1358 	}
1359 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen,
1360 	    IPSEC_ULPROTO_ANY);
1361 	if (!p) {
1362 		free(newmsg);
1363 		return -1;
1364 	}
1365 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen,
1366 	    IPSEC_ULPROTO_ANY);
1367 	if (!p || p != ep) {
1368 		free(newmsg);
1369 		return -1;
1370 	}
1371 
1372 	/* send message */
1373 	len = pfkey_send(so, newmsg, len);
1374 	free(newmsg);
1375 
1376 	if (len < 0)
1377 		return -1;
1378 
1379 	__ipsec_errcode = EIPSEC_NO_ERROR;
1380 	return len;
1381 }
1382 
1383 /*
1384  * sending SADB_REGISTER, SADB_FLUSH, SADB_DUMP or SADB_X_PROMISC message
1385  * to the kernel
1386  */
1387 static int
1388 pfkey_send_x3(so, type, satype)
1389 	int so;
1390 	u_int type, satype;
1391 {
1392 	struct sadb_msg *newmsg;
1393 	int len;
1394 	caddr_t p;
1395 	caddr_t ep;
1396 
1397 	/* validity check */
1398 	switch (type) {
1399 	case SADB_X_PROMISC:
1400 		if (satype != 0 && satype != 1) {
1401 			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
1402 			return -1;
1403 		}
1404 		break;
1405 	default:
1406 		switch (satype) {
1407 		case SADB_SATYPE_UNSPEC:
1408 		case SADB_SATYPE_AH:
1409 		case SADB_SATYPE_ESP:
1410 		case SADB_X_SATYPE_IPCOMP:
1411 		case SADB_X_SATYPE_TCPSIGNATURE:
1412 			break;
1413 		default:
1414 			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
1415 			return -1;
1416 		}
1417 	}
1418 
1419 	/* create new sadb_msg to send. */
1420 	len = sizeof(struct sadb_msg);
1421 
1422 	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
1423 		__ipsec_set_strerror(strerror(errno));
1424 		return -1;
1425 	}
1426 	ep = ((caddr_t)newmsg) + len;
1427 
1428 	p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, 0,
1429 	    getpid());
1430 	if (!p || p != ep) {
1431 		free(newmsg);
1432 		return -1;
1433 	}
1434 
1435 	/* send message */
1436 	len = pfkey_send(so, newmsg, len);
1437 	free(newmsg);
1438 
1439 	if (len < 0)
1440 		return -1;
1441 
1442 	__ipsec_errcode = EIPSEC_NO_ERROR;
1443 	return len;
1444 }
1445 
1446 /* sending SADB_X_SPDADD message to the kernel */
1447 static int
1448 pfkey_send_x4(so, type, src, prefs, dst, prefd, proto,
1449 		ltime, vtime, policy, policylen, seq)
1450 	int so;
1451 	struct sockaddr *src, *dst;
1452 	u_int type, prefs, prefd, proto;
1453 	u_int64_t ltime, vtime;
1454 	char *policy;
1455 	int policylen;
1456 	u_int32_t seq;
1457 {
1458 	struct sadb_msg *newmsg;
1459 	int len;
1460 	caddr_t p;
1461 	int plen;
1462 	caddr_t ep;
1463 
1464 	/* validity check */
1465 	if (src == NULL || dst == NULL) {
1466 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1467 		return -1;
1468 	}
1469 	if (src->sa_family != dst->sa_family) {
1470 		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1471 		return -1;
1472 	}
1473 
1474 	switch (src->sa_family) {
1475 	case AF_INET:
1476 		plen = sizeof(struct in_addr) << 3;
1477 		break;
1478 	case AF_INET6:
1479 		plen = sizeof(struct in6_addr) << 3;
1480 		break;
1481 	default:
1482 		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
1483 		return -1;
1484 	}
1485 	if (prefs > plen || prefd > plen) {
1486 		__ipsec_errcode = EIPSEC_INVAL_PREFIXLEN;
1487 		return -1;
1488 	}
1489 
1490 	/* create new sadb_msg to reply. */
1491 	len = sizeof(struct sadb_msg)
1492 		+ sizeof(struct sadb_address)
1493 		+ PFKEY_ALIGN8(src->sa_len)
1494 		+ sizeof(struct sadb_address)
1495 		+ PFKEY_ALIGN8(src->sa_len)
1496 		+ sizeof(struct sadb_lifetime)
1497 		+ policylen;
1498 
1499 	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
1500 		__ipsec_set_strerror(strerror(errno));
1501 		return -1;
1502 	}
1503 	ep = ((caddr_t)newmsg) + len;
1504 
1505 	p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len,
1506 	    SADB_SATYPE_UNSPEC, seq, getpid());
1507 	if (!p) {
1508 		free(newmsg);
1509 		return -1;
1510 	}
1511 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, prefs, proto);
1512 	if (!p) {
1513 		free(newmsg);
1514 		return -1;
1515 	}
1516 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, prefd, proto);
1517 	if (!p) {
1518 		free(newmsg);
1519 		return -1;
1520 	}
1521 	p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD,
1522 			0, 0, ltime, vtime);
1523 	if (!p || p + policylen != ep) {
1524 		free(newmsg);
1525 		return -1;
1526 	}
1527 	memcpy(p, policy, policylen);
1528 
1529 	/* send message */
1530 	len = pfkey_send(so, newmsg, len);
1531 	free(newmsg);
1532 
1533 	if (len < 0)
1534 		return -1;
1535 
1536 	__ipsec_errcode = EIPSEC_NO_ERROR;
1537 	return len;
1538 }
1539 
1540 /* sending SADB_X_SPDGET or SADB_X_SPDDELETE message to the kernel */
1541 static int
1542 pfkey_send_x5(so, type, spid)
1543 	int so;
1544 	u_int type;
1545 	u_int32_t spid;
1546 {
1547 	struct sadb_msg *newmsg;
1548 	struct sadb_x_policy xpl;
1549 	int len;
1550 	caddr_t p;
1551 	caddr_t ep;
1552 
1553 	/* create new sadb_msg to reply. */
1554 	len = sizeof(struct sadb_msg)
1555 		+ sizeof(xpl);
1556 
1557 	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
1558 		__ipsec_set_strerror(strerror(errno));
1559 		return -1;
1560 	}
1561 	ep = ((caddr_t)newmsg) + len;
1562 
1563 	p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len,
1564 	    SADB_SATYPE_UNSPEC, 0, getpid());
1565 	if (!p) {
1566 		free(newmsg);
1567 		return -1;
1568 	}
1569 
1570 	if (p + sizeof(xpl) != ep) {
1571 		free(newmsg);
1572 		return -1;
1573 	}
1574 	memset(&xpl, 0, sizeof(xpl));
1575 	xpl.sadb_x_policy_len = PFKEY_UNIT64(sizeof(xpl));
1576 	xpl.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
1577 	xpl.sadb_x_policy_id = spid;
1578 	memcpy(p, &xpl, sizeof(xpl));
1579 
1580 	/* send message */
1581 	len = pfkey_send(so, newmsg, len);
1582 	free(newmsg);
1583 
1584 	if (len < 0)
1585 		return -1;
1586 
1587 	__ipsec_errcode = EIPSEC_NO_ERROR;
1588 	return len;
1589 }
1590 
1591 /*
1592  * open a socket.
1593  * OUT:
1594  *	-1: fail.
1595  *	others : success and return value of socket.
1596  */
1597 int
1598 pfkey_open()
1599 {
1600 	int so;
1601 	const int bufsiz = 128 * 1024;	/*is 128K enough?*/
1602 
1603 	if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) {
1604 		__ipsec_set_strerror(strerror(errno));
1605 		return -1;
1606 	}
1607 
1608 	/*
1609 	 * This is a temporary workaround for KAME PR 154.
1610 	 * Don't really care even if it fails.
1611 	 */
1612 	(void)setsockopt(so, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz));
1613 	(void)setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz));
1614 
1615 	__ipsec_errcode = EIPSEC_NO_ERROR;
1616 	return so;
1617 }
1618 
1619 /*
1620  * close a socket.
1621  * OUT:
1622  *	 0: success.
1623  *	-1: fail.
1624  */
1625 void
1626 pfkey_close(so)
1627 	int so;
1628 {
1629 	(void)close(so);
1630 
1631 	__ipsec_errcode = EIPSEC_NO_ERROR;
1632 	return;
1633 }
1634 
1635 /*
1636  * receive sadb_msg data, and return pointer to new buffer allocated.
1637  * Must free this buffer later.
1638  * OUT:
1639  *	NULL	: error occured.
1640  *	others	: a pointer to sadb_msg structure.
1641  *
1642  * XXX should be rewritten to pass length explicitly
1643  */
1644 struct sadb_msg *
1645 pfkey_recv(so)
1646 	int so;
1647 {
1648 	struct sadb_msg buf, *newmsg;
1649 	int len, reallen;
1650 
1651 	while ((len = recv(so, (caddr_t)&buf, sizeof(buf), MSG_PEEK)) < 0) {
1652 		if (errno == EINTR)
1653 			continue;
1654 		__ipsec_set_strerror(strerror(errno));
1655 		return NULL;
1656 	}
1657 
1658 	if (len < sizeof(buf)) {
1659 		recv(so, (caddr_t)&buf, sizeof(buf), 0);
1660 		__ipsec_errcode = EIPSEC_MAX;
1661 		return NULL;
1662 	}
1663 
1664 	/* read real message */
1665 	reallen = PFKEY_UNUNIT64(buf.sadb_msg_len);
1666 	if ((newmsg = CALLOC(reallen, struct sadb_msg *)) == NULL) {
1667 		__ipsec_set_strerror(strerror(errno));
1668 		return NULL;
1669 	}
1670 
1671 	while ((len = recv(so, (caddr_t)newmsg, reallen, 0)) < 0) {
1672 		if (errno == EINTR)
1673 			continue;
1674 		__ipsec_set_strerror(strerror(errno));
1675 		free(newmsg);
1676 		return NULL;
1677 	}
1678 
1679 	if (len != reallen) {
1680 		__ipsec_errcode = EIPSEC_SYSTEM_ERROR;
1681 		free(newmsg);
1682 		return NULL;
1683 	}
1684 
1685 	/* don't trust what the kernel says, validate! */
1686 	if (PFKEY_UNUNIT64(newmsg->sadb_msg_len) != len) {
1687 		__ipsec_errcode = EIPSEC_SYSTEM_ERROR;
1688 		free(newmsg);
1689 		return NULL;
1690 	}
1691 
1692 	__ipsec_errcode = EIPSEC_NO_ERROR;
1693 	return newmsg;
1694 }
1695 
1696 /*
1697  * send message to a socket.
1698  * OUT:
1699  *	 others: success and return length sent.
1700  *	-1     : fail.
1701  */
1702 int
1703 pfkey_send(so, msg, len)
1704 	int so;
1705 	struct sadb_msg *msg;
1706 	int len;
1707 {
1708 	if ((len = send(so, (caddr_t)msg, len, 0)) < 0) {
1709 		__ipsec_set_strerror(strerror(errno));
1710 		return -1;
1711 	}
1712 
1713 	__ipsec_errcode = EIPSEC_NO_ERROR;
1714 	return len;
1715 }
1716 
1717 /*
1718  * %%% Utilities
1719  * NOTE: These functions are derived from netkey/key.c in KAME.
1720  */
1721 /*
1722  * set the pointer to each header in this message buffer.
1723  * IN:	msg: pointer to message buffer.
1724  *	mhp: pointer to the buffer initialized like below:
1725  *		caddr_t mhp[SADB_EXT_MAX + 1];
1726  * OUT:	-1: invalid.
1727  *	 0: valid.
1728  *
1729  * XXX should be rewritten to obtain length explicitly
1730  */
1731 int
1732 pfkey_align(msg, mhp)
1733 	struct sadb_msg *msg;
1734 	caddr_t *mhp;
1735 {
1736 	struct sadb_ext *ext;
1737 	int i;
1738 	caddr_t p;
1739 	caddr_t ep;	/* XXX should be passed from upper layer */
1740 
1741 	/* validity check */
1742 	if (msg == NULL || mhp == NULL) {
1743 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1744 		return -1;
1745 	}
1746 
1747 	/* initialize */
1748 	for (i = 0; i < SADB_EXT_MAX + 1; i++)
1749 		mhp[i] = NULL;
1750 
1751 	mhp[0] = (caddr_t)msg;
1752 
1753 	/* initialize */
1754 	p = (caddr_t) msg;
1755 	ep = p + PFKEY_UNUNIT64(msg->sadb_msg_len);
1756 
1757 	/* skip base header */
1758 	p += sizeof(struct sadb_msg);
1759 
1760 	while (p < ep) {
1761 		ext = (struct sadb_ext *)p;
1762 		if (ep < p + sizeof(*ext) || PFKEY_EXTLEN(ext) < sizeof(*ext) ||
1763 		    ep < p + PFKEY_EXTLEN(ext)) {
1764 			/* invalid format */
1765 			break;
1766 		}
1767 
1768 		/* duplicate check */
1769 		/* XXX Are there duplication either KEY_AUTH or KEY_ENCRYPT ?*/
1770 		if (mhp[ext->sadb_ext_type] != NULL) {
1771 			__ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
1772 			return -1;
1773 		}
1774 
1775 		/* set pointer */
1776 		switch (ext->sadb_ext_type) {
1777 		case SADB_EXT_SA:
1778 		case SADB_EXT_LIFETIME_CURRENT:
1779 		case SADB_EXT_LIFETIME_HARD:
1780 		case SADB_EXT_LIFETIME_SOFT:
1781 		case SADB_EXT_ADDRESS_SRC:
1782 		case SADB_EXT_ADDRESS_DST:
1783 		case SADB_EXT_ADDRESS_PROXY:
1784 		case SADB_EXT_KEY_AUTH:
1785 			/* XXX should to be check weak keys. */
1786 		case SADB_EXT_KEY_ENCRYPT:
1787 			/* XXX should to be check weak keys. */
1788 		case SADB_EXT_IDENTITY_SRC:
1789 		case SADB_EXT_IDENTITY_DST:
1790 		case SADB_EXT_SENSITIVITY:
1791 		case SADB_EXT_PROPOSAL:
1792 		case SADB_EXT_SUPPORTED_AUTH:
1793 		case SADB_EXT_SUPPORTED_ENCRYPT:
1794 		case SADB_EXT_SPIRANGE:
1795 		case SADB_X_EXT_POLICY:
1796 		case SADB_X_EXT_SA2:
1797 		case SADB_X_EXT_NAT_T_TYPE:
1798 		case SADB_X_EXT_NAT_T_SPORT:
1799 		case SADB_X_EXT_NAT_T_DPORT:
1800 		case SADB_X_EXT_NAT_T_OAI:
1801 		case SADB_X_EXT_NAT_T_OAR:
1802 		case SADB_X_EXT_NAT_T_FRAG:
1803 		case SADB_X_EXT_SA_REPLAY:
1804 		case SADB_X_EXT_NEW_ADDRESS_SRC:
1805 		case SADB_X_EXT_NEW_ADDRESS_DST:
1806 			mhp[ext->sadb_ext_type] = (caddr_t)ext;
1807 			break;
1808 		default:
1809 			__ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
1810 			return -1;
1811 		}
1812 
1813 		p += PFKEY_EXTLEN(ext);
1814 	}
1815 
1816 	if (p != ep) {
1817 		__ipsec_errcode = EIPSEC_INVAL_SADBMSG;
1818 		return -1;
1819 	}
1820 
1821 	__ipsec_errcode = EIPSEC_NO_ERROR;
1822 	return 0;
1823 }
1824 
1825 /*
1826  * check basic usage for sadb_msg,
1827  * NOTE: This routine is derived from netkey/key.c in KAME.
1828  * IN:	msg: pointer to message buffer.
1829  *	mhp: pointer to the buffer initialized like below:
1830  *
1831  *		caddr_t mhp[SADB_EXT_MAX + 1];
1832  *
1833  * OUT:	-1: invalid.
1834  *	 0: valid.
1835  */
1836 int
1837 pfkey_check(mhp)
1838 	caddr_t *mhp;
1839 {
1840 	struct sadb_msg *msg;
1841 
1842 	/* validity check */
1843 	if (mhp == NULL || mhp[0] == NULL) {
1844 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1845 		return -1;
1846 	}
1847 
1848 	msg = (struct sadb_msg *)mhp[0];
1849 
1850 	/* check version */
1851 	if (msg->sadb_msg_version != PF_KEY_V2) {
1852 		__ipsec_errcode = EIPSEC_INVAL_VERSION;
1853 		return -1;
1854 	}
1855 
1856 	/* check type */
1857 	if (msg->sadb_msg_type > SADB_MAX) {
1858 		__ipsec_errcode = EIPSEC_INVAL_MSGTYPE;
1859 		return -1;
1860 	}
1861 
1862 	/* check SA type */
1863 	switch (msg->sadb_msg_satype) {
1864 	case SADB_SATYPE_UNSPEC:
1865 		switch (msg->sadb_msg_type) {
1866 		case SADB_GETSPI:
1867 		case SADB_UPDATE:
1868 		case SADB_ADD:
1869 		case SADB_DELETE:
1870 		case SADB_GET:
1871 		case SADB_ACQUIRE:
1872 		case SADB_EXPIRE:
1873 			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
1874 			return -1;
1875 		}
1876 		break;
1877 	case SADB_SATYPE_ESP:
1878 	case SADB_SATYPE_AH:
1879 	case SADB_X_SATYPE_IPCOMP:
1880 	case SADB_X_SATYPE_TCPSIGNATURE:
1881 		switch (msg->sadb_msg_type) {
1882 		case SADB_X_SPDADD:
1883 		case SADB_X_SPDDELETE:
1884 		case SADB_X_SPDGET:
1885 		case SADB_X_SPDDUMP:
1886 		case SADB_X_SPDFLUSH:
1887 			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
1888 			return -1;
1889 		}
1890 		break;
1891 	case SADB_SATYPE_RSVP:
1892 	case SADB_SATYPE_OSPFV2:
1893 	case SADB_SATYPE_RIPV2:
1894 	case SADB_SATYPE_MIP:
1895 		__ipsec_errcode = EIPSEC_NOT_SUPPORTED;
1896 		return -1;
1897 	case 1:	/* XXX: What does it do ? */
1898 		if (msg->sadb_msg_type == SADB_X_PROMISC)
1899 			break;
1900 		/*FALLTHROUGH*/
1901 	default:
1902 		__ipsec_errcode = EIPSEC_INVAL_SATYPE;
1903 		return -1;
1904 	}
1905 
1906 	/* check field of upper layer protocol and address family */
1907 	if (mhp[SADB_EXT_ADDRESS_SRC] != NULL
1908 	 && mhp[SADB_EXT_ADDRESS_DST] != NULL) {
1909 		struct sadb_address *src0, *dst0;
1910 
1911 		src0 = (struct sadb_address *)(mhp[SADB_EXT_ADDRESS_SRC]);
1912 		dst0 = (struct sadb_address *)(mhp[SADB_EXT_ADDRESS_DST]);
1913 
1914 		if (src0->sadb_address_proto != dst0->sadb_address_proto) {
1915 			__ipsec_errcode = EIPSEC_PROTO_MISMATCH;
1916 			return -1;
1917 		}
1918 
1919 		if (PFKEY_ADDR_SADDR(src0)->sa_family
1920 		 != PFKEY_ADDR_SADDR(dst0)->sa_family) {
1921 			__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1922 			return -1;
1923 		}
1924 
1925 		switch (PFKEY_ADDR_SADDR(src0)->sa_family) {
1926 		case AF_INET:
1927 		case AF_INET6:
1928 			break;
1929 		default:
1930 			__ipsec_errcode = EIPSEC_INVAL_FAMILY;
1931 			return -1;
1932 		}
1933 
1934 		/*
1935 		 * prefixlen == 0 is valid because there must be the case
1936 		 * all addresses are matched.
1937 		 */
1938 	}
1939 
1940 	__ipsec_errcode = EIPSEC_NO_ERROR;
1941 	return 0;
1942 }
1943 
1944 /*
1945  * set data into sadb_msg.
1946  * `buf' must has been allocated sufficiently.
1947  */
1948 static caddr_t
1949 pfkey_setsadbmsg(buf, lim, type, tlen, satype, seq, pid)
1950 	caddr_t buf;
1951 	caddr_t lim;
1952 	u_int type, satype;
1953 	u_int tlen;
1954 	u_int32_t seq;
1955 	pid_t pid;
1956 {
1957 	struct sadb_msg *p;
1958 	u_int len;
1959 
1960 	p = (struct sadb_msg *)buf;
1961 	len = sizeof(struct sadb_msg);
1962 
1963 	if (buf + len > lim)
1964 		return NULL;
1965 
1966 	memset(p, 0, len);
1967 	p->sadb_msg_version = PF_KEY_V2;
1968 	p->sadb_msg_type = type;
1969 	p->sadb_msg_errno = 0;
1970 	p->sadb_msg_satype = satype;
1971 	p->sadb_msg_len = PFKEY_UNIT64(tlen);
1972 	p->sadb_msg_reserved = 0;
1973 	p->sadb_msg_seq = seq;
1974 	p->sadb_msg_pid = (u_int32_t)pid;
1975 
1976 	return(buf + len);
1977 }
1978 
1979 /*
1980  * copy secasvar data into sadb_address.
1981  * `buf' must has been allocated sufficiently.
1982  */
1983 static caddr_t
1984 pfkey_setsadbsa(buf, lim, spi, wsize, auth, enc, flags)
1985 	caddr_t buf;
1986 	caddr_t lim;
1987 	u_int32_t spi, flags;
1988 	u_int wsize, auth, enc;
1989 {
1990 	struct sadb_sa *p;
1991 	u_int len;
1992 
1993 	p = (struct sadb_sa *)buf;
1994 	len = sizeof(struct sadb_sa);
1995 
1996 	if (buf + len > lim)
1997 		return NULL;
1998 
1999 	memset(p, 0, len);
2000 	p->sadb_sa_len = PFKEY_UNIT64(len);
2001 	p->sadb_sa_exttype = SADB_EXT_SA;
2002 	p->sadb_sa_spi = spi;
2003 	p->sadb_sa_replay = wsize > UINT8_MAX ? UINT8_MAX: wsize;
2004 	p->sadb_sa_state = SADB_SASTATE_LARVAL;
2005 	p->sadb_sa_auth = auth;
2006 	p->sadb_sa_encrypt = enc;
2007 	p->sadb_sa_flags = flags;
2008 
2009 	return(buf + len);
2010 }
2011 
2012 /*
2013  * Set data into sadb_x_sa_replay.
2014  * `buf' must has been allocated sufficiently.
2015  */
2016 static caddr_t
2017 pfkey_setsadbxreplay(caddr_t buf, caddr_t lim, uint32_t wsize)
2018 {
2019 	struct sadb_x_sa_replay *p;
2020 	u_int len;
2021 
2022 	p = (struct sadb_x_sa_replay *)buf;
2023 	len = sizeof(struct sadb_x_sa_replay);
2024 
2025 	if (buf + len > lim)
2026 		return (NULL);
2027 
2028 	memset(p, 0, len);
2029 	p->sadb_x_sa_replay_len = PFKEY_UNIT64(len);
2030 	p->sadb_x_sa_replay_exttype = SADB_X_EXT_SA_REPLAY;
2031 	/* Convert wsize from bytes to number of packets. */
2032 	p->sadb_x_sa_replay_replay = wsize << 3;
2033 
2034 	return (buf + len);
2035 }
2036 
2037 /*
2038  * set data into sadb_address.
2039  * `buf' must has been allocated sufficiently.
2040  * prefixlen is in bits.
2041  */
2042 static caddr_t
2043 pfkey_setsadbaddr(buf, lim, exttype, saddr, prefixlen, ul_proto)
2044 	caddr_t buf;
2045 	caddr_t lim;
2046 	u_int exttype;
2047 	struct sockaddr *saddr;
2048 	u_int prefixlen;
2049 	u_int ul_proto;
2050 {
2051 	struct sadb_address *p;
2052 	u_int len;
2053 
2054 	p = (struct sadb_address *)buf;
2055 	len = sizeof(struct sadb_address) + PFKEY_ALIGN8(saddr->sa_len);
2056 
2057 	if (buf + len > lim)
2058 		return NULL;
2059 
2060 	memset(p, 0, len);
2061 	p->sadb_address_len = PFKEY_UNIT64(len);
2062 	p->sadb_address_exttype = exttype & 0xffff;
2063 	p->sadb_address_proto = ul_proto & 0xff;
2064 	p->sadb_address_prefixlen = prefixlen;
2065 	p->sadb_address_reserved = 0;
2066 
2067 	memcpy(p + 1, saddr, saddr->sa_len);
2068 
2069 	return(buf + len);
2070 }
2071 
2072 /*
2073  * set sadb_key structure after clearing buffer with zero.
2074  * OUT: the pointer of buf + len.
2075  */
2076 static caddr_t
2077 pfkey_setsadbkey(buf, lim, type, key, keylen)
2078 	caddr_t buf;
2079 	caddr_t lim;
2080 	caddr_t key;
2081 	u_int type, keylen;
2082 {
2083 	struct sadb_key *p;
2084 	u_int len;
2085 
2086 	p = (struct sadb_key *)buf;
2087 	len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen);
2088 
2089 	if (buf + len > lim)
2090 		return NULL;
2091 
2092 	memset(p, 0, len);
2093 	p->sadb_key_len = PFKEY_UNIT64(len);
2094 	p->sadb_key_exttype = type;
2095 	p->sadb_key_bits = keylen << 3;
2096 	p->sadb_key_reserved = 0;
2097 
2098 	memcpy(p + 1, key, keylen);
2099 
2100 	return buf + len;
2101 }
2102 
2103 /*
2104  * set sadb_lifetime structure after clearing buffer with zero.
2105  * OUT: the pointer of buf + len.
2106  */
2107 static caddr_t
2108 pfkey_setsadblifetime(buf, lim, type, l_alloc, l_bytes, l_addtime, l_usetime)
2109 	caddr_t buf;
2110 	caddr_t lim;
2111 	u_int type;
2112 	u_int32_t l_alloc, l_bytes, l_addtime, l_usetime;
2113 {
2114 	struct sadb_lifetime *p;
2115 	u_int len;
2116 
2117 	p = (struct sadb_lifetime *)buf;
2118 	len = sizeof(struct sadb_lifetime);
2119 
2120 	if (buf + len > lim)
2121 		return NULL;
2122 
2123 	memset(p, 0, len);
2124 	p->sadb_lifetime_len = PFKEY_UNIT64(len);
2125 	p->sadb_lifetime_exttype = type;
2126 
2127 	switch (type) {
2128 	case SADB_EXT_LIFETIME_SOFT:
2129 		p->sadb_lifetime_allocations
2130 			= (l_alloc * soft_lifetime_allocations_rate) /100;
2131 		p->sadb_lifetime_bytes
2132 			= (l_bytes * soft_lifetime_bytes_rate) /100;
2133 		p->sadb_lifetime_addtime
2134 			= (l_addtime * soft_lifetime_addtime_rate) /100;
2135 		p->sadb_lifetime_usetime
2136 			= (l_usetime * soft_lifetime_usetime_rate) /100;
2137 		break;
2138 	case SADB_EXT_LIFETIME_HARD:
2139 		p->sadb_lifetime_allocations = l_alloc;
2140 		p->sadb_lifetime_bytes = l_bytes;
2141 		p->sadb_lifetime_addtime = l_addtime;
2142 		p->sadb_lifetime_usetime = l_usetime;
2143 		break;
2144 	}
2145 
2146 	return buf + len;
2147 }
2148 
2149 /*
2150  * copy secasvar data into sadb_address.
2151  * `buf' must has been allocated sufficiently.
2152  */
2153 static caddr_t
2154 pfkey_setsadbxsa2(buf, lim, mode0, reqid)
2155 	caddr_t buf;
2156 	caddr_t lim;
2157 	u_int32_t mode0;
2158 	u_int32_t reqid;
2159 {
2160 	struct sadb_x_sa2 *p;
2161 	u_int8_t mode = mode0 & 0xff;
2162 	u_int len;
2163 
2164 	p = (struct sadb_x_sa2 *)buf;
2165 	len = sizeof(struct sadb_x_sa2);
2166 
2167 	if (buf + len > lim)
2168 		return NULL;
2169 
2170 	memset(p, 0, len);
2171 	p->sadb_x_sa2_len = PFKEY_UNIT64(len);
2172 	p->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
2173 	p->sadb_x_sa2_mode = mode;
2174 	p->sadb_x_sa2_reqid = reqid;
2175 
2176 	return(buf + len);
2177 }
2178