Annotation of embedaddon/ipsec-tools/src/libipsec/pfkey.c, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>