xref: /netbsd-src/crypto/dist/ipsec-tools/src/libipsec/pfkey.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
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 
56 static int findsupportedmap __P((int));
57 static int setsupportedmap __P((struct sadb_supported *));
58 static struct sadb_alg *findsupportedalg __P((u_int, u_int));
59 static int pfkey_send_x1 __P((struct pfkey_send_sa_args *));
60 static int pfkey_send_x2 __P((int, u_int, u_int, u_int,
61 	struct sockaddr *, struct sockaddr *, u_int32_t));
62 static int pfkey_send_x3 __P((int, u_int, u_int));
63 static 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));
66 static int pfkey_send_x5 __P((int, u_int, u_int32_t));
67 
68 static caddr_t pfkey_setsadbmsg __P((caddr_t, caddr_t, u_int, u_int,
69 	u_int, u_int32_t, pid_t));
70 static caddr_t pfkey_setsadbsa __P((caddr_t, caddr_t, u_int32_t, u_int,
71 	u_int, u_int, u_int32_t));
72 static 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
76 static caddr_t pfkey_setsadbkmaddr __P((caddr_t, caddr_t, struct sockaddr *,
77 	struct sockaddr *));
78 #endif
79 
80 static caddr_t pfkey_setsadbkey __P((caddr_t, caddr_t, u_int, caddr_t, u_int));
81 static caddr_t pfkey_setsadblifetime __P((caddr_t, caddr_t, u_int, u_int32_t,
82 	u_int32_t, u_int32_t, u_int32_t));
83 static caddr_t pfkey_setsadbxsa2 __P((caddr_t, caddr_t, u_int32_t, u_int32_t));
84 
85 #ifdef SADB_X_EXT_NAT_T_TYPE
86 static caddr_t pfkey_set_natt_type __P((caddr_t, caddr_t, u_int, u_int8_t));
87 static 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
90 static 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
94 static 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 
98 int 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  */
113 static struct sadb_supported *ipsec_supported[] = { NULL, NULL, NULL,
114 #ifdef SADB_X_SATYPE_TCPSIGNATURE
115     NULL,
116 #endif
117 };
118 
119 static 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 
128 static int
129 findsupportedmap(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 
140 static struct sadb_alg *
141 findsupportedalg(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 
178 static int
179 setsupportedmap(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  */
218 int
219 ipsec_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  */
250 int
251 ipsec_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  */
281 int
282 ipsec_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  */
321 static u_int soft_lifetime_allocations_rate = PFKEY_SOFT_LIFETIME_RATE;
322 static u_int soft_lifetime_bytes_rate = PFKEY_SOFT_LIFETIME_RATE;
323 static u_int soft_lifetime_addtime_rate = PFKEY_SOFT_LIFETIME_RATE;
324 static u_int soft_lifetime_usetime_rate = PFKEY_SOFT_LIFETIME_RATE;
325 
326 u_int
327 pfkey_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  */
358 u_int
359 pfkey_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  */
382 int
383 pfkey_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 
537 int
538 pfkey_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  */
553 int
554 pfkey_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  */
572 int
573 pfkey_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  */
590 int
591 pfkey_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*/
611 int
612 pfkey_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  */
691 int
692 pfkey_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  */
708 int
709 pfkey_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  */
748 int
749 pfkey_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  */
787 int
788 pfkey_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  */
849 int
850 pfkey_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  */
866 int
867 pfkey_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  */
889 int
890 pfkey_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  */
907 int
908 pfkey_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  */
929 int
930 pfkey_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  */
951 int
952 pfkey_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  */
973 int
974 pfkey_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  */
995 int
996 pfkey_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  */
1022 int
1023 pfkey_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  */
1039 int
1040 pfkey_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  */
1056 int
1057 pfkey_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  */
1083 int
1084 pfkey_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  */
1100 int
1101 pfkey_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  */
1119 int
1120 pfkey_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 */
1224 static int
1225 pfkey_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*/
1497 static int
1498 pfkey_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  */
1581 static int
1582 pfkey_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 */
1641 static int
1642 pfkey_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 */
1729 static int
1730 pfkey_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  */
1782 int
1783 pfkey_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 
1826 int
1827 pfkey_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  */
1868 void
1869 pfkey_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  */
1886 struct sadb_msg *
1887 pfkey_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  */
1943 int
1944 pfkey_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  */
1969 int
1970 pfkey_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  */
2084 int
2085 pfkey_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  */
2213 static caddr_t
2214 pfkey_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  */
2243 static caddr_t
2244 pfkey_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  */
2274 static caddr_t
2275 pfkey_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  */
2304 static caddr_t
2305 pfkey_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  */
2340 static caddr_t
2341 pfkey_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  */
2368 static caddr_t
2369 pfkey_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  */
2411 static caddr_t
2412 pfkey_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
2434 static caddr_t
2435 pfkey_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 
2454 static caddr_t
2455 pfkey_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
2476 static caddr_t
2477 pfkey_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
2499 static caddr_t
2500 pfkey_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  */
2529 int
2530 pfkey_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 
2563 int
2564 pfkey_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 
2604 int
2605 pfkey_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 
2638 int
2639 pfkey_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