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

1.1.1.2 ! misho       1: /*     $NetBSD: pfkey.c,v 1.21.2.1 2011/11/14 13:25:06 tteras Exp $    */
1.1       misho       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;
1.1.1.2 ! misho    1786:        int bufsiz_current, bufsiz_wanted;
        !          1787:        int ret;
        !          1788:        socklen_t len;
1.1       misho    1789: 
                   1790:        if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) {
                   1791:                __ipsec_set_strerror(strerror(errno));
                   1792:                return -1;
                   1793:        }
                   1794: 
                   1795:        /*
                   1796:         * This is a temporary workaround for KAME PR 154.
                   1797:         * Don't really care even if it fails.
                   1798:         */
1.1.1.2 ! misho    1799:        /* Try to have 128k. If we have more, do not lower it. */
        !          1800:        bufsiz_wanted = 128 * 1024;
        !          1801:        len = sizeof(bufsiz_current);
        !          1802:        ret = getsockopt(so, SOL_SOCKET, SO_SNDBUF,
        !          1803:                &bufsiz_current, &len);
        !          1804:        if ((ret < 0) || (bufsiz_current < bufsiz_wanted))
        !          1805:                (void)setsockopt(so, SOL_SOCKET, SO_SNDBUF,
        !          1806:                        &bufsiz_wanted, sizeof(bufsiz_wanted));
        !          1807: 
        !          1808:        /* Try to have have at least 2MB. If we have more, do not lower it. */
        !          1809:        bufsiz_wanted = 2 * 1024 * 1024;
        !          1810:        len = sizeof(bufsiz_current);
        !          1811:        ret = getsockopt(so, SOL_SOCKET, SO_RCVBUF,
        !          1812:                &bufsiz_current, &len);
        !          1813:        if (ret < 0)
        !          1814:                bufsiz_current = 128 * 1024;
        !          1815: 
        !          1816:        for (; bufsiz_wanted > bufsiz_current; bufsiz_wanted /= 2) {
        !          1817:                if (setsockopt(so, SOL_SOCKET, SO_RCVBUF,
        !          1818:                                &bufsiz_wanted, sizeof(bufsiz_wanted)) == 0)
        !          1819:                        break;
        !          1820:        }
        !          1821: 
