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