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