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