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