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