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