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