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