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