xref: /freebsd/lib/libipsec/pfkey.c (revision 148a8da8)
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(void)
1599 {
1600 	int so;
1601 	int bufsiz_current, bufsiz_wanted;
1602 	int ret;
1603 	socklen_t len;
1604 
1605 	if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) {
1606 		__ipsec_set_strerror(strerror(errno));
1607 		return -1;
1608 	}
1609 
1610 	/*
1611 	 * This is a temporary workaround for KAME PR 154.
1612 	 * Don't really care even if it fails.
1613 	 */
1614 	/* Try to have 128k. If we have more, do not lower it. */
1615 	bufsiz_wanted = 128 * 1024;
1616 	len = sizeof(bufsiz_current);
1617 	ret = getsockopt(so, SOL_SOCKET, SO_SNDBUF,
1618 		&bufsiz_current, &len);
1619 	if ((ret < 0) || (bufsiz_current < bufsiz_wanted))
1620 		(void)setsockopt(so, SOL_SOCKET, SO_SNDBUF,
1621 			&bufsiz_wanted, sizeof(bufsiz_wanted));
1622 
1623 	/* Try to have have at least 2MB. If we have more, do not lower it. */
1624 	bufsiz_wanted = 2 * 1024 * 1024;
1625 	len = sizeof(bufsiz_current);
1626 	ret = getsockopt(so, SOL_SOCKET, SO_RCVBUF,
1627 		&bufsiz_current, &len);
1628 	if (ret < 0)
1629 		bufsiz_current = 128 * 1024;
1630 
1631 	for (; bufsiz_wanted > bufsiz_current; bufsiz_wanted /= 2) {
1632 		if (setsockopt(so, SOL_SOCKET, SO_RCVBUF,
1633 				&bufsiz_wanted, sizeof(bufsiz_wanted)) == 0)
1634 			break;
1635 	}
1636 
1637 	__ipsec_errcode = EIPSEC_NO_ERROR;
1638 	return so;
1639 }
1640 
1641 /*
1642  * close a socket.
1643  * OUT:
1644  *	 0: success.
1645  *	-1: fail.
1646  */
1647 void
1648 pfkey_close(so)
1649 	int so;
1650 {
1651 	(void)close(so);
1652 
1653 	__ipsec_errcode = EIPSEC_NO_ERROR;
1654 	return;
1655 }
1656 
1657 /*
1658  * receive sadb_msg data, and return pointer to new buffer allocated.
1659  * Must free this buffer later.
1660  * OUT:
1661  *	NULL	: error occured.
1662  *	others	: a pointer to sadb_msg structure.
1663  *
1664  * XXX should be rewritten to pass length explicitly
1665  */
1666 struct sadb_msg *
1667 pfkey_recv(so)
1668 	int so;
1669 {
1670 	struct sadb_msg buf, *newmsg;
1671 	int len, reallen;
1672 
1673 	while ((len = recv(so, (caddr_t)&buf, sizeof(buf), MSG_PEEK)) < 0) {
1674 		if (errno == EINTR)
1675 			continue;
1676 		__ipsec_set_strerror(strerror(errno));
1677 		return NULL;
1678 	}
1679 
1680 	if (len < sizeof(buf)) {
1681 		recv(so, (caddr_t)&buf, sizeof(buf), 0);
1682 		__ipsec_errcode = EIPSEC_MAX;
1683 		return NULL;
1684 	}
1685 
1686 	/* read real message */
1687 	reallen = PFKEY_UNUNIT64(buf.sadb_msg_len);
1688 	if ((newmsg = CALLOC(reallen, struct sadb_msg *)) == NULL) {
1689 		__ipsec_set_strerror(strerror(errno));
1690 		return NULL;
1691 	}
1692 
1693 	while ((len = recv(so, (caddr_t)newmsg, reallen, 0)) < 0) {
1694 		if (errno == EINTR)
1695 			continue;
1696 		__ipsec_set_strerror(strerror(errno));
1697 		free(newmsg);
1698 		return NULL;
1699 	}
1700 
1701 	if (len != reallen) {
1702 		__ipsec_errcode = EIPSEC_SYSTEM_ERROR;
1703 		free(newmsg);
1704 		return NULL;
1705 	}
1706 
1707 	/* don't trust what the kernel says, validate! */
1708 	if (PFKEY_UNUNIT64(newmsg->sadb_msg_len) != len) {
1709 		__ipsec_errcode = EIPSEC_SYSTEM_ERROR;
1710 		free(newmsg);
1711 		return NULL;
1712 	}
1713 
1714 	__ipsec_errcode = EIPSEC_NO_ERROR;
1715 	return newmsg;
1716 }
1717 
1718 /*
1719  * send message to a socket.
1720  * OUT:
1721  *	 others: success and return length sent.
1722  *	-1     : fail.
1723  */
1724 int
1725 pfkey_send(so, msg, len)
1726 	int so;
1727 	struct sadb_msg *msg;
1728 	int len;
1729 {
1730 	if ((len = send(so, (caddr_t)msg, len, 0)) < 0) {
1731 		__ipsec_set_strerror(strerror(errno));
1732 		return -1;
1733 	}
1734 
1735 	__ipsec_errcode = EIPSEC_NO_ERROR;
1736 	return len;
1737 }
1738 
1739 /*
1740  * %%% Utilities
1741  * NOTE: These functions are derived from netkey/key.c in KAME.
1742  */
1743 /*
1744  * set the pointer to each header in this message buffer.
1745  * IN:	msg: pointer to message buffer.
1746  *	mhp: pointer to the buffer initialized like below:
1747  *		caddr_t mhp[SADB_EXT_MAX + 1];
1748  * OUT:	-1: invalid.
1749  *	 0: valid.
1750  *
1751  * XXX should be rewritten to obtain length explicitly
1752  */
1753 int
1754 pfkey_align(msg, mhp)
1755 	struct sadb_msg *msg;
1756 	caddr_t *mhp;
1757 {
1758 	struct sadb_ext *ext;
1759 	int i;
1760 	caddr_t p;
1761 	caddr_t ep;	/* XXX should be passed from upper layer */
1762 
1763 	/* validity check */
1764 	if (msg == NULL || mhp == NULL) {
1765 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1766 		return -1;
1767 	}
1768 
1769 	/* initialize */
1770 	for (i = 0; i < SADB_EXT_MAX + 1; i++)
1771 		mhp[i] = NULL;
1772 
1773 	mhp[0] = (caddr_t)msg;
1774 
1775 	/* initialize */
1776 	p = (caddr_t) msg;
1777 	ep = p + PFKEY_UNUNIT64(msg->sadb_msg_len);
1778 
1779 	/* skip base header */
1780 	p += sizeof(struct sadb_msg);
1781 
1782 	while (p < ep) {
1783 		ext = (struct sadb_ext *)p;
1784 		if (ep < p + sizeof(*ext) || PFKEY_EXTLEN(ext) < sizeof(*ext) ||
1785 		    ep < p + PFKEY_EXTLEN(ext)) {
1786 			/* invalid format */
1787 			break;
1788 		}
1789 
1790 		/* duplicate check */
1791 		/* XXX Are there duplication either KEY_AUTH or KEY_ENCRYPT ?*/
1792 		if (mhp[ext->sadb_ext_type] != NULL) {
1793 			__ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
1794 			return -1;
1795 		}
1796 
1797 		/* set pointer */
1798 		switch (ext->sadb_ext_type) {
1799 		case SADB_EXT_SA:
1800 		case SADB_EXT_LIFETIME_CURRENT:
1801 		case SADB_EXT_LIFETIME_HARD:
1802 		case SADB_EXT_LIFETIME_SOFT:
1803 		case SADB_EXT_ADDRESS_SRC:
1804 		case SADB_EXT_ADDRESS_DST:
1805 		case SADB_EXT_ADDRESS_PROXY:
1806 		case SADB_EXT_KEY_AUTH:
1807 			/* XXX should to be check weak keys. */
1808 		case SADB_EXT_KEY_ENCRYPT:
1809 			/* XXX should to be check weak keys. */
1810 		case SADB_EXT_IDENTITY_SRC:
1811 		case SADB_EXT_IDENTITY_DST:
1812 		case SADB_EXT_SENSITIVITY:
1813 		case SADB_EXT_PROPOSAL:
1814 		case SADB_EXT_SUPPORTED_AUTH:
1815 		case SADB_EXT_SUPPORTED_ENCRYPT:
1816 		case SADB_EXT_SPIRANGE:
1817 		case SADB_X_EXT_POLICY:
1818 		case SADB_X_EXT_SA2:
1819 		case SADB_X_EXT_NAT_T_TYPE:
1820 		case SADB_X_EXT_NAT_T_SPORT:
1821 		case SADB_X_EXT_NAT_T_DPORT:
1822 		case SADB_X_EXT_NAT_T_OAI:
1823 		case SADB_X_EXT_NAT_T_OAR:
1824 		case SADB_X_EXT_NAT_T_FRAG:
1825 		case SADB_X_EXT_SA_REPLAY:
1826 		case SADB_X_EXT_NEW_ADDRESS_SRC:
1827 		case SADB_X_EXT_NEW_ADDRESS_DST:
1828 			mhp[ext->sadb_ext_type] = (caddr_t)ext;
1829 			break;
1830 		default:
1831 			__ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
1832 			return -1;
1833 		}
1834 
1835 		p += PFKEY_EXTLEN(ext);
1836 	}
1837 
1838 	if (p != ep) {
1839 		__ipsec_errcode = EIPSEC_INVAL_SADBMSG;
1840 		return -1;
1841 	}
1842 
1843 	__ipsec_errcode = EIPSEC_NO_ERROR;
1844 	return 0;
1845 }
1846 
1847 /*
1848  * check basic usage for sadb_msg,
1849  * NOTE: This routine is derived from netkey/key.c in KAME.
1850  * IN:	msg: pointer to message buffer.
1851  *	mhp: pointer to the buffer initialized like below:
1852  *
1853  *		caddr_t mhp[SADB_EXT_MAX + 1];
1854  *
1855  * OUT:	-1: invalid.
1856  *	 0: valid.
1857  */
1858 int
1859 pfkey_check(mhp)
1860 	caddr_t *mhp;
1861 {
1862 	struct sadb_msg *msg;
1863 
1864 	/* validity check */
1865 	if (mhp == NULL || mhp[0] == NULL) {
1866 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1867 		return -1;
1868 	}
1869 
1870 	msg = (struct sadb_msg *)mhp[0];
1871 
1872 	/* check version */
1873 	if (msg->sadb_msg_version != PF_KEY_V2) {
1874 		__ipsec_errcode = EIPSEC_INVAL_VERSION;
1875 		return -1;
1876 	}
1877 
1878 	/* check type */
1879 	if (msg->sadb_msg_type > SADB_MAX) {
1880 		__ipsec_errcode = EIPSEC_INVAL_MSGTYPE;
1881 		return -1;
1882 	}
1883 
1884 	/* check SA type */
1885 	switch (msg->sadb_msg_satype) {
1886 	case SADB_SATYPE_UNSPEC:
1887 		switch (msg->sadb_msg_type) {
1888 		case SADB_GETSPI:
1889 		case SADB_UPDATE:
1890 		case SADB_ADD:
1891 		case SADB_DELETE:
1892 		case SADB_GET:
1893 		case SADB_ACQUIRE:
1894 		case SADB_EXPIRE:
1895 			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
1896 			return -1;
1897 		}
1898 		break;
1899 	case SADB_SATYPE_ESP:
1900 	case SADB_SATYPE_AH:
1901 	case SADB_X_SATYPE_IPCOMP:
1902 	case SADB_X_SATYPE_TCPSIGNATURE:
1903 		switch (msg->sadb_msg_type) {
1904 		case SADB_X_SPDADD:
1905 		case SADB_X_SPDDELETE:
1906 		case SADB_X_SPDGET:
1907 		case SADB_X_SPDDUMP:
1908 		case SADB_X_SPDFLUSH:
1909 			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
1910 			return -1;
1911 		}
1912 		break;
1913 	case SADB_SATYPE_RSVP:
1914 	case SADB_SATYPE_OSPFV2:
1915 	case SADB_SATYPE_RIPV2:
1916 	case SADB_SATYPE_MIP:
1917 		__ipsec_errcode = EIPSEC_NOT_SUPPORTED;
1918 		return -1;
1919 	case 1:	/* XXX: What does it do ? */
1920 		if (msg->sadb_msg_type == SADB_X_PROMISC)
1921 			break;
1922 		/*FALLTHROUGH*/
1923 	default:
1924 		__ipsec_errcode = EIPSEC_INVAL_SATYPE;
1925 		return -1;
1926 	}
1927 
1928 	/* check field of upper layer protocol and address family */
1929 	if (mhp[SADB_EXT_ADDRESS_SRC] != NULL
1930 	 && mhp[SADB_EXT_ADDRESS_DST] != NULL) {
1931 		struct sadb_address *src0, *dst0;
1932 
1933 		src0 = (struct sadb_address *)(mhp[SADB_EXT_ADDRESS_SRC]);
1934 		dst0 = (struct sadb_address *)(mhp[SADB_EXT_ADDRESS_DST]);
1935 
1936 		if (src0->sadb_address_proto != dst0->sadb_address_proto) {
1937 			__ipsec_errcode = EIPSEC_PROTO_MISMATCH;
1938 			return -1;
1939 		}
1940 
1941 		if (PFKEY_ADDR_SADDR(src0)->sa_family
1942 		 != PFKEY_ADDR_SADDR(dst0)->sa_family) {
1943 			__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1944 			return -1;
1945 		}
1946 
1947 		switch (PFKEY_ADDR_SADDR(src0)->sa_family) {
1948 		case AF_INET:
1949 		case AF_INET6:
1950 			break;
1951 		default:
1952 			__ipsec_errcode = EIPSEC_INVAL_FAMILY;
1953 			return -1;
1954 		}
1955 
1956 		/*
1957 		 * prefixlen == 0 is valid because there must be the case
1958 		 * all addresses are matched.
1959 		 */
1960 	}
1961 
1962 	__ipsec_errcode = EIPSEC_NO_ERROR;
1963 	return 0;
1964 }
1965 
1966 /*
1967  * set data into sadb_msg.
1968  * `buf' must has been allocated sufficiently.
1969  */
1970 static caddr_t
1971 pfkey_setsadbmsg(buf, lim, type, tlen, satype, seq, pid)
1972 	caddr_t buf;
1973 	caddr_t lim;
1974 	u_int type, satype;
1975 	u_int tlen;
1976 	u_int32_t seq;
1977 	pid_t pid;
1978 {
1979 	struct sadb_msg *p;
1980 	u_int len;
1981 
1982 	p = (struct sadb_msg *)buf;
1983 	len = sizeof(struct sadb_msg);
1984 
1985 	if (buf + len > lim)
1986 		return NULL;
1987 
1988 	memset(p, 0, len);
1989 	p->sadb_msg_version = PF_KEY_V2;
1990 	p->sadb_msg_type = type;
1991 	p->sadb_msg_errno = 0;
1992 	p->sadb_msg_satype = satype;
1993 	p->sadb_msg_len = PFKEY_UNIT64(tlen);
1994 	p->sadb_msg_reserved = 0;
1995 	p->sadb_msg_seq = seq;
1996 	p->sadb_msg_pid = (u_int32_t)pid;
1997 
1998 	return(buf + len);
1999 }
2000 
2001 /*
2002  * copy secasvar data into sadb_address.
2003  * `buf' must has been allocated sufficiently.
2004  */
2005 static caddr_t
2006 pfkey_setsadbsa(buf, lim, spi, wsize, auth, enc, flags)
2007 	caddr_t buf;
2008 	caddr_t lim;
2009 	u_int32_t spi, flags;
2010 	u_int wsize, auth, enc;
2011 {
2012 	struct sadb_sa *p;
2013 	u_int len;
2014 
2015 	p = (struct sadb_sa *)buf;
2016 	len = sizeof(struct sadb_sa);
2017 
2018 	if (buf + len > lim)
2019 		return NULL;
2020 
2021 	memset(p, 0, len);
2022 	p->sadb_sa_len = PFKEY_UNIT64(len);
2023 	p->sadb_sa_exttype = SADB_EXT_SA;
2024 	p->sadb_sa_spi = spi;
2025 	p->sadb_sa_replay = wsize > UINT8_MAX ? UINT8_MAX: wsize;
2026 	p->sadb_sa_state = SADB_SASTATE_LARVAL;
2027 	p->sadb_sa_auth = auth;
2028 	p->sadb_sa_encrypt = enc;
2029 	p->sadb_sa_flags = flags;
2030 
2031 	return(buf + len);
2032 }
2033 
2034 /*
2035  * Set data into sadb_x_sa_replay.
2036  * `buf' must has been allocated sufficiently.
2037  */
2038 static caddr_t
2039 pfkey_setsadbxreplay(caddr_t buf, caddr_t lim, uint32_t wsize)
2040 {
2041 	struct sadb_x_sa_replay *p;
2042 	u_int len;
2043 
2044 	p = (struct sadb_x_sa_replay *)buf;
2045 	len = sizeof(struct sadb_x_sa_replay);
2046 
2047 	if (buf + len > lim)
2048 		return (NULL);
2049 
2050 	memset(p, 0, len);
2051 	p->sadb_x_sa_replay_len = PFKEY_UNIT64(len);
2052 	p->sadb_x_sa_replay_exttype = SADB_X_EXT_SA_REPLAY;
2053 	/* Convert wsize from bytes to number of packets. */
2054 	p->sadb_x_sa_replay_replay = wsize << 3;
2055 
2056 	return (buf + len);
2057 }
2058 
2059 /*
2060  * set data into sadb_address.
2061  * `buf' must has been allocated sufficiently.
2062  * prefixlen is in bits.
2063  */
2064 static caddr_t
2065 pfkey_setsadbaddr(buf, lim, exttype, saddr, prefixlen, ul_proto)
2066 	caddr_t buf;
2067 	caddr_t lim;
2068 	u_int exttype;
2069 	struct sockaddr *saddr;
2070 	u_int prefixlen;
2071 	u_int ul_proto;
2072 {
2073 	struct sadb_address *p;
2074 	u_int len;
2075 
2076 	p = (struct sadb_address *)buf;
2077 	len = sizeof(struct sadb_address) + PFKEY_ALIGN8(saddr->sa_len);
2078 
2079 	if (buf + len > lim)
2080 		return NULL;
2081 
2082 	memset(p, 0, len);
2083 	p->sadb_address_len = PFKEY_UNIT64(len);
2084 	p->sadb_address_exttype = exttype & 0xffff;
2085 	p->sadb_address_proto = ul_proto & 0xff;
2086 	p->sadb_address_prefixlen = prefixlen;
2087 	p->sadb_address_reserved = 0;
2088 
2089 	memcpy(p + 1, saddr, saddr->sa_len);
2090 
2091 	return(buf + len);
2092 }
2093 
2094 /*
2095  * set sadb_key structure after clearing buffer with zero.
2096  * OUT: the pointer of buf + len.
2097  */
2098 static caddr_t
2099 pfkey_setsadbkey(buf, lim, type, key, keylen)
2100 	caddr_t buf;
2101 	caddr_t lim;
2102 	caddr_t key;
2103 	u_int type, keylen;
2104 {
2105 	struct sadb_key *p;
2106 	u_int len;
2107 
2108 	p = (struct sadb_key *)buf;
2109 	len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen);
2110 
2111 	if (buf + len > lim)
2112 		return NULL;
2113 
2114 	memset(p, 0, len);
2115 	p->sadb_key_len = PFKEY_UNIT64(len);
2116 	p->sadb_key_exttype = type;
2117 	p->sadb_key_bits = keylen << 3;
2118 	p->sadb_key_reserved = 0;
2119 
2120 	memcpy(p + 1, key, keylen);
2121 
2122 	return buf + len;
2123 }
2124 
2125 /*
2126  * set sadb_lifetime structure after clearing buffer with zero.
2127  * OUT: the pointer of buf + len.
2128  */
2129 static caddr_t
2130 pfkey_setsadblifetime(buf, lim, type, l_alloc, l_bytes, l_addtime, l_usetime)
2131 	caddr_t buf;
2132 	caddr_t lim;
2133 	u_int type;
2134 	u_int32_t l_alloc, l_bytes, l_addtime, l_usetime;
2135 {
2136 	struct sadb_lifetime *p;
2137 	u_int len;
2138 
2139 	p = (struct sadb_lifetime *)buf;
2140 	len = sizeof(struct sadb_lifetime);
2141 
2142 	if (buf + len > lim)
2143 		return NULL;
2144 
2145 	memset(p, 0, len);
2146 	p->sadb_lifetime_len = PFKEY_UNIT64(len);
2147 	p->sadb_lifetime_exttype = type;
2148 
2149 	switch (type) {
2150 	case SADB_EXT_LIFETIME_SOFT:
2151 		p->sadb_lifetime_allocations
2152 			= (l_alloc * soft_lifetime_allocations_rate) /100;
2153 		p->sadb_lifetime_bytes
2154 			= (l_bytes * soft_lifetime_bytes_rate) /100;
2155 		p->sadb_lifetime_addtime
2156 			= (l_addtime * soft_lifetime_addtime_rate) /100;
2157 		p->sadb_lifetime_usetime
2158 			= (l_usetime * soft_lifetime_usetime_rate) /100;
2159 		break;
2160 	case SADB_EXT_LIFETIME_HARD:
2161 		p->sadb_lifetime_allocations = l_alloc;
2162 		p->sadb_lifetime_bytes = l_bytes;
2163 		p->sadb_lifetime_addtime = l_addtime;
2164 		p->sadb_lifetime_usetime = l_usetime;
2165 		break;
2166 	}
2167 
2168 	return buf + len;
2169 }
2170 
2171 /*
2172  * copy secasvar data into sadb_address.
2173  * `buf' must has been allocated sufficiently.
2174  */
2175 static caddr_t
2176 pfkey_setsadbxsa2(buf, lim, mode0, reqid)
2177 	caddr_t buf;
2178 	caddr_t lim;
2179 	u_int32_t mode0;
2180 	u_int32_t reqid;
2181 {
2182 	struct sadb_x_sa2 *p;
2183 	u_int8_t mode = mode0 & 0xff;
2184 	u_int len;
2185 
2186 	p = (struct sadb_x_sa2 *)buf;
2187 	len = sizeof(struct sadb_x_sa2);
2188 
2189 	if (buf + len > lim)
2190 		return NULL;
2191 
2192 	memset(p, 0, len);
2193 	p->sadb_x_sa2_len = PFKEY_UNIT64(len);
2194 	p->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
2195 	p->sadb_x_sa2_mode = mode;
2196 	p->sadb_x_sa2_reqid = reqid;
2197 
2198 	return(buf + len);
2199 }
2200