xref: /freebsd/lib/libipsec/pfkey.c (revision 77a0943ded95b9e6438f7db70c4a28e4d93946d4)
1 /*	$FreeBSD$	*/
2 /*	$KAME: pfkey.c,v 1.31 2000/06/10 14:17:43 sakane 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 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/socket.h>
36 #include <net/pfkeyv2.h>
37 #include <netkey/key_var.h>
38 #include <netinet/in.h>
39 #include <netinet6/ipsec.h>
40 
41 #include <stdlib.h>
42 #include <unistd.h>
43 #include <string.h>
44 #include <errno.h>
45 
46 #include "ipsec_strerror.h"
47 #include "libpfkey.h"
48 
49 #define CALLOC(size, cast) (cast)calloc(1, (size))
50 
51 static int pfkey_send_x1 __P((int, u_int, u_int, u_int, struct sockaddr *,
52 	struct sockaddr *, u_int32_t, u_int32_t, u_int, caddr_t,
53 	u_int, u_int, u_int, u_int, u_int, u_int32_t, u_int32_t,
54 	u_int32_t, u_int32_t, u_int32_t));
55 static int pfkey_send_x2 __P((int, u_int, u_int, u_int,
56 	struct sockaddr *, struct sockaddr *, u_int32_t));
57 static int pfkey_send_x3 __P((int, u_int, u_int));
58 static int pfkey_send_x4 __P((int, u_int, struct sockaddr *, u_int,
59 	struct sockaddr *, u_int, u_int, char *, int, u_int32_t));
60 static int pfkey_send_x5 __P((int, u_int, u_int32_t));
61 
62 static caddr_t pfkey_setsadbmsg __P((caddr_t, u_int, u_int,
63 	u_int, u_int32_t, pid_t));
64 static caddr_t pfkey_setsadbsa __P((caddr_t, u_int32_t, u_int,
65 	u_int, u_int, u_int32_t));
66 static caddr_t pfkey_setsadbaddr __P((caddr_t, u_int,
67 	struct sockaddr *, u_int, u_int));
68 static caddr_t pfkey_setsadbkey __P((caddr_t, u_int, caddr_t, u_int));
69 static caddr_t pfkey_setsadblifetime __P((caddr_t, u_int, u_int32_t, u_int32_t,
70 	u_int32_t, u_int32_t));
71 static caddr_t pfkey_setsadbxsa2 __P((caddr_t, u_int32_t, u_int32_t));
72 
73 /*
74  * check key length against algorithm specified.
75  * supported is either SADB_EXT_SUPPORTED_ENCRYPT or SADB_EXT_SUPPORTED_AUTH.
76  * Refer to keyv2.h to get more info.
77  * keylen is the unit of bit.
78  * OUT:
79  *	-1: invalid.
80  *	 0: valid.
81  */
82 struct sadb_msg *ipsec_supported = NULL;
83 
84 int
85 ipsec_check_keylen(supported, alg_id, keylen)
86 	u_int supported;
87 	u_int alg_id;
88 	u_int keylen;
89 {
90 	u_int tlen;
91 	caddr_t p;
92 	struct sadb_supported *sup;
93 	struct sadb_alg *alg;
94 
95 	/* validity check */
96 	if (ipsec_supported == NULL) {
97 		__ipsec_errcode = EIPSEC_DO_GET_SUPP_LIST;
98 		return -1;
99 	}
100 	switch (supported) {
101 	case SADB_EXT_SUPPORTED_AUTH:
102 	case SADB_EXT_SUPPORTED_ENCRYPT:
103 		break;
104 	default:
105 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
106 		return -1;
107 	}
108 
109 	tlen = ipsec_supported->sadb_msg_len - sizeof(struct sadb_msg);
110 	p = (caddr_t)ipsec_supported + sizeof(struct sadb_msg);
111 
112 	for (;
113 	     tlen > 0;
114 	     tlen -= sup->sadb_supported_len, p += sup->sadb_supported_len) {
115 
116 		sup = (struct sadb_supported *)p;
117 
118 		if (sup->sadb_supported_exttype != supported)
119 			continue;
120 
121 	    {
122 		u_int ttlen = sup->sadb_supported_len;
123 		caddr_t pp = p + sizeof(*sup);
124 
125 		for (;
126 		     ttlen > 0;
127 	     	     ttlen -= sizeof(*alg), pp += sizeof(*alg)) {
128 			alg = (struct sadb_alg *)pp;
129 
130 			if (alg->sadb_alg_id == alg_id)
131 				goto found;
132 	    	}
133 	    }
134 	}
135 
136 	__ipsec_errcode = EIPSEC_NOT_SUPPORTED;
137 	return -1;
138 	/* NOTREACHED */
139 
140     found:
141 	if (keylen < alg->sadb_alg_minbits
142 	 || keylen > alg->sadb_alg_maxbits) {
143 		__ipsec_errcode = EIPSEC_INVAL_KEYLEN;
144 		return -1;
145 	}
146 
147 	__ipsec_errcode = EIPSEC_NO_ERROR;
148 	return 0;
149 }
150 
151 /*
152  * set the rate for SOFT lifetime against HARD one.
153  * If rate is more than 100 or equal to zero, then set to 100.
154  */
155 static u_int soft_lifetime_allocations_rate = PFKEY_SOFT_LIFETIME_RATE;
156 static u_int soft_lifetime_bytes_rate = PFKEY_SOFT_LIFETIME_RATE;
157 static u_int soft_lifetime_addtime_rate = PFKEY_SOFT_LIFETIME_RATE;
158 static u_int soft_lifetime_usetime_rate = PFKEY_SOFT_LIFETIME_RATE;
159 
160 u_int
161 pfkey_set_softrate(type, rate)
162 	u_int type, rate;
163 {
164 	__ipsec_errcode = EIPSEC_NO_ERROR;
165 
166 	if (rate > 100 || rate == 0)
167 		rate = 100;
168 
169 	switch (type) {
170 	case SADB_X_LIFETIME_ALLOCATIONS:
171 		soft_lifetime_allocations_rate = rate;
172 		return 0;
173 	case SADB_X_LIFETIME_BYTES:
174 		soft_lifetime_bytes_rate = rate;
175 		return 0;
176 	case SADB_X_LIFETIME_ADDTIME:
177 		soft_lifetime_addtime_rate = rate;
178 		return 0;
179 	case SADB_X_LIFETIME_USETIME:
180 		soft_lifetime_usetime_rate = rate;
181 		return 0;
182 	}
183 
184 	__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
185 	return 1;
186 }
187 
188 /*
189  * get current rate for SOFT lifetime against HARD one.
190  * ATTENTION: ~0 is returned if invalid type was passed.
191  */
192 u_int
193 pfkey_get_softrate(type)
194 	u_int type;
195 {
196 	switch (type) {
197 	case SADB_X_LIFETIME_ALLOCATIONS:
198 		return soft_lifetime_allocations_rate;
199 	case SADB_X_LIFETIME_BYTES:
200 		return soft_lifetime_bytes_rate;
201 	case SADB_X_LIFETIME_ADDTIME:
202 		return soft_lifetime_addtime_rate;
203 	case SADB_X_LIFETIME_USETIME:
204 		return soft_lifetime_usetime_rate;
205 	}
206 
207 	return ~0;
208 }
209 
210 /*
211  * sending SADB_GETSPI message to the kernel.
212  * OUT:
213  *	positive: success and return length sent.
214  *	-1	: error occured, and set errno.
215  */
216 int
217 pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq)
218 	int so;
219 	u_int satype, mode;
220 	struct sockaddr *src, *dst;
221 	u_int32_t min, max, reqid, seq;
222 {
223 	struct sadb_msg *newmsg;
224 	int len;
225 	int need_spirange = 0;
226 	caddr_t p;
227 	int plen;
228 
229 	/* validity check */
230 	if (src == NULL || dst == NULL) {
231 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
232 		return -1;
233 	}
234 	if (src->sa_family != dst->sa_family) {
235 		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
236 		return -1;
237 	}
238 	if (min > max || (min > 0 && min <= 255)) {
239 		__ipsec_errcode = EIPSEC_INVAL_SPI;
240 		return -1;
241 	}
242 	switch (src->sa_family) {
243 	case AF_INET:
244 		plen = sizeof(struct in_addr) << 3;
245 		break;
246 	case AF_INET6:
247 		plen = sizeof(struct in6_addr) << 3;
248 		break;
249 	default:
250 		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
251 		return -1;
252 	}
253 
254 	/* create new sadb_msg to send. */
255 	len = sizeof(struct sadb_msg)
256 		+ sizeof(struct sadb_x_sa2)
257 		+ sizeof(struct sadb_address)
258 		+ PFKEY_ALIGN8(src->sa_len)
259 		+ sizeof(struct sadb_address)
260 		+ PFKEY_ALIGN8(dst->sa_len);
261 
262 	if (min > 255 && max < ~0) {
263 		need_spirange++;
264 		len += sizeof(struct sadb_spirange);
265 	}
266 
267 	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
268 		__ipsec_set_strerror(strerror(errno));
269 		return -1;
270 	}
271 
272 	p = pfkey_setsadbmsg((caddr_t)newmsg, SADB_GETSPI,
273 	                     len, satype, seq, getpid());
274 
275 	p = pfkey_setsadbxsa2(p, mode, reqid);
276 
277 	/* set sadb_address for source */
278 	p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_SRC, src, plen,
279 	    IPSEC_ULPROTO_ANY);
280 
281 	/* set sadb_address for destination */
282 	p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_DST, dst, plen,
283 	    IPSEC_ULPROTO_ANY);
284 
285 	/* proccessing spi range */
286 	if (need_spirange) {
287 		int _len = sizeof(struct sadb_spirange);
288 
289 #define _SADB_SPIRANGE(p) ((struct sadb_spirange *)(p))
290 		_SADB_SPIRANGE(p)->sadb_spirange_len = PFKEY_UNIT64(_len);
291 		_SADB_SPIRANGE(p)->sadb_spirange_exttype = SADB_EXT_SPIRANGE;
292 		_SADB_SPIRANGE(p)->sadb_spirange_min = min;
293 		_SADB_SPIRANGE(p)->sadb_spirange_max = max;
294 #undef _SADB_SPIRANGE(p)
295 		p += _len;
296 	}
297 
298 	/* send message */
299 	len = pfkey_send(so, newmsg, len);
300 	free(newmsg);
301 
302 	if (len < 0)
303 		return -1;
304 
305 	__ipsec_errcode = EIPSEC_NO_ERROR;
306 	return len;
307 }
308 
309 /*
310  * sending SADB_UPDATE message to the kernel.
311  * The length of key material is a_keylen + e_keylen.
312  * OUT:
313  *	positive: success and return length sent.
314  *	-1	: error occured, and set errno.
315  */
316 int
317 pfkey_send_update(so, satype, mode, src, dst, spi, reqid, wsize,
318 		keymat, e_type, e_keylen, a_type, a_keylen, flags,
319 		l_alloc, l_bytes, l_addtime, l_usetime, seq)
320 	int so;
321 	u_int satype, mode, wsize;
322 	struct sockaddr *src, *dst;
323 	u_int32_t spi, reqid;
324 	caddr_t keymat;
325 	u_int e_type, e_keylen, a_type, a_keylen, flags;
326 	u_int32_t l_alloc;
327 	u_int64_t l_bytes, l_addtime, l_usetime;
328 	u_int32_t seq;
329 {
330 	int len;
331 	if ((len = pfkey_send_x1(so, SADB_UPDATE, satype, mode, src, dst, spi,
332 			reqid, wsize,
333 			keymat, e_type, e_keylen, a_type, a_keylen, flags,
334 			l_alloc, l_bytes, l_addtime, l_usetime, seq)) < 0)
335 		return -1;
336 
337 	return len;
338 }
339 
340 /*
341  * sending SADB_ADD message to the kernel.
342  * The length of key material is a_keylen + e_keylen.
343  * OUT:
344  *	positive: success and return length sent.
345  *	-1	: error occured, and set errno.
346  */
347 int
348 pfkey_send_add(so, satype, mode, src, dst, spi, reqid, wsize,
349 		keymat, e_type, e_keylen, a_type, a_keylen, flags,
350 		l_alloc, l_bytes, l_addtime, l_usetime, seq)
351 	int so;
352 	u_int satype, mode, wsize;
353 	struct sockaddr *src, *dst;
354 	u_int32_t spi, reqid;
355 	caddr_t keymat;
356 	u_int e_type, e_keylen, a_type, a_keylen, flags;
357 	u_int32_t l_alloc;
358 	u_int64_t l_bytes, l_addtime, l_usetime;
359 	u_int32_t seq;
360 {
361 	int len;
362 	if ((len = pfkey_send_x1(so, SADB_ADD, satype, mode, src, dst, spi,
363 			reqid, wsize,
364 			keymat, e_type, e_keylen, a_type, a_keylen, flags,
365 			l_alloc, l_bytes, l_addtime, l_usetime, seq)) < 0)
366 		return -1;
367 
368 	return len;
369 }
370 
371 /*
372  * sending SADB_DELETE message to the kernel.
373  * OUT:
374  *	positive: success and return length sent.
375  *	-1	: error occured, and set errno.
376  */
377 int
378 pfkey_send_delete(so, satype, mode, src, dst, spi)
379 	int so;
380 	u_int satype, mode;
381 	struct sockaddr *src, *dst;
382 	u_int32_t spi;
383 {
384 	int len;
385 	if ((len = pfkey_send_x2(so, SADB_DELETE, satype, mode, src, dst, spi)) < 0)
386 		return -1;
387 
388 	return len;
389 }
390 
391 /*
392  * sending SADB_GET message to the kernel.
393  * OUT:
394  *	positive: success and return length sent.
395  *	-1	: error occured, and set errno.
396  */
397 int
398 pfkey_send_get(so, satype, mode, src, dst, spi)
399 	int so;
400 	u_int satype, mode;
401 	struct sockaddr *src, *dst;
402 	u_int32_t spi;
403 {
404 	int len;
405 	if ((len = pfkey_send_x2(so, SADB_GET, satype, mode, src, dst, spi)) < 0)
406 		return -1;
407 
408 	return len;
409 }
410 
411 /*
412  * sending SADB_REGISTER message to the kernel.
413  * OUT:
414  *	positive: success and return length sent.
415  *	-1	: error occured, and set errno.
416  */
417 int
418 pfkey_send_register(so, satype)
419 	int so;
420 	u_int satype;
421 {
422 	int len;
423 
424 	if ((len = pfkey_send_x3(so, SADB_REGISTER, satype)) < 0)
425 		return -1;
426 
427 	return len;
428 }
429 
430 /*
431  * receiving SADB_REGISTER message from the kernel, and copy buffer for
432  * sadb_supported returned into ipsec_supported.
433  * OUT:
434  *	 0: success and return length sent.
435  *	-1: error occured, and set errno.
436  */
437 int
438 pfkey_recv_register(so)
439 	int so;
440 {
441 	pid_t pid = getpid();
442 	struct sadb_msg *newmsg;
443 	struct sadb_supported *sup;
444 	caddr_t p;
445 	int tlen;
446 
447 	/* receive message */
448 	do {
449 		if ((newmsg = pfkey_recv(so)) == NULL)
450 			return -1;
451 
452 	} while (newmsg->sadb_msg_type != SADB_REGISTER
453 	    || newmsg->sadb_msg_pid != pid);
454 
455 	/* check and fix */
456 	newmsg->sadb_msg_len = PFKEY_UNUNIT64(newmsg->sadb_msg_len);
457 
458 	tlen = newmsg->sadb_msg_len - sizeof(struct sadb_msg);
459 	p = (caddr_t)newmsg + sizeof(struct sadb_msg);
460 	while (tlen > 0) {
461 		sup = (struct sadb_supported *)p;
462 		switch (sup->sadb_supported_exttype) {
463 		case SADB_EXT_SUPPORTED_AUTH:
464 		case SADB_EXT_SUPPORTED_ENCRYPT:
465 			sup->sadb_supported_len = PFKEY_EXTLEN(sup);
466 			break;
467 		default:
468 			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
469 			free(newmsg);
470 			return -1;
471 		}
472 
473 		tlen -= sup->sadb_supported_len;
474 		p += sup->sadb_supported_len;
475 	}
476 
477 	if (tlen < 0) {
478 		__ipsec_errcode = EIPSEC_INVAL_SATYPE;
479 		return -1;
480 	}
481 
482 	if (ipsec_supported != NULL)
483 		free(ipsec_supported);
484 
485 	ipsec_supported = newmsg;
486 
487 	__ipsec_errcode = EIPSEC_NO_ERROR;
488 	return 0;
489 }
490 
491 /*
492  * sending SADB_FLUSH message to the kernel.
493  * OUT:
494  *	positive: success and return length sent.
495  *	-1	: error occured, and set errno.
496  */
497 int
498 pfkey_send_flush(so, satype)
499 	int so;
500 	u_int satype;
501 {
502 	int len;
503 
504 	if ((len = pfkey_send_x3(so, SADB_FLUSH, satype)) < 0)
505 		return -1;
506 
507 	return len;
508 }
509 
510 /*
511  * sending SADB_DUMP message to the kernel.
512  * OUT:
513  *	positive: success and return length sent.
514  *	-1	: error occured, and set errno.
515  */
516 int
517 pfkey_send_dump(so, satype)
518 	int so;
519 	u_int satype;
520 {
521 	int len;
522 
523 	if ((len = pfkey_send_x3(so, SADB_DUMP, satype)) < 0)
524 		return -1;
525 
526 	return len;
527 }
528 
529 /*
530  * sending SADB_X_PROMISC message to the kernel.
531  * NOTE that this function handles promisc mode toggle only.
532  * IN:
533  *	flag:	set promisc off if zero, set promisc on if non-zero.
534  * OUT:
535  *	positive: success and return length sent.
536  *	-1	: error occured, and set errno.
537  *	0     : error occured, and set errno.
538  *	others: a pointer to new allocated buffer in which supported
539  *	        algorithms is.
540  */
541 int
542 pfkey_send_promisc_toggle(so, flag)
543 	int so;
544 	int flag;
545 {
546 	int len;
547 
548 	if ((len = pfkey_send_x3(so, SADB_X_PROMISC, (flag ? 1 : 0))) < 0)
549 		return -1;
550 
551 	return len;
552 }
553 
554 /*
555  * sending SADB_X_SPDADD message to the kernel.
556  * OUT:
557  *	positive: success and return length sent.
558  *	-1	: error occured, and set errno.
559  */
560 int
561 pfkey_send_spdadd(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
562 	int so;
563 	struct sockaddr *src, *dst;
564 	u_int prefs, prefd, proto;
565 	caddr_t policy;
566 	int policylen;
567 	u_int32_t seq;
568 {
569 	int len;
570 
571 	if ((len = pfkey_send_x4(so, SADB_X_SPDADD,
572 				src, prefs, dst, prefd, proto,
573 				policy, policylen, seq)) < 0)
574 		return -1;
575 
576 	return len;
577 }
578 
579 /*
580  * sending SADB_X_SPDUPDATE message to the kernel.
581  * OUT:
582  *	positive: success and return length sent.
583  *	-1	: error occured, and set errno.
584  */
585 int
586 pfkey_send_spdupdate(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
587 	int so;
588 	struct sockaddr *src, *dst;
589 	u_int prefs, prefd, proto;
590 	caddr_t policy;
591 	int policylen;
592 	u_int32_t seq;
593 {
594 	int len;
595 
596 	if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE,
597 				src, prefs, dst, prefd, proto,
598 				policy, policylen, seq)) < 0)
599 		return -1;
600 
601 	return len;
602 }
603 
604 /*
605  * sending SADB_X_SPDDELETE message to the kernel.
606  * OUT:
607  *	positive: success and return length sent.
608  *	-1	: error occured, and set errno.
609  */
610 int
611 pfkey_send_spddelete(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
612 	int so;
613 	struct sockaddr *src, *dst;
614 	u_int prefs, prefd, proto;
615 	caddr_t policy;
616 	int policylen;
617 	u_int32_t seq;
618 {
619 	int len;
620 
621 	if (policylen != sizeof(struct sadb_x_policy)) {
622 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
623 		return -1;
624 	}
625 
626 	if ((len = pfkey_send_x4(so, SADB_X_SPDDELETE,
627 				src, prefs, dst, prefd, proto,
628 				policy, policylen, seq)) < 0)
629 		return -1;
630 
631 	return len;
632 }
633 
634 /*
635  * sending SADB_X_SPDDELETE message to the kernel.
636  * OUT:
637  *	positive: success and return length sent.
638  *	-1	: error occured, and set errno.
639  */
640 int
641 pfkey_send_spddelete2(so, spid)
642 	int so;
643 	u_int32_t spid;
644 {
645 	int len;
646 
647 	if ((len = pfkey_send_x5(so, SADB_X_SPDDELETE2, spid)) < 0)
648 		return -1;
649 
650 	return len;
651 }
652 
653 /*
654  * sending SADB_X_SPDGET message to the kernel.
655  * OUT:
656  *	positive: success and return length sent.
657  *	-1	: error occured, and set errno.
658  */
659 int
660 pfkey_send_spdget(so, spid)
661 	int so;
662 	u_int32_t spid;
663 {
664 	int len;
665 
666 	if ((len = pfkey_send_x5(so, SADB_X_SPDGET, spid)) < 0)
667 		return -1;
668 
669 	return len;
670 }
671 
672 /*
673  * sending SADB_X_SPDSETIDX message to the kernel.
674  * OUT:
675  *	positive: success and return length sent.
676  *	-1	: error occured, and set errno.
677  */
678 int
679 pfkey_send_spdsetidx(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
680 	int so;
681 	struct sockaddr *src, *dst;
682 	u_int prefs, prefd, proto;
683 	caddr_t policy;
684 	int policylen;
685 	u_int32_t seq;
686 {
687 	int len;
688 
689 	if (policylen != sizeof(struct sadb_x_policy)) {
690 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
691 		return -1;
692 	}
693 
694 	if ((len = pfkey_send_x4(so, SADB_X_SPDSETIDX,
695 				src, prefs, dst, prefd, proto,
696 				policy, policylen, seq)) < 0)
697 		return -1;
698 
699 	return len;
700 }
701 
702 /*
703  * sending SADB_SPDFLUSH message to the kernel.
704  * OUT:
705  *	positive: success and return length sent.
706  *	-1	: error occured, and set errno.
707  */
708 int
709 pfkey_send_spdflush(so)
710 	int so;
711 {
712 	int len;
713 
714 	if ((len = pfkey_send_x3(so, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC)) < 0)
715 		return -1;
716 
717 	return len;
718 }
719 
720 /*
721  * sending SADB_SPDDUMP message to the kernel.
722  * OUT:
723  *	positive: success and return length sent.
724  *	-1	: error occured, and set errno.
725  */
726 int
727 pfkey_send_spddump(so)
728 	int so;
729 {
730 	int len;
731 
732 	if ((len = pfkey_send_x3(so, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC)) < 0)
733 		return -1;
734 
735 	return len;
736 }
737 
738 /* sending SADB_ADD or SADB_UPDATE message to the kernel */
739 static int
740 pfkey_send_x1(so, type, satype, mode, src, dst, spi, reqid, wsize,
741 		keymat, e_type, e_keylen, a_type, a_keylen, flags,
742 		l_alloc, l_bytes, l_addtime, l_usetime, seq)
743 	int so;
744 	u_int type, satype, mode;
745 	struct sockaddr *src, *dst;
746 	u_int32_t spi, reqid;
747 	u_int wsize;
748 	caddr_t keymat;
749 	u_int e_type, e_keylen, a_type, a_keylen, flags;
750 	u_int32_t l_alloc, l_bytes, l_addtime, l_usetime, seq;
751 {
752 	struct sadb_msg *newmsg;
753 	int len;
754 	caddr_t p;
755 	int plen;
756 
757 	/* validity check */
758 	if (src == NULL || dst == NULL) {
759 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
760 		return -1;
761 	}
762 	if (src->sa_family != dst->sa_family) {
763 		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
764 		return -1;
765 	}
766 	switch (src->sa_family) {
767 	case AF_INET:
768 		plen = sizeof(struct in_addr) << 3;
769 		break;
770 	case AF_INET6:
771 		plen = sizeof(struct in6_addr) << 3;
772 		break;
773 	default:
774 		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
775 		return -1;
776 	}
777 
778 	switch (satype) {
779 	case SADB_SATYPE_ESP:
780 		if (e_type == SADB_EALG_NONE) {
781 			__ipsec_errcode = EIPSEC_NO_ALGS;
782 			return -1;
783 		}
784 		break;
785 	case SADB_SATYPE_AH:
786 		if (e_type != SADB_EALG_NONE) {
787 			__ipsec_errcode = EIPSEC_INVAL_ALGS;
788 			return -1;
789 		}
790 		if (a_type == SADB_AALG_NONE) {
791 			__ipsec_errcode = EIPSEC_NO_ALGS;
792 			return -1;
793 		}
794 		break;
795 	case SADB_X_SATYPE_IPCOMP:
796 		break;
797 	default:
798 		__ipsec_errcode = EIPSEC_INVAL_SATYPE;
799 		return -1;
800 	}
801 
802 	/* create new sadb_msg to reply. */
803 	len = sizeof(struct sadb_msg)
804 		+ sizeof(struct sadb_sa)
805 		+ sizeof(struct sadb_x_sa2)
806 		+ sizeof(struct sadb_address)
807 		+ PFKEY_ALIGN8(src->sa_len)
808 		+ sizeof(struct sadb_address)
809 		+ PFKEY_ALIGN8(dst->sa_len)
810 		+ sizeof(struct sadb_lifetime)
811 		+ sizeof(struct sadb_lifetime);
812 
813 	if (e_type != SADB_EALG_NONE)
814 		len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(e_keylen));
815 	if (a_type != SADB_AALG_NONE)
816 		len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(a_keylen));
817 
818 	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
819 		__ipsec_set_strerror(strerror(errno));
820 		return -1;
821 	}
822 
823 	p = pfkey_setsadbmsg((caddr_t)newmsg, type, len,
824 	                     satype, seq, getpid());
825 	p = pfkey_setsadbsa(p, spi, wsize, a_type, e_type, flags);
826 	p = pfkey_setsadbxsa2(p, mode, reqid);
827 	p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_SRC, src, plen,
828 	    IPSEC_ULPROTO_ANY);
829 	p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_DST, dst, plen,
830 	    IPSEC_ULPROTO_ANY);
831 
832 	if (e_type != SADB_EALG_NONE)
833 		p = pfkey_setsadbkey(p, SADB_EXT_KEY_ENCRYPT,
834 		                   keymat, e_keylen);
835 	if (a_type != SADB_AALG_NONE)
836 		p = pfkey_setsadbkey(p, SADB_EXT_KEY_AUTH,
837 		                   keymat + e_keylen, a_keylen);
838 
839 	/* set sadb_lifetime for destination */
840 	p = pfkey_setsadblifetime(p, SADB_EXT_LIFETIME_HARD,
841 			l_alloc, l_bytes, l_addtime, l_usetime);
842 	p = pfkey_setsadblifetime(p, SADB_EXT_LIFETIME_SOFT,
843 			l_alloc, l_bytes, l_addtime, l_usetime);
844 
845 	/* send message */
846 	len = pfkey_send(so, newmsg, len);
847 	free(newmsg);
848 
849 	if (len < 0)
850 		return -1;
851 
852 	__ipsec_errcode = EIPSEC_NO_ERROR;
853 	return len;
854 }
855 
856 /* sending SADB_DELETE or SADB_GET message to the kernel */
857 static int
858 pfkey_send_x2(so, type, satype, mode, src, dst, spi)
859 	int so;
860 	u_int type, satype, mode;
861 	struct sockaddr *src, *dst;
862 	u_int32_t spi;
863 {
864 	struct sadb_msg *newmsg;
865 	int len;
866 	caddr_t p;
867 	int plen;
868 
869 	/* validity check */
870 	if (src == NULL || dst == NULL) {
871 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
872 		return -1;
873 	}
874 	if (src->sa_family != dst->sa_family) {
875 		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
876 		return -1;
877 	}
878 	switch (src->sa_family) {
879 	case AF_INET:
880 		plen = sizeof(struct in_addr) << 3;
881 		break;
882 	case AF_INET6:
883 		plen = sizeof(struct in6_addr) << 3;
884 		break;
885 	default:
886 		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
887 		return -1;
888 	}
889 
890 	/* create new sadb_msg to reply. */
891 	len = sizeof(struct sadb_msg)
892 		+ sizeof(struct sadb_sa)
893 		+ sizeof(struct sadb_address)
894 		+ PFKEY_ALIGN8(src->sa_len)
895 		+ sizeof(struct sadb_address)
896 		+ PFKEY_ALIGN8(dst->sa_len);
897 
898 	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
899 		__ipsec_set_strerror(strerror(errno));
900 		return -1;
901 	}
902 
903 	p = pfkey_setsadbmsg((caddr_t)newmsg, type, len, satype, 0, getpid());
904 	p = pfkey_setsadbsa(p, spi, 0, 0, 0, 0);
905 	p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_SRC, src, plen,
906 	    IPSEC_ULPROTO_ANY);
907 	p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_DST, dst, plen,
908 	    IPSEC_ULPROTO_ANY);
909 
910 	/* send message */
911 	len = pfkey_send(so, newmsg, len);
912 	free(newmsg);
913 
914 	if (len < 0)
915 		return -1;
916 
917 	__ipsec_errcode = EIPSEC_NO_ERROR;
918 	return len;
919 }
920 
921 /*
922  * sending SADB_REGISTER, SADB_FLUSH, SADB_DUMP or SADB_X_PROMISC message
923  * to the kernel
924  */
925 static int
926 pfkey_send_x3(so, type, satype)
927 	int so;
928 	u_int type, satype;
929 {
930 	struct sadb_msg *newmsg;
931 	int len;
932 
933 	/* validity check */
934 	switch (type) {
935 	case SADB_X_PROMISC:
936 		if (satype != 0 && satype != 1) {
937 			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
938 			return -1;
939 		}
940 		break;
941 	default:
942 		switch (satype) {
943 		case SADB_SATYPE_UNSPEC:
944 		case SADB_SATYPE_AH:
945 		case SADB_SATYPE_ESP:
946 		case SADB_X_SATYPE_IPCOMP:
947 			break;
948 		default:
949 			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
950 			return -1;
951 		}
952 	}
953 
954 	/* create new sadb_msg to send. */
955 	len = sizeof(struct sadb_msg);
956 
957 	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
958 		__ipsec_set_strerror(strerror(errno));
959 		return -1;
960 	}
961 
962 	(void)pfkey_setsadbmsg((caddr_t)newmsg, type, len, satype, 0, getpid());
963 
964 	/* send message */
965 	len = pfkey_send(so, newmsg, len);
966 	free(newmsg);
967 
968 	if (len < 0)
969 		return -1;
970 
971 	__ipsec_errcode = EIPSEC_NO_ERROR;
972 	return len;
973 }
974 
975 /* sending SADB_X_SPDADD message to the kernel */
976 static int
977 pfkey_send_x4(so, type, src, prefs, dst, prefd, proto, policy, policylen, seq)
978 	int so;
979 	struct sockaddr *src, *dst;
980 	u_int type, prefs, prefd, proto;
981 	char *policy;
982 	int policylen;
983 	u_int32_t seq;
984 {
985 	struct sadb_msg *newmsg;
986 	int len;
987 	caddr_t p;
988 	int plen;
989 
990 	/* validity check */
991 	if (src == NULL || dst == NULL) {
992 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
993 		return -1;
994 	}
995 	if (src->sa_family != dst->sa_family) {
996 		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
997 		return -1;
998 	}
999 
1000 	switch (src->sa_family) {
1001 	case AF_INET:
1002 		plen = sizeof(struct in_addr) << 3;
1003 		break;
1004 	case AF_INET6:
1005 		plen = sizeof(struct in6_addr) << 3;
1006 		break;
1007 	default:
1008 		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
1009 		return -1;
1010 	}
1011 	if (prefs > plen || prefd > plen) {
1012 		__ipsec_errcode = EIPSEC_INVAL_PREFIXLEN;
1013 		return -1;
1014 	}
1015 
1016 	/* create new sadb_msg to reply. */
1017 	len = sizeof(struct sadb_msg)
1018 		+ sizeof(struct sadb_address)
1019 		+ PFKEY_ALIGN8(src->sa_len)
1020 		+ sizeof(struct sadb_address)
1021 		+ PFKEY_ALIGN8(src->sa_len)
1022 		+ policylen;
1023 
1024 	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
1025 		__ipsec_set_strerror(strerror(errno));
1026 		return -1;
1027 	}
1028 
1029 	p = pfkey_setsadbmsg((caddr_t)newmsg, type, len,
1030 	                     SADB_SATYPE_UNSPEC, seq, getpid());
1031 	p = pfkey_setsadbaddr(p,
1032 	                      SADB_EXT_ADDRESS_SRC,
1033 	                      src,
1034 	                      prefs,
1035 	                      proto);
1036 	p = pfkey_setsadbaddr(p,
1037 	                      SADB_EXT_ADDRESS_DST,
1038 	                      dst,
1039 	                      prefd,
1040 	                      proto);
1041 	memcpy(p, policy, policylen);
1042 
1043 	/* send message */
1044 	len = pfkey_send(so, newmsg, len);
1045 	free(newmsg);
1046 
1047 	if (len < 0)
1048 		return -1;
1049 
1050 	__ipsec_errcode = EIPSEC_NO_ERROR;
1051 	return len;
1052 }
1053 
1054 /* sending SADB_X_SPDGET or SADB_X_SPDDELETE message to the kernel */
1055 static int
1056 pfkey_send_x5(so, type, spid)
1057 	int so;
1058 	u_int type;
1059 	u_int32_t spid;
1060 {
1061 	struct sadb_msg *newmsg;
1062 	struct sadb_x_policy xpl;
1063 	int len;
1064 	caddr_t p;
1065 
1066 	/* create new sadb_msg to reply. */
1067 	len = sizeof(struct sadb_msg)
1068 		+ sizeof(xpl);
1069 
1070 	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
1071 		__ipsec_set_strerror(strerror(errno));
1072 		return -1;
1073 	}
1074 
1075 	p = pfkey_setsadbmsg((caddr_t)newmsg, type, len,
1076 	                     SADB_SATYPE_UNSPEC, 0, getpid());
1077 
1078 	memset(&xpl, 0, sizeof(xpl));
1079 	xpl.sadb_x_policy_len = PFKEY_UNUNIT64(sizeof(xpl));
1080 	xpl.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
1081 	xpl.sadb_x_policy_id = spid;
1082 
1083 	memcpy(p, &xpl, sizeof(xpl));
1084 
1085 	/* send message */
1086 	len = pfkey_send(so, newmsg, len);
1087 	free(newmsg);
1088 
1089 	if (len < 0)
1090 		return -1;
1091 
1092 	__ipsec_errcode = EIPSEC_NO_ERROR;
1093 	return len;
1094 }
1095 
1096 /*
1097  * open a socket.
1098  * OUT:
1099  *	-1: fail.
1100  *	others : success and return value of socket.
1101  */
1102 int
1103 pfkey_open()
1104 {
1105 	int so;
1106 	const int bufsiz = 128 * 1024;	/*is 128K enough?*/
1107 
1108 	if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) {
1109 		__ipsec_set_strerror(strerror(errno));
1110 		return -1;
1111 	}
1112 
1113 	/*
1114 	 * This is a temporary workaround for KAME PR 154.
1115 	 * Don't really care even if it fails.
1116 	 */
1117 	(void)setsockopt(so, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz));
1118 	(void)setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz));
1119 
1120 	__ipsec_errcode = EIPSEC_NO_ERROR;
1121 	return so;
1122 }
1123 
1124 /*
1125  * close a socket.
1126  * OUT:
1127  *	 0: success.
1128  *	-1: fail.
1129  */
1130 void
1131 pfkey_close(so)
1132 	int so;
1133 {
1134 	(void)close(so);
1135 
1136 	__ipsec_errcode = EIPSEC_NO_ERROR;
1137 	return;
1138 }
1139 
1140 /*
1141  * receive sadb_msg data, and return pointer to new buffer allocated.
1142  * Must free this buffer later.
1143  * OUT:
1144  *	NULL	: error occured.
1145  *	others	: a pointer to sadb_msg structure.
1146  */
1147 struct sadb_msg *
1148 pfkey_recv(so)
1149 	int so;
1150 {
1151 	struct sadb_msg buf, *newmsg;
1152 	int len, reallen;
1153 
1154 	while ((len = recv(so, (caddr_t)&buf, sizeof(buf), MSG_PEEK)) < 0) {
1155 		if (errno == EINTR) continue;
1156 		__ipsec_set_strerror(strerror(errno));
1157 		return NULL;
1158 	}
1159 
1160 	if (len < sizeof(buf)) {
1161 		recv(so, (caddr_t)&buf, sizeof(buf), 0);
1162 		__ipsec_errcode = EIPSEC_MAX;
1163 		return NULL;
1164 	}
1165 
1166 	/* read real message */
1167 	reallen = PFKEY_UNUNIT64(buf.sadb_msg_len);
1168 	if ((newmsg = CALLOC(reallen, struct sadb_msg *)) == 0) {
1169 		__ipsec_set_strerror(strerror(errno));
1170 		return NULL;
1171 	}
1172 
1173 	while ((len = recv(so, (caddr_t)newmsg, reallen, 0)) < 0) {
1174 		if (errno == EINTR) continue;
1175 		__ipsec_set_strerror(strerror(errno));
1176 		free(newmsg);
1177 		return NULL;
1178 	}
1179 
1180 	if (len != reallen) {
1181 		__ipsec_errcode = EIPSEC_SYSTEM_ERROR;
1182 		free(newmsg);
1183 		return NULL;
1184 	}
1185 
1186 	__ipsec_errcode = EIPSEC_NO_ERROR;
1187 	return newmsg;
1188 }
1189 
1190 /*
1191  * send message to a socket.
1192  * OUT:
1193  *	 others: success and return length sent.
1194  *	-1     : fail.
1195  */
1196 int
1197 pfkey_send(so, msg, len)
1198 	int so;
1199 	struct sadb_msg *msg;
1200 	int len;
1201 {
1202 	if ((len = send(so, (caddr_t)msg, len, 0)) < 0) {
1203 		__ipsec_set_strerror(strerror(errno));
1204 		return -1;
1205 	}
1206 
1207 	__ipsec_errcode = EIPSEC_NO_ERROR;
1208 	return len;
1209 }
1210 
1211 /*
1212  * %%% Utilities
1213  * NOTE: These functions are derived from netkey/key.c in KAME.
1214  */
1215 /*
1216  * set the pointer to each header in this message buffer.
1217  * IN:	msg: pointer to message buffer.
1218  *	mhp: pointer to the buffer initialized like below:
1219  *		caddr_t mhp[SADB_EXT_MAX + 1];
1220  * OUT:	-1: invalid.
1221  *	 0: valid.
1222  */
1223 int
1224 pfkey_align(msg, mhp)
1225 	struct sadb_msg *msg;
1226 	caddr_t *mhp;
1227 {
1228 	struct sadb_ext *ext;
1229 	int tlen, extlen;
1230 	int i;
1231 
1232 	/* validity check */
1233 	if (msg == NULL || mhp == NULL) {
1234 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1235 		return -1;
1236 	}
1237 
1238 	/* initialize */
1239 	for (i = 0; i < SADB_EXT_MAX + 1; i++)
1240 		mhp[i] = NULL;
1241 
1242 	mhp[0] = (caddr_t)msg;
1243 
1244 	tlen = PFKEY_UNUNIT64(msg->sadb_msg_len) - sizeof(struct sadb_msg);
1245 	ext = (struct sadb_ext *)((caddr_t)msg + sizeof(struct sadb_msg));
1246 
1247 	while (tlen > 0) {
1248 		/* duplicate check */
1249 		/* XXX Are there duplication either KEY_AUTH or KEY_ENCRYPT ?*/
1250 		if (mhp[ext->sadb_ext_type] != NULL) {
1251 			__ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
1252 			return -1;
1253 		}
1254 
1255 		/* set pointer */
1256 		switch (ext->sadb_ext_type) {
1257 		case SADB_EXT_SA:
1258 		case SADB_EXT_LIFETIME_CURRENT:
1259 		case SADB_EXT_LIFETIME_HARD:
1260 		case SADB_EXT_LIFETIME_SOFT:
1261 		case SADB_EXT_ADDRESS_SRC:
1262 		case SADB_EXT_ADDRESS_DST:
1263 		case SADB_EXT_ADDRESS_PROXY:
1264 		case SADB_EXT_KEY_AUTH:
1265 			/* XXX should to be check weak keys. */
1266 		case SADB_EXT_KEY_ENCRYPT:
1267 			/* XXX should to be check weak keys. */
1268 		case SADB_EXT_IDENTITY_SRC:
1269 		case SADB_EXT_IDENTITY_DST:
1270 		case SADB_EXT_SENSITIVITY:
1271 		case SADB_EXT_PROPOSAL:
1272 		case SADB_EXT_SUPPORTED_AUTH:
1273 		case SADB_EXT_SUPPORTED_ENCRYPT:
1274 		case SADB_EXT_SPIRANGE:
1275 		case SADB_X_EXT_POLICY:
1276 		case SADB_X_EXT_SA2:
1277 			mhp[ext->sadb_ext_type] = (caddr_t)ext;
1278 			break;
1279 		default:
1280 			__ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
1281 			return -1;
1282 		}
1283 
1284 		extlen = PFKEY_EXTLEN(ext);
1285 		tlen -= extlen;
1286 		ext = (struct sadb_ext *)((caddr_t)ext + extlen);
1287 	}
1288 
1289 	__ipsec_errcode = EIPSEC_NO_ERROR;
1290 	return 0;
1291 }
1292 
1293 /*
1294  * check basic usage for sadb_msg,
1295  * NOTE: This routine is derived from netkey/key.c in KAME.
1296  * IN:	msg: pointer to message buffer.
1297  *	mhp: pointer to the buffer initialized like below:
1298  *
1299  *		caddr_t mhp[SADB_EXT_MAX + 1];
1300  *
1301  * OUT:	-1: invalid.
1302  *	 0: valid.
1303  */
1304 int
1305 pfkey_check(mhp)
1306 	caddr_t *mhp;
1307 {
1308 	struct sadb_msg *msg;
1309 
1310 	/* validity check */
1311 	if (mhp == NULL || mhp[0] == NULL) {
1312 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1313 		return -1;
1314 	}
1315 
1316 	msg = (struct sadb_msg *)mhp[0];
1317 
1318 	/* check version */
1319 	if (msg->sadb_msg_version != PF_KEY_V2) {
1320 		__ipsec_errcode = EIPSEC_INVAL_VERSION;
1321 		return -1;
1322 	}
1323 
1324 	/* check type */
1325 	if (msg->sadb_msg_type > SADB_MAX) {
1326 		__ipsec_errcode = EIPSEC_INVAL_MSGTYPE;
1327 		return -1;
1328 	}
1329 
1330 	/* check SA type */
1331 	switch (msg->sadb_msg_satype) {
1332 	case SADB_SATYPE_UNSPEC:
1333 		switch (msg->sadb_msg_type) {
1334 		case SADB_GETSPI:
1335 		case SADB_UPDATE:
1336 		case SADB_ADD:
1337 		case SADB_DELETE:
1338 		case SADB_GET:
1339 		case SADB_ACQUIRE:
1340 		case SADB_EXPIRE:
1341 			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
1342 			return -1;
1343 		}
1344 		break;
1345 	case SADB_SATYPE_ESP:
1346 	case SADB_SATYPE_AH:
1347 	case SADB_X_SATYPE_IPCOMP:
1348 		switch (msg->sadb_msg_type) {
1349 		case SADB_X_SPDADD:
1350 		case SADB_X_SPDDELETE:
1351 		case SADB_X_SPDGET:
1352 		case SADB_X_SPDDUMP:
1353 		case SADB_X_SPDFLUSH:
1354 			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
1355 			return -1;
1356 		}
1357 		break;
1358 	case SADB_SATYPE_RSVP:
1359 	case SADB_SATYPE_OSPFV2:
1360 	case SADB_SATYPE_RIPV2:
1361 	case SADB_SATYPE_MIP:
1362 		__ipsec_errcode = EIPSEC_NOT_SUPPORTED;
1363 		return -1;
1364 	case 1:	/* XXX: What does it do ? */
1365 		if (msg->sadb_msg_type == SADB_X_PROMISC)
1366 			break;
1367 		/*FALLTHROUGH*/
1368 	default:
1369 		__ipsec_errcode = EIPSEC_INVAL_SATYPE;
1370 		return -1;
1371 	}
1372 
1373 	/* check field of upper layer protocol and address family */
1374 	if (mhp[SADB_EXT_ADDRESS_SRC] != NULL
1375 	 && mhp[SADB_EXT_ADDRESS_DST] != NULL) {
1376 		struct sadb_address *src0, *dst0;
1377 
1378 		src0 = (struct sadb_address *)(mhp[SADB_EXT_ADDRESS_SRC]);
1379 		dst0 = (struct sadb_address *)(mhp[SADB_EXT_ADDRESS_DST]);
1380 
1381 		if (src0->sadb_address_proto != dst0->sadb_address_proto) {
1382 			__ipsec_errcode = EIPSEC_PROTO_MISMATCH;
1383 			return -1;
1384 		}
1385 
1386 		if (PFKEY_ADDR_SADDR(src0)->sa_family
1387 		 != PFKEY_ADDR_SADDR(dst0)->sa_family) {
1388 			__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1389 			return -1;
1390 		}
1391 
1392 		switch (PFKEY_ADDR_SADDR(src0)->sa_family) {
1393 		case AF_INET:
1394 		case AF_INET6:
1395 			break;
1396 		default:
1397 			__ipsec_errcode = EIPSEC_INVAL_FAMILY;
1398 			return -1;
1399 		}
1400 
1401 		/*
1402 		 * prefixlen == 0 is valid because there must be the case
1403 		 * all addresses are matched.
1404 		 */
1405 	}
1406 
1407 	__ipsec_errcode = EIPSEC_NO_ERROR;
1408 	return 0;
1409 }
1410 
1411 /*
1412  * set data into sadb_msg.
1413  * `buf' must has been allocated sufficiently.
1414  */
1415 static caddr_t
1416 pfkey_setsadbmsg(buf, type, tlen, satype, seq, pid)
1417 	caddr_t buf;
1418 	u_int type, satype;
1419 	u_int tlen;
1420 	u_int32_t seq;
1421 	pid_t pid;
1422 {
1423 	struct sadb_msg *p;
1424 	u_int len;
1425 
1426 	p = (struct sadb_msg *)buf;
1427 	len = sizeof(struct sadb_msg);
1428 
1429 	memset(p, 0, len);
1430 	p->sadb_msg_version = PF_KEY_V2;
1431 	p->sadb_msg_type = type;
1432 	p->sadb_msg_errno = 0;
1433 	p->sadb_msg_satype = satype;
1434 	p->sadb_msg_len = PFKEY_UNIT64(tlen);
1435 	p->sadb_msg_reserved = 0;
1436 	p->sadb_msg_seq = seq;
1437 	p->sadb_msg_pid = (u_int32_t)pid;
1438 
1439 	return(buf + len);
1440 }
1441 
1442 /*
1443  * copy secasvar data into sadb_address.
1444  * `buf' must has been allocated sufficiently.
1445  */
1446 static caddr_t
1447 pfkey_setsadbsa(buf, spi, wsize, auth, enc, flags)
1448 	caddr_t buf;
1449 	u_int32_t spi, flags;
1450 	u_int wsize, auth, enc;
1451 {
1452 	struct sadb_sa *p;
1453 	u_int len;
1454 
1455 	p = (struct sadb_sa *)buf;
1456 	len = sizeof(struct sadb_sa);
1457 
1458 	memset(p, 0, len);
1459 	p->sadb_sa_len = PFKEY_UNIT64(len);
1460 	p->sadb_sa_exttype = SADB_EXT_SA;
1461 	p->sadb_sa_spi = spi;
1462 	p->sadb_sa_replay = wsize;
1463 	p->sadb_sa_state = SADB_SASTATE_LARVAL;
1464 	p->sadb_sa_auth = auth;
1465 	p->sadb_sa_encrypt = enc;
1466 	p->sadb_sa_flags = flags;
1467 
1468 	return(buf + len);
1469 }
1470 
1471 /*
1472  * set data into sadb_address.
1473  * `buf' must has been allocated sufficiently.
1474  * prefixlen is in bits.
1475  */
1476 static caddr_t
1477 pfkey_setsadbaddr(buf, exttype, saddr, prefixlen, ul_proto)
1478 	caddr_t buf;
1479 	u_int exttype;
1480 	struct sockaddr *saddr;
1481 	u_int prefixlen;
1482 	u_int ul_proto;
1483 {
1484 	struct sadb_address *p;
1485 	u_int len;
1486 
1487 	p = (struct sadb_address *)buf;
1488 	len = sizeof(struct sadb_address) + PFKEY_ALIGN8(saddr->sa_len);
1489 
1490 	memset(p, 0, len);
1491 	p->sadb_address_len = PFKEY_UNIT64(len);
1492 	p->sadb_address_exttype = exttype & 0xffff;
1493 	p->sadb_address_proto = ul_proto & 0xff;
1494 	p->sadb_address_prefixlen = prefixlen;
1495 	p->sadb_address_reserved = 0;
1496 
1497 	memcpy(p + 1, saddr, saddr->sa_len);
1498 
1499 	return(buf + len);
1500 }
1501 
1502 /*
1503  * set sadb_key structure after clearing buffer with zero.
1504  * OUT: the pointer of buf + len.
1505  */
1506 static caddr_t
1507 pfkey_setsadbkey(buf, type, key, keylen)
1508 	caddr_t buf, key;
1509 	u_int type, keylen;
1510 {
1511 	struct sadb_key *p;
1512 	u_int len;
1513 
1514 	p = (struct sadb_key *)buf;
1515 	len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen);
1516 
1517 	memset(p, 0, len);
1518 	p->sadb_key_len = PFKEY_UNIT64(len);
1519 	p->sadb_key_exttype = type;
1520 	p->sadb_key_bits = keylen << 3;
1521 	p->sadb_key_reserved = 0;
1522 
1523 	memcpy(p + 1, key, keylen);
1524 
1525 	return buf + len;
1526 }
1527 
1528 /*
1529  * set sadb_lifetime structure after clearing buffer with zero.
1530  * OUT: the pointer of buf + len.
1531  */
1532 static caddr_t
1533 pfkey_setsadblifetime(buf, type, l_alloc, l_bytes, l_addtime, l_usetime)
1534 	caddr_t buf;
1535 	u_int type;
1536 	u_int32_t l_alloc, l_bytes, l_addtime, l_usetime;
1537 {
1538 	struct sadb_lifetime *p;
1539 	u_int len;
1540 
1541 	p = (struct sadb_lifetime *)buf;
1542 	len = sizeof(struct sadb_lifetime);
1543 
1544 	memset(p, 0, len);
1545 	p->sadb_lifetime_len = PFKEY_UNIT64(len);
1546 	p->sadb_lifetime_exttype = type;
1547 
1548 	switch (type) {
1549 	case SADB_EXT_LIFETIME_SOFT:
1550 		p->sadb_lifetime_allocations
1551 			= (l_alloc * soft_lifetime_allocations_rate) /100;
1552 		p->sadb_lifetime_bytes
1553 			= (l_bytes * soft_lifetime_bytes_rate) /100;
1554 		p->sadb_lifetime_addtime
1555 			= (l_addtime * soft_lifetime_addtime_rate) /100;
1556 		p->sadb_lifetime_usetime
1557 			= (l_usetime * soft_lifetime_usetime_rate) /100;
1558 		break;
1559 	case SADB_EXT_LIFETIME_HARD:
1560 		p->sadb_lifetime_allocations = l_alloc;
1561 		p->sadb_lifetime_bytes = l_bytes;
1562 		p->sadb_lifetime_addtime = l_addtime;
1563 		p->sadb_lifetime_usetime = l_usetime;
1564 		break;
1565 	}
1566 
1567 	return buf + len;
1568 }
1569 
1570 /*
1571  * copy secasvar data into sadb_address.
1572  * `buf' must has been allocated sufficiently.
1573  */
1574 static caddr_t
1575 pfkey_setsadbxsa2(buf, mode0, reqid)
1576 	caddr_t buf;
1577 	u_int32_t mode0;
1578 	u_int32_t reqid;
1579 {
1580 	struct sadb_x_sa2 *p;
1581 	u_int8_t mode = mode0 & 0xff;
1582 	u_int len;
1583 
1584 	p = (struct sadb_x_sa2 *)buf;
1585 	len = sizeof(struct sadb_x_sa2);
1586 
1587 	memset(p, 0, len);
1588 	p->sadb_x_sa2_len = PFKEY_UNIT64(len);
1589 	p->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
1590 	p->sadb_x_sa2_mode = mode;
1591 	p->sadb_x_sa2_reqid = reqid;
1592 
1593 	return(buf + len);
1594 }
1595 
1596