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