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