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