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