source: rtems-libbsd/ipsec-tools/src/libipsec/pfkey.c

6-freebsd-12
Last change on this file was 330f65f9, checked in by Christian Mauderer <christian.mauderer@…>, on 02/22/22 at 08:25:36

ipsec-tools: Reduce allocated buffer size

By default, pfkey allocates a 2MB buffer that is used for SPD entries.
This size is a good choice for a server system where a lot of clients
should be handled. But on our embedded systems, an application with that
much clients is unlikely and 2MB is a lot of space. So reduce that to
the default value of 128kB which should be enough for a small number of
ipsec connections.

See https://bugzilla.redhat.com/show_bug.cgi?id=607361 for more details
why the upstream project originally increased the size.

If someone really needs a bigger size, there is a option in the
configuration file of pfkey called pfkey_buffer that can overwrite
this value.

Closes #4621

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