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