Sync usage with man page.
[netbsd-mini2440.git] / crypto / dist / ipsec-tools / src / libipsec / pfkey.c
blobb408db444ff551fa3451fc78249859c60a0b711d
1 /* $NetBSD: pfkey.c,v 1.18 2008/12/05 06:02:20 tteras Exp $ */
3 /* $KAME: pfkey.c,v 1.47 2003/10/02 19:52:12 itojun Exp $ */
5 /*
6 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
7 * All rights reserved.
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.
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.
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/socket.h>
41 #include <net/pfkeyv2.h>
42 #include <netinet/in.h>
43 #include PATH_IPSEC_H
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <string.h>
48 #include <errno.h>
49 #include <stdio.h>
51 #include "ipsec_strerror.h"
52 #include "libpfkey.h"
54 #define CALLOC(size, cast) (cast)calloc(1, (size))
56 static int findsupportedmap __P((int));
57 static int setsupportedmap __P((struct sadb_supported *));
58 static struct sadb_alg *findsupportedalg __P((u_int, u_int));
59 static int pfkey_send_x1 __P((struct pfkey_send_sa_args *));
60 static int pfkey_send_x2 __P((int, u_int, u_int, u_int,
61 struct sockaddr *, struct sockaddr *, u_int32_t));
62 static int pfkey_send_x3 __P((int, u_int, u_int));
63 static int pfkey_send_x4 __P((int, u_int, struct sockaddr *, u_int,
64 struct sockaddr *, u_int, u_int, u_int64_t, u_int64_t,
65 char *, int, u_int32_t));
66 static int pfkey_send_x5 __P((int, u_int, u_int32_t));
68 static caddr_t pfkey_setsadbmsg __P((caddr_t, caddr_t, u_int, u_int,
69 u_int, u_int32_t, pid_t));
70 static caddr_t pfkey_setsadbsa __P((caddr_t, caddr_t, u_int32_t, u_int,
71 u_int, u_int, u_int32_t));
72 static caddr_t pfkey_setsadbaddr __P((caddr_t, caddr_t, u_int,
73 struct sockaddr *, u_int, u_int));
75 #ifdef SADB_X_EXT_KMADDRESS
76 static caddr_t pfkey_setsadbkmaddr __P((caddr_t, caddr_t, struct sockaddr *,
77 struct sockaddr *));
78 #endif
80 static caddr_t pfkey_setsadbkey __P((caddr_t, caddr_t, u_int, caddr_t, u_int));
81 static caddr_t pfkey_setsadblifetime __P((caddr_t, caddr_t, u_int, u_int32_t,
82 u_int32_t, u_int32_t, u_int32_t));
83 static caddr_t pfkey_setsadbxsa2 __P((caddr_t, caddr_t, u_int32_t, u_int32_t));
85 #ifdef SADB_X_EXT_NAT_T_TYPE
86 static caddr_t pfkey_set_natt_type __P((caddr_t, caddr_t, u_int, u_int8_t));
87 static caddr_t pfkey_set_natt_port __P((caddr_t, caddr_t, u_int, u_int16_t));
88 #endif
89 #ifdef SADB_X_EXT_NAT_T_FRAG
90 static caddr_t pfkey_set_natt_frag __P((caddr_t, caddr_t, u_int, u_int16_t));
91 #endif
93 #ifdef SADB_X_EXT_SEC_CTX
94 static caddr_t pfkey_setsecctx __P((caddr_t, caddr_t, u_int, u_int8_t, u_int8_t,
95 caddr_t, u_int16_t));
96 #endif
98 int libipsec_opt = 0
99 #ifdef SADB_X_EXT_NAT_T_TYPE
100 | LIBIPSEC_OPT_NATT
101 #endif
102 #ifdef SADB_X_EXT_NAT_T_FRAG
103 | LIBIPSEC_OPT_FRAG
104 #endif
105 #ifdef SADB_X_EXT_NAT_T_SEC_CTX
106 | LIBIPSEC_OPT_SEC_CTX
107 #endif
111 * make and search supported algorithm structure.
113 static struct sadb_supported *ipsec_supported[] = { NULL, NULL, NULL,
114 #ifdef SADB_X_SATYPE_TCPSIGNATURE
115 NULL,
116 #endif
119 static int supported_map[] = {
120 SADB_SATYPE_AH,
121 SADB_SATYPE_ESP,
122 SADB_X_SATYPE_IPCOMP,
123 #ifdef SADB_X_SATYPE_TCPSIGNATURE
124 SADB_X_SATYPE_TCPSIGNATURE,
125 #endif
128 static int
129 findsupportedmap(satype)
130 int satype;
132 int i;
134 for (i = 0; i < sizeof(supported_map)/sizeof(supported_map[0]); i++)
135 if (supported_map[i] == satype)
136 return i;
137 return -1;
140 static struct sadb_alg *
141 findsupportedalg(satype, alg_id)
142 u_int satype, alg_id;
144 int algno;
145 int tlen;
146 caddr_t p;
148 /* validity check */
149 algno = findsupportedmap((int)satype);
150 if (algno == -1) {
151 __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
152 return NULL;
154 if (ipsec_supported[algno] == NULL) {
155 __ipsec_errcode = EIPSEC_DO_GET_SUPP_LIST;
156 return NULL;
159 tlen = ipsec_supported[algno]->sadb_supported_len
160 - sizeof(struct sadb_supported);
161 p = (void *)(ipsec_supported[algno] + 1);
162 while (tlen > 0) {
163 if (tlen < sizeof(struct sadb_alg)) {
164 /* invalid format */
165 break;
167 if (((struct sadb_alg *)(void *)p)->sadb_alg_id == alg_id)
168 return (void *)p;
170 tlen -= sizeof(struct sadb_alg);
171 p += sizeof(struct sadb_alg);
174 __ipsec_errcode = EIPSEC_NOT_SUPPORTED;
175 return NULL;
178 static int
179 setsupportedmap(sup)
180 struct sadb_supported *sup;
182 struct sadb_supported **ipsup;
184 switch (sup->sadb_supported_exttype) {
185 case SADB_EXT_SUPPORTED_AUTH:
186 ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_AH)];
187 break;
188 case SADB_EXT_SUPPORTED_ENCRYPT:
189 ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_ESP)];
190 break;
191 default:
192 __ipsec_errcode = EIPSEC_INVAL_SATYPE;
193 return -1;
196 if (*ipsup)
197 free(*ipsup);
199 *ipsup = malloc((size_t)sup->sadb_supported_len);
200 if (!*ipsup) {
201 __ipsec_set_strerror(strerror(errno));
202 return -1;
204 memcpy(*ipsup, sup, (size_t)sup->sadb_supported_len);
206 return 0;
210 * check key length against algorithm specified.
211 * This function is called with SADB_EXT_SUPPORTED_{AUTH,ENCRYPT} as the
212 * augument, and only calls to ipsec_check_keylen2();
213 * keylen is the unit of bit.
214 * OUT:
215 * -1: invalid.
216 * 0: valid.
219 ipsec_check_keylen(supported, alg_id, keylen)
220 u_int supported;
221 u_int alg_id;
222 u_int keylen;
224 u_int satype;
226 /* validity check */
227 switch (supported) {
228 case SADB_EXT_SUPPORTED_AUTH:
229 satype = SADB_SATYPE_AH;
230 break;
231 case SADB_EXT_SUPPORTED_ENCRYPT:
232 satype = SADB_SATYPE_ESP;
233 break;
234 default:
235 __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
236 return -1;
239 return ipsec_check_keylen2(satype, alg_id, keylen);
243 * check key length against algorithm specified.
244 * satype is one of satype defined at pfkeyv2.h.
245 * keylen is the unit of bit.
246 * OUT:
247 * -1: invalid.
248 * 0: valid.
251 ipsec_check_keylen2(satype, alg_id, keylen)
252 u_int satype;
253 u_int alg_id;
254 u_int keylen;
256 struct sadb_alg *alg;
258 alg = findsupportedalg(satype, alg_id);
259 if (!alg)
260 return -1;
262 if (keylen < alg->sadb_alg_minbits || keylen > alg->sadb_alg_maxbits) {
263 fprintf(stderr, "%d %d %d\n", keylen, alg->sadb_alg_minbits,
264 alg->sadb_alg_maxbits);
265 __ipsec_errcode = EIPSEC_INVAL_KEYLEN;
266 return -1;
269 __ipsec_errcode = EIPSEC_NO_ERROR;
270 return 0;
274 * get max/min key length against algorithm specified.
275 * satype is one of satype defined at pfkeyv2.h.
276 * keylen is the unit of bit.
277 * OUT:
278 * -1: invalid.
279 * 0: valid.
282 ipsec_get_keylen(supported, alg_id, alg0)
283 u_int supported, alg_id;
284 struct sadb_alg *alg0;
286 struct sadb_alg *alg;
287 u_int satype;
289 /* validity check */
290 if (!alg0) {
291 __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
292 return -1;
295 switch (supported) {
296 case SADB_EXT_SUPPORTED_AUTH:
297 satype = SADB_SATYPE_AH;
298 break;
299 case SADB_EXT_SUPPORTED_ENCRYPT:
300 satype = SADB_SATYPE_ESP;
301 break;
302 default:
303 __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
304 return -1;
307 alg = findsupportedalg(satype, alg_id);
308 if (!alg)
309 return -1;
311 memcpy(alg0, alg, sizeof(*alg0));
313 __ipsec_errcode = EIPSEC_NO_ERROR;
314 return 0;
318 * set the rate for SOFT lifetime against HARD one.
319 * If rate is more than 100 or equal to zero, then set to 100.
321 static u_int soft_lifetime_allocations_rate = PFKEY_SOFT_LIFETIME_RATE;
322 static u_int soft_lifetime_bytes_rate = PFKEY_SOFT_LIFETIME_RATE;
323 static u_int soft_lifetime_addtime_rate = PFKEY_SOFT_LIFETIME_RATE;
324 static u_int soft_lifetime_usetime_rate = PFKEY_SOFT_LIFETIME_RATE;
326 u_int
327 pfkey_set_softrate(type, rate)
328 u_int type, rate;
330 __ipsec_errcode = EIPSEC_NO_ERROR;
332 if (rate > 100 || rate == 0)
333 rate = 100;
335 switch (type) {
336 case SADB_X_LIFETIME_ALLOCATIONS:
337 soft_lifetime_allocations_rate = rate;
338 return 0;
339 case SADB_X_LIFETIME_BYTES:
340 soft_lifetime_bytes_rate = rate;
341 return 0;
342 case SADB_X_LIFETIME_ADDTIME:
343 soft_lifetime_addtime_rate = rate;
344 return 0;
345 case SADB_X_LIFETIME_USETIME:
346 soft_lifetime_usetime_rate = rate;
347 return 0;
350 __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
351 return 1;
355 * get current rate for SOFT lifetime against HARD one.
356 * ATTENTION: ~0 is returned if invalid type was passed.
358 u_int
359 pfkey_get_softrate(type)
360 u_int type;
362 switch (type) {
363 case SADB_X_LIFETIME_ALLOCATIONS:
364 return soft_lifetime_allocations_rate;
365 case SADB_X_LIFETIME_BYTES:
366 return soft_lifetime_bytes_rate;
367 case SADB_X_LIFETIME_ADDTIME:
368 return soft_lifetime_addtime_rate;
369 case SADB_X_LIFETIME_USETIME:
370 return soft_lifetime_usetime_rate;
373 return (u_int)~0;
377 * sending SADB_GETSPI message to the kernel.
378 * OUT:
379 * positive: success and return length sent.
380 * -1 : error occured, and set errno.
383 pfkey_send_getspi_nat(so, satype, mode, src, dst, natt_type, sport, dport, min, max, reqid, seq)
384 int so;
385 u_int satype, mode;
386 struct sockaddr *src, *dst;
387 u_int8_t natt_type;
388 u_int16_t sport, dport;
389 u_int32_t min, max, reqid, seq;
391 struct sadb_msg *newmsg;
392 caddr_t ep;
393 int len;
394 int need_spirange = 0;
395 caddr_t p;
396 int plen;
398 /* validity check */
399 if (src == NULL || dst == NULL) {
400 __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
401 return -1;
403 if (src->sa_family != dst->sa_family) {
404 __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
405 return -1;
407 if (min > max || (min > 0 && min <= 255)) {
408 __ipsec_errcode = EIPSEC_INVAL_SPI;
409 return -1;
411 switch (src->sa_family) {
412 case AF_INET:
413 plen = sizeof(struct in_addr) << 3;
414 break;
415 case AF_INET6:
416 plen = sizeof(struct in6_addr) << 3;
417 break;
418 default:
419 __ipsec_errcode = EIPSEC_INVAL_FAMILY;
420 return -1;
423 /* create new sadb_msg to send. */
424 len = sizeof(struct sadb_msg)
425 + sizeof(struct sadb_x_sa2)
426 + sizeof(struct sadb_address)
427 + PFKEY_ALIGN8(sysdep_sa_len(src))
428 + sizeof(struct sadb_address)
429 + PFKEY_ALIGN8(sysdep_sa_len(dst));
431 if (min > 255 && max < (u_int)~0) {
432 need_spirange++;
433 len += sizeof(struct sadb_spirange);
436 #ifdef SADB_X_EXT_NAT_T_TYPE
437 if(natt_type||sport||dport){
438 len += sizeof(struct sadb_x_nat_t_type);
439 len += sizeof(struct sadb_x_nat_t_port);
440 len += sizeof(struct sadb_x_nat_t_port);
442 #endif
444 if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
445 __ipsec_set_strerror(strerror(errno));
446 return -1;
448 ep = ((caddr_t)(void *)newmsg) + len;
450 p = pfkey_setsadbmsg((void *)newmsg, ep, SADB_GETSPI,
451 (u_int)len, satype, seq, getpid());
452 if (!p) {
453 free(newmsg);
454 return -1;
457 p = pfkey_setsadbxsa2(p, ep, mode, reqid);
458 if (!p) {
459 free(newmsg);
460 return -1;
463 /* set sadb_address for source */
464 p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, (u_int)plen,
465 IPSEC_ULPROTO_ANY);
466 if (!p) {
467 free(newmsg);
468 return -1;
471 /* set sadb_address for destination */
472 p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, (u_int)plen,
473 IPSEC_ULPROTO_ANY);
474 if (!p) {
475 free(newmsg);
476 return -1;
479 #ifdef SADB_X_EXT_NAT_T_TYPE
480 /* Add nat-t messages */
481 if (natt_type) {
482 p = pfkey_set_natt_type(p, ep, SADB_X_EXT_NAT_T_TYPE,
483 natt_type);
484 if (!p) {
485 free(newmsg);
486 return -1;
489 p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_SPORT,
490 sport);
491 if (!p) {
492 free(newmsg);
493 return -1;
496 p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_DPORT,
497 dport);
498 if (!p) {
499 free(newmsg);
500 return -1;
503 #endif
505 /* proccessing spi range */
506 if (need_spirange) {
507 struct sadb_spirange spirange;
509 if (p + sizeof(spirange) > ep) {
510 free(newmsg);
511 return -1;
514 memset(&spirange, 0, sizeof(spirange));
515 spirange.sadb_spirange_len = PFKEY_UNIT64(sizeof(spirange));
516 spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE;
517 spirange.sadb_spirange_min = min;
518 spirange.sadb_spirange_max = max;
520 memcpy(p, &spirange, sizeof(spirange));
522 p += sizeof(spirange);
524 if (p != ep) {
525 free(newmsg);
526 return -1;
529 /* send message */
530 len = pfkey_send(so, newmsg, len);
531 free(newmsg);
533 if (len < 0)
534 return -1;
536 __ipsec_errcode = EIPSEC_NO_ERROR;
537 return len;
541 pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq)
542 int so;
543 u_int satype, mode;
544 struct sockaddr *src, *dst;
545 u_int32_t min, max, reqid, seq;
547 return pfkey_send_getspi_nat(so, satype, mode, src, dst, 0, 0, 0,
548 min, max, reqid, seq);
552 * sending SADB_UPDATE message to the kernel.
553 * The length of key material is a_keylen + e_keylen.
554 * OUT:
555 * positive: success and return length sent.
556 * -1 : error occured, and set errno.
559 pfkey_send_update2(sa_parms)
560 struct pfkey_send_sa_args *sa_parms;
562 int len;
565 sa_parms->type = SADB_UPDATE;
566 if ((len = pfkey_send_x1(sa_parms)) < 0)
567 return -1;
569 return len;
573 * sending SADB_ADD message to the kernel.
574 * The length of key material is a_keylen + e_keylen.
575 * OUT:
576 * positive: success and return length sent.
577 * -1 : error occured, and set errno.
580 pfkey_send_add2(sa_parms)
581 struct pfkey_send_sa_args *sa_parms;
583 int len;
585 sa_parms->type = SADB_ADD;
586 if ((len = pfkey_send_x1(sa_parms)) < 0)
587 return -1;
589 return len;
593 * sending SADB_DELETE message to the kernel.
594 * OUT:
595 * positive: success and return length sent.
596 * -1 : error occured, and set errno.
599 pfkey_send_delete(so, satype, mode, src, dst, spi)
600 int so;
601 u_int satype, mode;
602 struct sockaddr *src, *dst;
603 u_int32_t spi;
605 int len;
606 if ((len = pfkey_send_x2(so, SADB_DELETE, satype, mode, src, dst, spi)) < 0)
607 return -1;
609 return len;
613 * sending SADB_DELETE without spi to the kernel. This is
614 * the "delete all" request (an extension also present in
615 * Solaris).
617 * OUT:
618 * positive: success and return length sent
619 * -1 : error occured, and set errno
621 /*ARGSUSED*/
623 pfkey_send_delete_all(so, satype, mode, src, dst)
624 int so;
625 u_int satype, mode;
626 struct sockaddr *src, *dst;
628 struct sadb_msg *newmsg;
629 int len;
630 caddr_t p;
631 int plen;
632 caddr_t ep;
634 /* validity check */
635 if (src == NULL || dst == NULL) {
636 __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
637 return -1;
639 if (src->sa_family != dst->sa_family) {
640 __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
641 return -1;
643 switch (src->sa_family) {
644 case AF_INET:
645 plen = sizeof(struct in_addr) << 3;
646 break;
647 case AF_INET6:
648 plen = sizeof(struct in6_addr) << 3;
649 break;
650 default:
651 __ipsec_errcode = EIPSEC_INVAL_FAMILY;
652 return -1;
655 /* create new sadb_msg to reply. */
656 len = sizeof(struct sadb_msg)
657 + sizeof(struct sadb_address)
658 + PFKEY_ALIGN8(sysdep_sa_len(src))
659 + sizeof(struct sadb_address)
660 + PFKEY_ALIGN8(sysdep_sa_len(dst));
662 if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
663 __ipsec_set_strerror(strerror(errno));
664 return -1;
666 ep = ((caddr_t)(void *)newmsg) + len;
668 p = pfkey_setsadbmsg((void *)newmsg, ep, SADB_DELETE, (u_int)len,
669 satype, 0, getpid());
670 if (!p) {
671 free(newmsg);
672 return -1;
674 p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, (u_int)plen,
675 IPSEC_ULPROTO_ANY);
676 if (!p) {
677 free(newmsg);
678 return -1;
680 p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, (u_int)plen,
681 IPSEC_ULPROTO_ANY);
682 if (!p || p != ep) {
683 free(newmsg);
684 return -1;
687 /* send message */
688 len = pfkey_send(so, newmsg, len);
689 free(newmsg);
691 if (len < 0)
692 return -1;
694 __ipsec_errcode = EIPSEC_NO_ERROR;
695 return len;
699 * sending SADB_GET message to the kernel.
700 * OUT:
701 * positive: success and return length sent.
702 * -1 : error occured, and set errno.
705 pfkey_send_get(so, satype, mode, src, dst, spi)
706 int so;
707 u_int satype, mode;
708 struct sockaddr *src, *dst;
709 u_int32_t spi;
711 int len;
712 if ((len = pfkey_send_x2(so, SADB_GET, satype, mode, src, dst, spi)) < 0)
713 return -1;
715 return len;
719 * sending SADB_REGISTER message to the kernel.
720 * OUT:
721 * positive: success and return length sent.
722 * -1 : error occured, and set errno.
725 pfkey_send_register(so, satype)
726 int so;
727 u_int satype;
729 int len, algno;
731 if (satype == PF_UNSPEC) {
732 for (algno = 0;
733 algno < sizeof(supported_map)/sizeof(supported_map[0]);
734 algno++) {
735 if (ipsec_supported[algno]) {
736 free(ipsec_supported[algno]);
737 ipsec_supported[algno] = NULL;
740 } else {
741 algno = findsupportedmap((int)satype);
742 if (algno == -1) {
743 __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
744 return -1;
747 if (ipsec_supported[algno]) {
748 free(ipsec_supported[algno]);
749 ipsec_supported[algno] = NULL;
753 if ((len = pfkey_send_x3(so, SADB_REGISTER, satype)) < 0)
754 return -1;
756 return len;
760 * receiving SADB_REGISTER message from the kernel, and copy buffer for
761 * sadb_supported returned into ipsec_supported.
762 * OUT:
763 * 0: success and return length sent.
764 * -1: error occured, and set errno.
767 pfkey_recv_register(so)
768 int so;
770 pid_t pid = getpid();
771 struct sadb_msg *newmsg;
772 int error = -1;
774 /* receive message */
775 for (;;) {
776 if ((newmsg = pfkey_recv(so)) == NULL)
777 return -1;
778 if (newmsg->sadb_msg_type == SADB_REGISTER &&
779 newmsg->sadb_msg_pid == pid)
780 break;
781 free(newmsg);
784 /* check and fix */
785 newmsg->sadb_msg_len = PFKEY_UNUNIT64(newmsg->sadb_msg_len);
787 error = pfkey_set_supported(newmsg, newmsg->sadb_msg_len);
788 free(newmsg);
790 if (error == 0)
791 __ipsec_errcode = EIPSEC_NO_ERROR;
793 return error;
797 * receiving SADB_REGISTER message from the kernel, and copy buffer for
798 * sadb_supported returned into ipsec_supported.
799 * NOTE: sadb_msg_len must be host order.
800 * IN:
801 * tlen: msg length, it's to makeing sure.
802 * OUT:
803 * 0: success and return length sent.
804 * -1: error occured, and set errno.
807 pfkey_set_supported(msg, tlen)
808 struct sadb_msg *msg;
809 int tlen;
811 struct sadb_supported *sup;
812 caddr_t p;
813 caddr_t ep;
815 /* validity */
816 if (msg->sadb_msg_len != tlen) {
817 __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
818 return -1;
821 p = (void *)msg;
822 ep = p + tlen;
824 p += sizeof(struct sadb_msg);
826 while (p < ep) {
827 sup = (void *)p;
828 if (ep < p + sizeof(*sup) ||
829 PFKEY_EXTLEN(sup) < sizeof(*sup) ||
830 ep < p + sup->sadb_supported_len) {
831 /* invalid format */
832 break;
835 switch (sup->sadb_supported_exttype) {
836 case SADB_EXT_SUPPORTED_AUTH:
837 case SADB_EXT_SUPPORTED_ENCRYPT:
838 break;
839 default:
840 __ipsec_errcode = EIPSEC_INVAL_SATYPE;
841 return -1;
844 /* fixed length */
845 sup->sadb_supported_len = PFKEY_EXTLEN(sup);
847 /* set supported map */
848 if (setsupportedmap(sup) != 0)
849 return -1;
851 p += sup->sadb_supported_len;
854 if (p != ep) {
855 __ipsec_errcode = EIPSEC_INVAL_SATYPE;
856 return -1;
859 __ipsec_errcode = EIPSEC_NO_ERROR;
861 return 0;
865 * sending SADB_FLUSH message to the kernel.
866 * OUT:
867 * positive: success and return length sent.
868 * -1 : error occured, and set errno.
871 pfkey_send_flush(so, satype)
872 int so;
873 u_int satype;
875 int len;
877 if ((len = pfkey_send_x3(so, SADB_FLUSH, satype)) < 0)
878 return -1;
880 return len;
884 * sending SADB_DUMP message to the kernel.
885 * OUT:
886 * positive: success and return length sent.
887 * -1 : error occured, and set errno.
890 pfkey_send_dump(so, satype)
891 int so;
892 u_int satype;
894 int len;
896 if ((len = pfkey_send_x3(so, SADB_DUMP, satype)) < 0)
897 return -1;
899 return len;
903 * sending SADB_X_PROMISC message to the kernel.
904 * NOTE that this function handles promisc mode toggle only.
905 * IN:
906 * flag: set promisc off if zero, set promisc on if non-zero.
907 * OUT:
908 * positive: success and return length sent.
909 * -1 : error occured, and set errno.
910 * 0 : error occured, and set errno.
911 * others: a pointer to new allocated buffer in which supported
912 * algorithms is.
915 pfkey_send_promisc_toggle(so, flag)
916 int so;
917 int flag;
919 int len;
921 if ((len = pfkey_send_x3(so, SADB_X_PROMISC,
922 (u_int)(flag ? 1 : 0))) < 0)
923 return -1;
925 return len;
929 * sending SADB_X_SPDADD message to the kernel.
930 * OUT:
931 * positive: success and return length sent.
932 * -1 : error occured, and set errno.
935 pfkey_send_spdadd(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
936 int so;
937 struct sockaddr *src, *dst;
938 u_int prefs, prefd, proto;
939 caddr_t policy;
940 int policylen;
941 u_int32_t seq;
943 int len;
945 if ((len = pfkey_send_x4(so, SADB_X_SPDADD,
946 src, prefs, dst, prefd, proto,
947 (u_int64_t)0, (u_int64_t)0,
948 policy, policylen, seq)) < 0)
949 return -1;
951 return len;
955 * sending SADB_X_SPDADD message to the kernel.
956 * OUT:
957 * positive: success and return length sent.
958 * -1 : error occured, and set errno.
961 pfkey_send_spdadd2(so, src, prefs, dst, prefd, proto, ltime, vtime,
962 policy, policylen, seq)
963 int so;
964 struct sockaddr *src, *dst;
965 u_int prefs, prefd, proto;
966 u_int64_t ltime, vtime;
967 caddr_t policy;
968 int policylen;
969 u_int32_t seq;
971 int len;
973 if ((len = pfkey_send_x4(so, SADB_X_SPDADD,
974 src, prefs, dst, prefd, proto,
975 ltime, vtime,
976 policy, policylen, seq)) < 0)
977 return -1;
979 return len;
983 * sending SADB_X_SPDUPDATE message to the kernel.
984 * OUT:
985 * positive: success and return length sent.
986 * -1 : error occured, and set errno.
989 pfkey_send_spdupdate(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
990 int so;
991 struct sockaddr *src, *dst;
992 u_int prefs, prefd, proto;
993 caddr_t policy;
994 int policylen;
995 u_int32_t seq;
997 int len;
999 if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE,
1000 src, prefs, dst, prefd, proto,
1001 (u_int64_t)0, (u_int64_t)0,
1002 policy, policylen, seq)) < 0)
1003 return -1;
1005 return len;
1009 * sending SADB_X_SPDUPDATE message to the kernel.
1010 * OUT:
1011 * positive: success and return length sent.
1012 * -1 : error occured, and set errno.
1015 pfkey_send_spdupdate2(so, src, prefs, dst, prefd, proto, ltime, vtime,
1016 policy, policylen, seq)
1017 int so;
1018 struct sockaddr *src, *dst;
1019 u_int prefs, prefd, proto;
1020 u_int64_t ltime, vtime;
1021 caddr_t policy;
1022 int policylen;
1023 u_int32_t seq;
1025 int len;
1027 if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE,
1028 src, prefs, dst, prefd, proto,
1029 ltime, vtime,
1030 policy, policylen, seq)) < 0)
1031 return -1;
1033 return len;
1037 * sending SADB_X_SPDDELETE message to the kernel.
1038 * OUT:
1039 * positive: success and return length sent.
1040 * -1 : error occured, and set errno.
1043 pfkey_send_spddelete(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
1044 int so;
1045 struct sockaddr *src, *dst;
1046 u_int prefs, prefd, proto;
1047 caddr_t policy;
1048 int policylen;
1049 u_int32_t seq;
1051 int len;
1053 if (policylen != sizeof(struct sadb_x_policy)) {
1054 __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1055 return -1;
1058 if ((len = pfkey_send_x4(so, SADB_X_SPDDELETE,
1059 src, prefs, dst, prefd, proto,
1060 (u_int64_t)0, (u_int64_t)0,
1061 policy, policylen, seq)) < 0)
1062 return -1;
1064 return len;
1068 * sending SADB_X_SPDDELETE message to the kernel.
1069 * OUT:
1070 * positive: success and return length sent.
1071 * -1 : error occured, and set errno.
1074 pfkey_send_spddelete2(so, spid)
1075 int so;
1076 u_int32_t spid;
1078 int len;
1080 if ((len = pfkey_send_x5(so, SADB_X_SPDDELETE2, spid)) < 0)
1081 return -1;
1083 return len;
1087 * sending SADB_X_SPDGET message to the kernel.
1088 * OUT:
1089 * positive: success and return length sent.
1090 * -1 : error occured, and set errno.
1093 pfkey_send_spdget(so, spid)
1094 int so;
1095 u_int32_t spid;
1097 int len;
1099 if ((len = pfkey_send_x5(so, SADB_X_SPDGET, spid)) < 0)
1100 return -1;
1102 return len;
1106 * sending SADB_X_SPDSETIDX message to the kernel.
1107 * OUT:
1108 * positive: success and return length sent.
1109 * -1 : error occured, and set errno.
1112 pfkey_send_spdsetidx(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
1113 int so;
1114 struct sockaddr *src, *dst;
1115 u_int prefs, prefd, proto;
1116 caddr_t policy;
1117 int policylen;
1118 u_int32_t seq;
1120 int len;
1122 if (policylen != sizeof(struct sadb_x_policy)) {
1123 __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1124 return -1;
1127 if ((len = pfkey_send_x4(so, SADB_X_SPDSETIDX,
1128 src, prefs, dst, prefd, proto,
1129 (u_int64_t)0, (u_int64_t)0,
1130 policy, policylen, seq)) < 0)
1131 return -1;
1133 return len;
1137 * sending SADB_SPDFLUSH message to the kernel.
1138 * OUT:
1139 * positive: success and return length sent.
1140 * -1 : error occured, and set errno.
1143 pfkey_send_spdflush(so)
1144 int so;
1146 int len;
1148 if ((len = pfkey_send_x3(so, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC)) < 0)
1149 return -1;
1151 return len;
1155 * sending SADB_SPDDUMP message to the kernel.
1156 * OUT:
1157 * positive: success and return length sent.
1158 * -1 : error occured, and set errno.
1161 pfkey_send_spddump(so)
1162 int so;
1164 int len;
1166 if ((len = pfkey_send_x3(so, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC)) < 0)
1167 return -1;
1169 return len;
1173 #ifdef SADB_X_MIGRATE
1175 * sending SADB_X_MIGRATE message to the kernel.
1176 * OUT:
1177 * positive: success and return length sent.
1178 * -1 : error occured, and set errno.
1181 pfkey_send_migrate(so, local, remote, src, prefs, dst, prefd, proto, policy, policylen, seq)
1182 int so;
1183 struct sockaddr *src, *dst;
1184 struct sockaddr *local, *remote;
1185 u_int prefs, prefd, proto;
1186 caddr_t policy;
1187 int policylen;
1188 u_int32_t seq;
1190 struct sadb_msg *newmsg;
1191 int len;
1192 caddr_t p;
1193 int plen;
1194 caddr_t ep;
1196 /* validity check */
1197 if (src == NULL || dst == NULL) {
1198 __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1199 return -1;
1201 if (src->sa_family != dst->sa_family) {
1202 __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1203 return -1;
1206 if (local == NULL || remote == NULL) {
1207 __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1208 return -1;
1210 #ifdef SADB_X_EXT_KMADDRESS
1211 if (local->sa_family != remote->sa_family) {
1212 __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1213 return -1;
1215 #endif
1217 switch (src->sa_family) {
1218 case AF_INET:
1219 plen = sizeof(struct in_addr) << 3;
1220 break;
1221 case AF_INET6:
1222 plen = sizeof(struct in6_addr) << 3;
1223 break;
1224 default:
1225 __ipsec_errcode = EIPSEC_INVAL_FAMILY;
1226 return -1;
1228 if (prefs > plen || prefd > plen) {
1229 __ipsec_errcode = EIPSEC_INVAL_PREFIXLEN;
1230 return -1;
1233 /* create new sadb_msg to reply. */
1234 len = sizeof(struct sadb_msg)
1235 #ifdef SADB_X_EXT_KMADDRESS
1236 + sizeof(struct sadb_x_kmaddress)
1237 + PFKEY_ALIGN8(2*sysdep_sa_len(local))
1238 #endif
1239 + sizeof(struct sadb_address)
1240 + PFKEY_ALIGN8(sysdep_sa_len(src))
1241 + sizeof(struct sadb_address)
1242 + PFKEY_ALIGN8(sysdep_sa_len(dst))
1243 + policylen;
1245 if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
1246 __ipsec_set_strerror(strerror(errno));
1247 return -1;
1249 ep = ((caddr_t)newmsg) + len;
1251 p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_X_MIGRATE, (u_int)len,
1252 SADB_SATYPE_UNSPEC, seq, getpid());
1253 if (!p) {
1254 free(newmsg);
1255 return -1;
1257 #ifdef SADB_X_EXT_KMADDRESS
1258 p = pfkey_setsadbkmaddr(p, ep, local, remote);
1259 if (!p) {
1260 free(newmsg);
1261 return -1;
1263 #endif
1264 p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, prefs, proto);
1265 if (!p) {
1266 free(newmsg);
1267 return -1;
1269 p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, prefd, proto);
1270 if (!p || p + policylen != ep) {
1271 free(newmsg);
1272 return -1;
1274 memcpy(p, policy, policylen);
1276 /* send message */
1277 len = pfkey_send(so, newmsg, len);
1278 free(newmsg);
1280 if (len < 0)
1281 return -1;
1283 __ipsec_errcode = EIPSEC_NO_ERROR;
1284 return len;
1286 #endif
1289 /* sending SADB_ADD or SADB_UPDATE message to the kernel */
1290 static int
1291 pfkey_send_x1(sa_parms)
1292 struct pfkey_send_sa_args *sa_parms;
1294 struct sadb_msg *newmsg;
1295 int len;
1296 caddr_t p;
1297 int plen;
1298 caddr_t ep;
1300 /* validity check */
1301 if (sa_parms->src == NULL || sa_parms->dst == NULL) {
1302 __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1303 return -1;
1305 if (sa_parms->src->sa_family != sa_parms->dst->sa_family) {
1306 __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1307 return -1;
1309 switch (sa_parms->src->sa_family) {
1310 case AF_INET:
1311 plen = sizeof(struct in_addr) << 3;
1312 break;
1313 case AF_INET6:
1314 plen = sizeof(struct in6_addr) << 3;
1315 break;
1316 default:
1317 __ipsec_errcode = EIPSEC_INVAL_FAMILY;
1318 return -1;
1321 switch (sa_parms->satype) {
1322 case SADB_SATYPE_ESP:
1323 if (sa_parms->e_type == SADB_EALG_NONE) {
1324 __ipsec_errcode = EIPSEC_NO_ALGS;
1325 return -1;
1327 break;
1328 case SADB_SATYPE_AH:
1329 if (sa_parms->e_type != SADB_EALG_NONE) {
1330 __ipsec_errcode = EIPSEC_INVAL_ALGS;
1331 return -1;
1333 if (sa_parms->a_type == SADB_AALG_NONE) {
1334 __ipsec_errcode = EIPSEC_NO_ALGS;
1335 return -1;
1337 break;
1338 case SADB_X_SATYPE_IPCOMP:
1339 if (sa_parms->e_type == SADB_X_CALG_NONE) {
1340 __ipsec_errcode = EIPSEC_INVAL_ALGS;
1341 return -1;
1343 if (sa_parms->a_type != SADB_AALG_NONE) {
1344 __ipsec_errcode = EIPSEC_NO_ALGS;
1345 return -1;
1347 break;
1348 #ifdef SADB_X_AALG_TCP_MD5
1349 case SADB_X_SATYPE_TCPSIGNATURE:
1350 if (sa_parms->e_type != SADB_EALG_NONE) {
1351 __ipsec_errcode = EIPSEC_INVAL_ALGS;
1352 return -1;
1354 if (sa_parms->a_type != SADB_X_AALG_TCP_MD5) {
1355 __ipsec_errcode = EIPSEC_INVAL_ALGS;
1356 return -1;
1358 break;
1359 #endif
1360 default:
1361 __ipsec_errcode = EIPSEC_INVAL_SATYPE;
1362 return -1;
1365 /* create new sadb_msg to reply. */
1366 len = sizeof(struct sadb_msg)
1367 + sizeof(struct sadb_sa)
1368 + sizeof(struct sadb_x_sa2)
1369 + sizeof(struct sadb_address)
1370 + PFKEY_ALIGN8(sysdep_sa_len(sa_parms->src))
1371 + sizeof(struct sadb_address)
1372 + PFKEY_ALIGN8(sysdep_sa_len(sa_parms->dst))
1373 + sizeof(struct sadb_lifetime)
1374 + sizeof(struct sadb_lifetime);
1376 if (sa_parms->e_type != SADB_EALG_NONE &&
1377 sa_parms->satype != SADB_X_SATYPE_IPCOMP)
1378 len += (sizeof(struct sadb_key) +
1379 PFKEY_ALIGN8(sa_parms->e_keylen));
1380 if (sa_parms->a_type != SADB_AALG_NONE)
1381 len += (sizeof(struct sadb_key) +
1382 PFKEY_ALIGN8(sa_parms->a_keylen));
1384 #ifdef SADB_X_EXT_SEC_CTX
1385 if (sa_parms->ctxstr != NULL)
1386 len += (sizeof(struct sadb_x_sec_ctx)
1387 + PFKEY_ALIGN8(sa_parms->ctxstrlen));
1388 #endif
1390 #ifdef SADB_X_EXT_NAT_T_TYPE
1391 /* add nat-t packets */
1392 if (sa_parms->l_natt_type) {
1393 switch(sa_parms->satype) {
1394 case SADB_SATYPE_ESP:
1395 case SADB_X_SATYPE_IPCOMP:
1396 break;
1397 default:
1398 __ipsec_errcode = EIPSEC_NO_ALGS;
1399 return -1;
1402 len += sizeof(struct sadb_x_nat_t_type);
1403 len += sizeof(struct sadb_x_nat_t_port);
1404 len += sizeof(struct sadb_x_nat_t_port);
1405 if (sa_parms->l_natt_oa)
1406 len += sizeof(struct sadb_address) +
1407 PFKEY_ALIGN8(sysdep_sa_len(sa_parms->l_natt_oa));
1408 #ifdef SADB_X_EXT_NAT_T_FRAG
1409 if (sa_parms->l_natt_frag)
1410 len += sizeof(struct sadb_x_nat_t_frag);
1411 #endif
1413 #endif
1415 if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
1416 __ipsec_set_strerror(strerror(errno));
1417 return -1;
1419 ep = ((caddr_t)(void *)newmsg) + len;
1421 p = pfkey_setsadbmsg((void *)newmsg, ep, sa_parms->type, (u_int)len,
1422 sa_parms->satype, sa_parms->seq, getpid());
1423 if (!p) {
1424 free(newmsg);
1425 return -1;
1427 p = pfkey_setsadbsa(p, ep, sa_parms->spi, sa_parms->wsize,
1428 sa_parms->a_type, sa_parms->e_type,
1429 sa_parms->flags);
1430 if (!p) {
1431 free(newmsg);
1432 return -1;
1434 p = pfkey_setsadbxsa2(p, ep, sa_parms->mode, sa_parms->reqid);
1435 if (!p) {
1436 free(newmsg);
1437 return -1;
1439 p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, sa_parms->src,
1440 (u_int)plen, IPSEC_ULPROTO_ANY);
1441 if (!p) {
1442 free(newmsg);
1443 return -1;
1445 p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, sa_parms->dst,
1446 (u_int)plen, IPSEC_ULPROTO_ANY);
1447 if (!p) {
1448 free(newmsg);
1449 return -1;
1452 if (sa_parms->e_type != SADB_EALG_NONE &&
1453 sa_parms->satype != SADB_X_SATYPE_IPCOMP) {
1454 p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_ENCRYPT,
1455 sa_parms->keymat, sa_parms->e_keylen);
1456 if (!p) {
1457 free(newmsg);
1458 return -1;
1461 if (sa_parms->a_type != SADB_AALG_NONE) {
1462 p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_AUTH,
1463 sa_parms->keymat + sa_parms->e_keylen,
1464 sa_parms->a_keylen);
1465 if (!p) {
1466 free(newmsg);
1467 return -1;
1471 /* set sadb_lifetime for destination */
1472 p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD,
1473 sa_parms->l_alloc, sa_parms->l_bytes,
1474 sa_parms->l_addtime, sa_parms->l_usetime);
1475 if (!p) {
1476 free(newmsg);
1477 return -1;
1479 p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_SOFT,
1480 sa_parms->l_alloc, sa_parms->l_bytes,
1481 sa_parms->l_addtime, sa_parms->l_usetime);
1482 if (!p) {
1483 free(newmsg);
1484 return -1;
1486 #ifdef SADB_X_EXT_SEC_CTX
1487 if (sa_parms->ctxstr != NULL) {
1488 p = pfkey_setsecctx(p, ep, SADB_X_EXT_SEC_CTX, sa_parms->ctxdoi,
1489 sa_parms->ctxalg, sa_parms->ctxstr,
1490 sa_parms->ctxstrlen);
1491 if (!p) {
1492 free(newmsg);
1493 return -1;
1496 #endif
1498 #ifdef SADB_X_EXT_NAT_T_TYPE
1499 /* Add nat-t messages */
1500 if (sa_parms->l_natt_type) {
1501 p = pfkey_set_natt_type(p, ep, SADB_X_EXT_NAT_T_TYPE,
1502 sa_parms->l_natt_type);
1503 if (!p) {
1504 free(newmsg);
1505 return -1;
1508 p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_SPORT,
1509 sa_parms->l_natt_sport);
1510 if (!p) {
1511 free(newmsg);
1512 return -1;
1515 p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_DPORT,
1516 sa_parms->l_natt_dport);
1517 if (!p) {
1518 free(newmsg);
1519 return -1;
1522 if (sa_parms->l_natt_oa) {
1523 p = pfkey_setsadbaddr(p, ep, SADB_X_EXT_NAT_T_OA,
1524 sa_parms->l_natt_oa,
1525 (u_int)PFKEY_ALIGN8(sysdep_sa_len(sa_parms->l_natt_oa)),
1526 IPSEC_ULPROTO_ANY);
1527 if (!p) {
1528 free(newmsg);
1529 return -1;
1533 #ifdef SADB_X_EXT_NAT_T_FRAG
1534 if (sa_parms->l_natt_frag) {
1535 p = pfkey_set_natt_frag(p, ep, SADB_X_EXT_NAT_T_FRAG,
1536 sa_parms->l_natt_frag);
1537 if (!p) {
1538 free(newmsg);
1539 return -1;
1542 #endif
1544 #endif
1546 if (p != ep) {
1547 free(newmsg);
1548 return -1;
1551 /* send message */
1552 len = pfkey_send(sa_parms->so, newmsg, len);
1553 free(newmsg);
1555 if (len < 0)
1556 return -1;
1558 __ipsec_errcode = EIPSEC_NO_ERROR;
1559 return len;
1562 /* sending SADB_DELETE or SADB_GET message to the kernel */
1563 /*ARGSUSED*/
1564 static int
1565 pfkey_send_x2(so, type, satype, mode, src, dst, spi)
1566 int so;
1567 u_int type, satype, mode;
1568 struct sockaddr *src, *dst;
1569 u_int32_t spi;
1571 struct sadb_msg *newmsg;
1572 int len;
1573 caddr_t p;
1574 int plen;
1575 caddr_t ep;
1577 /* validity check */
1578 if (src == NULL || dst == NULL) {
1579 __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1580 return -1;
1582 if (src->sa_family != dst->sa_family) {
1583 __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1584 return -1;
1586 switch (src->sa_family) {
1587 case AF_INET:
1588 plen = sizeof(struct in_addr) << 3;
1589 break;
1590 case AF_INET6:
1591 plen = sizeof(struct in6_addr) << 3;
1592 break;
1593 default:
1594 __ipsec_errcode = EIPSEC_INVAL_FAMILY;
1595 return -1;
1598 /* create new sadb_msg to reply. */
1599 len = sizeof(struct sadb_msg)
1600 + sizeof(struct sadb_sa)
1601 + sizeof(struct sadb_address)
1602 + PFKEY_ALIGN8(sysdep_sa_len(src))
1603 + sizeof(struct sadb_address)
1604 + PFKEY_ALIGN8(sysdep_sa_len(dst));
1606 if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
1607 __ipsec_set_strerror(strerror(errno));
1608 return -1;
1610 ep = ((caddr_t)(void *)newmsg) + len;
1612 p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len, satype, 0,
1613 getpid());
1614 if (!p) {
1615 free(newmsg);
1616 return -1;
1618 p = pfkey_setsadbsa(p, ep, spi, 0, 0, 0, 0);
1619 if (!p) {
1620 free(newmsg);
1621 return -1;
1623 p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, (u_int)plen,
1624 IPSEC_ULPROTO_ANY);
1625 if (!p) {
1626 free(newmsg);
1627 return -1;
1629 p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, (u_int)plen,
1630 IPSEC_ULPROTO_ANY);
1631 if (!p || p != ep) {
1632 free(newmsg);
1633 return -1;
1636 /* send message */
1637 len = pfkey_send(so, newmsg, len);
1638 free(newmsg);
1640 if (len < 0)
1641 return -1;
1643 __ipsec_errcode = EIPSEC_NO_ERROR;
1644 return len;
1648 * sending SADB_REGISTER, SADB_FLUSH, SADB_DUMP or SADB_X_PROMISC message
1649 * to the kernel
1651 static int
1652 pfkey_send_x3(so, type, satype)
1653 int so;
1654 u_int type, satype;
1656 struct sadb_msg *newmsg;
1657 int len;
1658 caddr_t p;
1659 caddr_t ep;
1661 /* validity check */
1662 switch (type) {
1663 case SADB_X_PROMISC:
1664 if (satype != 0 && satype != 1) {
1665 __ipsec_errcode = EIPSEC_INVAL_SATYPE;
1666 return -1;
1668 break;
1669 default:
1670 switch (satype) {
1671 case SADB_SATYPE_UNSPEC:
1672 case SADB_SATYPE_AH:
1673 case SADB_SATYPE_ESP:
1674 case SADB_X_SATYPE_IPCOMP:
1675 #ifdef SADB_X_SATYPE_TCPSIGNATURE
1676 case SADB_X_SATYPE_TCPSIGNATURE:
1677 #endif
1678 break;
1679 default:
1680 __ipsec_errcode = EIPSEC_INVAL_SATYPE;
1681 return -1;
1685 /* create new sadb_msg to send. */
1686 len = sizeof(struct sadb_msg);
1688 if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
1689 __ipsec_set_strerror(strerror(errno));
1690 return -1;
1692 ep = ((caddr_t)(void *)newmsg) + len;
1694 p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len, satype, 0,
1695 getpid());
1696 if (!p || p != ep) {
1697 free(newmsg);
1698 return -1;
1701 /* send message */
1702 len = pfkey_send(so, newmsg, len);
1703 free(newmsg);
1705 if (len < 0)
1706 return -1;
1708 __ipsec_errcode = EIPSEC_NO_ERROR;
1709 return len;
1712 /* sending SADB_X_SPDADD message to the kernel */
1713 static int
1714 pfkey_send_x4(so, type, src, prefs, dst, prefd, proto,
1715 ltime, vtime, policy, policylen, seq)
1716 int so;
1717 struct sockaddr *src, *dst;
1718 u_int type, prefs, prefd, proto;
1719 u_int64_t ltime, vtime;
1720 char *policy;
1721 int policylen;
1722 u_int32_t seq;
1724 struct sadb_msg *newmsg;
1725 int len;
1726 caddr_t p;
1727 int plen;
1728 caddr_t ep;
1730 /* validity check */
1731 if (src == NULL || dst == NULL) {
1732 __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1733 return -1;
1735 if (src->sa_family != dst->sa_family) {
1736 __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1737 return -1;
1740 switch (src->sa_family) {
1741 case AF_INET:
1742 plen = sizeof(struct in_addr) << 3;
1743 break;
1744 case AF_INET6:
1745 plen = sizeof(struct in6_addr) << 3;
1746 break;
1747 default:
1748 __ipsec_errcode = EIPSEC_INVAL_FAMILY;
1749 return -1;
1751 if (prefs > plen || prefd > plen) {
1752 __ipsec_errcode = EIPSEC_INVAL_PREFIXLEN;
1753 return -1;
1756 /* create new sadb_msg to reply. */
1757 len = sizeof(struct sadb_msg)
1758 + sizeof(struct sadb_address)
1759 + PFKEY_ALIGN8(sysdep_sa_len(src))
1760 + sizeof(struct sadb_address)
1761 + PFKEY_ALIGN8(sysdep_sa_len(src))
1762 + sizeof(struct sadb_lifetime)
1763 + policylen;
1765 if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
1766 __ipsec_set_strerror(strerror(errno));
1767 return -1;
1769 ep = ((caddr_t)(void *)newmsg) + len;
1771 p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len,
1772 SADB_SATYPE_UNSPEC, seq, getpid());
1773 if (!p) {
1774 free(newmsg);
1775 return -1;
1777 p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, prefs, proto);
1778 if (!p) {
1779 free(newmsg);
1780 return -1;
1782 p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, prefd, proto);
1783 if (!p) {
1784 free(newmsg);
1785 return -1;
1787 p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD,
1788 0, 0, (u_int)ltime, (u_int)vtime);
1789 if (!p || p + policylen != ep) {
1790 free(newmsg);
1791 return -1;
1793 memcpy(p, policy, (size_t)policylen);
1795 /* send message */
1796 len = pfkey_send(so, newmsg, len);
1797 free(newmsg);
1799 if (len < 0)
1800 return -1;
1802 __ipsec_errcode = EIPSEC_NO_ERROR;
1803 return len;
1806 /* sending SADB_X_SPDGET or SADB_X_SPDDELETE message to the kernel */
1807 static int
1808 pfkey_send_x5(so, type, spid)
1809 int so;
1810 u_int type;
1811 u_int32_t spid;
1813 struct sadb_msg *newmsg;
1814 struct sadb_x_policy xpl;
1815 int len;
1816 caddr_t p;
1817 caddr_t ep;
1819 /* create new sadb_msg to reply. */
1820 len = sizeof(struct sadb_msg)
1821 + sizeof(xpl);
1823 if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
1824 __ipsec_set_strerror(strerror(errno));
1825 return -1;
1827 ep = ((caddr_t)(void *)newmsg) + len;
1829 p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len,
1830 SADB_SATYPE_UNSPEC, 0, getpid());
1831 if (!p) {
1832 free(newmsg);
1833 return -1;
1836 if (p + sizeof(xpl) != ep) {
1837 free(newmsg);
1838 return -1;
1840 memset(&xpl, 0, sizeof(xpl));
1841 xpl.sadb_x_policy_len = PFKEY_UNIT64(sizeof(xpl));
1842 xpl.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
1843 xpl.sadb_x_policy_id = spid;
1844 memcpy(p, &xpl, sizeof(xpl));
1846 /* send message */
1847 len = pfkey_send(so, newmsg, len);
1848 free(newmsg);
1850 if (len < 0)
1851 return -1;
1853 __ipsec_errcode = EIPSEC_NO_ERROR;
1854 return len;
1858 * open a socket.
1859 * OUT:
1860 * -1: fail.
1861 * others : success and return value of socket.
1864 pfkey_open()
1866 int so;
1867 int bufsiz = 128 * 1024; /*is 128K enough?*/
1869 if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) {
1870 __ipsec_set_strerror(strerror(errno));
1871 return -1;
1875 * This is a temporary workaround for KAME PR 154.
1876 * Don't really care even if it fails.
1878 (void)setsockopt(so, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz));
1879 (void)setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz));
1880 bufsiz = 256 * 1024;
1881 (void)setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz));
1882 bufsiz = 512 * 1024;
1883 (void)setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz));
1884 bufsiz = 1024 * 1024;
1885 (void)setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz));
1886 __ipsec_errcode = EIPSEC_NO_ERROR;
1887 return so;
1891 pfkey_set_buffer_size(so, size)
1892 int so;
1893 int size;
1895 int newsize;
1896 int actual_bufsiz;
1897 socklen_t sizebufsiz;
1898 int desired_bufsiz;
1901 * on linux you may need to allow the kernel to allocate
1902 * more buffer space by increasing:
1903 * /proc/sys/net/core/rmem_max and wmem_max
1905 if (size > 0) {
1906 actual_bufsiz = 0;
1907 sizebufsiz = sizeof(actual_bufsiz);
1908 desired_bufsiz = size * 1024;
1909 if ((getsockopt(so, SOL_SOCKET, SO_RCVBUF,
1910 &actual_bufsiz, &sizebufsiz) < 0)
1911 || (actual_bufsiz < desired_bufsiz)) {
1912 if (setsockopt(so, SOL_SOCKET, SO_RCVBUF,
1913 &desired_bufsiz, sizeof(desired_bufsiz)) < 0) {
1914 __ipsec_set_strerror(strerror(errno));
1915 return -1;
1920 /* return actual buffer size */
1921 actual_bufsiz = 0;
1922 sizebufsiz = sizeof(actual_bufsiz);
1923 getsockopt(so, SOL_SOCKET, SO_RCVBUF,
1924 &actual_bufsiz, &sizebufsiz);
1925 return actual_bufsiz / 1024;
1929 * close a socket.
1930 * OUT:
1931 * 0: success.
1932 * -1: fail.
1934 void
1935 pfkey_close(so)
1936 int so;
1938 (void)close(so);
1940 __ipsec_errcode = EIPSEC_NO_ERROR;
1941 return;
1945 * receive sadb_msg data, and return pointer to new buffer allocated.
1946 * Must free this buffer later.
1947 * OUT:
1948 * NULL : error occured.
1949 * others : a pointer to sadb_msg structure.
1951 * XXX should be rewritten to pass length explicitly
1953 struct sadb_msg *
1954 pfkey_recv(so)
1955 int so;
1957 struct sadb_msg buf, *newmsg;
1958 int len, reallen;
1960 while ((len = recv(so, (void *)&buf, sizeof(buf), MSG_PEEK)) < 0) {
1961 if (errno == EINTR)
1962 continue;
1963 __ipsec_set_strerror(strerror(errno));
1964 return NULL;
1967 if (len < sizeof(buf)) {
1968 recv(so, (void *)&buf, sizeof(buf), 0);
1969 __ipsec_errcode = EIPSEC_MAX;
1970 return NULL;
1973 /* read real message */
1974 reallen = PFKEY_UNUNIT64(buf.sadb_msg_len);
1975 if ((newmsg = CALLOC((size_t)reallen, struct sadb_msg *)) == 0) {
1976 __ipsec_set_strerror(strerror(errno));
1977 return NULL;
1980 while ((len = recv(so, (void *)newmsg, (socklen_t)reallen, 0)) < 0) {
1981 if (errno == EINTR)
1982 continue;
1983 __ipsec_set_strerror(strerror(errno));
1984 free(newmsg);
1985 return NULL;
1988 if (len != reallen) {
1989 __ipsec_errcode = EIPSEC_SYSTEM_ERROR;
1990 free(newmsg);
1991 return NULL;
1994 /* don't trust what the kernel says, validate! */
1995 if (PFKEY_UNUNIT64(newmsg->sadb_msg_len) != len) {
1996 __ipsec_errcode = EIPSEC_SYSTEM_ERROR;
1997 free(newmsg);
1998 return NULL;
2001 __ipsec_errcode = EIPSEC_NO_ERROR;
2002 return newmsg;
2006 * send message to a socket.
2007 * OUT:
2008 * others: success and return length sent.
2009 * -1 : fail.
2012 pfkey_send(so, msg, len)
2013 int so;
2014 struct sadb_msg *msg;
2015 int len;
2017 if ((len = send(so, (void *)msg, (socklen_t)len, 0)) < 0) {
2018 __ipsec_set_strerror(strerror(errno));
2019 return -1;
2022 __ipsec_errcode = EIPSEC_NO_ERROR;
2023 return len;
2027 * %%% Utilities
2028 * NOTE: These functions are derived from netkey/key.c in KAME.
2031 * set the pointer to each header in this message buffer.
2032 * IN: msg: pointer to message buffer.
2033 * mhp: pointer to the buffer initialized like below:
2034 * caddr_t mhp[SADB_EXT_MAX + 1];
2035 * OUT: -1: invalid.
2036 * 0: valid.
2038 * XXX should be rewritten to obtain length explicitly
2041 pfkey_align(msg, mhp)
2042 struct sadb_msg *msg;
2043 caddr_t *mhp;
2045 struct sadb_ext *ext;
2046 int i;
2047 caddr_t p;
2048 caddr_t ep; /* XXX should be passed from upper layer */
2050 /* validity check */
2051 if (msg == NULL || mhp == NULL) {
2052 __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
2053 return -1;
2056 /* initialize */
2057 for (i = 0; i < SADB_EXT_MAX + 1; i++)
2058 mhp[i] = NULL;
2060 mhp[0] = (void *)msg;
2062 /* initialize */
2063 p = (void *) msg;
2064 ep = p + PFKEY_UNUNIT64(msg->sadb_msg_len);
2066 /* skip base header */
2067 p += sizeof(struct sadb_msg);
2069 while (p < ep) {
2070 ext = (void *)p;
2071 if (ep < p + sizeof(*ext) || PFKEY_EXTLEN(ext) < sizeof(*ext) ||
2072 ep < p + PFKEY_EXTLEN(ext)) {
2073 /* invalid format */
2074 break;
2077 /* duplicate check */
2078 /* XXX Are there duplication either KEY_AUTH or KEY_ENCRYPT ?*/
2079 if (mhp[ext->sadb_ext_type] != NULL) {
2080 __ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
2081 return -1;
2084 /* set pointer */
2085 switch (ext->sadb_ext_type) {
2086 case SADB_EXT_SA:
2087 case SADB_EXT_LIFETIME_CURRENT:
2088 case SADB_EXT_LIFETIME_HARD:
2089 case SADB_EXT_LIFETIME_SOFT:
2090 case SADB_EXT_ADDRESS_SRC:
2091 case SADB_EXT_ADDRESS_DST:
2092 case SADB_EXT_ADDRESS_PROXY:
2093 case SADB_EXT_KEY_AUTH:
2094 /* XXX should to be check weak keys. */
2095 case SADB_EXT_KEY_ENCRYPT:
2096 /* XXX should to be check weak keys. */
2097 case SADB_EXT_IDENTITY_SRC:
2098 case SADB_EXT_IDENTITY_DST:
2099 case SADB_EXT_SENSITIVITY:
2100 case SADB_EXT_PROPOSAL:
2101 case SADB_EXT_SUPPORTED_AUTH:
2102 case SADB_EXT_SUPPORTED_ENCRYPT:
2103 case SADB_EXT_SPIRANGE:
2104 case SADB_X_EXT_POLICY:
2105 case SADB_X_EXT_SA2:
2106 #ifdef SADB_X_EXT_NAT_T_TYPE
2107 case SADB_X_EXT_NAT_T_TYPE:
2108 case SADB_X_EXT_NAT_T_SPORT:
2109 case SADB_X_EXT_NAT_T_DPORT:
2110 case SADB_X_EXT_NAT_T_OA:
2111 #endif
2112 #ifdef SADB_X_EXT_TAG
2113 case SADB_X_EXT_TAG:
2114 #endif
2115 #ifdef SADB_X_EXT_PACKET
2116 case SADB_X_EXT_PACKET:
2117 #endif
2118 #ifdef SADB_X_EXT_KMADDRESS
2119 case SADB_X_EXT_KMADDRESS:
2120 #endif
2121 #ifdef SADB_X_EXT_SEC_CTX
2122 case SADB_X_EXT_SEC_CTX:
2123 #endif
2124 mhp[ext->sadb_ext_type] = (void *)ext;
2125 break;
2126 default:
2127 __ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
2128 return -1;
2131 p += PFKEY_EXTLEN(ext);
2134 if (p != ep) {
2135 __ipsec_errcode = EIPSEC_INVAL_SADBMSG;
2136 return -1;
2139 __ipsec_errcode = EIPSEC_NO_ERROR;
2140 return 0;
2144 * check basic usage for sadb_msg,
2145 * NOTE: This routine is derived from netkey/key.c in KAME.
2146 * IN: msg: pointer to message buffer.
2147 * mhp: pointer to the buffer initialized like below:
2149 * caddr_t mhp[SADB_EXT_MAX + 1];
2151 * OUT: -1: invalid.
2152 * 0: valid.
2155 pfkey_check(mhp)
2156 caddr_t *mhp;
2158 struct sadb_msg *msg;
2160 /* validity check */
2161 if (mhp == NULL || mhp[0] == NULL) {
2162 __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
2163 return -1;
2166 msg = (void *)mhp[0];
2168 /* check version */
2169 if (msg->sadb_msg_version != PF_KEY_V2) {
2170 __ipsec_errcode = EIPSEC_INVAL_VERSION;
2171 return -1;
2174 /* check type */
2175 if (msg->sadb_msg_type > SADB_MAX) {
2176 __ipsec_errcode = EIPSEC_INVAL_MSGTYPE;
2177 return -1;
2180 /* check SA type */
2181 switch (msg->sadb_msg_satype) {
2182 case SADB_SATYPE_UNSPEC:
2183 switch (msg->sadb_msg_type) {
2184 case SADB_GETSPI:
2185 case SADB_UPDATE:
2186 case SADB_ADD:
2187 case SADB_DELETE:
2188 case SADB_GET:
2189 case SADB_ACQUIRE:
2190 case SADB_EXPIRE:
2191 #ifdef SADB_X_NAT_T_NEW_MAPPING
2192 case SADB_X_NAT_T_NEW_MAPPING:
2193 #endif
2194 __ipsec_errcode = EIPSEC_INVAL_SATYPE;
2195 return -1;
2197 break;
2198 case SADB_SATYPE_ESP:
2199 case SADB_SATYPE_AH:
2200 case SADB_X_SATYPE_IPCOMP:
2201 #ifdef SADB_X_SATYPE_TCPSIGNATURE
2202 case SADB_X_SATYPE_TCPSIGNATURE:
2203 #endif
2204 switch (msg->sadb_msg_type) {
2205 case SADB_X_SPDADD:
2206 case SADB_X_SPDDELETE:
2207 case SADB_X_SPDGET:
2208 case SADB_X_SPDDUMP:
2209 case SADB_X_SPDFLUSH:
2210 __ipsec_errcode = EIPSEC_INVAL_SATYPE;
2211 return -1;
2213 #ifdef SADB_X_NAT_T_NEW_MAPPING
2214 if (msg->sadb_msg_type == SADB_X_NAT_T_NEW_MAPPING &&
2215 msg->sadb_msg_satype != SADB_SATYPE_ESP) {
2216 __ipsec_errcode = EIPSEC_INVAL_SATYPE;
2217 return -1;
2219 #endif
2220 break;
2221 case SADB_SATYPE_RSVP:
2222 case SADB_SATYPE_OSPFV2:
2223 case SADB_SATYPE_RIPV2:
2224 case SADB_SATYPE_MIP:
2225 __ipsec_errcode = EIPSEC_NOT_SUPPORTED;
2226 return -1;
2227 case 1: /* XXX: What does it do ? */
2228 if (msg->sadb_msg_type == SADB_X_PROMISC)
2229 break;
2230 /*FALLTHROUGH*/
2231 default:
2232 #ifdef __linux__
2233 /* Linux kernel seems to be buggy and return
2234 * uninitialized satype for spd flush message */
2235 if (msg->sadb_msg_type == SADB_X_SPDFLUSH)
2236 break;
2237 #endif
2238 __ipsec_errcode = EIPSEC_INVAL_SATYPE;
2239 return -1;
2242 /* check field of upper layer protocol and address family */
2243 if (mhp[SADB_EXT_ADDRESS_SRC] != NULL
2244 && mhp[SADB_EXT_ADDRESS_DST] != NULL) {
2245 struct sadb_address *src0, *dst0;
2247 src0 = (void *)(mhp[SADB_EXT_ADDRESS_SRC]);
2248 dst0 = (void *)(mhp[SADB_EXT_ADDRESS_DST]);
2250 if (src0->sadb_address_proto != dst0->sadb_address_proto) {
2251 __ipsec_errcode = EIPSEC_PROTO_MISMATCH;
2252 return -1;
2255 if (PFKEY_ADDR_SADDR(src0)->sa_family
2256 != PFKEY_ADDR_SADDR(dst0)->sa_family) {
2257 __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
2258 return -1;
2261 switch (PFKEY_ADDR_SADDR(src0)->sa_family) {
2262 case AF_INET:
2263 case AF_INET6:
2264 break;
2265 default:
2266 __ipsec_errcode = EIPSEC_INVAL_FAMILY;
2267 return -1;
2271 * prefixlen == 0 is valid because there must be the case
2272 * all addresses are matched.
2276 __ipsec_errcode = EIPSEC_NO_ERROR;
2277 return 0;
2281 * set data into sadb_msg.
2282 * `buf' must has been allocated sufficiently.
2284 static caddr_t
2285 pfkey_setsadbmsg(buf, lim, type, tlen, satype, seq, pid)
2286 caddr_t buf;
2287 caddr_t lim;
2288 u_int type, satype;
2289 u_int tlen;
2290 u_int32_t seq;
2291 pid_t pid;
2293 struct sadb_msg *p;
2294 u_int len;
2296 p = (void *)buf;
2297 len = sizeof(struct sadb_msg);
2299 if (buf + len > lim)
2300 return NULL;
2302 memset(p, 0, len);
2303 p->sadb_msg_version = PF_KEY_V2;
2304 p->sadb_msg_type = type;
2305 p->sadb_msg_errno = 0;
2306 p->sadb_msg_satype = satype;
2307 p->sadb_msg_len = PFKEY_UNIT64(tlen);
2308 p->sadb_msg_reserved = 0;
2309 p->sadb_msg_seq = seq;
2310 p->sadb_msg_pid = (u_int32_t)pid;
2312 return(buf + len);
2316 * copy secasvar data into sadb_address.
2317 * `buf' must has been allocated sufficiently.
2319 static caddr_t
2320 pfkey_setsadbsa(buf, lim, spi, wsize, auth, enc, flags)
2321 caddr_t buf;
2322 caddr_t lim;
2323 u_int32_t spi, flags;
2324 u_int wsize, auth, enc;
2326 struct sadb_sa *p;
2327 u_int len;
2329 p = (void *)buf;
2330 len = sizeof(struct sadb_sa);
2332 if (buf + len > lim)
2333 return NULL;
2335 memset(p, 0, len);
2336 p->sadb_sa_len = PFKEY_UNIT64(len);
2337 p->sadb_sa_exttype = SADB_EXT_SA;
2338 p->sadb_sa_spi = spi;
2339 p->sadb_sa_replay = wsize;
2340 p->sadb_sa_state = SADB_SASTATE_LARVAL;
2341 p->sadb_sa_auth = auth;
2342 p->sadb_sa_encrypt = enc;
2343 p->sadb_sa_flags = flags;
2345 return(buf + len);
2349 * set data into sadb_address.
2350 * `buf' must has been allocated sufficiently.
2351 * prefixlen is in bits.
2353 static caddr_t
2354 pfkey_setsadbaddr(buf, lim, exttype, saddr, prefixlen, ul_proto)
2355 caddr_t buf;
2356 caddr_t lim;
2357 u_int exttype;
2358 struct sockaddr *saddr;
2359 u_int prefixlen;
2360 u_int ul_proto;
2362 struct sadb_address *p;
2363 u_int len;
2365 p = (void *)buf;
2366 len = sizeof(struct sadb_address) + PFKEY_ALIGN8(sysdep_sa_len(saddr));
2368 if (buf + len > lim)
2369 return NULL;
2371 memset(p, 0, len);
2372 p->sadb_address_len = PFKEY_UNIT64(len);
2373 p->sadb_address_exttype = exttype & 0xffff;
2374 p->sadb_address_proto = ul_proto & 0xff;
2375 p->sadb_address_prefixlen = prefixlen;
2376 p->sadb_address_reserved = 0;
2378 memcpy(p + 1, saddr, (size_t)sysdep_sa_len(saddr));
2380 return(buf + len);
2383 #ifdef SADB_X_EXT_KMADDRESS
2385 * set data into sadb_x_kmaddress.
2386 * `buf' must has been allocated sufficiently.
2388 static caddr_t
2389 pfkey_setsadbkmaddr(buf, lim, local, remote)
2390 caddr_t buf;
2391 caddr_t lim;
2392 struct sockaddr *local, *remote;
2394 struct sadb_x_kmaddress *p;
2395 struct sockaddr *sa;
2396 u_int salen = sysdep_sa_len(local);
2397 u_int len;
2399 /* sanity check */
2400 if (local->sa_family != remote->sa_family)
2401 return NULL;
2403 p = (void *)buf;
2404 len = sizeof(struct sadb_x_kmaddress) + PFKEY_ALIGN8(2*salen);
2406 if (buf + len > lim)
2407 return NULL;
2409 memset(p, 0, len);
2410 p->sadb_x_kmaddress_len = PFKEY_UNIT64(len);
2411 p->sadb_x_kmaddress_exttype = SADB_X_EXT_KMADDRESS;
2412 p->sadb_x_kmaddress_reserved = 0;
2414 sa = (struct sockaddr *)(p + 1);
2415 memcpy(sa, local, salen);
2416 sa = (struct sockaddr *)((char *)sa + salen);
2417 memcpy(sa, remote, salen);
2419 return(buf + len);
2421 #endif
2424 * set sadb_key structure after clearing buffer with zero.
2425 * OUT: the pointer of buf + len.
2427 static caddr_t
2428 pfkey_setsadbkey(buf, lim, type, key, keylen)
2429 caddr_t buf;
2430 caddr_t lim;
2431 caddr_t key;
2432 u_int type, keylen;
2434 struct sadb_key *p;
2435 u_int len;
2437 p = (void *)buf;
2438 len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen);
2440 if (buf + len > lim)
2441 return NULL;
2443 memset(p, 0, len);
2444 p->sadb_key_len = PFKEY_UNIT64(len);
2445 p->sadb_key_exttype = type;
2446 p->sadb_key_bits = keylen << 3;
2447 p->sadb_key_reserved = 0;
2449 memcpy(p + 1, key, keylen);
2451 return buf + len;
2455 * set sadb_lifetime structure after clearing buffer with zero.
2456 * OUT: the pointer of buf + len.
2458 static caddr_t
2459 pfkey_setsadblifetime(buf, lim, type, l_alloc, l_bytes, l_addtime, l_usetime)
2460 caddr_t buf;
2461 caddr_t lim;
2462 u_int type;
2463 u_int32_t l_alloc, l_bytes, l_addtime, l_usetime;
2465 struct sadb_lifetime *p;
2466 u_int len;
2468 p = (void *)buf;
2469 len = sizeof(struct sadb_lifetime);
2471 if (buf + len > lim)
2472 return NULL;
2474 memset(p, 0, len);
2475 p->sadb_lifetime_len = PFKEY_UNIT64(len);
2476 p->sadb_lifetime_exttype = type;
2478 switch (type) {
2479 case SADB_EXT_LIFETIME_SOFT:
2480 p->sadb_lifetime_allocations
2481 = (l_alloc * soft_lifetime_allocations_rate) /100;
2482 p->sadb_lifetime_bytes
2483 = (l_bytes * soft_lifetime_bytes_rate) /100;
2484 p->sadb_lifetime_addtime
2485 = (l_addtime * soft_lifetime_addtime_rate) /100;
2486 p->sadb_lifetime_usetime
2487 = (l_usetime * soft_lifetime_usetime_rate) /100;
2488 break;
2489 case SADB_EXT_LIFETIME_HARD:
2490 p->sadb_lifetime_allocations = l_alloc;
2491 p->sadb_lifetime_bytes = l_bytes;
2492 p->sadb_lifetime_addtime = l_addtime;
2493 p->sadb_lifetime_usetime = l_usetime;
2494 break;
2497 return buf + len;
2501 * copy secasvar data into sadb_address.
2502 * `buf' must has been allocated sufficiently.
2504 static caddr_t
2505 pfkey_setsadbxsa2(buf, lim, mode0, reqid)
2506 caddr_t buf;
2507 caddr_t lim;
2508 u_int32_t mode0;
2509 u_int32_t reqid;
2511 struct sadb_x_sa2 *p;
2512 u_int8_t mode = mode0 & 0xff;
2513 u_int len;
2515 p = (void *)buf;
2516 len = sizeof(struct sadb_x_sa2);
2518 if (buf + len > lim)
2519 return NULL;
2521 memset(p, 0, len);
2522 p->sadb_x_sa2_len = PFKEY_UNIT64(len);
2523 p->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
2524 p->sadb_x_sa2_mode = mode;
2525 p->sadb_x_sa2_reqid = reqid;
2527 return(buf + len);
2530 #ifdef SADB_X_EXT_NAT_T_TYPE
2531 static caddr_t
2532 pfkey_set_natt_type(buf, lim, type, l_natt_type)
2533 caddr_t buf;
2534 caddr_t lim;
2535 u_int type;
2536 u_int8_t l_natt_type;
2538 struct sadb_x_nat_t_type *p;
2539 u_int len;
2541 p = (void *)buf;
2542 len = sizeof(struct sadb_x_nat_t_type);
2544 if (buf + len > lim)
2545 return NULL;
2547 memset(p, 0, len);
2548 p->sadb_x_nat_t_type_len = PFKEY_UNIT64(len);
2549 p->sadb_x_nat_t_type_exttype = type;
2550 p->sadb_x_nat_t_type_type = l_natt_type;
2552 return(buf + len);
2555 static caddr_t
2556 pfkey_set_natt_port(buf, lim, type, l_natt_port)
2557 caddr_t buf;
2558 caddr_t lim;
2559 u_int type;
2560 u_int16_t l_natt_port;
2562 struct sadb_x_nat_t_port *p;
2563 u_int len;
2565 p = (void *)buf;
2566 len = sizeof(struct sadb_x_nat_t_port);
2568 if (buf + len > lim)
2569 return NULL;
2571 memset(p, 0, len);
2572 p->sadb_x_nat_t_port_len = PFKEY_UNIT64(len);
2573 p->sadb_x_nat_t_port_exttype = type;
2574 p->sadb_x_nat_t_port_port = htons(l_natt_port);
2576 return(buf + len);
2578 #endif
2580 #ifdef SADB_X_EXT_NAT_T_FRAG
2581 static caddr_t
2582 pfkey_set_natt_frag(buf, lim, type, l_natt_frag)
2583 caddr_t buf;
2584 caddr_t lim;
2585 u_int type;
2586 u_int16_t l_natt_frag;
2588 struct sadb_x_nat_t_frag *p;
2589 u_int len;
2591 p = (void *)buf;
2592 len = sizeof(struct sadb_x_nat_t_frag);
2594 if (buf + len > lim)
2595 return NULL;
2597 memset(p, 0, len);
2598 p->sadb_x_nat_t_frag_len = PFKEY_UNIT64(len);
2599 p->sadb_x_nat_t_frag_exttype = type;
2600 p->sadb_x_nat_t_frag_fraglen = l_natt_frag;
2602 return(buf + len);
2604 #endif
2606 #ifdef SADB_X_EXT_SEC_CTX
2607 static caddr_t
2608 pfkey_setsecctx(buf, lim, type, ctx_doi, ctx_alg, sec_ctx, sec_ctxlen)
2609 caddr_t buf;
2610 caddr_t lim;
2611 u_int type;
2612 u_int8_t ctx_doi, ctx_alg;
2613 caddr_t sec_ctx;
2614 u_int16_t sec_ctxlen;
2616 struct sadb_x_sec_ctx *p;
2617 u_int len;
2619 p = (struct sadb_x_sec_ctx *)buf;
2620 len = sizeof(struct sadb_x_sec_ctx) + PFKEY_ALIGN8(sec_ctxlen);
2622 if (buf + len > lim)
2623 return NULL;
2625 memset(p, 0, len);
2626 p->sadb_x_sec_len = PFKEY_UNIT64(len);
2627 p->sadb_x_sec_exttype = type;
2628 p->sadb_x_ctx_len = sec_ctxlen;
2629 p->sadb_x_ctx_doi = ctx_doi;
2630 p->sadb_x_ctx_alg = ctx_alg;
2632 memcpy(p + 1, sec_ctx, sec_ctxlen);
2634 return buf + len;
2636 #endif
2639 * Deprecated, available for backward compatibility with third party
2640 * libipsec users. Please use pfkey_send_update2 and pfkey_send_add2 instead
2643 pfkey_send_update(so, satype, mode, src, dst, spi, reqid, wsize,
2644 keymat, e_type, e_keylen, a_type, a_keylen, flags,
2645 l_alloc, l_bytes, l_addtime, l_usetime, seq)
2646 int so;
2647 u_int satype, mode, wsize;
2648 struct sockaddr *src, *dst;
2649 u_int32_t spi, reqid;
2650 caddr_t keymat;
2651 u_int e_type, e_keylen, a_type, a_keylen, flags;
2652 u_int32_t l_alloc;
2653 u_int64_t l_bytes, l_addtime, l_usetime;
2654 u_int32_t seq;
2656 struct pfkey_send_sa_args psaa;
2658 memset(&psaa, 0, sizeof(psaa));
2659 psaa.so = so;
2660 psaa.type = SADB_UPDATE;
2661 psaa.satype = satype;
2662 psaa.mode = mode;
2663 psaa.wsize = wsize;
2664 psaa.src = src;
2665 psaa.dst = dst;
2666 psaa.spi = spi;
2667 psaa.reqid = reqid;
2668 psaa.keymat = keymat;
2669 psaa.e_type = e_type;
2670 psaa.e_keylen = e_keylen;
2671 psaa.a_type = a_type;
2672 psaa.a_keylen = a_keylen;
2673 psaa.flags = flags;
2674 psaa.l_alloc = l_alloc;
2675 psaa.l_bytes = l_bytes;
2676 psaa.l_addtime = l_addtime;
2677 psaa.l_usetime = l_usetime;
2678 psaa.seq = seq;
2680 return pfkey_send_update2(&psaa);
2684 pfkey_send_update_nat(so, satype, mode, src, dst, spi, reqid, wsize,
2685 keymat, e_type, e_keylen, a_type, a_keylen, flags,
2686 l_alloc, l_bytes, l_addtime, l_usetime, seq,
2687 l_natt_type, l_natt_sport, l_natt_dport, l_natt_oa,
2688 l_natt_frag)
2689 int so;
2690 u_int satype, mode, wsize;
2691 struct sockaddr *src, *dst;
2692 u_int32_t spi, reqid;
2693 caddr_t keymat;
2694 u_int e_type, e_keylen, a_type, a_keylen, flags;
2695 u_int32_t l_alloc;
2696 u_int64_t l_bytes, l_addtime, l_usetime;
2697 u_int32_t seq;
2698 u_int8_t l_natt_type;
2699 u_int16_t l_natt_sport, l_natt_dport;
2700 struct sockaddr *l_natt_oa;
2701 u_int16_t l_natt_frag;
2703 struct pfkey_send_sa_args psaa;
2705 memset(&psaa, 0, sizeof(psaa));
2706 psaa.so = so;
2707 psaa.type = SADB_UPDATE;
2708 psaa.satype = satype;
2709 psaa.mode = mode;
2710 psaa.wsize = wsize;
2711 psaa.src = src;
2712 psaa.dst = dst;
2713 psaa.spi = spi;
2714 psaa.reqid = reqid;
2715 psaa.keymat = keymat;
2716 psaa.e_type = e_type;
2717 psaa.e_keylen = e_keylen;
2718 psaa.a_type = a_type;
2719 psaa.a_keylen = a_keylen;
2720 psaa.flags = flags;
2721 psaa.l_alloc = l_alloc;
2722 psaa.l_bytes = l_bytes;
2723 psaa.l_addtime = l_addtime;
2724 psaa.l_usetime = l_usetime;
2725 psaa.seq = seq;
2726 psaa.l_natt_type = l_natt_type;
2727 psaa.l_natt_sport = l_natt_sport;
2728 psaa.l_natt_dport = l_natt_dport;
2729 psaa.l_natt_oa = l_natt_oa;
2730 psaa.l_natt_frag = l_natt_frag;
2732 return pfkey_send_update2(&psaa);
2736 pfkey_send_add(so, satype, mode, src, dst, spi, reqid, wsize,
2737 keymat, e_type, e_keylen, a_type, a_keylen, flags,
2738 l_alloc, l_bytes, l_addtime, l_usetime, seq)
2739 int so;
2740 u_int satype, mode, wsize;
2741 struct sockaddr *src, *dst;
2742 u_int32_t spi, reqid;
2743 caddr_t keymat;
2744 u_int e_type, e_keylen, a_type, a_keylen, flags;
2745 u_int32_t l_alloc;
2746 u_int64_t l_bytes, l_addtime, l_usetime;
2747 u_int32_t seq;
2749 struct pfkey_send_sa_args psaa;
2751 memset(&psaa, 0, sizeof(psaa));
2752 psaa.so = so;
2753 psaa.type = SADB_ADD;
2754 psaa.satype = satype;
2755 psaa.mode = mode;
2756 psaa.wsize = wsize;
2757 psaa.src = src;
2758 psaa.dst = dst;
2759 psaa.spi = spi;
2760 psaa.reqid = reqid;
2761 psaa.keymat = keymat;
2762 psaa.e_type = e_type;
2763 psaa.e_keylen = e_keylen;
2764 psaa.a_type = a_type;
2765 psaa.a_keylen = a_keylen;
2766 psaa.flags = flags;
2767 psaa.l_alloc = l_alloc;
2768 psaa.l_bytes = l_bytes;
2769 psaa.l_addtime = l_addtime;
2770 psaa.l_usetime = l_usetime;
2771 psaa.seq = seq;
2773 return pfkey_send_add2(&psaa);
2777 pfkey_send_add_nat(so, satype, mode, src, dst, spi, reqid, wsize,
2778 keymat, e_type, e_keylen, a_type, a_keylen, flags,
2779 l_alloc, l_bytes, l_addtime, l_usetime, seq,
2780 l_natt_type, l_natt_sport, l_natt_dport, l_natt_oa,
2781 l_natt_frag)
2782 int so;
2783 u_int satype, mode, wsize;
2784 struct sockaddr *src, *dst;
2785 u_int32_t spi, reqid;
2786 caddr_t keymat;
2787 u_int e_type, e_keylen, a_type, a_keylen, flags;
2788 u_int32_t l_alloc;
2789 u_int64_t l_bytes, l_addtime, l_usetime;
2790 u_int32_t seq;
2791 u_int8_t l_natt_type;
2792 u_int16_t l_natt_sport, l_natt_dport;
2793 struct sockaddr *l_natt_oa;
2794 u_int16_t l_natt_frag;
2796 struct pfkey_send_sa_args psaa;
2798 memset(&psaa, 0, sizeof(psaa));
2799 psaa.so = so;
2800 psaa.type = SADB_ADD;
2801 psaa.satype = satype;
2802 psaa.mode = mode;
2803 psaa.wsize = wsize;
2804 psaa.src = src;
2805 psaa.dst = dst;
2806 psaa.spi = spi;
2807 psaa.reqid = reqid;
2808 psaa.keymat = keymat;
2809 psaa.e_type = e_type;
2810 psaa.e_keylen = e_keylen;
2811 psaa.a_type = a_type;
2812 psaa.a_keylen = a_keylen;
2813 psaa.flags = flags;
2814 psaa.l_alloc = l_alloc;
2815 psaa.l_bytes = l_bytes;
2816 psaa.l_addtime = l_addtime;
2817 psaa.l_usetime = l_usetime;
2818 psaa.seq = seq;
2819 psaa.l_natt_type = l_natt_type;
2820 psaa.l_natt_sport = l_natt_sport;
2821 psaa.l_natt_dport = l_natt_dport;
2822 psaa.l_natt_oa = l_natt_oa;
2823 psaa.l_natt_frag = l_natt_frag;
2825 return pfkey_send_add2(&psaa);