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