1.1       misho    1822:        __ipsec_errcode = EIPSEC_NO_ERROR;
                   1823:        return so;
                   1824: }
                   1825: 
                   1826: int
                   1827: pfkey_set_buffer_size(int so, int size)
                   1828: {
                   1829:        int newsize;
                   1830:        int actual_bufsiz;
                   1831:        socklen_t sizebufsiz;
                   1832:        int desired_bufsiz;
                   1833: 
                   1834:        /*
                   1835:         * on linux you may need to allow the kernel to allocate
                   1836:         * more buffer space by increasing:
                   1837:         * /proc/sys/net/core/rmem_max and wmem_max
                   1838:         */
                   1839:        if (size > 0) {
                   1840:                actual_bufsiz = 0;
                   1841:                sizebufsiz = sizeof(actual_bufsiz);
                   1842:                desired_bufsiz = size * 1024;
                   1843:                if ((getsockopt(so, SOL_SOCKET, SO_RCVBUF,
                   1844:                                &actual_bufsiz, &sizebufsiz) < 0)
                   1845:                    || (actual_bufsiz < desired_bufsiz)) {
                   1846:                        if (setsockopt(so, SOL_SOCKET, SO_RCVBUF,
                   1847:                                       &desired_bufsiz, sizeof(desired_bufsiz)) < 0) {
                   1848:                                __ipsec_set_strerror(strerror(errno));
                   1849:                                return -1;
                   1850:                        }
                   1851:                }
                   1852:        }
                   1853: 
                   1854:        /* return actual buffer size */
                   1855:        actual_bufsiz = 0;
                   1856:        sizebufsiz = sizeof(actual_bufsiz);
                   1857:        getsockopt(so, SOL_SOCKET, SO_RCVBUF,
                   1858:                   &actual_bufsiz, &sizebufsiz);
                   1859:        return actual_bufsiz / 1024;
                   1860: }
                   1861: 
                   1862: /*
                   1863:  * close a socket.
                   1864:  * OUT:
                   1865:  *      0: success.
                   1866:  *     -1: fail.
                   1867:  */
                   1868: void
                   1869: pfkey_close(int so)
                   1870: {
                   1871:        (void)close(so);
                   1872: 
                   1873:        __ipsec_errcode = EIPSEC_NO_ERROR;
                   1874:        return;
                   1875: }
                   1876: 
                   1877: /*
                   1878:  * receive sadb_msg data, and return pointer to new buffer allocated.
                   1879:  * Must free this buffer later.
                   1880:  * OUT:
                   1881:  *     NULL    : error occured.
                   1882:  *     others  : a pointer to sadb_msg structure.
                   1883:  *
                   1884:  * XXX should be rewritten to pass length explicitly
                   1885:  */
                   1886: struct sadb_msg *
                   1887: pfkey_recv(int so)
                   1888: {
                   1889:        struct sadb_msg buf, *newmsg;
                   1890:        int len, reallen;
                   1891: 
                   1892:        while ((len = recv(so, (void *)&buf, sizeof(buf), MSG_PEEK)) < 0) {
                   1893:                if (errno == EINTR)
                   1894:                        continue;
                   1895:                __ipsec_set_strerror(strerror(errno));
                   1896:                return NULL;
                   1897:        }
                   1898: 
                   1899:        if (len < sizeof(buf)) {
                   1900:                recv(so, (void *)&buf, sizeof(buf), 0);
                   1901:                __ipsec_errcode = EIPSEC_MAX;
                   1902:                return NULL;
                   1903:        }
                   1904: 
                   1905:        /* read real message */
                   1906:        reallen = PFKEY_UNUNIT64(buf.sadb_msg_len);
                   1907:        if ((newmsg = CALLOC((size_t)reallen, struct sadb_msg *)) == 0) {
                   1908:                __ipsec_set_strerror(strerror(errno));
                   1909:                return NULL;
                   1910:        }
                   1911: 
                   1912:        while ((len = recv(so, (void *)newmsg, (socklen_t)reallen, 0)) < 0) {
                   1913:                if (errno == EINTR)
                   1914:                        continue;
                   1915:                __ipsec_set_strerror(strerror(errno));
                   1916:                free(newmsg);
                   1917:                return NULL;
                   1918:        }
                   1919: 
                   1920:        if (len != reallen) {
                   1921:                __ipsec_errcode = EIPSEC_SYSTEM_ERROR;
                   1922:                free(newmsg);
                   1923:                return NULL;
                   1924:        }
                   1925: 
                   1926:        /* don't trust what the kernel says, validate! */
                   1927:        if (PFKEY_UNUNIT64(newmsg->sadb_msg_len) != len) {
                   1928:                __ipsec_errcode = EIPSEC_SYSTEM_ERROR;
                   1929:                free(newmsg);
                   1930:                return NULL;
                   1931:        }
                   1932: 
                   1933:        __ipsec_errcode = EIPSEC_NO_ERROR;
                   1934:        return newmsg;
                   1935: }
                   1936: 
                   1937: /*
                   1938:  * send message to a socket.
                   1939:  * OUT:
                   1940:  *      others: success and return length sent.
                   1941:  *     -1     : fail.
                   1942:  */
                   1943: int
                   1944: pfkey_send(int so, struct sadb_msg *msg, int len)
                   1945: {
                   1946:        if ((len = send(so, (void *)msg, (socklen_t)len, 0)) < 0) {
                   1947:                __ipsec_set_strerror(strerror(errno));
                   1948:                return -1;
                   1949:        }
                   1950: 
                   1951:        __ipsec_errcode = EIPSEC_NO_ERROR;
                   1952:        return len;
                   1953: }
                   1954: 
                   1955: /*
                   1956:  * %%% Utilities
                   1957:  * NOTE: These functions are derived from netkey/key.c in KAME.
                   1958:  */
                   1959: /*
                   1960:  * set the pointer to each header in this message buffer.
                   1961:  * IN: msg: pointer to message buffer.
                   1962:  *     mhp: pointer to the buffer initialized like below:
                   1963:  *             caddr_t mhp[SADB_EXT_MAX + 1];
                   1964:  * OUT:        -1: invalid.
                   1965:  *      0: valid.
                   1966:  *
                   1967:  * XXX should be rewritten to obtain length explicitly
                   1968:  */
                   1969: int
                   1970: pfkey_align(struct sadb_msg *msg, caddr_t *mhp)
                   1971: {
                   1972:        struct sadb_ext *ext;
                   1973:        int i;
                   1974:        caddr_t p;
                   1975:        caddr_t ep;     /* XXX should be passed from upper layer */
                   1976: 
                   1977:        /* validity check */
                   1978:        if (msg == NULL || mhp == NULL) {
                   1979:                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
                   1980:                return -1;
                   1981:        }
                   1982: 
                   1983:        /* initialize */
                   1984:        for (i = 0; i < SADB_EXT_MAX + 1; i++)
                   1985:                mhp[i] = NULL;
                   1986: 
                   1987:        mhp[0] = (void *)msg;
                   1988: 
                   1989:        /* initialize */
                   1990:        p = (void *) msg;
                   1991:        ep = p + PFKEY_UNUNIT64(msg->sadb_msg_len);
                   1992: 
                   1993:        /* skip base header */
                   1994:        p += sizeof(struct sadb_msg);
                   1995: 
                   1996:        while (p < ep) {
                   1997:                ext = (void *)p;
                   1998:                if (ep < p + sizeof(*ext) || PFKEY_EXTLEN(ext) < sizeof(*ext) ||
                   1999:                    ep < p + PFKEY_EXTLEN(ext)) {
                   2000:                        /* invalid format */
                   2001:                        break;
                   2002:                }
                   2003: 
                   2004:                /* duplicate check */
                   2005:                /* XXX Are there duplication either KEY_AUTH or KEY_ENCRYPT ?*/
                   2006:                if (mhp[ext->sadb_ext_type] != NULL) {
                   2007:                        __ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
                   2008:                        return -1;
                   2009:                }
                   2010: 
                   2011:                /* set pointer */
                   2012:                switch (ext->sadb_ext_type) {
                   2013:                case SADB_EXT_SA:
                   2014:                case SADB_EXT_LIFETIME_CURRENT:
                   2015:                case SADB_EXT_LIFETIME_HARD:
                   2016:                case SADB_EXT_LIFETIME_SOFT:
                   2017:                case SADB_EXT_ADDRESS_SRC:
                   2018:                case SADB_EXT_ADDRESS_DST:
                   2019:                case SADB_EXT_ADDRESS_PROXY:
                   2020:                case SADB_EXT_KEY_AUTH:
                   2021:                        /* XXX should to be check weak keys. */
                   2022:                case SADB_EXT_KEY_ENCRYPT:
                   2023:                        /* XXX should to be check weak keys. */
                   2024:                case SADB_EXT_IDENTITY_SRC:
                   2025:                case SADB_EXT_IDENTITY_DST:
                   2026:                case SADB_EXT_SENSITIVITY:
                   2027:                case SADB_EXT_PROPOSAL:
                   2028:                case SADB_EXT_SUPPORTED_AUTH:
                   2029:                case SADB_EXT_SUPPORTED_ENCRYPT:
                   2030:                case SADB_EXT_SPIRANGE:
                   2031:                case SADB_X_EXT_POLICY:
                   2032:                case SADB_X_EXT_SA2:
                   2033: #ifdef SADB_X_EXT_NAT_T_TYPE
                   2034:                case SADB_X_EXT_NAT_T_TYPE:
                   2035:                case SADB_X_EXT_NAT_T_SPORT:
                   2036:                case SADB_X_EXT_NAT_T_DPORT:
                   2037:                case SADB_X_EXT_NAT_T_OA:
                   2038: #endif
                   2039: #ifdef SADB_X_EXT_TAG
                   2040:                case SADB_X_EXT_TAG:
                   2041: #endif
                   2042: #ifdef SADB_X_EXT_PACKET
                   2043:                case SADB_X_EXT_PACKET:
                   2044: #endif
                   2045: #ifdef SADB_X_EXT_KMADDRESS
                   2046:                case SADB_X_EXT_KMADDRESS:
                   2047: #endif
                   2048: #ifdef SADB_X_EXT_SEC_CTX
                   2049:                case SADB_X_EXT_SEC_CTX:
                   2050: #endif
                   2051:                        mhp[ext->sadb_ext_type] = (void *)ext;
                   2052:                        break;
                   2053:                default:
                   2054:                        __ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
                   2055:                        return -1;
                   2056:                }
                   2057: 
                   2058:                p += PFKEY_EXTLEN(ext);
                   2059:        }
                   2060: 
                   2061:        if (p != ep) {
                   2062:                __ipsec_errcode = EIPSEC_INVAL_SADBMSG;
                   2063:                return -1;
                   2064:        }
                   2065: 
                   2066:        __ipsec_errcode = EIPSEC_NO_ERROR;
                   2067:        return 0;
                   2068: }
                   2069: 
                   2070: /*
                   2071:  * check basic usage for sadb_msg,
                   2072:  * NOTE: This routine is derived from netkey/key.c in KAME.
                   2073:  * IN: msg: pointer to message buffer.
                   2074:  *     mhp: pointer to the buffer initialized like below:
                   2075:  *
                   2076:  *             caddr_t mhp[SADB_EXT_MAX + 1];
                   2077:  *
                   2078:  * OUT:        -1: invalid.
                   2079:  *      0: valid.
                   2080:  */
                   2081: int
                   2082: pfkey_check(caddr_t *mhp)
                   2083: {
                   2084:        struct sadb_msg *msg;
                   2085: 
                   2086:        /* validity check */
                   2087:        if (mhp == NULL || mhp[0] == NULL) {
                   2088:                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
                   2089:                return -1;
                   2090:        }
                   2091: 
                   2092:        msg = (void *)mhp[0];
                   2093: 
                   2094:        /* check version */
                   2095:        if (msg->sadb_msg_version != PF_KEY_V2) {
                   2096:                __ipsec_errcode = EIPSEC_INVAL_VERSION;
                   2097:                return -1;
                   2098:        }
                   2099: 
                   2100:        /* check type */
                   2101:        if (msg->sadb_msg_type > SADB_MAX) {
                   2102:                __ipsec_errcode = EIPSEC_INVAL_MSGTYPE;
                   2103:                return -1;
                   2104:        }
                   2105: 
                   2106:        /* check SA type */
                   2107:        switch (msg->sadb_msg_satype) {
                   2108:        case SADB_SATYPE_UNSPEC:
                   2109:                switch (msg->sadb_msg_type) {
                   2110:                case SADB_GETSPI:
                   2111:                case SADB_UPDATE:
                   2112:                case SADB_ADD:
                   2113:                case SADB_DELETE:
                   2114:                case SADB_GET:
                   2115:                case SADB_ACQUIRE:
                   2116:                case SADB_EXPIRE:
                   2117: #ifdef SADB_X_NAT_T_NEW_MAPPING
                   2118:                case SADB_X_NAT_T_NEW_MAPPING:
                   2119: #endif
                   2120:                        __ipsec_errcode = EIPSEC_INVAL_SATYPE;
                   2121:                        return -1;
                   2122:                }
                   2123:                break;
                   2124:        case SADB_SATYPE_ESP:
                   2125:        case SADB_SATYPE_AH:
                   2126:        case SADB_X_SATYPE_IPCOMP:
                   2127: #ifdef SADB_X_SATYPE_TCPSIGNATURE
                   2128:        case SADB_X_SATYPE_TCPSIGNATURE:
                   2129: #endif
                   2130:                switch (msg->sadb_msg_type) {
                   2131:                case SADB_X_SPDADD:
                   2132:                case SADB_X_SPDDELETE:
                   2133:                case SADB_X_SPDGET:
                   2134:                case SADB_X_SPDDUMP:
                   2135:                case SADB_X_SPDFLUSH:
                   2136:                        __ipsec_errcode = EIPSEC_INVAL_SATYPE;
                   2137:                        return -1;
                   2138:                }
                   2139: #ifdef SADB_X_NAT_T_NEW_MAPPING
                   2140:                if (msg->sadb_msg_type == SADB_X_NAT_T_NEW_MAPPING &&
                   2141:                    msg->sadb_msg_satype != SADB_SATYPE_ESP) {
                   2142:                        __ipsec_errcode = EIPSEC_INVAL_SATYPE;
                   2143:                        return -1;
                   2144:                }
                   2145: #endif
                   2146:                break;
                   2147:        case SADB_SATYPE_RSVP:
                   2148:        case SADB_SATYPE_OSPFV2:
                   2149:        case SADB_SATYPE_RIPV2:
                   2150:        case SADB_SATYPE_MIP:
                   2151:                __ipsec_errcode = EIPSEC_NOT_SUPPORTED;
                   2152:                return -1;
                   2153:        case 1: /* XXX: What does it do ? */
                   2154:                if (msg->sadb_msg_type == SADB_X_PROMISC)
                   2155:                        break;
                   2156:                /*FALLTHROUGH*/
                   2157:        default:
                   2158: #ifdef __linux__
                   2159:                /* Linux kernel seems to be buggy and return
                   2160:                 * uninitialized satype for spd flush message */
                   2161:                if (msg->sadb_msg_type == SADB_X_SPDFLUSH)
                   2162:                        break;
                   2163: #endif
                   2164:                __ipsec_errcode = EIPSEC_INVAL_SATYPE;
                   2165:                return -1;
                   2166:        }
                   2167: 
                   2168:        /* check field of upper layer protocol and address family */
                   2169:        if (mhp[SADB_EXT_ADDRESS_SRC] != NULL
                   2170:         && mhp[SADB_EXT_ADDRESS_DST] != NULL) {
                   2171:                struct sadb_address *src0, *dst0;
                   2172: 
                   2173:                src0 = (void *)(mhp[SADB_EXT_ADDRESS_SRC]);
                   2174:                dst0 = (void *)(mhp[SADB_EXT_ADDRESS_DST]);
                   2175: 
                   2176:                if (src0->sadb_address_proto != dst0->sadb_address_proto) {
                   2177:                        __ipsec_errcode = EIPSEC_PROTO_MISMATCH;
                   2178:                        return -1;
                   2179:                }
                   2180: 
                   2181:                if (PFKEY_ADDR_SADDR(src0)->sa_family
                   2182:                 != PFKEY_ADDR_SADDR(dst0)->sa_family) {
                   2183:                        __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
                   2184:                        return -1;
                   2185:                }
                   2186: 
                   2187:                switch (PFKEY_ADDR_SADDR(src0)->sa_family) {
                   2188:                case AF_INET:
                   2189:                case AF_INET6:
                   2190:                        break;
                   2191:                default:
                   2192:                        __ipsec_errcode = EIPSEC_INVAL_FAMILY;
                   2193:                        return -1;
                   2194:                }
                   2195: 
                   2196:                /*
                   2197:                 * prefixlen == 0 is valid because there must be the case
                   2198:                 * all addresses are matched.
                   2199:                 */
                   2200:        }
                   2201: 
                   2202:        __ipsec_errcode = EIPSEC_NO_ERROR;
                   2203:        return 0;
                   2204: }
                   2205: 
                   2206: /*
                   2207:  * set data into sadb_msg.
                   2208:  * `buf' must has been allocated sufficiently.
                   2209:  */
                   2210: static caddr_t
                   2211: pfkey_setsadbmsg(caddr_t buf, caddr_t lim, u_int type, u_int tlen,
                   2212:     u_int satype, u_int32_t seq, pid_t pid)
                   2213: {
                   2214:        struct sadb_msg *p;
                   2215:        u_int len;
                   2216: 
                   2217:        p = (void *)buf;
                   2218:        len = sizeof(struct sadb_msg);
                   2219: 
                   2220:        if (buf + len > lim)
                   2221:                return NULL;
                   2222: 
                   2223:        memset(p, 0, len);
                   2224:        p->sadb_msg_version = PF_KEY_V2;
                   2225:        p->sadb_msg_type = type;
                   2226:        p->sadb_msg_errno = 0;
                   2227:        p->sadb_msg_satype = satype;
                   2228:        p->sadb_msg_len = PFKEY_UNIT64(tlen);
                   2229:        p->sadb_msg_reserved = 0;
                   2230:        p->sadb_msg_seq = seq;
                   2231:        p->sadb_msg_pid = (u_int32_t)pid;
                   2232: 
                   2233:        return(buf + len);
                   2234: }
                   2235: 
                   2236: /*
                   2237:  * copy secasvar data into sadb_address.
                   2238:  * `buf' must has been allocated sufficiently.
                   2239:  */
                   2240: static caddr_t
                   2241: pfkey_setsadbsa(caddr_t buf, caddr_t lim, u_int32_t spi, u_int wsize,
                   2242:     u_int auth, u_int enc, u_int32_t flags)
                   2243: {
                   2244:        struct sadb_sa *p;
                   2245:        u_int len;
                   2246: 
                   2247:        p = (void *)buf;
                   2248:        len = sizeof(struct sadb_sa);
                   2249: 
                   2250:        if (buf + len > lim)
                   2251:                return NULL;
                   2252: 
                   2253:        memset(p, 0, len);
                   2254:        p->sadb_sa_len = PFKEY_UNIT64(len);
                   2255:        p->sadb_sa_exttype = SADB_EXT_SA;
                   2256:        p->sadb_sa_spi = spi;
                   2257:        p->sadb_sa_replay = wsize;
                   2258:        p->sadb_sa_state = SADB_SASTATE_LARVAL;
                   2259:        p->sadb_sa_auth = auth;
                   2260:        p->sadb_sa_encrypt = enc;
                   2261:        p->sadb_sa_flags = flags;
                   2262: 
                   2263:        return(buf + len);
                   2264: }
                   2265: 
                   2266: /*
                   2267:  * set data into sadb_address.
                   2268:  * `buf' must has been allocated sufficiently.
                   2269:  * prefixlen is in bits.
                   2270:  */
                   2271: static caddr_t
                   2272: pfkey_setsadbaddr(caddr_t buf, caddr_t lim, u_int exttype,
                   2273:     struct sockaddr *saddr, u_int prefixlen, u_int ul_proto)
                   2274: {
                   2275:        struct sadb_address *p;
                   2276:        u_int len;
                   2277: 
                   2278:        p = (void *)buf;
                   2279:        len = sizeof(struct sadb_address) + PFKEY_ALIGN8(sysdep_sa_len(saddr));
                   2280: 
                   2281:        if (buf + len > lim)
                   2282:                return NULL;
                   2283: 
                   2284:        memset(p, 0, len);
                   2285:        p->sadb_address_len = PFKEY_UNIT64(len);
                   2286:        p->sadb_address_exttype = exttype & 0xffff;
                   2287:        p->sadb_address_proto = ul_proto & 0xff;
                   2288:        p->sadb_address_prefixlen = prefixlen;
                   2289:        p->sadb_address_reserved = 0;
                   2290: 
                   2291:        memcpy(p + 1, saddr, (size_t)sysdep_sa_len(saddr));
                   2292: 
                   2293:        return(buf + len);
                   2294: }
                   2295: 
                   2296: #ifdef SADB_X_EXT_KMADDRESS
                   2297: /*
                   2298:  * set data into sadb_x_kmaddress.
                   2299:  * `buf' must has been allocated sufficiently.
                   2300:  */
                   2301: static caddr_t
                   2302: pfkey_setsadbkmaddr(caddr_t buf, caddr_t lim, struct sockaddr *local,
                   2303:     struct sockaddr *remote)
                   2304: {
                   2305:        struct sadb_x_kmaddress *p;
                   2306:        struct sockaddr *sa;
                   2307:        u_int salen = sysdep_sa_len(local);
                   2308:        u_int len;
                   2309: 
                   2310:        /* sanity check */
                   2311:        if (local->sa_family != remote->sa_family)
                   2312:                return NULL;
                   2313: 
                   2314:        p = (void *)buf;
                   2315:        len = sizeof(struct sadb_x_kmaddress) + PFKEY_ALIGN8(2*salen);
                   2316: 
                   2317:        if (buf + len > lim)
                   2318:                return NULL;
                   2319: 
                   2320:        memset(p, 0, len);
                   2321:        p->sadb_x_kmaddress_len = PFKEY_UNIT64(len);
                   2322:        p->sadb_x_kmaddress_exttype = SADB_X_EXT_KMADDRESS;
                   2323:        p->sadb_x_kmaddress_reserved = 0;
                   2324:        sa = (struct sockaddr *)(p + 1);
                   2325:        memcpy(sa, local, salen);
                   2326:        sa = (struct sockaddr *)((char *)sa + salen);
                   2327:        memcpy(sa, remote, salen);
                   2328: 
                   2329:        return(buf + len);
                   2330: }
                   2331: #endif
                   2332: 
                   2333: /*
                   2334:  * set sadb_key structure after clearing buffer with zero.
                   2335:  * OUT: the pointer of buf + len.
                   2336:  */
                   2337: static caddr_t
                   2338: pfkey_setsadbkey(caddr_t buf, caddr_t lim, u_int type, caddr_t key,
                   2339:     u_int keylen)
                   2340: {
                   2341:        struct sadb_key *p;
                   2342:        u_int len;
                   2343: 
                   2344:        p = (void *)buf;
                   2345:        len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen);
                   2346: 
                   2347:        if (buf + len > lim)
                   2348:                return NULL;
                   2349: 
                   2350:        memset(p, 0, len);
                   2351:        p->sadb_key_len = PFKEY_UNIT64(len);
                   2352:        p->sadb_key_exttype = type;
                   2353:        p->sadb_key_bits = keylen << 3;
                   2354:        p->sadb_key_reserved = 0;
                   2355: 
                   2356:        memcpy(p + 1, key, keylen);
                   2357: 
                   2358:        return buf + len;
                   2359: }
                   2360: 
                   2361: /*
                   2362:  * set sadb_lifetime structure after clearing buffer with zero.
                   2363:  * OUT: the pointer of buf + len.
                   2364:  */
                   2365: static caddr_t
                   2366: pfkey_setsadblifetime(caddr_t buf, caddr_t lim, u_int type, u_int32_t l_alloc,
                   2367:     u_int32_t l_bytes, u_int32_t l_addtime, u_int32_t l_usetime)
                   2368: {
                   2369:        struct sadb_lifetime *p;
                   2370:        u_int len;
                   2371: 
                   2372:        p = (void *)buf;
                   2373:        len = sizeof(struct sadb_lifetime);
                   2374: 
                   2375:        if (buf + len > lim)
                   2376:                return NULL;
                   2377: 
                   2378:        memset(p, 0, len);
                   2379:        p->sadb_lifetime_len = PFKEY_UNIT64(len);
                   2380:        p->sadb_lifetime_exttype = type;
                   2381: 
                   2382:        switch (type) {
                   2383:        case SADB_EXT_LIFETIME_SOFT:
                   2384:                p->sadb_lifetime_allocations
                   2385:                        = (l_alloc * soft_lifetime_allocations_rate) /100;
                   2386:                p->sadb_lifetime_bytes
                   2387:                        = (l_bytes * soft_lifetime_bytes_rate) /100;
                   2388:                p->sadb_lifetime_addtime
                   2389:                        = (l_addtime * soft_lifetime_addtime_rate) /100;
                   2390:                p->sadb_lifetime_usetime
                   2391:                        = (l_usetime * soft_lifetime_usetime_rate) /100;
                   2392:                break;
                   2393:        case SADB_EXT_LIFETIME_HARD:
                   2394:                p->sadb_lifetime_allocations = l_alloc;
                   2395:                p->sadb_lifetime_bytes = l_bytes;
                   2396:                p->sadb_lifetime_addtime = l_addtime;
                   2397:                p->sadb_lifetime_usetime = l_usetime;
                   2398:                break;
                   2399:        }
                   2400: 
                   2401:        return buf + len;
                   2402: }
                   2403: 
                   2404: /*
                   2405:  * copy secasvar data into sadb_address.
                   2406:  * `buf' must has been allocated sufficiently.
                   2407:  */
                   2408: static caddr_t
                   2409: pfkey_setsadbxsa2(caddr_t buf, caddr_t lim, u_int32_t mode0, u_int32_t reqid)
                   2410: {
                   2411:        struct sadb_x_sa2 *p;
                   2412:        u_int8_t mode = mode0 & 0xff;
                   2413:        u_int len;
                   2414: 
                   2415:        p = (void *)buf;
                   2416:        len = sizeof(struct sadb_x_sa2);
                   2417: 
                   2418:        if (buf + len > lim)
                   2419:                return NULL;
                   2420: 
                   2421:        memset(p, 0, len);
                   2422:        p->sadb_x_sa2_len = PFKEY_UNIT64(len);
                   2423:        p->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
                   2424:        p->sadb_x_sa2_mode = mode;
                   2425:        p->sadb_x_sa2_reqid = reqid;
                   2426: 
                   2427:        return(buf + len);
                   2428: }
                   2429: 
                   2430: #ifdef SADB_X_EXT_NAT_T_TYPE
                   2431: static caddr_t
                   2432: pfkey_set_natt_type(caddr_t buf, caddr_t lim, u_int type, u_int8_t l_natt_type)
                   2433: {
                   2434:        struct sadb_x_nat_t_type *p;
                   2435:        u_int len;
                   2436: 
                   2437:        p = (void *)buf;
                   2438:        len = sizeof(struct sadb_x_nat_t_type);
                   2439: 
                   2440:        if (buf + len > lim)
                   2441:                return NULL;
                   2442: 
                   2443:        memset(p, 0, len);
                   2444:        p->sadb_x_nat_t_type_len = PFKEY_UNIT64(len);
                   2445:        p->sadb_x_nat_t_type_exttype = type;
                   2446:        p->sadb_x_nat_t_type_type = l_natt_type;
                   2447: 
                   2448:        return(buf + len);
                   2449: }
                   2450: 
                   2451: static caddr_t
                   2452: pfkey_set_natt_port(caddr_t buf, caddr_t lim, u_int type, u_int16_t l_natt_port)
                   2453: {
                   2454:        struct sadb_x_nat_t_port *p;
                   2455:        u_int len;
                   2456: 
                   2457:        p = (void *)buf;
                   2458:        len = sizeof(struct sadb_x_nat_t_port);
                   2459: 
                   2460:        if (buf + len > lim)
                   2461:                return NULL;
                   2462: 
                   2463:        memset(p, 0, len);
                   2464:        p->sadb_x_nat_t_port_len = PFKEY_UNIT64(len);
                   2465:        p->sadb_x_nat_t_port_exttype = type;
                   2466:        p->sadb_x_nat_t_port_port = htons(l_natt_port);
                   2467: 
                   2468:        return(buf + len);
                   2469: }
                   2470: #endif
                   2471: 
                   2472: #ifdef SADB_X_EXT_NAT_T_FRAG
                   2473: static caddr_t
                   2474: pfkey_set_natt_frag(caddr_t buf, caddr_t lim, u_int type, 
                   2475:     u_int16_t l_natt_frag)
                   2476: {
                   2477:        struct sadb_x_nat_t_frag *p;
                   2478:        u_int len;
                   2479: 
                   2480:        p = (void *)buf;
                   2481:        len = sizeof(struct sadb_x_nat_t_frag);
                   2482: 
                   2483:        if (buf + len > lim)
                   2484:                return NULL;
                   2485: 
                   2486:        memset(p, 0, len);
                   2487:        p->sadb_x_nat_t_frag_len = PFKEY_UNIT64(len);
                   2488:        p->sadb_x_nat_t_frag_exttype = type;
                   2489:        p->sadb_x_nat_t_frag_fraglen = l_natt_frag;
                   2490: 
                   2491:        return(buf + len);
                   2492: }
                   2493: #endif
                   2494: 
                   2495: #ifdef SADB_X_EXT_SEC_CTX
                   2496: static caddr_t
                   2497: pfkey_setsecctx(caddr_t buf, caddr_t lim, u_int type, u_int8_t ctx_doi,
                   2498:     u_int8_t ctx_alg, caddr_t sec_ctx, u_int16_t sec_ctxlen)
                   2499: {
                   2500:        struct sadb_x_sec_ctx *p;
                   2501:        u_int len;
                   2502: 
                   2503:        p = (struct sadb_x_sec_ctx *)buf;
                   2504:        len = sizeof(struct sadb_x_sec_ctx) + PFKEY_ALIGN8(sec_ctxlen);
                   2505: 
                   2506:        if (buf + len > lim)
                   2507:                return NULL;
                   2508: 
                   2509:        memset(p, 0, len);
                   2510:        p->sadb_x_sec_len = PFKEY_UNIT64(len);
                   2511:        p->sadb_x_sec_exttype = type;
                   2512:        p->sadb_x_ctx_len = sec_ctxlen;
                   2513:        p->sadb_x_ctx_doi = ctx_doi;
                   2514:        p->sadb_x_ctx_alg = ctx_alg;
                   2515: 
                   2516:        memcpy(p + 1, sec_ctx, sec_ctxlen);
                   2517: 
                   2518:        return buf + len;
                   2519: }
                   2520: #endif
                   2521: 
                   2522: /* 
                   2523:  * Deprecated, available for backward compatibility with third party 
                   2524:  * libipsec users. Please use pfkey_send_update2 and pfkey_send_add2 instead 
                   2525:  */
                   2526: int
                   2527: pfkey_send_update(int so, u_int satype, u_int mode, struct sockaddr *src,
                   2528:     struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize,
                   2529:     caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type,
                   2530:     u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes,
                   2531:     u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq)
                   2532: {
                   2533:        struct pfkey_send_sa_args psaa;
                   2534: 
                   2535:        memset(&psaa, 0, sizeof(psaa));
                   2536:        psaa.so = so;
                   2537:        psaa.type = SADB_UPDATE;
                   2538:        psaa.satype = satype;
                   2539:        psaa.mode = mode;
                   2540:        psaa.wsize = wsize;
                   2541:        psaa.src = src;
                   2542:        psaa.dst = dst;
                   2543:        psaa.spi = spi;
                   2544:        psaa.reqid = reqid;
                   2545:        psaa.keymat = keymat;
                   2546:        psaa.e_type = e_type;
                   2547:        psaa.e_keylen = e_keylen;
                   2548:        psaa.a_type = a_type;
                   2549:        psaa.a_keylen = a_keylen;
                   2550:        psaa.flags = flags;
                   2551:        psaa.l_alloc = l_alloc;
                   2552:        psaa.l_bytes = l_bytes;
                   2553:        psaa.l_addtime = l_addtime;
                   2554:        psaa.l_usetime = l_usetime;
                   2555:        psaa.seq = seq;
                   2556: 
                   2557:        return pfkey_send_update2(&psaa);
                   2558: }
                   2559: 
                   2560: int
                   2561: pfkey_send_update_nat(int so, u_int satype, u_int mode, struct sockaddr *src,
                   2562:     struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize,
                   2563:     caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type,
                   2564:     u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes,
                   2565:     u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq,
                   2566:     u_int8_t l_natt_type, u_int16_t l_natt_sport, u_int16_t l_natt_dport,
                   2567:     struct sockaddr *l_natt_oa, u_int16_t l_natt_frag)
                   2568: {
                   2569:        struct pfkey_send_sa_args psaa;
                   2570: 
                   2571:        memset(&psaa, 0, sizeof(psaa));
                   2572:        psaa.so = so;
                   2573:        psaa.type = SADB_UPDATE;
                   2574:        psaa.satype = satype;
                   2575:        psaa.mode = mode;
                   2576:        psaa.wsize = wsize;
                   2577:        psaa.src = src;
                   2578:        psaa.dst = dst;
                   2579:        psaa.spi = spi;
                   2580:        psaa.reqid = reqid;
                   2581:        psaa.keymat = keymat;
                   2582:        psaa.e_type = e_type;
                   2583:        psaa.e_keylen = e_keylen;
                   2584:        psaa.a_type = a_type;
                   2585:        psaa.a_keylen = a_keylen;
                   2586:        psaa.flags = flags;
                   2587:        psaa.l_alloc = l_alloc;
                   2588:        psaa.l_bytes = l_bytes;
                   2589:        psaa.l_addtime = l_addtime;
                   2590:        psaa.l_usetime = l_usetime;
                   2591:        psaa.seq = seq;
                   2592:        psaa.l_natt_type = l_natt_type;
                   2593:        psaa.l_natt_sport = l_natt_sport;
                   2594:        psaa.l_natt_dport = l_natt_dport;
                   2595:        psaa.l_natt_oa = l_natt_oa;
                   2596:        psaa.l_natt_frag = l_natt_frag;
                   2597: 
                   2598:        return pfkey_send_update2(&psaa);
                   2599: }
                   2600: 
                   2601: int
                   2602: pfkey_send_add(int so, u_int satype, u_int mode, struct sockaddr *src,
                   2603:     struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize,
                   2604:     caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type,
                   2605:     u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes,
                   2606:     u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq)
                   2607: {
                   2608:        struct pfkey_send_sa_args psaa;
                   2609: 
                   2610:        memset(&psaa, 0, sizeof(psaa));
                   2611:        psaa.so = so;
                   2612:        psaa.type = SADB_ADD;
                   2613:        psaa.satype = satype;
                   2614:        psaa.mode = mode;
                   2615:        psaa.wsize = wsize;
                   2616:        psaa.src = src;
                   2617:        psaa.dst = dst;
                   2618:        psaa.spi = spi;
                   2619:        psaa.reqid = reqid;
                   2620:        psaa.keymat = keymat;
                   2621:        psaa.e_type = e_type;
                   2622:        psaa.e_keylen = e_keylen;
                   2623:        psaa.a_type = a_type;
                   2624:        psaa.a_keylen = a_keylen;
                   2625:        psaa.flags = flags;
                   2626:        psaa.l_alloc = l_alloc;
                   2627:        psaa.l_bytes = l_bytes;
                   2628:        psaa.l_addtime = l_addtime;
                   2629:        psaa.l_usetime = l_usetime;
                   2630:        psaa.seq = seq;
                   2631: 
                   2632:        return pfkey_send_add2(&psaa);
                   2633: }
                   2634: 
                   2635: int
                   2636: pfkey_send_add_nat(int so, u_int satype, u_int mode, struct sockaddr *src,
                   2637:     struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize,
                   2638:     caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type,
                   2639:     u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes,
                   2640:     u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq,
                   2641:     u_int8_t l_natt_type, u_int16_t l_natt_sport, u_int16_t l_natt_dport,
                   2642:     struct sockaddr *l_natt_oa, u_int16_t l_natt_frag)
                   2643: {
                   2644:        struct pfkey_send_sa_args psaa;
                   2645: 
                   2646:        memset(&psaa, 0, sizeof(psaa));
                   2647:        psaa.so = so;
                   2648:        psaa.type = SADB_ADD;
                   2649:        psaa.satype = satype;
                   2650:        psaa.mode = mode;
                   2651:        psaa.wsize = wsize;
                   2652:        psaa.src = src;
                   2653:        psaa.dst = dst;
                   2654:        psaa.spi = spi;
                   2655:        psaa.reqid = reqid;
                   2656:        psaa.keymat = keymat;
                   2657:        psaa.e_type = e_type;
                   2658:        psaa.e_keylen = e_keylen;
                   2659:        psaa.a_type = a_type;
                   2660:        psaa.a_keylen = a_keylen;
                   2661:        psaa.flags = flags;
                   2662:        psaa.l_alloc = l_alloc;
                   2663:        psaa.l_bytes = l_bytes;
                   2664:        psaa.l_addtime = l_addtime;
                   2665:        psaa.l_usetime = l_usetime;
                   2666:        psaa.seq = seq;
                   2667:        psaa.l_natt_type = l_natt_type;
                   2668:        psaa.l_natt_sport = l_natt_sport;
                   2669:        psaa.l_natt_dport = l_natt_dport;
                   2670:        psaa.l_natt_oa = l_natt_oa;
                   2671:        psaa.l_natt_frag = l_natt_frag;
                   2672: 
                   2673:        return pfkey_send_add2(&psaa);
                   2674: }

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