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