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