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