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