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