pfkey.c revision 62583
1/*	$FreeBSD: head/lib/libipsec/pfkey.c 62583 2000-07-04 16:22:05Z itojun $	*/
2/*	$KAME: pfkey.c,v 1.31 2000/06/10 14:17:43 sakane Exp $	*/
3
4/*
5 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <sys/types.h>
34#include <sys/param.h>
35#include <sys/socket.h>
36#include <net/pfkeyv2.h>
37#include <netkey/key_var.h>
38#include <netinet/in.h>
39#include <netinet6/ipsec.h>
40
41#include <stdlib.h>
42#include <unistd.h>
43#include <string.h>
44#include <errno.h>
45
46#include "ipsec_strerror.h"
47#include "libpfkey.h"
48
49#define CALLOC(size, cast) (cast)calloc(1, (size))
50
51static int pfkey_send_x1 __P((int, u_int, u_int, u_int, struct sockaddr *,
52	struct sockaddr *, u_int32_t, u_int32_t, u_int, caddr_t,
53	u_int, u_int, u_int, u_int, u_int, u_int32_t, u_int32_t,
54	u_int32_t, u_int32_t, u_int32_t));
55static int pfkey_send_x2 __P((int, u_int, u_int, u_int,
56	struct sockaddr *, struct sockaddr *, u_int32_t));
57static int pfkey_send_x3 __P((int, u_int, u_int));
58static int pfkey_send_x4 __P((int, u_int, struct sockaddr *, u_int,
59	struct sockaddr *, u_int, u_int, char *, int, u_int32_t));
60static int pfkey_send_x5 __P((int, u_int, u_int32_t));
61
62static caddr_t pfkey_setsadbmsg __P((caddr_t, u_int, u_int,
63	u_int, u_int32_t, pid_t));
64static caddr_t pfkey_setsadbsa __P((caddr_t, u_int32_t, u_int,
65	u_int, u_int, u_int32_t));
66static caddr_t pfkey_setsadbaddr __P((caddr_t, u_int,
67	struct sockaddr *, u_int, u_int));
68static caddr_t pfkey_setsadbkey __P((caddr_t, u_int, caddr_t, u_int));
69static caddr_t pfkey_setsadblifetime __P((caddr_t, u_int, u_int32_t, u_int32_t,
70	u_int32_t, u_int32_t));
71static caddr_t pfkey_setsadbxsa2 __P((caddr_t, u_int32_t, u_int32_t));
72
73/*
74 * check key length against algorithm specified.
75 * supported is either SADB_EXT_SUPPORTED_ENCRYPT or SADB_EXT_SUPPORTED_AUTH.
76 * Refer to keyv2.h to get more info.
77 * keylen is the unit of bit.
78 * OUT:
79 *	-1: invalid.
80 *	 0: valid.
81 */
82struct sadb_msg *ipsec_supported = NULL;
83
84int
85ipsec_check_keylen(supported, alg_id, keylen)
86	u_int supported;
87	u_int alg_id;
88	u_int keylen;
89{
90	u_int tlen;
91	caddr_t p;
92	struct sadb_supported *sup;
93	struct sadb_alg *alg;
94
95	/* validity check */
96	if (ipsec_supported == NULL) {
97		__ipsec_errcode = EIPSEC_DO_GET_SUPP_LIST;
98		return -1;
99	}
100	switch (supported) {
101	case SADB_EXT_SUPPORTED_AUTH:
102	case SADB_EXT_SUPPORTED_ENCRYPT:
103		break;
104	default:
105		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
106		return -1;
107	}
108
109	tlen = ipsec_supported->sadb_msg_len - sizeof(struct sadb_msg);
110	p = (caddr_t)ipsec_supported + sizeof(struct sadb_msg);
111
112	for (;
113	     tlen > 0;
114	     tlen -= sup->sadb_supported_len, p += sup->sadb_supported_len) {
115
116		sup = (struct sadb_supported *)p;
117
118		if (sup->sadb_supported_exttype != supported)
119			continue;
120
121	    {
122		u_int ttlen = sup->sadb_supported_len;
123		caddr_t pp = p + sizeof(*sup);
124
125		for (;
126		     ttlen > 0;
127	     	     ttlen -= sizeof(*alg), pp += sizeof(*alg)) {
128			alg = (struct sadb_alg *)pp;
129
130			if (alg->sadb_alg_id == alg_id)
131				goto found;
132	    	}
133	    }
134	}
135
136	__ipsec_errcode = EIPSEC_NOT_SUPPORTED;
137	return -1;
138	/* NOTREACHED */
139
140    found:
141	if (keylen < alg->sadb_alg_minbits
142	 || keylen > alg->sadb_alg_maxbits) {
143		__ipsec_errcode = EIPSEC_INVAL_KEYLEN;
144		return -1;
145	}
146
147	__ipsec_errcode = EIPSEC_NO_ERROR;
148	return 0;
149}
150
151/*
152 * set the rate for SOFT lifetime against HARD one.
153 * If rate is more than 100 or equal to zero, then set to 100.
154 */
155static u_int soft_lifetime_allocations_rate = PFKEY_SOFT_LIFETIME_RATE;
156static u_int soft_lifetime_bytes_rate = PFKEY_SOFT_LIFETIME_RATE;
157static u_int soft_lifetime_addtime_rate = PFKEY_SOFT_LIFETIME_RATE;
158static u_int soft_lifetime_usetime_rate = PFKEY_SOFT_LIFETIME_RATE;
159
160u_int
161pfkey_set_softrate(type, rate)
162	u_int type, rate;
163{
164	__ipsec_errcode = EIPSEC_NO_ERROR;
165
166	if (rate > 100 || rate == 0)
167		rate = 100;
168
169	switch (type) {
170	case SADB_X_LIFETIME_ALLOCATIONS:
171		soft_lifetime_allocations_rate = rate;
172		return 0;
173	case SADB_X_LIFETIME_BYTES:
174		soft_lifetime_bytes_rate = rate;
175		return 0;
176	case SADB_X_LIFETIME_ADDTIME:
177		soft_lifetime_addtime_rate = rate;
178		return 0;
179	case SADB_X_LIFETIME_USETIME:
180		soft_lifetime_usetime_rate = rate;
181		return 0;
182	}
183
184	__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
185	return 1;
186}
187
188/*
189 * get current rate for SOFT lifetime against HARD one.
190 * ATTENTION: ~0 is returned if invalid type was passed.
191 */
192u_int
193pfkey_get_softrate(type)
194	u_int type;
195{
196	switch (type) {
197	case SADB_X_LIFETIME_ALLOCATIONS:
198		return soft_lifetime_allocations_rate;
199	case SADB_X_LIFETIME_BYTES:
200		return soft_lifetime_bytes_rate;
201	case SADB_X_LIFETIME_ADDTIME:
202		return soft_lifetime_addtime_rate;
203	case SADB_X_LIFETIME_USETIME:
204		return soft_lifetime_usetime_rate;
205	}
206
207	return ~0;
208}
209
210/*
211 * sending SADB_GETSPI message to the kernel.
212 * OUT:
213 *	positive: success and return length sent.
214 *	-1	: error occured, and set errno.
215 */
216int
217pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq)
218	int so;
219	u_int satype, mode;
220	struct sockaddr *src, *dst;
221	u_int32_t min, max, reqid, seq;
222{
223	struct sadb_msg *newmsg;
224	int len;
225	int need_spirange = 0;
226	caddr_t p;
227	int plen;
228
229	/* validity check */
230	if (src == NULL || dst == NULL) {
231		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
232		return -1;
233	}
234	if (src->sa_family != dst->sa_family) {
235		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
236		return -1;
237	}
238	if (min > max || (min > 0 && min <= 255)) {
239		__ipsec_errcode = EIPSEC_INVAL_SPI;
240		return -1;
241	}
242	switch (src->sa_family) {
243	case AF_INET:
244		plen = sizeof(struct in_addr) << 3;
245		break;
246	case AF_INET6:
247		plen = sizeof(struct in6_addr) << 3;
248		break;
249	default:
250		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
251		return -1;
252	}
253
254	/* create new sadb_msg to send. */
255	len = sizeof(struct sadb_msg)
256		+ sizeof(struct sadb_x_sa2)
257		+ sizeof(struct sadb_address)
258		+ PFKEY_ALIGN8(src->sa_len)
259		+ sizeof(struct sadb_address)
260		+ PFKEY_ALIGN8(dst->sa_len);
261
262	if (min > 255 && max < ~0) {
263		need_spirange++;
264		len += sizeof(struct sadb_spirange);
265	}
266
267	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
268		__ipsec_set_strerror(strerror(errno));
269		return -1;
270	}
271
272	p = pfkey_setsadbmsg((caddr_t)newmsg, SADB_GETSPI,
273	                     len, satype, seq, getpid());
274
275	p = pfkey_setsadbxsa2(p, mode, reqid);
276
277	/* set sadb_address for source */
278	p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_SRC, src, plen,
279	    IPSEC_ULPROTO_ANY);
280
281	/* set sadb_address for destination */
282	p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_DST, dst, plen,
283	    IPSEC_ULPROTO_ANY);
284
285	/* proccessing spi range */
286	if (need_spirange) {
287		int _len = sizeof(struct sadb_spirange);
288
289#define _SADB_SPIRANGE(p) ((struct sadb_spirange *)(p))
290		_SADB_SPIRANGE(p)->sadb_spirange_len = PFKEY_UNIT64(_len);
291		_SADB_SPIRANGE(p)->sadb_spirange_exttype = SADB_EXT_SPIRANGE;
292		_SADB_SPIRANGE(p)->sadb_spirange_min = min;
293		_SADB_SPIRANGE(p)->sadb_spirange_max = max;
294#undef _SADB_SPIRANGE(p)
295		p += _len;
296	}
297
298	/* send message */
299	len = pfkey_send(so, newmsg, len);
300	free(newmsg);
301
302	if (len < 0)
303		return -1;
304
305	__ipsec_errcode = EIPSEC_NO_ERROR;
306	return len;
307}
308
309/*
310 * sending SADB_UPDATE message to the kernel.
311 * The length of key material is a_keylen + e_keylen.
312 * OUT:
313 *	positive: success and return length sent.
314 *	-1	: error occured, and set errno.
315 */
316int
317pfkey_send_update(so, satype, mode, src, dst, spi, reqid, wsize,
318		keymat, e_type, e_keylen, a_type, a_keylen, flags,
319		l_alloc, l_bytes, l_addtime, l_usetime, seq)
320	int so;
321	u_int satype, mode, wsize;
322	struct sockaddr *src, *dst;
323	u_int32_t spi, reqid;
324	caddr_t keymat;
325	u_int e_type, e_keylen, a_type, a_keylen, flags;
326	u_int32_t l_alloc;
327	u_int64_t l_bytes, l_addtime, l_usetime;
328	u_int32_t seq;
329{
330	int len;
331	if ((len = pfkey_send_x1(so, SADB_UPDATE, satype, mode, src, dst, spi,
332			reqid, wsize,
333			keymat, e_type, e_keylen, a_type, a_keylen, flags,
334			l_alloc, l_bytes, l_addtime, l_usetime, seq)) < 0)
335		return -1;
336
337	return len;
338}
339
340/*
341 * sending SADB_ADD message to the kernel.
342 * The length of key material is a_keylen + e_keylen.
343 * OUT:
344 *	positive: success and return length sent.
345 *	-1	: error occured, and set errno.
346 */
347int
348pfkey_send_add(so, satype, mode, src, dst, spi, reqid, wsize,
349		keymat, e_type, e_keylen, a_type, a_keylen, flags,
350		l_alloc, l_bytes, l_addtime, l_usetime, seq)
351	int so;
352	u_int satype, mode, wsize;
353	struct sockaddr *src, *dst;
354	u_int32_t spi, reqid;
355	caddr_t keymat;
356	u_int e_type, e_keylen, a_type, a_keylen, flags;
357	u_int32_t l_alloc;
358	u_int64_t l_bytes, l_addtime, l_usetime;
359	u_int32_t seq;
360{
361	int len;
362	if ((len = pfkey_send_x1(so, SADB_ADD, satype, mode, src, dst, spi,
363			reqid, wsize,
364			keymat, e_type, e_keylen, a_type, a_keylen, flags,
365			l_alloc, l_bytes, l_addtime, l_usetime, seq)) < 0)
366		return -1;
367
368	return len;
369}
370
371/*
372 * sending SADB_DELETE message to the kernel.
373 * OUT:
374 *	positive: success and return length sent.
375 *	-1	: error occured, and set errno.
376 */
377int
378pfkey_send_delete(so, satype, mode, src, dst, spi)
379	int so;
380	u_int satype, mode;
381	struct sockaddr *src, *dst;
382	u_int32_t spi;
383{
384	int len;
385	if ((len = pfkey_send_x2(so, SADB_DELETE, satype, mode, src, dst, spi)) < 0)
386		return -1;
387
388	return len;
389}
390
391/*
392 * sending SADB_GET message to the kernel.
393 * OUT:
394 *	positive: success and return length sent.
395 *	-1	: error occured, and set errno.
396 */
397int
398pfkey_send_get(so, satype, mode, src, dst, spi)
399	int so;
400	u_int satype, mode;
401	struct sockaddr *src, *dst;
402	u_int32_t spi;
403{
404	int len;
405	if ((len = pfkey_send_x2(so, SADB_GET, satype, mode, src, dst, spi)) < 0)
406		return -1;
407
408	return len;
409}
410
411/*
412 * sending SADB_REGISTER message to the kernel.
413 * OUT:
414 *	positive: success and return length sent.
415 *	-1	: error occured, and set errno.
416 */
417int
418pfkey_send_register(so, satype)
419	int so;
420	u_int satype;
421{
422	int len;
423
424	if ((len = pfkey_send_x3(so, SADB_REGISTER, satype)) < 0)
425		return -1;
426
427	return len;
428}
429
430/*
431 * receiving SADB_REGISTER message from the kernel, and copy buffer for
432 * sadb_supported returned into ipsec_supported.
433 * OUT:
434 *	 0: success and return length sent.
435 *	-1: error occured, and set errno.
436 */
437int
438pfkey_recv_register(so)
439	int so;
440{
441	pid_t pid = getpid();
442	struct sadb_msg *newmsg;
443	struct sadb_supported *sup;
444	caddr_t p;
445	int tlen;
446
447	/* receive message */
448	do {
449		if ((newmsg = pfkey_recv(so)) == NULL)
450			return -1;
451
452	} while (newmsg->sadb_msg_type != SADB_REGISTER
453	    || newmsg->sadb_msg_pid != pid);
454
455	/* check and fix */
456	newmsg->sadb_msg_len = PFKEY_UNUNIT64(newmsg->sadb_msg_len);
457
458	tlen = newmsg->sadb_msg_len - sizeof(struct sadb_msg);
459	p = (caddr_t)newmsg + sizeof(struct sadb_msg);
460	while (tlen > 0) {
461		sup = (struct sadb_supported *)p;
462		switch (sup->sadb_supported_exttype) {
463		case SADB_EXT_SUPPORTED_AUTH:
464		case SADB_EXT_SUPPORTED_ENCRYPT:
465			sup->sadb_supported_len = PFKEY_EXTLEN(sup);
466			break;
467		default:
468			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
469			free(newmsg);
470			return -1;
471		}
472
473		tlen -= sup->sadb_supported_len;
474		p += sup->sadb_supported_len;
475	}
476
477	if (tlen < 0) {
478		__ipsec_errcode = EIPSEC_INVAL_SATYPE;
479		return -1;
480	}
481
482	if (ipsec_supported != NULL)
483		free(ipsec_supported);
484
485	ipsec_supported = newmsg;
486
487	__ipsec_errcode = EIPSEC_NO_ERROR;
488	return 0;
489}
490
491/*
492 * sending SADB_FLUSH message to the kernel.
493 * OUT:
494 *	positive: success and return length sent.
495 *	-1	: error occured, and set errno.
496 */
497int
498pfkey_send_flush(so, satype)
499	int so;
500	u_int satype;
501{
502	int len;
503
504	if ((len = pfkey_send_x3(so, SADB_FLUSH, satype)) < 0)
505		return -1;
506
507	return len;
508}
509
510/*
511 * sending SADB_DUMP message to the kernel.
512 * OUT:
513 *	positive: success and return length sent.
514 *	-1	: error occured, and set errno.
515 */
516int
517pfkey_send_dump(so, satype)
518	int so;
519	u_int satype;
520{
521	int len;
522
523	if ((len = pfkey_send_x3(so, SADB_DUMP, satype)) < 0)
524		return -1;
525
526	return len;
527}
528
529/*
530 * sending SADB_X_PROMISC message to the kernel.
531 * NOTE that this function handles promisc mode toggle only.
532 * IN:
533 *	flag:	set promisc off if zero, set promisc on if non-zero.
534 * OUT:
535 *	positive: success and return length sent.
536 *	-1	: error occured, and set errno.
537 *	0     : error occured, and set errno.
538 *	others: a pointer to new allocated buffer in which supported
539 *	        algorithms is.
540 */
541int
542pfkey_send_promisc_toggle(so, flag)
543	int so;
544	int flag;
545{
546	int len;
547
548	if ((len = pfkey_send_x3(so, SADB_X_PROMISC, (flag ? 1 : 0))) < 0)
549		return -1;
550
551	return len;
552}
553
554/*
555 * sending SADB_X_SPDADD message to the kernel.
556 * OUT:
557 *	positive: success and return length sent.
558 *	-1	: error occured, and set errno.
559 */
560int
561pfkey_send_spdadd(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
562	int so;
563	struct sockaddr *src, *dst;
564	u_int prefs, prefd, proto;
565	caddr_t policy;
566	int policylen;
567	u_int32_t seq;
568{
569	int len;
570
571	if ((len = pfkey_send_x4(so, SADB_X_SPDADD,
572				src, prefs, dst, prefd, proto,
573				policy, policylen, seq)) < 0)
574		return -1;
575
576	return len;
577}
578
579/*
580 * sending SADB_X_SPDUPDATE message to the kernel.
581 * OUT:
582 *	positive: success and return length sent.
583 *	-1	: error occured, and set errno.
584 */
585int
586pfkey_send_spdupdate(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
587	int so;
588	struct sockaddr *src, *dst;
589	u_int prefs, prefd, proto;
590	caddr_t policy;
591	int policylen;
592	u_int32_t seq;
593{
594	int len;
595
596	if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE,
597				src, prefs, dst, prefd, proto,
598				policy, policylen, seq)) < 0)
599		return -1;
600
601	return len;
602}
603
604/*
605 * sending SADB_X_SPDDELETE message to the kernel.
606 * OUT:
607 *	positive: success and return length sent.
608 *	-1	: error occured, and set errno.
609 */
610int
611pfkey_send_spddelete(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
612	int so;
613	struct sockaddr *src, *dst;
614	u_int prefs, prefd, proto;
615	caddr_t policy;
616	int policylen;
617	u_int32_t seq;
618{
619	int len;
620
621	if (policylen != sizeof(struct sadb_x_policy)) {
622		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
623		return -1;
624	}
625
626	if ((len = pfkey_send_x4(so, SADB_X_SPDDELETE,
627				src, prefs, dst, prefd, proto,
628				policy, policylen, seq)) < 0)
629		return -1;
630
631	return len;
632}
633
634/*
635 * sending SADB_X_SPDDELETE message to the kernel.
636 * OUT:
637 *	positive: success and return length sent.
638 *	-1	: error occured, and set errno.
639 */
640int
641pfkey_send_spddelete2(so, spid)
642	int so;
643	u_int32_t spid;
644{
645	int len;
646
647	if ((len = pfkey_send_x5(so, SADB_X_SPDDELETE2, spid)) < 0)
648		return -1;
649
650	return len;
651}
652
653/*
654 * sending SADB_X_SPDGET message to the kernel.
655 * OUT:
656 *	positive: success and return length sent.
657 *	-1	: error occured, and set errno.
658 */
659int
660pfkey_send_spdget(so, spid)
661	int so;
662	u_int32_t spid;
663{
664	int len;
665
666	if ((len = pfkey_send_x5(so, SADB_X_SPDGET, spid)) < 0)
667		return -1;
668
669	return len;
670}
671
672/*
673 * sending SADB_X_SPDSETIDX message to the kernel.
674 * OUT:
675 *	positive: success and return length sent.
676 *	-1	: error occured, and set errno.
677 */
678int
679pfkey_send_spdsetidx(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
680	int so;
681	struct sockaddr *src, *dst;
682	u_int prefs, prefd, proto;
683	caddr_t policy;
684	int policylen;
685	u_int32_t seq;
686{
687	int len;
688
689	if (policylen != sizeof(struct sadb_x_policy)) {
690		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
691		return -1;
692	}
693
694	if ((len = pfkey_send_x4(so, SADB_X_SPDSETIDX,
695				src, prefs, dst, prefd, proto,
696				policy, policylen, seq)) < 0)
697		return -1;
698
699	return len;
700}
701
702/*
703 * sending SADB_SPDFLUSH message to the kernel.
704 * OUT:
705 *	positive: success and return length sent.
706 *	-1	: error occured, and set errno.
707 */
708int
709pfkey_send_spdflush(so)
710	int so;
711{
712	int len;
713
714	if ((len = pfkey_send_x3(so, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC)) < 0)
715		return -1;
716
717	return len;
718}
719
720/*
721 * sending SADB_SPDDUMP message to the kernel.
722 * OUT:
723 *	positive: success and return length sent.
724 *	-1	: error occured, and set errno.
725 */
726int
727pfkey_send_spddump(so)
728	int so;
729{
730	int len;
731
732	if ((len = pfkey_send_x3(so, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC)) < 0)
733		return -1;
734
735	return len;
736}
737
738/* sending SADB_ADD or SADB_UPDATE message to the kernel */
739static int
740pfkey_send_x1(so, type, satype, mode, src, dst, spi, reqid, wsize,
741		keymat, e_type, e_keylen, a_type, a_keylen, flags,
742		l_alloc, l_bytes, l_addtime, l_usetime, seq)
743	int so;
744	u_int type, satype, mode;
745	struct sockaddr *src, *dst;
746	u_int32_t spi, reqid;
747	u_int wsize;
748	caddr_t keymat;
749	u_int e_type, e_keylen, a_type, a_keylen, flags;
750	u_int32_t l_alloc, l_bytes, l_addtime, l_usetime, seq;
751{
752	struct sadb_msg *newmsg;
753	int len;
754	caddr_t p;
755	int plen;
756
757	/* validity check */
758	if (src == NULL || dst == NULL) {
759		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
760		return -1;
761	}
762	if (src->sa_family != dst->sa_family) {
763		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
764		return -1;
765	}
766	switch (src->sa_family) {
767	case AF_INET:
768		plen = sizeof(struct in_addr) << 3;
769		break;
770	case AF_INET6:
771		plen = sizeof(struct in6_addr) << 3;
772		break;
773	default:
774		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
775		return -1;
776	}
777
778	switch (satype) {
779	case SADB_SATYPE_ESP:
780		if (e_type == SADB_EALG_NONE) {
781			__ipsec_errcode = EIPSEC_NO_ALGS;
782			return -1;
783		}
784		break;
785	case SADB_SATYPE_AH:
786		if (e_type != SADB_EALG_NONE) {
787			__ipsec_errcode = EIPSEC_INVAL_ALGS;
788			return -1;
789		}
790		if (a_type == SADB_AALG_NONE) {
791			__ipsec_errcode = EIPSEC_NO_ALGS;
792			return -1;
793		}
794		break;
795	case SADB_X_SATYPE_IPCOMP:
796		break;
797	default:
798		__ipsec_errcode = EIPSEC_INVAL_SATYPE;
799		return -1;
800	}
801
802	/* create new sadb_msg to reply. */
803	len = sizeof(struct sadb_msg)
804		+ sizeof(struct sadb_sa)
805		+ sizeof(struct sadb_x_sa2)
806		+ sizeof(struct sadb_address)
807		+ PFKEY_ALIGN8(src->sa_len)
808		+ sizeof(struct sadb_address)
809		+ PFKEY_ALIGN8(dst->sa_len)
810		+ sizeof(struct sadb_lifetime)
811		+ sizeof(struct sadb_lifetime);
812
813	if (e_type != SADB_EALG_NONE)
814		len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(e_keylen));
815	if (a_type != SADB_AALG_NONE)
816		len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(a_keylen));
817
818	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
819		__ipsec_set_strerror(strerror(errno));
820		return -1;
821	}
822
823	p = pfkey_setsadbmsg((caddr_t)newmsg, type, len,
824	                     satype, seq, getpid());
825	p = pfkey_setsadbsa(p, spi, wsize, a_type, e_type, flags);
826	p = pfkey_setsadbxsa2(p, mode, reqid);
827	p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_SRC, src, plen,
828	    IPSEC_ULPROTO_ANY);
829	p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_DST, dst, plen,
830	    IPSEC_ULPROTO_ANY);
831
832	if (e_type != SADB_EALG_NONE)
833		p = pfkey_setsadbkey(p, SADB_EXT_KEY_ENCRYPT,
834		                   keymat, e_keylen);
835	if (a_type != SADB_AALG_NONE)
836		p = pfkey_setsadbkey(p, SADB_EXT_KEY_AUTH,
837		                   keymat + e_keylen, a_keylen);
838
839	/* set sadb_lifetime for destination */
840	p = pfkey_setsadblifetime(p, SADB_EXT_LIFETIME_HARD,
841			l_alloc, l_bytes, l_addtime, l_usetime);
842	p = pfkey_setsadblifetime(p, SADB_EXT_LIFETIME_SOFT,
843			l_alloc, l_bytes, l_addtime, l_usetime);
844
845	/* send message */
846	len = pfkey_send(so, newmsg, len);
847	free(newmsg);
848
849	if (len < 0)
850		return -1;
851
852	__ipsec_errcode = EIPSEC_NO_ERROR;
853	return len;
854}
855
856/* sending SADB_DELETE or SADB_GET message to the kernel */
857static int
858pfkey_send_x2(so, type, satype, mode, src, dst, spi)
859	int so;
860	u_int type, satype, mode;
861	struct sockaddr *src, *dst;
862	u_int32_t spi;
863{
864	struct sadb_msg *newmsg;
865	int len;
866	caddr_t p;
867	int plen;
868
869	/* validity check */
870	if (src == NULL || dst == NULL) {
871		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
872		return -1;
873	}
874	if (src->sa_family != dst->sa_family) {
875		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
876		return -1;
877	}
878	switch (src->sa_family) {
879	case AF_INET:
880		plen = sizeof(struct in_addr) << 3;
881		break;
882	case AF_INET6:
883		plen = sizeof(struct in6_addr) << 3;
884		break;
885	default:
886		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
887		return -1;
888	}
889
890	/* create new sadb_msg to reply. */
891	len = sizeof(struct sadb_msg)
892		+ sizeof(struct sadb_sa)
893		+ sizeof(struct sadb_address)
894		+ PFKEY_ALIGN8(src->sa_len)
895		+ sizeof(struct sadb_address)
896		+ PFKEY_ALIGN8(dst->sa_len);
897
898	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
899		__ipsec_set_strerror(strerror(errno));
900		return -1;
901	}
902
903	p = pfkey_setsadbmsg((caddr_t)newmsg, type, len, satype, 0, getpid());
904	p = pfkey_setsadbsa(p, spi, 0, 0, 0, 0);
905	p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_SRC, src, plen,
906	    IPSEC_ULPROTO_ANY);
907	p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_DST, dst, plen,
908	    IPSEC_ULPROTO_ANY);
909
910	/* send message */
911	len = pfkey_send(so, newmsg, len);
912	free(newmsg);
913
914	if (len < 0)
915		return -1;
916
917	__ipsec_errcode = EIPSEC_NO_ERROR;
918	return len;
919}
920
921/*
922 * sending SADB_REGISTER, SADB_FLUSH, SADB_DUMP or SADB_X_PROMISC message
923 * to the kernel
924 */
925static int
926pfkey_send_x3(so, type, satype)
927	int so;
928	u_int type, satype;
929{
930	struct sadb_msg *newmsg;
931	int len;
932
933	/* validity check */
934	switch (type) {
935	case SADB_X_PROMISC:
936		if (satype != 0 && satype != 1) {
937			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
938			return -1;
939		}
940		break;
941	default:
942		switch (satype) {
943		case SADB_SATYPE_UNSPEC:
944		case SADB_SATYPE_AH:
945		case SADB_SATYPE_ESP:
946		case SADB_X_SATYPE_IPCOMP:
947			break;
948		default:
949			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
950			return -1;
951		}
952	}
953
954	/* create new sadb_msg to send. */
955	len = sizeof(struct sadb_msg);
956
957	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
958		__ipsec_set_strerror(strerror(errno));
959		return -1;
960	}
961
962	(void)pfkey_setsadbmsg((caddr_t)newmsg, type, len, satype, 0, getpid());
963
964	/* send message */
965	len = pfkey_send(so, newmsg, len);
966	free(newmsg);
967
968	if (len < 0)
969		return -1;
970
971	__ipsec_errcode = EIPSEC_NO_ERROR;
972	return len;
973}
974
975/* sending SADB_X_SPDADD message to the kernel */
976static int
977pfkey_send_x4(so, type, src, prefs, dst, prefd, proto, policy, policylen, seq)
978	int so;
979	struct sockaddr *src, *dst;
980	u_int type, prefs, prefd, proto;
981	char *policy;
982	int policylen;
983	u_int32_t seq;
984{
985	struct sadb_msg *newmsg;
986	int len;
987	caddr_t p;
988	int plen;
989
990	/* validity check */
991	if (src == NULL || dst == NULL) {
992		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
993		return -1;
994	}
995	if (src->sa_family != dst->sa_family) {
996		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
997		return -1;
998	}
999
1000	switch (src->sa_family) {
1001	case AF_INET:
1002		plen = sizeof(struct in_addr) << 3;
1003		break;
1004	case AF_INET6:
1005		plen = sizeof(struct in6_addr) << 3;
1006		break;
1007	default:
1008		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
1009		return -1;
1010	}
1011	if (prefs > plen || prefd > plen) {
1012		__ipsec_errcode = EIPSEC_INVAL_PREFIXLEN;
1013		return -1;
1014	}
1015
1016	/* create new sadb_msg to reply. */
1017	len = sizeof(struct sadb_msg)
1018		+ sizeof(struct sadb_address)
1019		+ PFKEY_ALIGN8(src->sa_len)
1020		+ sizeof(struct sadb_address)
1021		+ PFKEY_ALIGN8(src->sa_len)
1022		+ policylen;
1023
1024	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
1025		__ipsec_set_strerror(strerror(errno));
1026		return -1;
1027	}
1028
1029	p = pfkey_setsadbmsg((caddr_t)newmsg, type, len,
1030	                     SADB_SATYPE_UNSPEC, seq, getpid());
1031	p = pfkey_setsadbaddr(p,
1032	                      SADB_EXT_ADDRESS_SRC,
1033	                      src,
1034	                      prefs,
1035	                      proto);
1036	p = pfkey_setsadbaddr(p,
1037	                      SADB_EXT_ADDRESS_DST,
1038	                      dst,
1039	                      prefd,
1040	                      proto);
1041	memcpy(p, policy, policylen);
1042
1043	/* send message */
1044	len = pfkey_send(so, newmsg, len);
1045	free(newmsg);
1046
1047	if (len < 0)
1048		return -1;
1049
1050	__ipsec_errcode = EIPSEC_NO_ERROR;
1051	return len;
1052}
1053
1054/* sending SADB_X_SPDGET or SADB_X_SPDDELETE message to the kernel */
1055static int
1056pfkey_send_x5(so, type, spid)
1057	int so;
1058	u_int type;
1059	u_int32_t spid;
1060{
1061	struct sadb_msg *newmsg;
1062	struct sadb_x_policy xpl;
1063	int len;
1064	caddr_t p;
1065
1066	/* create new sadb_msg to reply. */
1067	len = sizeof(struct sadb_msg)
1068		+ sizeof(xpl);
1069
1070	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
1071		__ipsec_set_strerror(strerror(errno));
1072		return -1;
1073	}
1074
1075	p = pfkey_setsadbmsg((caddr_t)newmsg, type, len,
1076	                     SADB_SATYPE_UNSPEC, 0, getpid());
1077
1078	memset(&xpl, 0, sizeof(xpl));
1079	xpl.sadb_x_policy_len = PFKEY_UNUNIT64(sizeof(xpl));
1080	xpl.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
1081	xpl.sadb_x_policy_id = spid;
1082
1083	memcpy(p, &xpl, sizeof(xpl));
1084
1085	/* send message */
1086	len = pfkey_send(so, newmsg, len);
1087	free(newmsg);
1088
1089	if (len < 0)
1090		return -1;
1091
1092	__ipsec_errcode = EIPSEC_NO_ERROR;
1093	return len;
1094}
1095
1096/*
1097 * open a socket.
1098 * OUT:
1099 *	-1: fail.
1100 *	others : success and return value of socket.
1101 */
1102int
1103pfkey_open()
1104{
1105	int so;
1106	const int bufsiz = 128 * 1024;	/*is 128K enough?*/
1107
1108	if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) {
1109		__ipsec_set_strerror(strerror(errno));
1110		return -1;
1111	}
1112
1113	/*
1114	 * This is a temporary workaround for KAME PR 154.
1115	 * Don't really care even if it fails.
1116	 */
1117	(void)setsockopt(so, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz));
1118	(void)setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz));
1119
1120	__ipsec_errcode = EIPSEC_NO_ERROR;
1121	return so;
1122}
1123
1124/*
1125 * close a socket.
1126 * OUT:
1127 *	 0: success.
1128 *	-1: fail.
1129 */
1130void
1131pfkey_close(so)
1132	int so;
1133{
1134	(void)close(so);
1135
1136	__ipsec_errcode = EIPSEC_NO_ERROR;
1137	return;
1138}
1139
1140/*
1141 * receive sadb_msg data, and return pointer to new buffer allocated.
1142 * Must free this buffer later.
1143 * OUT:
1144 *	NULL	: error occured.
1145 *	others	: a pointer to sadb_msg structure.
1146 */
1147struct sadb_msg *
1148pfkey_recv(so)
1149	int so;
1150{
1151	struct sadb_msg buf, *newmsg;
1152	int len, reallen;
1153
1154	while ((len = recv(so, (caddr_t)&buf, sizeof(buf), MSG_PEEK)) < 0) {
1155		if (errno == EINTR) continue;
1156		__ipsec_set_strerror(strerror(errno));
1157		return NULL;
1158	}
1159
1160	if (len < sizeof(buf)) {
1161		recv(so, (caddr_t)&buf, sizeof(buf), 0);
1162		__ipsec_errcode = EIPSEC_MAX;
1163		return NULL;
1164	}
1165
1166	/* read real message */
1167	reallen = PFKEY_UNUNIT64(buf.sadb_msg_len);
1168	if ((newmsg = CALLOC(reallen, struct sadb_msg *)) == 0) {
1169		__ipsec_set_strerror(strerror(errno));
1170		return NULL;
1171	}
1172
1173	while ((len = recv(so, (caddr_t)newmsg, reallen, 0)) < 0) {
1174		if (errno == EINTR) continue;
1175		__ipsec_set_strerror(strerror(errno));
1176		free(newmsg);
1177		return NULL;
1178	}
1179
1180	if (len != reallen) {
1181		__ipsec_errcode = EIPSEC_SYSTEM_ERROR;
1182		free(newmsg);
1183		return NULL;
1184	}
1185
1186	__ipsec_errcode = EIPSEC_NO_ERROR;
1187	return newmsg;
1188}
1189
1190/*
1191 * send message to a socket.
1192 * OUT:
1193 *	 others: success and return length sent.
1194 *	-1     : fail.
1195 */
1196int
1197pfkey_send(so, msg, len)
1198	int so;
1199	struct sadb_msg *msg;
1200	int len;
1201{
1202	if ((len = send(so, (caddr_t)msg, len, 0)) < 0) {
1203		__ipsec_set_strerror(strerror(errno));
1204		return -1;
1205	}
1206
1207	__ipsec_errcode = EIPSEC_NO_ERROR;
1208	return len;
1209}
1210
1211/*
1212 * %%% Utilities
1213 * NOTE: These functions are derived from netkey/key.c in KAME.
1214 */
1215/*
1216 * set the pointer to each header in this message buffer.
1217 * IN:	msg: pointer to message buffer.
1218 *	mhp: pointer to the buffer initialized like below:
1219 *		caddr_t mhp[SADB_EXT_MAX + 1];
1220 * OUT:	-1: invalid.
1221 *	 0: valid.
1222 */
1223int
1224pfkey_align(msg, mhp)
1225	struct sadb_msg *msg;
1226	caddr_t *mhp;
1227{
1228	struct sadb_ext *ext;
1229	int tlen, extlen;
1230	int i;
1231
1232	/* validity check */
1233	if (msg == NULL || mhp == NULL) {
1234		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1235		return -1;
1236	}
1237
1238	/* initialize */
1239	for (i = 0; i < SADB_EXT_MAX + 1; i++)
1240		mhp[i] = NULL;
1241
1242	mhp[0] = (caddr_t)msg;
1243
1244	tlen = PFKEY_UNUNIT64(msg->sadb_msg_len) - sizeof(struct sadb_msg);
1245	ext = (struct sadb_ext *)((caddr_t)msg + sizeof(struct sadb_msg));
1246
1247	while (tlen > 0) {
1248		/* duplicate check */
1249		/* XXX Are there duplication either KEY_AUTH or KEY_ENCRYPT ?*/
1250		if (mhp[ext->sadb_ext_type] != NULL) {
1251			__ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
1252			return -1;
1253		}
1254
1255		/* set pointer */
1256		switch (ext->sadb_ext_type) {
1257		case SADB_EXT_SA:
1258		case SADB_EXT_LIFETIME_CURRENT:
1259		case SADB_EXT_LIFETIME_HARD:
1260		case SADB_EXT_LIFETIME_SOFT:
1261		case SADB_EXT_ADDRESS_SRC:
1262		case SADB_EXT_ADDRESS_DST:
1263		case SADB_EXT_ADDRESS_PROXY:
1264		case SADB_EXT_KEY_AUTH:
1265			/* XXX should to be check weak keys. */
1266		case SADB_EXT_KEY_ENCRYPT:
1267			/* XXX should to be check weak keys. */
1268		case SADB_EXT_IDENTITY_SRC:
1269		case SADB_EXT_IDENTITY_DST:
1270		case SADB_EXT_SENSITIVITY:
1271		case SADB_EXT_PROPOSAL:
1272		case SADB_EXT_SUPPORTED_AUTH:
1273		case SADB_EXT_SUPPORTED_ENCRYPT:
1274		case SADB_EXT_SPIRANGE:
1275		case SADB_X_EXT_POLICY:
1276		case SADB_X_EXT_SA2:
1277			mhp[ext->sadb_ext_type] = (caddr_t)ext;
1278			break;
1279		default:
1280			__ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
1281			return -1;
1282		}
1283
1284		extlen = PFKEY_EXTLEN(ext);
1285		tlen -= extlen;
1286		ext = (struct sadb_ext *)((caddr_t)ext + extlen);
1287	}
1288
1289	__ipsec_errcode = EIPSEC_NO_ERROR;
1290	return 0;
1291}
1292
1293/*
1294 * check basic usage for sadb_msg,
1295 * NOTE: This routine is derived from netkey/key.c in KAME.
1296 * IN:	msg: pointer to message buffer.
1297 *	mhp: pointer to the buffer initialized like below:
1298 *
1299 *		caddr_t mhp[SADB_EXT_MAX + 1];
1300 *
1301 * OUT:	-1: invalid.
1302 *	 0: valid.
1303 */
1304int
1305pfkey_check(mhp)
1306	caddr_t *mhp;
1307{
1308	struct sadb_msg *msg;
1309
1310	/* validity check */
1311	if (mhp == NULL || mhp[0] == NULL) {
1312		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1313		return -1;
1314	}
1315
1316	msg = (struct sadb_msg *)mhp[0];
1317
1318	/* check version */
1319	if (msg->sadb_msg_version != PF_KEY_V2) {
1320		__ipsec_errcode = EIPSEC_INVAL_VERSION;
1321		return -1;
1322	}
1323
1324	/* check type */
1325	if (msg->sadb_msg_type > SADB_MAX) {
1326		__ipsec_errcode = EIPSEC_INVAL_MSGTYPE;
1327		return -1;
1328	}
1329
1330	/* check SA type */
1331	switch (msg->sadb_msg_satype) {
1332	case SADB_SATYPE_UNSPEC:
1333		switch (msg->sadb_msg_type) {
1334		case SADB_GETSPI:
1335		case SADB_UPDATE:
1336		case SADB_ADD:
1337		case SADB_DELETE:
1338		case SADB_GET:
1339		case SADB_ACQUIRE:
1340		case SADB_EXPIRE:
1341			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
1342			return -1;
1343		}
1344		break;
1345	case SADB_SATYPE_ESP:
1346	case SADB_SATYPE_AH:
1347	case SADB_X_SATYPE_IPCOMP:
1348		switch (msg->sadb_msg_type) {
1349		case SADB_X_SPDADD:
1350		case SADB_X_SPDDELETE:
1351		case SADB_X_SPDGET:
1352		case SADB_X_SPDDUMP:
1353		case SADB_X_SPDFLUSH:
1354			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
1355			return -1;
1356		}
1357		break;
1358	case SADB_SATYPE_RSVP:
1359	case SADB_SATYPE_OSPFV2:
1360	case SADB_SATYPE_RIPV2:
1361	case SADB_SATYPE_MIP:
1362		__ipsec_errcode = EIPSEC_NOT_SUPPORTED;
1363		return -1;
1364	case 1:	/* XXX: What does it do ? */
1365		if (msg->sadb_msg_type == SADB_X_PROMISC)
1366			break;
1367		/*FALLTHROUGH*/
1368	default:
1369		__ipsec_errcode = EIPSEC_INVAL_SATYPE;
1370		return -1;
1371	}
1372
1373	/* check field of upper layer protocol and address family */
1374	if (mhp[SADB_EXT_ADDRESS_SRC] != NULL
1375	 && mhp[SADB_EXT_ADDRESS_DST] != NULL) {
1376		struct sadb_address *src0, *dst0;
1377
1378		src0 = (struct sadb_address *)(mhp[SADB_EXT_ADDRESS_SRC]);
1379		dst0 = (struct sadb_address *)(mhp[SADB_EXT_ADDRESS_DST]);
1380
1381		if (src0->sadb_address_proto != dst0->sadb_address_proto) {
1382			__ipsec_errcode = EIPSEC_PROTO_MISMATCH;
1383			return -1;
1384		}
1385
1386		if (PFKEY_ADDR_SADDR(src0)->sa_family
1387		 != PFKEY_ADDR_SADDR(dst0)->sa_family) {
1388			__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1389			return -1;
1390		}
1391
1392		switch (PFKEY_ADDR_SADDR(src0)->sa_family) {
1393		case AF_INET:
1394		case AF_INET6:
1395			break;
1396		default:
1397			__ipsec_errcode = EIPSEC_INVAL_FAMILY;
1398			return -1;
1399		}
1400
1401		/*
1402		 * prefixlen == 0 is valid because there must be the case
1403		 * all addresses are matched.
1404		 */
1405	}
1406
1407	__ipsec_errcode = EIPSEC_NO_ERROR;
1408	return 0;
1409}
1410
1411/*
1412 * set data into sadb_msg.
1413 * `buf' must has been allocated sufficiently.
1414 */
1415static caddr_t
1416pfkey_setsadbmsg(buf, type, tlen, satype, seq, pid)
1417	caddr_t buf;
1418	u_int type, satype;
1419	u_int tlen;
1420	u_int32_t seq;
1421	pid_t pid;
1422{
1423	struct sadb_msg *p;
1424	u_int len;
1425
1426	p = (struct sadb_msg *)buf;
1427	len = sizeof(struct sadb_msg);
1428
1429	memset(p, 0, len);
1430	p->sadb_msg_version = PF_KEY_V2;
1431	p->sadb_msg_type = type;
1432	p->sadb_msg_errno = 0;
1433	p->sadb_msg_satype = satype;
1434	p->sadb_msg_len = PFKEY_UNIT64(tlen);
1435	p->sadb_msg_reserved = 0;
1436	p->sadb_msg_seq = seq;
1437	p->sadb_msg_pid = (u_int32_t)pid;
1438
1439	return(buf + len);
1440}
1441
1442/*
1443 * copy secasvar data into sadb_address.
1444 * `buf' must has been allocated sufficiently.
1445 */
1446static caddr_t
1447pfkey_setsadbsa(buf, spi, wsize, auth, enc, flags)
1448	caddr_t buf;
1449	u_int32_t spi, flags;
1450	u_int wsize, auth, enc;
1451{
1452	struct sadb_sa *p;
1453	u_int len;
1454
1455	p = (struct sadb_sa *)buf;
1456	len = sizeof(struct sadb_sa);
1457
1458	memset(p, 0, len);
1459	p->sadb_sa_len = PFKEY_UNIT64(len);
1460	p->sadb_sa_exttype = SADB_EXT_SA;
1461	p->sadb_sa_spi = spi;
1462	p->sadb_sa_replay = wsize;
1463	p->sadb_sa_state = SADB_SASTATE_LARVAL;
1464	p->sadb_sa_auth = auth;
1465	p->sadb_sa_encrypt = enc;
1466	p->sadb_sa_flags = flags;
1467
1468	return(buf + len);
1469}
1470
1471/*
1472 * set data into sadb_address.
1473 * `buf' must has been allocated sufficiently.
1474 * prefixlen is in bits.
1475 */
1476static caddr_t
1477pfkey_setsadbaddr(buf, exttype, saddr, prefixlen, ul_proto)
1478	caddr_t buf;
1479	u_int exttype;
1480	struct sockaddr *saddr;
1481	u_int prefixlen;
1482	u_int ul_proto;
1483{
1484	struct sadb_address *p;
1485	u_int len;
1486
1487	p = (struct sadb_address *)buf;
1488	len = sizeof(struct sadb_address) + PFKEY_ALIGN8(saddr->sa_len);
1489
1490	memset(p, 0, len);
1491	p->sadb_address_len = PFKEY_UNIT64(len);
1492	p->sadb_address_exttype = exttype & 0xffff;
1493	p->sadb_address_proto = ul_proto & 0xff;
1494	p->sadb_address_prefixlen = prefixlen;
1495	p->sadb_address_reserved = 0;
1496
1497	memcpy(p + 1, saddr, saddr->sa_len);
1498
1499	return(buf + len);
1500}
1501
1502/*
1503 * set sadb_key structure after clearing buffer with zero.
1504 * OUT: the pointer of buf + len.
1505 */
1506static caddr_t
1507pfkey_setsadbkey(buf, type, key, keylen)
1508	caddr_t buf, key;
1509	u_int type, keylen;
1510{
1511	struct sadb_key *p;
1512	u_int len;
1513
1514	p = (struct sadb_key *)buf;
1515	len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen);
1516
1517	memset(p, 0, len);
1518	p->sadb_key_len = PFKEY_UNIT64(len);
1519	p->sadb_key_exttype = type;
1520	p->sadb_key_bits = keylen << 3;
1521	p->sadb_key_reserved = 0;
1522
1523	memcpy(p + 1, key, keylen);
1524
1525	return buf + len;
1526}
1527
1528/*
1529 * set sadb_lifetime structure after clearing buffer with zero.
1530 * OUT: the pointer of buf + len.
1531 */
1532static caddr_t
1533pfkey_setsadblifetime(buf, type, l_alloc, l_bytes, l_addtime, l_usetime)
1534	caddr_t buf;
1535	u_int type;
1536	u_int32_t l_alloc, l_bytes, l_addtime, l_usetime;
1537{
1538	struct sadb_lifetime *p;
1539	u_int len;
1540
1541	p = (struct sadb_lifetime *)buf;
1542	len = sizeof(struct sadb_lifetime);
1543
1544	memset(p, 0, len);
1545	p->sadb_lifetime_len = PFKEY_UNIT64(len);
1546	p->sadb_lifetime_exttype = type;
1547
1548	switch (type) {
1549	case SADB_EXT_LIFETIME_SOFT:
1550		p->sadb_lifetime_allocations
1551			= (l_alloc * soft_lifetime_allocations_rate) /100;
1552		p->sadb_lifetime_bytes
1553			= (l_bytes * soft_lifetime_bytes_rate) /100;
1554		p->sadb_lifetime_addtime
1555			= (l_addtime * soft_lifetime_addtime_rate) /100;
1556		p->sadb_lifetime_usetime
1557			= (l_usetime * soft_lifetime_usetime_rate) /100;
1558		break;
1559	case SADB_EXT_LIFETIME_HARD:
1560		p->sadb_lifetime_allocations = l_alloc;
1561		p->sadb_lifetime_bytes = l_bytes;
1562		p->sadb_lifetime_addtime = l_addtime;
1563		p->sadb_lifetime_usetime = l_usetime;
1564		break;
1565	}
1566
1567	return buf + len;
1568}
1569
1570/*
1571 * copy secasvar data into sadb_address.
1572 * `buf' must has been allocated sufficiently.
1573 */
1574static caddr_t
1575pfkey_setsadbxsa2(buf, mode0, reqid)
1576	caddr_t buf;
1577	u_int32_t mode0;
1578	u_int32_t reqid;
1579{
1580	struct sadb_x_sa2 *p;
1581	u_int8_t mode = mode0 & 0xff;
1582	u_int len;
1583
1584	p = (struct sadb_x_sa2 *)buf;
1585	len = sizeof(struct sadb_x_sa2);
1586
1587	memset(p, 0, len);
1588	p->sadb_x_sa2_len = PFKEY_UNIT64(len);
1589	p->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
1590	p->sadb_x_sa2_mode = mode;
1591	p->sadb_x_sa2_reqid = reqid;
1592
1593	return(buf + len);
1594}
1595
1596