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

1.1     ! misho       1: /*     $NetBSD: pfkey.c,v 1.57 2011/03/15 13:20:14 vanhu Exp $ */
        !             2: 
        !             3: /* $Id: pfkey.c,v 1.57 2011/03/15 13:20:14 vanhu Exp $ */
        !             4: 
        !             5: /*
        !             6:  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
        !             7:  * All rights reserved.
        !             8:  *
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  * 3. Neither the name of the project nor the names of its contributors
        !            18:  *    may be used to endorse or promote products derived from this software
        !            19:  *    without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
        !            22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
        !            25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            31:  * SUCH DAMAGE.
        !            32:  */
        !            33: 
        !            34: #include "config.h"
        !            35: 
        !            36: #include <stdlib.h>
        !            37: #include <string.h>
        !            38: #include <stdio.h>
        !            39: #include <netdb.h>
        !            40: #include <errno.h>
        !            41: #ifdef HAVE_UNISTD_H
        !            42: #include <unistd.h>
        !            43: #endif
        !            44: #include <netdb.h>
        !            45: #include <netinet/in.h>
        !            46: #include <arpa/inet.h>
        !            47: 
        !            48: #ifdef ENABLE_NATT
        !            49: # ifdef __linux__
        !            50: #  include <linux/udp.h>
        !            51: # endif
        !            52: # if defined(__NetBSD__) || defined(__FreeBSD__) ||    \
        !            53:   (defined(__APPLE__) && defined(__MACH__))
        !            54: #  include <netinet/udp.h>
        !            55: # endif
        !            56: #endif
        !            57: 
        !            58: #include <sys/types.h>
        !            59: #include <sys/param.h>
        !            60: #include <sys/socket.h>
        !            61: #include <sys/queue.h>
        !            62: #include <sys/sysctl.h>
        !            63: 
        !            64: #include <net/route.h>
        !            65: #include <net/pfkeyv2.h>
        !            66: 
        !            67: #include <netinet/in.h>
        !            68: #include PATH_IPSEC_H
        !            69: #include <fcntl.h>
        !            70: 
        !            71: #include "libpfkey.h"
        !            72: 
        !            73: #include "var.h"
        !            74: #include "misc.h"
        !            75: #include "vmbuf.h"
        !            76: #include "plog.h"
        !            77: #include "sockmisc.h"
        !            78: #include "session.h"
        !            79: #include "debug.h"
        !            80: 
        !            81: #include "schedule.h"
        !            82: #include "localconf.h"
        !            83: #include "remoteconf.h"
        !            84: #include "handler.h"
        !            85: #include "policy.h"
        !            86: #include "proposal.h"
        !            87: #include "isakmp_var.h"
        !            88: #include "isakmp.h"
        !            89: #include "isakmp_inf.h"
        !            90: #include "ipsec_doi.h"
        !            91: #include "oakley.h"
        !            92: #include "pfkey.h"
        !            93: #include "algorithm.h"
        !            94: #include "sainfo.h"
        !            95: #include "admin.h"
        !            96: #include "evt.h"
        !            97: #include "privsep.h"
        !            98: #include "strnames.h"
        !            99: #include "backupsa.h"
        !           100: #include "gcmalloc.h"
        !           101: #include "nattraversal.h"
        !           102: #include "crypto_openssl.h"
        !           103: #include "grabmyaddr.h"
        !           104: 
        !           105: #if defined(SADB_X_EALG_RIJNDAELCBC) && !defined(SADB_X_EALG_AESCBC)
        !           106: #define SADB_X_EALG_AESCBC  SADB_X_EALG_RIJNDAELCBC
        !           107: #endif
        !           108: 
        !           109: /* prototype */
        !           110: static u_int ipsecdoi2pfkey_aalg __P((u_int));
        !           111: static u_int ipsecdoi2pfkey_ealg __P((u_int));
        !           112: static u_int ipsecdoi2pfkey_calg __P((u_int));
        !           113: static u_int ipsecdoi2pfkey_alg __P((u_int, u_int));
        !           114: static u_int keylen_aalg __P((u_int));
        !           115: static u_int keylen_ealg __P((u_int, int));
        !           116: 
        !           117: static int pk_recvgetspi __P((caddr_t *));
        !           118: static int pk_recvupdate __P((caddr_t *));
        !           119: static int pk_recvadd __P((caddr_t *));
        !           120: static int pk_recvdelete __P((caddr_t *));
        !           121: static int pk_recvacquire __P((caddr_t *));
        !           122: static int pk_recvexpire __P((caddr_t *));
        !           123: static int pk_recvflush __P((caddr_t *));
        !           124: static int getsadbpolicy __P((caddr_t *, int *, int, struct ph2handle *));
        !           125: static int pk_recvspdupdate __P((caddr_t *));
        !           126: static int pk_recvspdadd __P((caddr_t *));
        !           127: static int pk_recvspddelete __P((caddr_t *));
        !           128: static int pk_recvspdexpire __P((caddr_t *));
        !           129: static int pk_recvspdget __P((caddr_t *));
        !           130: static int pk_recvspddump __P((caddr_t *));
        !           131: static int pk_recvspdflush __P((caddr_t *));
        !           132: #if defined(SADB_X_MIGRATE) && defined(SADB_X_EXT_KMADDRESS)
        !           133: static int pk_recvmigrate __P((caddr_t *));
        !           134: #endif
        !           135: static struct sadb_msg *pk_recv __P((int, int *));
        !           136: 
        !           137: static int (*pkrecvf[]) __P((caddr_t *)) = {
        !           138: NULL,
        !           139: pk_recvgetspi,
        !           140: pk_recvupdate,
        !           141: pk_recvadd,
        !           142: pk_recvdelete,
        !           143: NULL,  /* SADB_GET */
        !           144: pk_recvacquire,
        !           145: NULL,  /* SABD_REGISTER */
        !           146: pk_recvexpire,
        !           147: pk_recvflush,
        !           148: NULL,  /* SADB_DUMP */
        !           149: NULL,  /* SADB_X_PROMISC */
        !           150: NULL,  /* SADB_X_PCHANGE */
        !           151: pk_recvspdupdate,
        !           152: pk_recvspdadd,
        !           153: pk_recvspddelete,
        !           154: pk_recvspdget,
        !           155: NULL,  /* SADB_X_SPDACQUIRE */
        !           156: pk_recvspddump,
        !           157: pk_recvspdflush,
        !           158: NULL,  /* SADB_X_SPDSETIDX */
        !           159: pk_recvspdexpire,
        !           160: NULL,  /* SADB_X_SPDDELETE2 */
        !           161: NULL,  /* SADB_X_NAT_T_NEW_MAPPING */
        !           162: #if defined(SADB_X_MIGRATE) && defined(SADB_X_EXT_KMADDRESS)
        !           163: pk_recvmigrate,
        !           164: #else
        !           165: NULL,  /* SADB_X_MIGRATE */
        !           166: #endif
        !           167: #if (SADB_MAX > 24)
        !           168: #error "SADB extra message?"
        !           169: #endif
        !           170: };
        !           171: 
        !           172: static int addnewsp __P((caddr_t *, struct sockaddr *, struct sockaddr *));
        !           173: 
        !           174: /* cope with old kame headers - ugly */
        !           175: #ifndef SADB_X_AALG_MD5
        !           176: #define SADB_X_AALG_MD5                SADB_AALG_MD5
        !           177: #endif
        !           178: #ifndef SADB_X_AALG_SHA
        !           179: #define SADB_X_AALG_SHA                SADB_AALG_SHA
        !           180: #endif
        !           181: #ifndef SADB_X_AALG_NULL
        !           182: #define SADB_X_AALG_NULL       SADB_AALG_NULL
        !           183: #endif
        !           184: 
        !           185: #ifndef SADB_X_EALG_BLOWFISHCBC
        !           186: #define SADB_X_EALG_BLOWFISHCBC        SADB_EALG_BLOWFISHCBC
        !           187: #endif
        !           188: #ifndef SADB_X_EALG_CAST128CBC
        !           189: #define SADB_X_EALG_CAST128CBC SADB_EALG_CAST128CBC
        !           190: #endif
        !           191: #ifndef SADB_X_EALG_RC5CBC
        !           192: #ifdef SADB_EALG_RC5CBC
        !           193: #define SADB_X_EALG_RC5CBC     SADB_EALG_RC5CBC
        !           194: #endif
        !           195: #endif
        !           196: 
        !           197: /*
        !           198:  * PF_KEY packet handler
        !           199:  *     0: success
        !           200:  *     -1: fail
        !           201:  */
        !           202: static int
        !           203: pfkey_handler(ctx, fd)
        !           204:        void *ctx;
        !           205:        int fd;
        !           206: {
        !           207:        struct sadb_msg *msg;
        !           208:        int len;
        !           209:        caddr_t mhp[SADB_EXT_MAX + 1];
        !           210:        int error = -1;
        !           211: 
        !           212:        /* receive pfkey message. */
        !           213:        len = 0;
        !           214:        msg = (struct sadb_msg *) pk_recv(fd, &len);
        !           215:        if (msg == NULL) {
        !           216:                if (len < 0) {
        !           217:                        /* do not report EAGAIN as error; well get
        !           218:                         * called from main loop later. and it's normal
        !           219:                         * when spd dump is received during reload and
        !           220:                         * this function is called in loop. */
        !           221:                        if (errno == EAGAIN)
        !           222:                                goto end;
        !           223: 
        !           224:                        plog(LLV_ERROR, LOCATION, NULL,
        !           225:                                "failed to recv from pfkey (%s)\n",
        !           226:                                strerror(errno));
        !           227:                        goto end;
        !           228:                } else {
        !           229:                        /* short message - msg not ready */
        !           230:                        return 0;
        !           231:                }
        !           232:        }
        !           233: 
        !           234:        plog(LLV_DEBUG, LOCATION, NULL, "got pfkey %s message\n",
        !           235:                s_pfkey_type(msg->sadb_msg_type));
        !           236:        plogdump(LLV_DEBUG2, msg, msg->sadb_msg_len << 3);
        !           237: 
        !           238:        /* validity check */
        !           239:        if (msg->sadb_msg_errno) {
        !           240:                int pri;
        !           241: 
        !           242:                /* when SPD is empty, treat the state as no error. */
        !           243:                if (msg->sadb_msg_type == SADB_X_SPDDUMP &&
        !           244:                    msg->sadb_msg_errno == ENOENT)
        !           245:                        pri = LLV_DEBUG;
        !           246:                else
        !           247:                        pri = LLV_ERROR;
        !           248: 
        !           249:                plog(pri, LOCATION, NULL,
        !           250:                        "pfkey %s failed: %s\n",
        !           251:                        s_pfkey_type(msg->sadb_msg_type),
        !           252:                        strerror(msg->sadb_msg_errno));
        !           253: 
        !           254:                goto end;
        !           255:        }
        !           256: 
        !           257:        /* check pfkey message. */
        !           258:        if (pfkey_align(msg, mhp)) {
        !           259:                plog(LLV_ERROR, LOCATION, NULL,
        !           260:                        "libipsec failed pfkey align (%s)\n",
        !           261:                        ipsec_strerror());
        !           262:                goto end;
        !           263:        }
        !           264:        if (pfkey_check(mhp)) {
        !           265:                plog(LLV_ERROR, LOCATION, NULL,
        !           266:                        "libipsec failed pfkey check (%s)\n",
        !           267:                        ipsec_strerror());
        !           268:                goto end;
        !           269:        }
        !           270:        msg = (struct sadb_msg *)mhp[0];
        !           271: 
        !           272:        /* safety check */
        !           273:        if (msg->sadb_msg_type >= ARRAYLEN(pkrecvf)) {
        !           274:                plog(LLV_ERROR, LOCATION, NULL,
        !           275:                        "unknown PF_KEY message type=%u\n",
        !           276:                        msg->sadb_msg_type);
        !           277:                goto end;
        !           278:        }
        !           279: 
        !           280:        if (pkrecvf[msg->sadb_msg_type] == NULL) {
        !           281:                plog(LLV_INFO, LOCATION, NULL,
        !           282:                        "unsupported PF_KEY message %s\n",
        !           283:                        s_pfkey_type(msg->sadb_msg_type));
        !           284:                goto end;
        !           285:        }
        !           286: 
        !           287:        if ((pkrecvf[msg->sadb_msg_type])(mhp) < 0)
        !           288:                goto end;
        !           289: 
        !           290:        error = 1;
        !           291: end:
        !           292:        if (msg)
        !           293:                racoon_free(msg);
        !           294:        return(error);
        !           295: }
        !           296: 
        !           297: /*
        !           298:  * dump SADB
        !           299:  */
        !           300: vchar_t *
        !           301: pfkey_dump_sadb(satype)
        !           302:        int satype;
        !           303: {
        !           304:        int s;
        !           305:        vchar_t *buf = NULL;
        !           306:        pid_t pid = getpid();
        !           307:        struct sadb_msg *msg = NULL;
        !           308:        size_t bl, ml;
        !           309:        int len;
        !           310:        int bufsiz;
        !           311: 
        !           312:        if ((s = privsep_socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) {
        !           313:                plog(LLV_ERROR, LOCATION, NULL,
        !           314:                        "libipsec failed pfkey open: %s\n",
        !           315:                        ipsec_strerror());
        !           316:                return NULL;
        !           317:        }
        !           318: 
        !           319:        if ((bufsiz = pfkey_set_buffer_size(s, lcconf->pfkey_buffer_size)) < 0) {
        !           320:                plog(LLV_ERROR, LOCATION, NULL,
        !           321:                     "libipsec failed pfkey set buffer size to %d: %s\n",
        !           322:                     lcconf->pfkey_buffer_size, ipsec_strerror());
        !           323:                return NULL;
        !           324:        } else if (bufsiz < lcconf->pfkey_buffer_size) {
        !           325:                plog(LLV_WARNING, LOCATION, NULL,
        !           326:                     "pfkey socket receive buffer set to %dKB, instead of %d\n",
        !           327:                     bufsiz, lcconf->pfkey_buffer_size);
        !           328:        }
        !           329: 
        !           330:        plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_dump\n");
        !           331:        if (pfkey_send_dump(s, satype) < 0) {
        !           332:                plog(LLV_ERROR, LOCATION, NULL,
        !           333:                        "libipsec failed dump: %s\n", ipsec_strerror());
        !           334:                goto fail;
        !           335:        }
        !           336: 
        !           337:        while (1) {
        !           338:                if (msg)
        !           339:                        racoon_free(msg);
        !           340:                msg = pk_recv(s, &len);
        !           341:                if (msg == NULL) {
        !           342:                        if (len < 0)
        !           343:                                goto done;
        !           344:                        else
        !           345:                                continue;
        !           346:                }
        !           347: 
        !           348:                if (msg->sadb_msg_type != SADB_DUMP || msg->sadb_msg_pid != pid)
        !           349:                {
        !           350:                    plog(LLV_DEBUG, LOCATION, NULL,
        !           351:                         "discarding non-sadb dump msg %p, our pid=%i\n", msg, pid);
        !           352:                    plog(LLV_DEBUG, LOCATION, NULL,
        !           353:                         "type %i, pid %i\n", msg->sadb_msg_type, msg->sadb_msg_pid);
        !           354:                    continue;
        !           355:                }
        !           356: 
        !           357: 
        !           358:                ml = msg->sadb_msg_len << 3;
        !           359:                bl = buf ? buf->l : 0;
        !           360:                buf = vrealloc(buf, bl + ml);
        !           361:                if (buf == NULL) {
        !           362:                        plog(LLV_ERROR, LOCATION, NULL,
        !           363:                                "failed to reallocate buffer to dump.\n");
        !           364:                        goto fail;
        !           365:                }
        !           366:                memcpy(buf->v + bl, msg, ml);
        !           367: 
        !           368:                if (msg->sadb_msg_seq == 0)
        !           369:                        break;
        !           370:        }
        !           371:        goto done;
        !           372: 
        !           373: fail:
        !           374:        if (buf)
        !           375:                vfree(buf);
        !           376:        buf = NULL;
        !           377: done:
        !           378:        if (msg)
        !           379:                racoon_free(msg);
        !           380:        close(s);
        !           381:        return buf;
        !           382: }
        !           383: 
        !           384: #ifdef ENABLE_ADMINPORT
        !           385: /*
        !           386:  * flush SADB
        !           387:  */
        !           388: void
        !           389: pfkey_flush_sadb(proto)
        !           390:        u_int proto;
        !           391: {
        !           392:        int satype;
        !           393: 
        !           394:        /* convert to SADB_SATYPE */
        !           395:        if ((satype = admin2pfkey_proto(proto)) < 0)
        !           396:                return;
        !           397: 
        !           398:        plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_flush\n");
        !           399:        if (pfkey_send_flush(lcconf->sock_pfkey, satype) < 0) {
        !           400:                plog(LLV_ERROR, LOCATION, NULL,
        !           401:                        "libipsec failed send flush (%s)\n", ipsec_strerror());
        !           402:                return;
        !           403:        }
        !           404: 
        !           405:        return;
        !           406: }
        !           407: #endif
        !           408: 
        !           409: /*
        !           410:  * These are the SATYPEs that we manage.  We register to get
        !           411:  * PF_KEY messages related to these SATYPEs, and we also use
        !           412:  * this list to determine which SATYPEs to delete SAs for when
        !           413:  * we receive an INITIAL-CONTACT.
        !           414:  */
        !           415: const struct pfkey_satype pfkey_satypes[] = {
        !           416:        { SADB_SATYPE_AH,       "AH" },
        !           417:        { SADB_SATYPE_ESP,      "ESP" },
        !           418:        { SADB_X_SATYPE_IPCOMP, "IPCOMP" },
        !           419: };
        !           420: const int pfkey_nsatypes =
        !           421:     sizeof(pfkey_satypes) / sizeof(pfkey_satypes[0]);
        !           422: 
        !           423: /*
        !           424:  * PF_KEY initialization
        !           425:  */
        !           426: int
        !           427: pfkey_init()
        !           428: {
        !           429:        int i, reg_fail;
        !           430:        int bufsiz;
        !           431: 
        !           432:        if ((lcconf->sock_pfkey = pfkey_open()) < 0) {
        !           433:                plog(LLV_ERROR, LOCATION, NULL,
        !           434:                        "libipsec failed pfkey open (%s)\n", ipsec_strerror());
        !           435:                return -1;
        !           436:        }
        !           437:        if ((bufsiz = pfkey_set_buffer_size(lcconf->sock_pfkey,
        !           438:                                            lcconf->pfkey_buffer_size)) < 0) {
        !           439:                plog(LLV_ERROR, LOCATION, NULL,
        !           440:                     "libipsec failed to set pfkey buffer size to %d (%s)\n",
        !           441:                     lcconf->pfkey_buffer_size, ipsec_strerror());
        !           442:                return -1;
        !           443:        } else if (bufsiz < lcconf->pfkey_buffer_size) {
        !           444:                plog(LLV_WARNING, LOCATION, NULL,
        !           445:                     "pfkey socket receive buffer set to %dKB, instead of %d\n",
        !           446:                     bufsiz, lcconf->pfkey_buffer_size);
        !           447:        }
        !           448: 
        !           449:        if (fcntl(lcconf->sock_pfkey, F_SETFL, O_NONBLOCK) == -1)
        !           450:                plog(LLV_WARNING, LOCATION, NULL,
        !           451:                    "failed to set the pfkey socket to NONBLOCK\n");
        !           452: 
        !           453:        for (i = 0, reg_fail = 0; i < pfkey_nsatypes; i++) {
        !           454:                plog(LLV_DEBUG, LOCATION, NULL,
        !           455:                    "call pfkey_send_register for %s\n",
        !           456:                    pfkey_satypes[i].ps_name);
        !           457:                if (pfkey_send_register(lcconf->sock_pfkey,
        !           458:                                        pfkey_satypes[i].ps_satype) < 0 ||
        !           459:                    pfkey_recv_register(lcconf->sock_pfkey) < 0) {
        !           460:                        plog(LLV_WARNING, LOCATION, NULL,
        !           461:                            "failed to register %s (%s)\n",
        !           462:                            pfkey_satypes[i].ps_name,
        !           463:                            ipsec_strerror());
        !           464:                        reg_fail++;
        !           465:                }
        !           466:        }
        !           467: 
        !           468:        if (reg_fail == pfkey_nsatypes) {
        !           469:                plog(LLV_ERROR, LOCATION, NULL,
        !           470:                        "failed to regist any protocol.\n");
        !           471:                pfkey_close(lcconf->sock_pfkey);
        !           472:                return -1;
        !           473:        }
        !           474: 
        !           475:        initsp();
        !           476: 
        !           477:        if (pfkey_send_spddump(lcconf->sock_pfkey) < 0) {
        !           478:                plog(LLV_ERROR, LOCATION, NULL,
        !           479:                        "libipsec sending spddump failed: %s\n",
        !           480:                        ipsec_strerror());
        !           481:                pfkey_close(lcconf->sock_pfkey);
        !           482:                return -1;
        !           483:        }
        !           484: #if 0
        !           485:        if (pfkey_promisc_toggle(1) < 0) {
        !           486:                pfkey_close(lcconf->sock_pfkey);
        !           487:                return -1;
        !           488:        }
        !           489: #endif
        !           490:        monitor_fd(lcconf->sock_pfkey, pfkey_handler, NULL, 0);
        !           491:        return 0;
        !           492: }
        !           493: 
        !           494: int
        !           495: pfkey_reload()
        !           496: {
        !           497:        flushsp();
        !           498: 
        !           499:        if (pfkey_send_spddump(lcconf->sock_pfkey) < 0) {
        !           500:                plog(LLV_ERROR, LOCATION, NULL,
        !           501:                        "libipsec sending spddump failed: %s\n",
        !           502:                        ipsec_strerror());
        !           503:                return -1;
        !           504:        }
        !           505: 
        !           506:        while (pfkey_handler(NULL, lcconf->sock_pfkey) > 0)
        !           507:                continue;
        !           508: 
        !           509:        return 0;
        !           510: }
        !           511: 
        !           512: /* %%% for conversion */
        !           513: /* IPSECDOI_ATTR_AUTH -> SADB_AALG */
        !           514: static u_int
        !           515: ipsecdoi2pfkey_aalg(hashtype)
        !           516:        u_int hashtype;
        !           517: {
        !           518:        switch (hashtype) {
        !           519:        case IPSECDOI_ATTR_AUTH_HMAC_MD5:
        !           520:                return SADB_AALG_MD5HMAC;
        !           521:        case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
        !           522:                return SADB_AALG_SHA1HMAC;
        !           523:        case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
        !           524: #if (defined SADB_X_AALG_SHA2_256) && !defined(SADB_X_AALG_SHA2_256HMAC)
        !           525:                return SADB_X_AALG_SHA2_256;
        !           526: #else
        !           527:                return SADB_X_AALG_SHA2_256HMAC;
        !           528: #endif
        !           529:        case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
        !           530: #if (defined SADB_X_AALG_SHA2_384) && !defined(SADB_X_AALG_SHA2_384HMAC)
        !           531:                return SADB_X_AALG_SHA2_384;
        !           532: #else
        !           533:                return SADB_X_AALG_SHA2_384HMAC;
        !           534: #endif
        !           535:        case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
        !           536: #if (defined SADB_X_AALG_SHA2_512) && !defined(SADB_X_AALG_SHA2_512HMAC)
        !           537:                return SADB_X_AALG_SHA2_512;
        !           538: #else
        !           539:                return SADB_X_AALG_SHA2_512HMAC;
        !           540: #endif
        !           541:        case IPSECDOI_ATTR_AUTH_KPDK:           /* need special care */
        !           542:                return SADB_AALG_NONE;
        !           543: 
        !           544:        /* not supported */
        !           545:        case IPSECDOI_ATTR_AUTH_DES_MAC:
        !           546:                plog(LLV_ERROR, LOCATION, NULL,
        !           547:                        "Not supported hash type: %u\n", hashtype);
        !           548:                return ~0;
        !           549: 
        !           550:        case 0: /* reserved */
        !           551:        default:
        !           552:                return SADB_AALG_NONE;
        !           553: 
        !           554:                plog(LLV_ERROR, LOCATION, NULL,
        !           555:                        "Invalid hash type: %u\n", hashtype);
        !           556:                return ~0;
        !           557:        }
        !           558:        /*NOTREACHED*/
        !           559: }
        !           560: 
        !           561: /* IPSECDOI_ESP -> SADB_EALG */
        !           562: static u_int
        !           563: ipsecdoi2pfkey_ealg(t_id)
        !           564:        u_int t_id;
        !           565: {
        !           566:        switch (t_id) {
        !           567:        case IPSECDOI_ESP_DES_IV64:             /* sa_flags |= SADB_X_EXT_OLD */
        !           568:                return SADB_EALG_DESCBC;
        !           569:        case IPSECDOI_ESP_DES:
        !           570:                return SADB_EALG_DESCBC;
        !           571:        case IPSECDOI_ESP_3DES:
        !           572:                return SADB_EALG_3DESCBC;
        !           573: #ifdef SADB_X_EALG_RC5CBC
        !           574:        case IPSECDOI_ESP_RC5:
        !           575:                return SADB_X_EALG_RC5CBC;
        !           576: #endif
        !           577:        case IPSECDOI_ESP_CAST:
        !           578:                return SADB_X_EALG_CAST128CBC;
        !           579:        case IPSECDOI_ESP_BLOWFISH:
        !           580:                return SADB_X_EALG_BLOWFISHCBC;
        !           581:        case IPSECDOI_ESP_DES_IV32:     /* flags |= (SADB_X_EXT_OLD|
        !           582:                                                        SADB_X_EXT_IV4B)*/
        !           583:                return SADB_EALG_DESCBC;
        !           584:        case IPSECDOI_ESP_NULL:
        !           585:                return SADB_EALG_NULL;
        !           586: #ifdef SADB_X_EALG_AESCBC
        !           587:        case IPSECDOI_ESP_AES:
        !           588:                return SADB_X_EALG_AESCBC;
        !           589: #endif
        !           590: #ifdef SADB_X_EALG_TWOFISHCBC
        !           591:        case IPSECDOI_ESP_TWOFISH:
        !           592:                return SADB_X_EALG_TWOFISHCBC;
        !           593: #endif
        !           594: #ifdef SADB_X_EALG_CAMELLIACBC
        !           595:        case IPSECDOI_ESP_CAMELLIA:
        !           596:                return SADB_X_EALG_CAMELLIACBC;
        !           597: #endif
        !           598: 
        !           599:        /* not supported */
        !           600:        case IPSECDOI_ESP_3IDEA:
        !           601:        case IPSECDOI_ESP_IDEA:
        !           602:        case IPSECDOI_ESP_RC4:
        !           603:                plog(LLV_ERROR, LOCATION, NULL,
        !           604:                        "Not supported transform: %u\n", t_id);
        !           605:                return ~0;
        !           606: 
        !           607:        case 0: /* reserved */
        !           608:        default:
        !           609:                plog(LLV_ERROR, LOCATION, NULL,
        !           610:                        "Invalid transform id: %u\n", t_id);
        !           611:                return ~0;
        !           612:        }
        !           613:        /*NOTREACHED*/
        !           614: }
        !           615: 
        !           616: /* IPCOMP -> SADB_CALG */
        !           617: static u_int
        !           618: ipsecdoi2pfkey_calg(t_id)
        !           619:        u_int t_id;
        !           620: {
        !           621:        switch (t_id) {
        !           622:        case IPSECDOI_IPCOMP_OUI:
        !           623:                return SADB_X_CALG_OUI;
        !           624:        case IPSECDOI_IPCOMP_DEFLATE:
        !           625:                return SADB_X_CALG_DEFLATE;
        !           626:        case IPSECDOI_IPCOMP_LZS:
        !           627:                return SADB_X_CALG_LZS;
        !           628: 
        !           629:        case 0: /* reserved */
        !           630:        default:
        !           631:                plog(LLV_ERROR, LOCATION, NULL,
        !           632:                        "Invalid transform id: %u\n", t_id);
        !           633:                return ~0;
        !           634:        }
        !           635:        /*NOTREACHED*/
        !           636: }
        !           637: 
        !           638: /* IPSECDOI_PROTO -> SADB_SATYPE */
        !           639: u_int
        !           640: ipsecdoi2pfkey_proto(proto)
        !           641:        u_int proto;
        !           642: {
        !           643:        switch (proto) {
        !           644:        case IPSECDOI_PROTO_IPSEC_AH:
        !           645:                return SADB_SATYPE_AH;
        !           646:        case IPSECDOI_PROTO_IPSEC_ESP:
        !           647:                return SADB_SATYPE_ESP;
        !           648:        case IPSECDOI_PROTO_IPCOMP:
        !           649:                return SADB_X_SATYPE_IPCOMP;
        !           650: 
        !           651:        default:
        !           652:                plog(LLV_ERROR, LOCATION, NULL,
        !           653:                        "Invalid ipsec_doi proto: %u\n", proto);
        !           654:                return ~0;
        !           655:        }
        !           656:        /*NOTREACHED*/
        !           657: }
        !           658: 
        !           659: static u_int
        !           660: ipsecdoi2pfkey_alg(algclass, type)
        !           661:        u_int algclass, type;
        !           662: {
        !           663:        switch (algclass) {
        !           664:        case IPSECDOI_ATTR_AUTH:
        !           665:                return ipsecdoi2pfkey_aalg(type);
        !           666:        case IPSECDOI_PROTO_IPSEC_ESP:
        !           667:                return ipsecdoi2pfkey_ealg(type);
        !           668:        case IPSECDOI_PROTO_IPCOMP:
        !           669:                return ipsecdoi2pfkey_calg(type);
        !           670:        default:
        !           671:                plog(LLV_ERROR, LOCATION, NULL,
        !           672:                        "Invalid ipsec_doi algclass: %u\n", algclass);
        !           673:                return ~0;
        !           674:        }
        !           675:        /*NOTREACHED*/
        !           676: }
        !           677: 
        !           678: /* SADB_SATYPE -> IPSECDOI_PROTO */
        !           679: u_int
        !           680: pfkey2ipsecdoi_proto(satype)
        !           681:        u_int satype;
        !           682: {
        !           683:        switch (satype) {
        !           684:        case SADB_SATYPE_AH:
        !           685:                return IPSECDOI_PROTO_IPSEC_AH;
        !           686:        case SADB_SATYPE_ESP:
        !           687:                return IPSECDOI_PROTO_IPSEC_ESP;
        !           688:        case SADB_X_SATYPE_IPCOMP:
        !           689:                return IPSECDOI_PROTO_IPCOMP;
        !           690: 
        !           691:        default:
        !           692:                plog(LLV_ERROR, LOCATION, NULL,
        !           693:                        "Invalid pfkey proto: %u\n", satype);
        !           694:                return ~0;
        !           695:        }
        !           696:        /*NOTREACHED*/
        !           697: }
        !           698: 
        !           699: /* IPSECDOI_ATTR_ENC_MODE -> IPSEC_MODE */
        !           700: u_int
        !           701: ipsecdoi2pfkey_mode(mode)
        !           702:        u_int mode;
        !           703: {
        !           704:        switch (mode) {
        !           705:        case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
        !           706: #ifdef ENABLE_NATT
        !           707:        case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
        !           708:        case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
        !           709: #endif
        !           710:                return IPSEC_MODE_TUNNEL;
        !           711:        case IPSECDOI_ATTR_ENC_MODE_TRNS:
        !           712: #ifdef ENABLE_NATT
        !           713:        case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
        !           714:        case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
        !           715: #endif
        !           716:                return IPSEC_MODE_TRANSPORT;
        !           717:        default:
        !           718:                plog(LLV_ERROR, LOCATION, NULL, "Invalid mode type: %u\n", mode);
        !           719:                return ~0;
        !           720:        }
        !           721:        /*NOTREACHED*/
        !           722: }
        !           723: 
        !           724: /* IPSECDOI_ATTR_ENC_MODE -> IPSEC_MODE */
        !           725: u_int
        !           726: pfkey2ipsecdoi_mode(mode)
        !           727:        u_int mode;
        !           728: {
        !           729:        switch (mode) {
        !           730:        case IPSEC_MODE_TUNNEL:
        !           731:                return IPSECDOI_ATTR_ENC_MODE_TUNNEL;
        !           732:        case IPSEC_MODE_TRANSPORT:
        !           733:                return IPSECDOI_ATTR_ENC_MODE_TRNS;
        !           734:        case IPSEC_MODE_ANY:
        !           735:                return IPSECDOI_ATTR_ENC_MODE_ANY;
        !           736:        default:
        !           737:                plog(LLV_ERROR, LOCATION, NULL, "Invalid mode type: %u\n", mode);
        !           738:                return ~0;
        !           739:        }
        !           740:        /*NOTREACHED*/
        !           741: }
        !           742: 
        !           743: /* default key length for encryption algorithm */
        !           744: static u_int
        !           745: keylen_aalg(hashtype)
        !           746:        u_int hashtype;
        !           747: {
        !           748:        int res;
        !           749: 
        !           750:        if (hashtype == 0)
        !           751:                return SADB_AALG_NONE;
        !           752: 
        !           753:        res = alg_ipsec_hmacdef_hashlen(hashtype);
        !           754:        if (res == -1) {
        !           755:                plog(LLV_ERROR, LOCATION, NULL,
        !           756:                        "invalid hmac algorithm %u.\n", hashtype);
        !           757:                return ~0;
        !           758:        }
        !           759:        return res;
        !           760: }
        !           761: 
        !           762: /* default key length for encryption algorithm */
        !           763: static u_int
        !           764: keylen_ealg(enctype, encklen)
        !           765:        u_int enctype;
        !           766:        int encklen;
        !           767: {
        !           768:        int res;
        !           769: 
        !           770:        res = alg_ipsec_encdef_keylen(enctype, encklen);
        !           771:        if (res == -1) {
        !           772:                plog(LLV_ERROR, LOCATION, NULL,
        !           773:                        "invalid encryption algorithm %u.\n", enctype);
        !           774:                return ~0;
        !           775:        }
        !           776:        return res;
        !           777: }
        !           778: 
        !           779: void
        !           780: pk_fixup_sa_addresses(mhp)
        !           781:        caddr_t *mhp;
        !           782: {
        !           783:        struct sockaddr *src, *dst;
        !           784: 
        !           785:        src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
        !           786:        dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
        !           787:        set_port(src, PORT_ISAKMP);
        !           788:        set_port(dst, PORT_ISAKMP);
        !           789: 
        !           790: #ifdef ENABLE_NATT
        !           791:        if (PFKEY_ADDR_X_NATTYPE(mhp[SADB_X_EXT_NAT_T_TYPE])) {
        !           792:                /* NAT-T is enabled for this SADB entry; copy
        !           793:                 * the ports from NAT-T extensions */
        !           794:                if(mhp[SADB_X_EXT_NAT_T_SPORT] != NULL)
        !           795:                        set_port(src, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_SPORT]));
        !           796:                if(mhp[SADB_X_EXT_NAT_T_DPORT] != NULL)
        !           797:                        set_port(dst, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_DPORT]));
        !           798:        }
        !           799: #endif
        !           800: }
        !           801: 
        !           802: int
        !           803: pfkey_convertfromipsecdoi(proto_id, t_id, hashtype,
        !           804:                e_type, e_keylen, a_type, a_keylen, flags)
        !           805:        u_int proto_id;
        !           806:        u_int t_id;
        !           807:        u_int hashtype;
        !           808:        u_int *e_type;
        !           809:        u_int *e_keylen;
        !           810:        u_int *a_type;
        !           811:        u_int *a_keylen;
        !           812:        u_int *flags;
        !           813: {
        !           814:        *flags = 0;
        !           815:        switch (proto_id) {
        !           816:        case IPSECDOI_PROTO_IPSEC_ESP:
        !           817:                if ((*e_type = ipsecdoi2pfkey_ealg(t_id)) == ~0)
        !           818:                        goto bad;
        !           819:                if ((*e_keylen = keylen_ealg(t_id, *e_keylen)) == ~0)
        !           820:                        goto bad;
        !           821:                *e_keylen >>= 3;
        !           822: 
        !           823:                if ((*a_type = ipsecdoi2pfkey_aalg(hashtype)) == ~0)
        !           824:                        goto bad;
        !           825:                if ((*a_keylen = keylen_aalg(hashtype)) == ~0)
        !           826:                        goto bad;
        !           827:                *a_keylen >>= 3;
        !           828: 
        !           829:                if (*e_type == SADB_EALG_NONE) {
        !           830:                        plog(LLV_ERROR, LOCATION, NULL, "no ESP algorithm.\n");
        !           831:                        goto bad;
        !           832:                }
        !           833:                break;
        !           834: 
        !           835:        case IPSECDOI_PROTO_IPSEC_AH:
        !           836:                if ((*a_type = ipsecdoi2pfkey_aalg(hashtype)) == ~0)
        !           837:                        goto bad;
        !           838:                if ((*a_keylen = keylen_aalg(hashtype)) == ~0)
        !           839:                        goto bad;
        !           840:                *a_keylen >>= 3;
        !           841: 
        !           842:                if (t_id == IPSECDOI_ATTR_AUTH_HMAC_MD5
        !           843:                 && hashtype == IPSECDOI_ATTR_AUTH_KPDK) {
        !           844:                        /* AH_MD5 + Auth(KPDK) = RFC1826 keyed-MD5 */
        !           845:                        *a_type = SADB_X_AALG_MD5;
        !           846:                        *flags |= SADB_X_EXT_OLD;
        !           847:                }
        !           848:                *e_type = SADB_EALG_NONE;
        !           849:                *e_keylen = 0;
        !           850:                if (*a_type == SADB_AALG_NONE) {
        !           851:                        plog(LLV_ERROR, LOCATION, NULL, "no AH algorithm.\n");
        !           852:                        goto bad;
        !           853:                }
        !           854:                break;
        !           855: 
        !           856:        case IPSECDOI_PROTO_IPCOMP:
        !           857:                if ((*e_type = ipsecdoi2pfkey_calg(t_id)) == ~0)
        !           858:                        goto bad;
        !           859:                *e_keylen = 0;
        !           860: 
        !           861:                *flags = SADB_X_EXT_RAWCPI;
        !           862: 
        !           863:                *a_type = SADB_AALG_NONE;
        !           864:                *a_keylen = 0;
        !           865:                if (*e_type == SADB_X_CALG_NONE) {
        !           866:                        plog(LLV_ERROR, LOCATION, NULL, "no IPCOMP algorithm.\n");
        !           867:                        goto bad;
        !           868:                }
        !           869:                break;
        !           870: 
        !           871:        default:
        !           872:                plog(LLV_ERROR, LOCATION, NULL, "unknown IPsec protocol.\n");
        !           873:                goto bad;
        !           874:        }
        !           875: 
        !           876:        return 0;
        !           877: 
        !           878:     bad:
        !           879:        errno = EINVAL;
        !           880:        return -1;
        !           881: }
        !           882: 
        !           883: /*%%%*/
        !           884: /* send getspi message per ipsec protocol per remote address */
        !           885: /*
        !           886:  * the local address and remote address in ph1handle are dealed
        !           887:  * with destination address and source address respectively.
        !           888:  * Because SPI is decided by responder.
        !           889:  */
        !           890: int
        !           891: pk_sendgetspi(iph2)
        !           892:        struct ph2handle *iph2;
        !           893: {
        !           894:        struct sockaddr *src = NULL, *dst = NULL;
        !           895:        u_int satype, mode;
        !           896:        struct saprop *pp;
        !           897:        struct saproto *pr;
        !           898:        u_int32_t minspi, maxspi;
        !           899:        u_int8_t natt_type = 0;
        !           900:        u_int16_t sport = 0, dport = 0;
        !           901: 
        !           902:        if (iph2->side == INITIATOR)
        !           903:                pp = iph2->proposal;
        !           904:        else
        !           905:                pp = iph2->approval;
        !           906: 
        !           907:        if (iph2->sa_src && iph2->sa_dst) {
        !           908:                /* MIPv6: Use SA addresses, not IKE ones */
        !           909:                src = dupsaddr(iph2->sa_src);
        !           910:                dst = dupsaddr(iph2->sa_dst);
        !           911:        } else {
        !           912:                /* Common case: SA addresses and IKE ones are the same */
        !           913:                src = dupsaddr(iph2->src);
        !           914:                dst = dupsaddr(iph2->dst);
        !           915:        }
        !           916: 
        !           917:        if (src == NULL || dst == NULL) {
        !           918:                racoon_free(src);
        !           919:                racoon_free(dst);
        !           920:                return -1;
        !           921:        }
        !           922: 
        !           923:        for (pr = pp->head; pr != NULL; pr = pr->next) {
        !           924: 
        !           925:                /* validity check */
        !           926:                satype = ipsecdoi2pfkey_proto(pr->proto_id);
        !           927:                if (satype == ~0) {
        !           928:                        plog(LLV_ERROR, LOCATION, NULL,
        !           929:                                "invalid proto_id %d\n", pr->proto_id);
        !           930:                        racoon_free(src);
        !           931:                        racoon_free(dst);
        !           932:                        return -1;
        !           933:                }
        !           934:                /* this works around a bug in Linux kernel where it allocates 4 byte
        !           935:                   spi's for IPCOMP */
        !           936:                else if (satype == SADB_X_SATYPE_IPCOMP) {
        !           937:                        minspi = 0x100;
        !           938:                        maxspi = 0xffff;
        !           939:                }
        !           940:                else {
        !           941:                        minspi = 0;
        !           942:                        maxspi = 0;
        !           943:                }
        !           944:                mode = ipsecdoi2pfkey_mode(pr->encmode);
        !           945:                if (mode == ~0) {
        !           946:                        plog(LLV_ERROR, LOCATION, NULL,
        !           947:                                "invalid encmode %d\n", pr->encmode);
        !           948:                        racoon_free(src);
        !           949:                        racoon_free(dst);
        !           950:                        return -1;
        !           951:                }
        !           952: 
        !           953: #ifdef ENABLE_NATT
        !           954:                if (pr->udp_encap) {
        !           955:                        natt_type = iph2->ph1->natt_options->encaps_type;
        !           956:                        sport=extract_port(src);
        !           957:                        dport=extract_port(dst);
        !           958:                }
        !           959: #endif
        !           960: 
        !           961:                plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_getspi\n");
        !           962:                if (pfkey_send_getspi_nat(
        !           963:                                lcconf->sock_pfkey,
        !           964:                                satype,
        !           965:                                mode,
        !           966:                                dst,                    /* src of SA */
        !           967:                                src,                    /* dst of SA */
        !           968:                                natt_type,
        !           969:                                dport,
        !           970:                                sport,
        !           971:                                minspi, maxspi,
        !           972:                                pr->reqid_in, iph2->seq) < 0) {
        !           973:                        plog(LLV_ERROR, LOCATION, NULL,
        !           974:                                "ipseclib failed send getspi (%s)\n",
        !           975:                                ipsec_strerror());
        !           976:                        racoon_free(src);
        !           977:                        racoon_free(dst);
        !           978:                        return -1;
        !           979:                }
        !           980:                plog(LLV_DEBUG, LOCATION, NULL,
        !           981:                        "pfkey GETSPI sent: %s\n",
        !           982:                        sadbsecas2str(dst, src, satype, 0, mode));
        !           983:        }
        !           984: 
        !           985:        racoon_free(src);
        !           986:        racoon_free(dst);
        !           987:        return 0;
        !           988: }
        !           989: 
        !           990: /*
        !           991:  * receive GETSPI from kernel.
        !           992:  */
        !           993: static int
        !           994: pk_recvgetspi(mhp)
        !           995:        caddr_t *mhp;
        !           996: {
        !           997:        struct sadb_msg *msg;
        !           998:        struct sadb_sa *sa;
        !           999:        struct ph2handle *iph2;
        !          1000:        struct sockaddr *src, *dst;
        !          1001:        int proto_id;
        !          1002:        int allspiok, notfound;
        !          1003:        struct saprop *pp;
        !          1004:        struct saproto *pr;
        !          1005: 
        !          1006:        /* validity check */
        !          1007:        if (mhp[SADB_EXT_SA] == NULL
        !          1008:         || mhp[SADB_EXT_ADDRESS_DST] == NULL
        !          1009:         || mhp[SADB_EXT_ADDRESS_SRC] == NULL) {
        !          1010:                plog(LLV_ERROR, LOCATION, NULL,
        !          1011:                        "inappropriate sadb getspi message passed.\n");
        !          1012:                return -1;
        !          1013:        }
        !          1014:        msg = (struct sadb_msg *)mhp[0];
        !          1015:        sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
        !          1016:        pk_fixup_sa_addresses(mhp);
        !          1017:        dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); /* note SA dir */
        !          1018:        src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
        !          1019: 
        !          1020:        /* the message has to be processed or not ? */
        !          1021:        if (msg->sadb_msg_pid != getpid()) {
        !          1022:                plog(LLV_DEBUG, LOCATION, NULL,
        !          1023:                        "%s message is not interesting "
        !          1024:                        "because pid %d is not mine.\n",
        !          1025:                        s_pfkey_type(msg->sadb_msg_type),
        !          1026:                        msg->sadb_msg_pid);
        !          1027:                return -1;
        !          1028:        }
        !          1029: 
        !          1030:        iph2 = getph2byseq(msg->sadb_msg_seq);
        !          1031:        if (iph2 == NULL) {
        !          1032:                plog(LLV_DEBUG, LOCATION, NULL,
        !          1033:                        "seq %d of %s message not interesting.\n",
        !          1034:                        msg->sadb_msg_seq,
        !          1035:                        s_pfkey_type(msg->sadb_msg_type));
        !          1036:                return -1;
        !          1037:        }
        !          1038: 
        !          1039:        if (iph2->status != PHASE2ST_GETSPISENT) {
        !          1040:                plog(LLV_ERROR, LOCATION, NULL,
        !          1041:                        "status mismatch (db:%d msg:%d)\n",
        !          1042:                        iph2->status, PHASE2ST_GETSPISENT);
        !          1043:                return -1;
        !          1044:        }
        !          1045: 
        !          1046:        /* set SPI, and check to get all spi whether or not */
        !          1047:        allspiok = 1;
        !          1048:        notfound = 1;
        !          1049:        proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
        !          1050:        pp = iph2->side == INITIATOR ? iph2->proposal : iph2->approval;
        !          1051: 
        !          1052:        for (pr = pp->head; pr != NULL; pr = pr->next) {
        !          1053:                if (pr->proto_id == proto_id && pr->spi == 0) {
        !          1054:                        pr->spi = sa->sadb_sa_spi;
        !          1055:                        notfound = 0;
        !          1056:                        plog(LLV_DEBUG, LOCATION, NULL,
        !          1057:                                "pfkey GETSPI succeeded: %s\n",
        !          1058:                                sadbsecas2str(dst, src,
        !          1059:                                    msg->sadb_msg_satype,
        !          1060:                                    sa->sadb_sa_spi,
        !          1061:                                    ipsecdoi2pfkey_mode(pr->encmode)));
        !          1062:                }
        !          1063:                if (pr->spi == 0)
        !          1064:                        allspiok = 0;   /* not get all spi */
        !          1065:        }
        !          1066: 
        !          1067:        if (notfound) {
        !          1068:                plog(LLV_ERROR, LOCATION, NULL,
        !          1069:                        "get spi for unknown address %s\n",
        !          1070:                        saddrwop2str(dst));
        !          1071:                return -1;
        !          1072:        }
        !          1073: 
        !          1074:        if (allspiok) {
        !          1075:                /* update status */
        !          1076:                iph2->status = PHASE2ST_GETSPIDONE;
        !          1077:                if (isakmp_post_getspi(iph2) < 0) {
        !          1078:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1079:                                "failed to start post getspi.\n");
        !          1080:                        remph2(iph2);
        !          1081:                        delph2(iph2);
        !          1082:                        iph2 = NULL;
        !          1083:                        return -1;
        !          1084:                }
        !          1085:        }
        !          1086: 
        !          1087:        return 0;
        !          1088: }
        !          1089: 
        !          1090: /*
        !          1091:  * set inbound SA
        !          1092:  */
        !          1093: int
        !          1094: pk_sendupdate(iph2)
        !          1095:        struct ph2handle *iph2;
        !          1096: {
        !          1097:        struct saproto *pr;
        !          1098:        struct pfkey_send_sa_args sa_args;
        !          1099: 
        !          1100:        /* sanity check */
        !          1101:        if (iph2->approval == NULL) {
        !          1102:                plog(LLV_ERROR, LOCATION, NULL,
        !          1103:                        "no approvaled SAs found.\n");
        !          1104:                return -1;
        !          1105:        }
        !          1106: 
        !          1107:        /* fill in some needed for pfkey_send_update2 */
        !          1108:        memset (&sa_args, 0, sizeof (sa_args));
        !          1109:        sa_args.so = lcconf->sock_pfkey;
        !          1110:        if (iph2->lifetime_secs)
        !          1111:                sa_args.l_addtime = iph2->lifetime_secs;
        !          1112:        else
        !          1113:                sa_args.l_addtime = iph2->approval->lifetime;
        !          1114:        sa_args.seq = iph2->seq;
        !          1115:        sa_args.wsize = 4;
        !          1116: 
        !          1117:        if (iph2->sa_src && iph2->sa_dst) {
        !          1118:                /* MIPv6: Use SA addresses, not IKE ones */
        !          1119:                sa_args.dst = dupsaddr(iph2->sa_src);
        !          1120:                sa_args.src = dupsaddr(iph2->sa_dst);
        !          1121:        } else {
        !          1122:                /* Common case: SA addresses and IKE ones are the same */
        !          1123:                sa_args.dst = dupsaddr(iph2->src);
        !          1124:                sa_args.src = dupsaddr(iph2->dst);
        !          1125:        }
        !          1126: 
        !          1127:        if (sa_args.src == NULL || sa_args.dst == NULL) {
        !          1128:                racoon_free(sa_args.src);
        !          1129:                racoon_free(sa_args.dst);
        !          1130:                return -1;
        !          1131:        }
        !          1132: 
        !          1133:        for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
        !          1134:                /* validity check */
        !          1135:                sa_args.satype = ipsecdoi2pfkey_proto(pr->proto_id);
        !          1136:                if (sa_args.satype == ~0) {
        !          1137:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1138:                                "invalid proto_id %d\n", pr->proto_id);
        !          1139:                        racoon_free(sa_args.src);
        !          1140:                        racoon_free(sa_args.dst);
        !          1141:                        return -1;
        !          1142:                }
        !          1143:                else if (sa_args.satype == SADB_X_SATYPE_IPCOMP) {
        !          1144:                        /* IPCOMP has no replay window */
        !          1145:                        sa_args.wsize = 0;
        !          1146:                }
        !          1147: #ifdef ENABLE_SAMODE_UNSPECIFIED
        !          1148:                sa_args.mode = IPSEC_MODE_ANY;
        !          1149: #else
        !          1150:                sa_args.mode = ipsecdoi2pfkey_mode(pr->encmode);
        !          1151:                if (sa_args.mode == ~0) {
        !          1152:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1153:                                "invalid encmode %d\n", pr->encmode);
        !          1154:                        racoon_free(sa_args.src);
        !          1155:                        racoon_free(sa_args.dst);
        !          1156:                        return -1;
        !          1157:                }
        !          1158: #endif
        !          1159:                /* set algorithm type and key length */
        !          1160:                sa_args.e_keylen = pr->head->encklen;
        !          1161:                if (pfkey_convertfromipsecdoi(
        !          1162:                                pr->proto_id,
        !          1163:                                pr->head->trns_id,
        !          1164:                                pr->head->authtype,
        !          1165:                                &sa_args.e_type, &sa_args.e_keylen,
        !          1166:                                &sa_args.a_type, &sa_args.a_keylen,
        !          1167:                                &sa_args.flags) < 0){
        !          1168:                        racoon_free(sa_args.src);
        !          1169:                        racoon_free(sa_args.dst);
        !          1170:                        return -1;
        !          1171:                }
        !          1172: 
        !          1173: #if 0
        !          1174:                sa_args.l_bytes = iph2->approval->lifebyte * 1024,
        !          1175: #else
        !          1176:                sa_args.l_bytes = 0;
        !          1177: #endif
        !          1178: 
        !          1179: #ifdef HAVE_SECCTX
        !          1180:                if (*iph2->approval->sctx.ctx_str) {
        !          1181:                        sa_args.ctxdoi = iph2->approval->sctx.ctx_doi;
        !          1182:                        sa_args.ctxalg = iph2->approval->sctx.ctx_alg;
        !          1183:                        sa_args.ctxstrlen = iph2->approval->sctx.ctx_strlen;
        !          1184:                        sa_args.ctxstr = iph2->approval->sctx.ctx_str;
        !          1185:                }
        !          1186: #endif /* HAVE_SECCTX */
        !          1187: 
        !          1188: #ifdef ENABLE_NATT
        !          1189:                if (pr->udp_encap) {
        !          1190:                        sa_args.l_natt_type = iph2->ph1->natt_options->encaps_type;
        !          1191:                        sa_args.l_natt_sport = extract_port(iph2->ph1->remote);
        !          1192:                        sa_args.l_natt_dport = extract_port(iph2->ph1->local);
        !          1193:                        sa_args.l_natt_oa = iph2->natoa_src;
        !          1194: #ifdef SADB_X_EXT_NAT_T_FRAG
        !          1195:                        sa_args.l_natt_frag = iph2->ph1->rmconf->esp_frag;
        !          1196: #endif
        !          1197:                }
        !          1198: #endif
        !          1199: 
        !          1200:                /* more info to fill in */
        !          1201:                sa_args.spi = pr->spi;
        !          1202:                sa_args.reqid = pr->reqid_in;
        !          1203:                sa_args.keymat = pr->keymat->v;
        !          1204: 
        !          1205:                plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_update2\n");
        !          1206:                if (pfkey_send_update2(&sa_args) < 0) {
        !          1207:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1208:                                "libipsec failed send update (%s)\n",
        !          1209:                                ipsec_strerror());
        !          1210:                        racoon_free(sa_args.src);
        !          1211:                        racoon_free(sa_args.dst);
        !          1212:                        return -1;
        !          1213:                }
        !          1214: 
        !          1215:                if (!lcconf->pathinfo[LC_PATHTYPE_BACKUPSA])
        !          1216:                        continue;
        !          1217: 
        !          1218:                /*
        !          1219:                 * It maybe good idea to call backupsa_to_file() after
        !          1220:                 * racoon will receive the sadb_update messages.
        !          1221:                 * But it is impossible because there is not key in the
        !          1222:                 * information from the kernel.
        !          1223:                 */
        !          1224: 
        !          1225:                /* change some things before backing up */
        !          1226:                sa_args.wsize = 4;
        !          1227:                sa_args.l_bytes = iph2->approval->lifebyte * 1024;
        !          1228: 
        !          1229:                if (backupsa_to_file(&sa_args) < 0) {
        !          1230:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1231:                                "backuped SA failed: %s\n",
        !          1232:                                sadbsecas2str(sa_args.src, sa_args.dst,
        !          1233:                                sa_args.satype, sa_args.spi, sa_args.mode));
        !          1234:                }
        !          1235:                plog(LLV_DEBUG, LOCATION, NULL,
        !          1236:                        "backuped SA: %s\n",
        !          1237:                        sadbsecas2str(sa_args.src, sa_args.dst,
        !          1238:                        sa_args.satype, sa_args.spi, sa_args.mode));
        !          1239:        }
        !          1240: 
        !          1241:        racoon_free(sa_args.src);
        !          1242:        racoon_free(sa_args.dst);
        !          1243:        return 0;
        !          1244: }
        !          1245: 
        !          1246: static int
        !          1247: pk_recvupdate(mhp)
        !          1248:        caddr_t *mhp;
        !          1249: {
        !          1250:        struct sadb_msg *msg;
        !          1251:        struct sadb_sa *sa;
        !          1252:        struct sockaddr *src, *dst;
        !          1253:        struct ph2handle *iph2;
        !          1254:        u_int proto_id, encmode, sa_mode;
        !          1255:        int incomplete = 0;
        !          1256:        struct saproto *pr;
        !          1257: 
        !          1258:        /* ignore this message because of local test mode. */
        !          1259:        if (f_local)
        !          1260:                return 0;
        !          1261: 
        !          1262:        /* sanity check */
        !          1263:        if (mhp[0] == NULL
        !          1264:         || mhp[SADB_EXT_SA] == NULL
        !          1265:         || mhp[SADB_EXT_ADDRESS_SRC] == NULL
        !          1266:         || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
        !          1267:                plog(LLV_ERROR, LOCATION, NULL,
        !          1268:                        "inappropriate sadb update message passed.\n");
        !          1269:                return -1;
        !          1270:        }
        !          1271:        msg = (struct sadb_msg *)mhp[0];
        !          1272:        pk_fixup_sa_addresses(mhp);
        !          1273:        src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
        !          1274:        dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
        !          1275:        sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
        !          1276: 
        !          1277:        sa_mode = mhp[SADB_X_EXT_SA2] == NULL
        !          1278:                ? IPSEC_MODE_ANY
        !          1279:                : ((struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
        !          1280: 
        !          1281:        /* the message has to be processed or not ? */
        !          1282:        if (msg->sadb_msg_pid != getpid()) {
        !          1283:                plog(LLV_DEBUG, LOCATION, NULL,
        !          1284:                        "%s message is not interesting "
        !          1285:                        "because pid %d is not mine.\n",
        !          1286:                        s_pfkey_type(msg->sadb_msg_type),
        !          1287:                        msg->sadb_msg_pid);
        !          1288:                return -1;
        !          1289:        }
        !          1290: 
        !          1291:        iph2 = getph2byseq(msg->sadb_msg_seq);
        !          1292:        if (iph2 == NULL) {
        !          1293:                plog(LLV_DEBUG, LOCATION, NULL,
        !          1294:                        "seq %d of %s message not interesting.\n",
        !          1295:                        msg->sadb_msg_seq,
        !          1296:                        s_pfkey_type(msg->sadb_msg_type));
        !          1297:                return -1;
        !          1298:        }
        !          1299: 
        !          1300:        if (iph2->status != PHASE2ST_ADDSA) {
        !          1301:                plog(LLV_ERROR, LOCATION, NULL,
        !          1302:                        "status mismatch (db:%d msg:%d)\n",
        !          1303:                        iph2->status, PHASE2ST_ADDSA);
        !          1304:                return -1;
        !          1305:        }
        !          1306: 
        !          1307:        /* check to complete all keys ? */
        !          1308:        for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
        !          1309:                proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
        !          1310:                if (proto_id == ~0) {
        !          1311:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1312:                                "invalid proto_id %d\n", msg->sadb_msg_satype);
        !          1313:                        return -1;
        !          1314:                }
        !          1315:                encmode = pfkey2ipsecdoi_mode(sa_mode);
        !          1316:                if (encmode == ~0) {
        !          1317:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1318:                                "invalid encmode %d\n", sa_mode);
        !          1319:                        return -1;
        !          1320:                }
        !          1321: 
        !          1322:                if (pr->proto_id == proto_id
        !          1323:                 && pr->spi == sa->sadb_sa_spi) {
        !          1324:                        pr->ok = 1;
        !          1325:                        plog(LLV_DEBUG, LOCATION, NULL,
        !          1326:                                "pfkey UPDATE succeeded: %s\n",
        !          1327:                                sadbsecas2str(dst, src,
        !          1328:                                    msg->sadb_msg_satype,
        !          1329:                                    sa->sadb_sa_spi,
        !          1330:                                    sa_mode));
        !          1331: 
        !          1332:                        plog(LLV_INFO, LOCATION, NULL,
        !          1333:                                "IPsec-SA established: %s\n",
        !          1334:                                sadbsecas2str(dst, src,
        !          1335:                                        msg->sadb_msg_satype, sa->sadb_sa_spi,
        !          1336:                                        sa_mode));
        !          1337:                }
        !          1338: 
        !          1339:                if (pr->ok == 0)
        !          1340:                        incomplete = 1;
        !          1341:        }
        !          1342: 
        !          1343:        if (incomplete)
        !          1344:                return 0;
        !          1345: 
        !          1346:        /* turn off the timer for calling pfkey_timeover() */
        !          1347:        sched_cancel(&iph2->sce);
        !          1348: 
        !          1349:        /* update status */
        !          1350:        iph2->status = PHASE2ST_ESTABLISHED;
        !          1351:        evt_phase2(iph2, EVT_PHASE2_UP, NULL);
        !          1352: 
        !          1353: #ifdef ENABLE_STATS
        !          1354:        gettimeofday(&iph2->end, NULL);
        !          1355:        syslog(LOG_NOTICE, "%s(%s): %8.6f",
        !          1356:                "phase2", "quick", timedelta(&iph2->start, &iph2->end));
        !          1357: #endif
        !          1358: 
        !          1359:        /* turn off schedule */
        !          1360:        sched_cancel(&iph2->scr);
        !          1361: 
        !          1362:        /*
        !          1363:         * since we are going to reuse the phase2 handler, we need to
        !          1364:         * remain it and refresh all the references between ph1 and ph2 to use.
        !          1365:         */
        !          1366:        sched_schedule(&iph2->sce, iph2->approval->lifetime,
        !          1367:                       isakmp_ph2expire_stub);
        !          1368: 
        !          1369:        plog(LLV_DEBUG, LOCATION, NULL, "===\n");
        !          1370:        return 0;
        !          1371: }
        !          1372: 
        !          1373: /*
        !          1374:  * set outbound SA
        !          1375:  */
        !          1376: int
        !          1377: pk_sendadd(iph2)
        !          1378:        struct ph2handle *iph2;
        !          1379: {
        !          1380:        struct saproto *pr;
        !          1381:        struct pfkey_send_sa_args sa_args;
        !          1382: 
        !          1383:        /* sanity check */
        !          1384:        if (iph2->approval == NULL) {
        !          1385:                plog(LLV_ERROR, LOCATION, NULL,
        !          1386:                        "no approvaled SAs found.\n");
        !          1387:                return -1;
        !          1388:        }
        !          1389: 
        !          1390:        /* fill in some needed for pfkey_send_update2 */
        !          1391:        memset (&sa_args, 0, sizeof (sa_args));
        !          1392:        sa_args.so = lcconf->sock_pfkey;
        !          1393:        if (iph2->lifetime_secs)
        !          1394:                sa_args.l_addtime = iph2->lifetime_secs;
        !          1395:        else
        !          1396:                sa_args.l_addtime = iph2->approval->lifetime;
        !          1397:        sa_args.seq = iph2->seq;
        !          1398:        sa_args.wsize = 4;
        !          1399: 
        !          1400:        if (iph2->sa_src && iph2->sa_dst) {
        !          1401:                /* MIPv6: Use SA addresses, not IKE ones */
        !          1402:                sa_args.src = dupsaddr(iph2->sa_src);
        !          1403:                sa_args.dst = dupsaddr(iph2->sa_dst);
        !          1404:        } else {
        !          1405:                /* Common case: SA addresses and IKE ones are the same */
        !          1406:                sa_args.src = dupsaddr(iph2->src);
        !          1407:                sa_args.dst = dupsaddr(iph2->dst);
        !          1408:        }
        !          1409: 
        !          1410:        if (sa_args.src == NULL || sa_args.dst == NULL) {
        !          1411:                racoon_free(sa_args.src);
        !          1412:                racoon_free(sa_args.dst);
        !          1413:                return -1;
        !          1414:        }
        !          1415: 
        !          1416:        for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
        !          1417:                /* validity check */
        !          1418:                sa_args.satype = ipsecdoi2pfkey_proto(pr->proto_id);
        !          1419:                if (sa_args.satype == ~0) {
        !          1420:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1421:                                "invalid proto_id %d\n", pr->proto_id);
        !          1422:                        racoon_free(sa_args.src);
        !          1423:                        racoon_free(sa_args.dst);
        !          1424:                        return -1;
        !          1425:                }
        !          1426:                else if (sa_args.satype == SADB_X_SATYPE_IPCOMP) {
        !          1427:                        /* no replay window for IPCOMP */
        !          1428:                        sa_args.wsize = 0;
        !          1429:                }
        !          1430: #ifdef ENABLE_SAMODE_UNSPECIFIED
        !          1431:                sa_args.mode = IPSEC_MODE_ANY;
        !          1432: #else
        !          1433:                sa_args.mode = ipsecdoi2pfkey_mode(pr->encmode);
        !          1434:                if (sa_args.mode == ~0) {
        !          1435:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1436:                                "invalid encmode %d\n", pr->encmode);
        !          1437:                        racoon_free(sa_args.src);
        !          1438:                        racoon_free(sa_args.dst);
        !          1439:                        return -1;
        !          1440:                }
        !          1441: #endif
        !          1442: 
        !          1443:                /* set algorithm type and key length */
        !          1444:                sa_args.e_keylen = pr->head->encklen;
        !          1445:                if (pfkey_convertfromipsecdoi(
        !          1446:                                pr->proto_id,
        !          1447:                                pr->head->trns_id,
        !          1448:                                pr->head->authtype,
        !          1449:                                &sa_args.e_type, &sa_args.e_keylen,
        !          1450:                                &sa_args.a_type, &sa_args.a_keylen,
        !          1451:                                &sa_args.flags) < 0){
        !          1452:                        racoon_free(sa_args.src);
        !          1453:                        racoon_free(sa_args.dst);
        !          1454:                        return -1;
        !          1455:                }
        !          1456: 
        !          1457: #if 0
        !          1458:                sa_args.l_bytes = iph2->approval->lifebyte * 1024,
        !          1459: #else
        !          1460:                sa_args.l_bytes = 0;
        !          1461: #endif
        !          1462: 
        !          1463: #ifdef HAVE_SECCTX
        !          1464:                if (*iph2->approval->sctx.ctx_str) {
        !          1465:                        sa_args.ctxdoi = iph2->approval->sctx.ctx_doi;
        !          1466:                        sa_args.ctxalg = iph2->approval->sctx.ctx_alg;
        !          1467:                        sa_args.ctxstrlen = iph2->approval->sctx.ctx_strlen;
        !          1468:                        sa_args.ctxstr = iph2->approval->sctx.ctx_str;
        !          1469:                }
        !          1470: #endif /* HAVE_SECCTX */
        !          1471: 
        !          1472: #ifdef ENABLE_NATT
        !          1473:                plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_add2 "
        !          1474:                    "(NAT flavor)\n");
        !          1475: 
        !          1476:                if (pr->udp_encap) {
        !          1477:                        sa_args.l_natt_type = UDP_ENCAP_ESPINUDP;
        !          1478:                        sa_args.l_natt_sport = extract_port(iph2->ph1->local);
        !          1479:                        sa_args.l_natt_dport = extract_port(iph2->ph1->remote);
        !          1480:                        sa_args.l_natt_oa = iph2->natoa_dst;
        !          1481: #ifdef SADB_X_EXT_NAT_T_FRAG
        !          1482:                        sa_args.l_natt_frag = iph2->ph1->rmconf->esp_frag;
        !          1483: #endif
        !          1484:                }
        !          1485: #endif
        !          1486:                /* more info to fill in */
        !          1487:                sa_args.spi = pr->spi_p;
        !          1488:                sa_args.reqid = pr->reqid_out;
        !          1489:                sa_args.keymat = pr->keymat_p->v;
        !          1490: 
        !          1491:                plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_add2\n");
        !          1492:                if (pfkey_send_add2(&sa_args) < 0) {
        !          1493:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1494:                                "libipsec failed send add (%s)\n",
        !          1495:                                ipsec_strerror());
        !          1496:                        racoon_free(sa_args.src);
        !          1497:                        racoon_free(sa_args.dst);
        !          1498:                        return -1;
        !          1499:                }
        !          1500: 
        !          1501:                if (!lcconf->pathinfo[LC_PATHTYPE_BACKUPSA])
        !          1502:                        continue;
        !          1503: 
        !          1504:                /*
        !          1505:                 * It maybe good idea to call backupsa_to_file() after
        !          1506:                 * racoon will receive the sadb_update messages.
        !          1507:                 * But it is impossible because there is not key in the
        !          1508:                 * information from the kernel.
        !          1509:                 */
        !          1510:                if (backupsa_to_file(&sa_args) < 0) {
        !          1511:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1512:                                "backuped SA failed: %s\n",
        !          1513:                                sadbsecas2str(sa_args.src, sa_args.dst,
        !          1514:                                sa_args.satype, sa_args.spi, sa_args.mode));
        !          1515:                }
        !          1516:                plog(LLV_DEBUG, LOCATION, NULL,
        !          1517:                        "backuped SA: %s\n",
        !          1518:                        sadbsecas2str(sa_args.src, sa_args.dst,
        !          1519:                        sa_args.satype, sa_args.spi, sa_args.mode));
        !          1520:        }
        !          1521:        racoon_free(sa_args.src);
        !          1522:        racoon_free(sa_args.dst);
        !          1523:        return 0;
        !          1524: }
        !          1525: 
        !          1526: static int
        !          1527: pk_recvadd(mhp)
        !          1528:        caddr_t *mhp;
        !          1529: {
        !          1530:        struct sadb_msg *msg;
        !          1531:        struct sadb_sa *sa;
        !          1532:        struct sockaddr *src, *dst;
        !          1533:        struct ph2handle *iph2;
        !          1534:        u_int sa_mode;
        !          1535: 
        !          1536:        /* ignore this message because of local test mode. */
        !          1537:        if (f_local)
        !          1538:                return 0;
        !          1539: 
        !          1540:        /* sanity check */
        !          1541:        if (mhp[0] == NULL
        !          1542:         || mhp[SADB_EXT_SA] == NULL
        !          1543:         || mhp[SADB_EXT_ADDRESS_SRC] == NULL
        !          1544:         || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
        !          1545:                plog(LLV_ERROR, LOCATION, NULL,
        !          1546:                        "inappropriate sadb add message passed.\n");
        !          1547:                return -1;
        !          1548:        }
        !          1549:        msg = (struct sadb_msg *)mhp[0];
        !          1550:        pk_fixup_sa_addresses(mhp);
        !          1551:        src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
        !          1552:        dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
        !          1553:        sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
        !          1554: 
        !          1555:        sa_mode = mhp[SADB_X_EXT_SA2] == NULL
        !          1556:                ? IPSEC_MODE_ANY
        !          1557:                : ((struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
        !          1558: 
        !          1559:        /* the message has to be processed or not ? */
        !          1560:        if (msg->sadb_msg_pid != getpid()) {
        !          1561:                plog(LLV_DEBUG, LOCATION, NULL,
        !          1562:                        "%s message is not interesting "
        !          1563:                        "because pid %d is not mine.\n",
        !          1564:                        s_pfkey_type(msg->sadb_msg_type),
        !          1565:                        msg->sadb_msg_pid);
        !          1566:                return -1;
        !          1567:        }
        !          1568: 
        !          1569:        iph2 = getph2byseq(msg->sadb_msg_seq);
        !          1570:        if (iph2 == NULL) {
        !          1571:                plog(LLV_DEBUG, LOCATION, NULL,
        !          1572:                        "seq %d of %s message not interesting.\n",
        !          1573:                        msg->sadb_msg_seq,
        !          1574:                        s_pfkey_type(msg->sadb_msg_type));
        !          1575:                return -1;
        !          1576:        }
        !          1577: 
        !          1578:        /*
        !          1579:         * NOTE don't update any status of phase2 handle
        !          1580:         * because they must be updated by SADB_UPDATE message
        !          1581:         */
        !          1582: 
        !          1583:        plog(LLV_INFO, LOCATION, NULL,
        !          1584:                "IPsec-SA established: %s\n",
        !          1585:                sadbsecas2str(src, dst,
        !          1586:                        msg->sadb_msg_satype, sa->sadb_sa_spi, sa_mode));
        !          1587: 
        !          1588:        plog(LLV_DEBUG, LOCATION, NULL, "===\n");
        !          1589:        return 0;
        !          1590: }
        !          1591: 
        !          1592: static int
        !          1593: pk_recvexpire(mhp)
        !          1594:        caddr_t *mhp;
        !          1595: {
        !          1596:        struct sadb_msg *msg;
        !          1597:        struct sadb_sa *sa;
        !          1598:        struct sockaddr *src, *dst;
        !          1599:        struct ph2handle *iph2;
        !          1600:        u_int proto_id, sa_mode;
        !          1601: 
        !          1602:        /* sanity check */
        !          1603:        if (mhp[0] == NULL
        !          1604:         || mhp[SADB_EXT_SA] == NULL
        !          1605:         || mhp[SADB_EXT_ADDRESS_SRC] == NULL
        !          1606:         || mhp[SADB_EXT_ADDRESS_DST] == NULL
        !          1607:         || (mhp[SADB_EXT_LIFETIME_HARD] != NULL
        !          1608:          && mhp[SADB_EXT_LIFETIME_SOFT] != NULL)) {
        !          1609:                plog(LLV_ERROR, LOCATION, NULL,
        !          1610:                        "inappropriate sadb expire message passed.\n");
        !          1611:                return -1;
        !          1612:        }
        !          1613:        msg = (struct sadb_msg *)mhp[0];
        !          1614:        sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
        !          1615:        pk_fixup_sa_addresses(mhp);
        !          1616:        src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
        !          1617:        dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
        !          1618: 
        !          1619:        sa_mode = mhp[SADB_X_EXT_SA2] == NULL
        !          1620:                ? IPSEC_MODE_ANY
        !          1621:                : ((struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
        !          1622: 
        !          1623:        proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
        !          1624:        if (proto_id == ~0) {
        !          1625:                plog(LLV_ERROR, LOCATION, NULL,
        !          1626:                        "invalid proto_id %d\n", msg->sadb_msg_satype);
        !          1627:                return -1;
        !          1628:        }
        !          1629: 
        !          1630:        plog(LLV_INFO, LOCATION, NULL,
        !          1631:                "IPsec-SA expired: %s\n",
        !          1632:                sadbsecas2str(src, dst,
        !          1633:                        msg->sadb_msg_satype, sa->sadb_sa_spi, sa_mode));
        !          1634: 
        !          1635:        iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
        !          1636:        if (iph2 == NULL) {
        !          1637:                /*
        !          1638:                 * Ignore it because two expire messages are come up.
        !          1639:                 * phase2 handler has been deleted already when 2nd message
        !          1640:                 * is received.
        !          1641:                 */
        !          1642:                plog(LLV_DEBUG, LOCATION, NULL,
        !          1643:                        "no such a SA found: %s\n",
        !          1644:                        sadbsecas2str(src, dst,
        !          1645:                            msg->sadb_msg_satype, sa->sadb_sa_spi,
        !          1646:                            sa_mode));
        !          1647:                return 0;
        !          1648:        }
        !          1649: 
        !          1650:        /* resent expiry message? */
        !          1651:        if (iph2->status > PHASE2ST_ESTABLISHED)
        !          1652:                return 0;
        !          1653: 
        !          1654:        /* still negotiating? */
        !          1655:        if (iph2->status < PHASE2ST_ESTABLISHED) {
        !          1656:                /* not a hard timeout? */
        !          1657:                if (mhp[SADB_EXT_LIFETIME_HARD] == NULL)
        !          1658:                        return 0;
        !          1659: 
        !          1660:                /*
        !          1661:                 * We were negotiating for that SA (w/o much success
        !          1662:                 * from current status) and kernel has decided our time
        !          1663:                 * is over trying (xfrm_larval_drop controls that and
        !          1664:                 * is enabled by default on Linux >= 2.6.28 kernels).
        !          1665:                 */
        !          1666:                plog(LLV_WARNING, LOCATION, NULL,
        !          1667:                     "PF_KEY EXPIRE message received from kernel for SA"
        !          1668:                     " being negotiated. Stopping negotiation.\n");
        !          1669:        }
        !          1670: 
        !          1671:        /* turn off the timer for calling isakmp_ph2expire() */
        !          1672:        sched_cancel(&iph2->sce);
        !          1673: 
        !          1674:        if (iph2->status == PHASE2ST_ESTABLISHED &&
        !          1675:            iph2->side == INITIATOR) {
        !          1676:                struct ph1handle *iph1hint;
        !          1677:                /*
        !          1678:                 * Active phase 2 expired and we were initiator.
        !          1679:                 * Begin new phase 2 exchange, so we can keep on sending
        !          1680:                 * traffic.
        !          1681:                 */
        !          1682: 
        !          1683:                /* update status for re-use */
        !          1684:                iph1hint = iph2->ph1;
        !          1685:                initph2(iph2);
        !          1686:                iph2->status = PHASE2ST_STATUS2;
        !          1687: 
        !          1688:                /* start quick exchange */
        !          1689:                if (isakmp_post_acquire(iph2, iph1hint, FALSE) < 0) {
        !          1690:                        plog(LLV_ERROR, LOCATION, iph2->dst,
        !          1691:                                "failed to begin ipsec sa "
        !          1692:                                "re-negotication.\n");
        !          1693:                        remph2(iph2);
        !          1694:                        delph2(iph2);
        !          1695:                        return -1;
        !          1696:                }
        !          1697: 
        !          1698:                return 0;
        !          1699:        }
        !          1700: 
        !          1701:        /*
        !          1702:         * We are responder or the phase 2 was not established.
        !          1703:         * Just remove the ph2handle to reflect SADB.
        !          1704:         */
        !          1705:        iph2->status = PHASE2ST_EXPIRED;
        !          1706:        remph2(iph2);
        !          1707:        delph2(iph2);
        !          1708: 
        !          1709:        return 0;
        !          1710: }
        !          1711: 
        !          1712: static int
        !          1713: pk_recvacquire(mhp)
        !          1714:        caddr_t *mhp;
        !          1715: {
        !          1716:        struct sadb_msg *msg;
        !          1717:        struct sadb_x_policy *xpl;
        !          1718:        struct secpolicy *sp_out = NULL, *sp_in = NULL;
        !          1719:        struct ph2handle *iph2;
        !          1720:        struct sockaddr *src, *dst;     /* IKE addresses (for exchanges) */
        !          1721:        struct sockaddr *sp_src, *sp_dst;   /* SP addresses (selectors). */
        !          1722:        struct sockaddr *sa_src = NULL, *sa_dst = NULL ; /* SA addresses */
        !          1723: #ifdef HAVE_SECCTX
        !          1724:        struct sadb_x_sec_ctx *m_sec_ctx;
        !          1725: #endif /* HAVE_SECCTX */
        !          1726:        struct policyindex spidx;
        !          1727: 
        !          1728:        /* ignore this message because of local test mode. */
        !          1729:        if (f_local)
        !          1730:                return 0;
        !          1731: 
        !          1732:        /* sanity check */
        !          1733:        if (mhp[0] == NULL
        !          1734:         || mhp[SADB_EXT_ADDRESS_SRC] == NULL
        !          1735:         || mhp[SADB_EXT_ADDRESS_DST] == NULL
        !          1736:         || mhp[SADB_X_EXT_POLICY] == NULL) {
        !          1737:                plog(LLV_ERROR, LOCATION, NULL,
        !          1738:                        "inappropriate sadb acquire message passed.\n");
        !          1739:                return -1;
        !          1740:        }
        !          1741:        msg = (struct sadb_msg *)mhp[0];
        !          1742:        xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
        !          1743:        /* acquire does not have nat-t ports; so do not bother setting
        !          1744:         * the default port 500; just use the port zero for wildcard
        !          1745:         * matching the get a valid natted destination */
        !          1746:        sp_src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
        !          1747:        sp_dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
        !          1748: 
        !          1749: #ifdef HAVE_SECCTX
        !          1750:        m_sec_ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
        !          1751: 
        !          1752:        if (m_sec_ctx != NULL) {
        !          1753:                plog(LLV_INFO, LOCATION, NULL, "security context doi: %u\n",
        !          1754:                     m_sec_ctx->sadb_x_ctx_doi);
        !          1755:                plog(LLV_INFO, LOCATION, NULL,
        !          1756:                     "security context algorithm: %u\n",
        !          1757:                     m_sec_ctx->sadb_x_ctx_alg);
        !          1758:                plog(LLV_INFO, LOCATION, NULL, "security context length: %u\n",
        !          1759:                     m_sec_ctx->sadb_x_ctx_len);
        !          1760:                plog(LLV_INFO, LOCATION, NULL, "security context: %s\n",
        !          1761:                     ((char *)m_sec_ctx + sizeof(struct sadb_x_sec_ctx)));
        !          1762:        }
        !          1763: #endif /* HAVE_SECCTX */
        !          1764: 
        !          1765:        /* ignore if type is not IPSEC_POLICY_IPSEC */
        !          1766:        if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) {
        !          1767:                plog(LLV_DEBUG, LOCATION, NULL,
        !          1768:                        "ignore ACQUIRE message. type is not IPsec.\n");
        !          1769:                return 0;
        !          1770:        }
        !          1771: 
        !          1772:        /* ignore it if src or dst are multicast addresses. */
        !          1773:        if ((sp_dst->sa_family == AF_INET
        !          1774:          && IN_MULTICAST(ntohl(((struct sockaddr_in *)sp_dst)->sin_addr.s_addr)))
        !          1775: #ifdef INET6
        !          1776:         || (sp_dst->sa_family == AF_INET6
        !          1777:          && IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)sp_dst)->sin6_addr))
        !          1778: #endif
        !          1779:        ) {
        !          1780:                plog(LLV_DEBUG, LOCATION, NULL,
        !          1781:                        "ignore due to multicast destination address: %s.\n",
        !          1782:                        saddrwop2str(sp_dst));
        !          1783:                return 0;
        !          1784:        }
        !          1785: 
        !          1786:        if ((sp_src->sa_family == AF_INET
        !          1787:          && IN_MULTICAST(ntohl(((struct sockaddr_in *)sp_src)->sin_addr.s_addr)))
        !          1788: #ifdef INET6
        !          1789:         || (sp_src->sa_family == AF_INET6
        !          1790:          && IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)sp_src)->sin6_addr))
        !          1791: #endif
        !          1792:        ) {
        !          1793:                plog(LLV_DEBUG, LOCATION, NULL,
        !          1794:                        "ignore due to multicast source address: %s.\n",
        !          1795:                        saddrwop2str(sp_src));
        !          1796:                return 0;
        !          1797:        }
        !          1798: 
        !          1799:        /* search for proper policyindex */
        !          1800:        sp_out = getspbyspid(xpl->sadb_x_policy_id);
        !          1801:        if (sp_out == NULL) {
        !          1802:                plog(LLV_ERROR, LOCATION, NULL, "no policy found: id:%d.\n",
        !          1803:                        xpl->sadb_x_policy_id);
        !          1804:                return -1;
        !          1805:        }
        !          1806:        plog(LLV_DEBUG, LOCATION, NULL,
        !          1807:                "suitable outbound SP found: %s.\n", spidx2str(&sp_out->spidx));
        !          1808: 
        !          1809:        /* Before going further, let first get the source and destination
        !          1810:         * address that would be used for IKE negotiation. The logic is:
        !          1811:         * - if SP from SPD image contains local and remote hints, we
        !          1812:         *   use them (provided by MIGRATE).
        !          1813:         * - otherwise, we use the ones from the ipsecrequest, which means:
        !          1814:         *   - the addresses from the request for transport mode
        !          1815:         *   - the endpoints addresses for tunnel mode
        !          1816:         *
        !          1817:         * Note that:
        !          1818:         * 1) racoon does not support negotiation of bundles which
        !          1819:         *    simplifies the lookup for the addresses in the ipsecrequest
        !          1820:         *    list, as we expect only one.
        !          1821:         * 2) We do source and destination parts all together and do not
        !          1822:         *    accept semi-defined information. This is just a decision,
        !          1823:         *    there might be needs.
        !          1824:         *
        !          1825:         * --arno
        !          1826:         */
        !          1827:        if (sp_out->req && sp_out->req->saidx.mode == IPSEC_MODE_TUNNEL) {
        !          1828:                /* For Tunnel mode, SA addresses are the endpoints */
        !          1829:                src = (struct sockaddr *) &sp_out->req->saidx.src;
        !          1830:                dst = (struct sockaddr *) &sp_out->req->saidx.dst;
        !          1831:        } else {
        !          1832:                /* Otherwise use requested addresses.
        !          1833:                 *
        !          1834:                 * We need to explicitly setup sa_src and sa_dst too,
        !          1835:                 * since the SA ports are different from IKE port. And
        !          1836:                 * src/dst ports will be overwritten when the matching
        !          1837:                 * phase1 is found. */
        !          1838:                src = sa_src = sp_src;
        !          1839:                dst = sa_dst = sp_dst;
        !          1840:        }
        !          1841:        if (sp_out->local && sp_out->remote) {
        !          1842:                /* hints available, let's use them */
        !          1843:                sa_src = src;
        !          1844:                sa_dst = dst;
        !          1845:                src = (struct sockaddr *) sp_out->local;
        !          1846:                dst = (struct sockaddr *) sp_out->remote;
        !          1847:        }
        !          1848: 
        !          1849:        /*
        !          1850:         * If there is a phase 2 handler against the policy identifier in
        !          1851:         * the acquire message, and if
        !          1852:         *    1. its state is less than PHASE2ST_ESTABLISHED, then racoon
        !          1853:         *       should ignore such a acquire message because the phase 2
        !          1854:         *       is just negotiating.
        !          1855:         *    2. its state is equal to PHASE2ST_ESTABLISHED, then racoon
        !          1856:         *       has to prcesss such a acquire message because racoon may
        !          1857:         *       lost the expire message.
        !          1858:         */
        !          1859:        iph2 = getph2byid(src, dst, xpl->sadb_x_policy_id);
        !          1860:        if (iph2 != NULL) {
        !          1861:                if (iph2->status < PHASE2ST_ESTABLISHED) {
        !          1862:                        plog(LLV_DEBUG, LOCATION, NULL,
        !          1863:                                "ignore the acquire because ph2 found\n");
        !          1864:                        return -1;
        !          1865:                }
        !          1866:                if (iph2->status == PHASE2ST_EXPIRED)
        !          1867:                        iph2 = NULL;
        !          1868:                /*FALLTHROUGH*/
        !          1869:        }
        !          1870: 
        !          1871:        /* Check we are listening on source address. If not, ignore. */
        !          1872:        if (myaddr_getsport(src) == -1) {
        !          1873:                plog(LLV_DEBUG, LOCATION, NULL,
        !          1874:                     "Not listening on source address %s. Ignoring ACQUIRE.\n",
        !          1875:                     saddrwop2str(src));
        !          1876:                return 0;
        !          1877:        }
        !          1878: 
        !          1879:        /* get inbound policy */
        !          1880:     {
        !          1881: 
        !          1882:        memset(&spidx, 0, sizeof(spidx));
        !          1883:        spidx.dir = IPSEC_DIR_INBOUND;
        !          1884:        memcpy(&spidx.src, &sp_out->spidx.dst, sizeof(spidx.src));
        !          1885:        memcpy(&spidx.dst, &sp_out->spidx.src, sizeof(spidx.dst));
        !          1886:        spidx.prefs = sp_out->spidx.prefd;
        !          1887:        spidx.prefd = sp_out->spidx.prefs;
        !          1888:        spidx.ul_proto = sp_out->spidx.ul_proto;
        !          1889: 
        !          1890: #ifdef HAVE_SECCTX
        !          1891:        if (m_sec_ctx) {
        !          1892:                spidx.sec_ctx.ctx_doi = m_sec_ctx->sadb_x_ctx_doi;
        !          1893:                spidx.sec_ctx.ctx_alg = m_sec_ctx->sadb_x_ctx_alg;
        !          1894:                spidx.sec_ctx.ctx_strlen = m_sec_ctx->sadb_x_ctx_len;
        !          1895:                memcpy(spidx.sec_ctx.ctx_str,
        !          1896:                      ((char *)m_sec_ctx + sizeof(struct sadb_x_sec_ctx)),
        !          1897:                      spidx.sec_ctx.ctx_strlen);
        !          1898:        }
        !          1899: #endif /* HAVE_SECCTX */
        !          1900: 
        !          1901:        sp_in = getsp(&spidx);
        !          1902:        if (sp_in) {
        !          1903:                plog(LLV_DEBUG, LOCATION, NULL,
        !          1904:                        "suitable inbound SP found: %s.\n",
        !          1905:                        spidx2str(&sp_in->spidx));
        !          1906:        } else {
        !          1907:                plog(LLV_NOTIFY, LOCATION, NULL,
        !          1908:                        "no in-bound policy found: %s\n",
        !          1909:                        spidx2str(&spidx));
        !          1910:        }
        !          1911:     }
        !          1912: 
        !          1913:        /* allocate a phase 2 */
        !          1914:        iph2 = newph2();
        !          1915:        if (iph2 == NULL) {
        !          1916:                plog(LLV_ERROR, LOCATION, NULL,
        !          1917:                        "failed to allocate phase2 entry.\n");
        !          1918:                return -1;
        !          1919:        }
        !          1920:        iph2->side = INITIATOR;
        !          1921:        iph2->spid = xpl->sadb_x_policy_id;
        !          1922:        iph2->satype = msg->sadb_msg_satype;
        !          1923:        iph2->seq = msg->sadb_msg_seq;
        !          1924:        iph2->status = PHASE2ST_STATUS2;
        !          1925: 
        !          1926:        /* set address used by IKE for the negotiation (might differ from
        !          1927:         * SA address, i.e. might not be tunnel endpoints or addresses
        !          1928:         * of transport mode SA) */
        !          1929:        iph2->dst = dupsaddr(dst);
        !          1930:        if (iph2->dst == NULL) {
        !          1931:                delph2(iph2);
        !          1932:                return -1;
        !          1933:        }
        !          1934:        iph2->src = dupsaddr(src);
        !          1935:        if (iph2->src == NULL) {
        !          1936:                delph2(iph2);
        !          1937:                return -1;
        !          1938:        }
        !          1939: 
        !          1940:        /* If sa_src and sa_dst have been set, this mean we have to
        !          1941:         * set iph2->sa_src and iph2->sa_dst to provide the addresses
        !          1942:         * of the SA because iph2->src and iph2->dst are only the ones
        !          1943:         * used for the IKE exchanges. Those that need these addresses
        !          1944:         * are for instance pk_sendupdate() or pk_sendgetspi() */
        !          1945:        if (sa_src) {
        !          1946:                iph2->sa_src = dupsaddr(sa_src);
        !          1947:                iph2->sa_dst = dupsaddr(sa_dst);
        !          1948:        }
        !          1949: 
        !          1950:        if (isakmp_get_sainfo(iph2, sp_out, sp_in) < 0) {
        !          1951:                delph2(iph2);
        !          1952:                return -1;
        !          1953:        }
        !          1954: 
        !          1955: #ifdef HAVE_SECCTX
        !          1956:        if (m_sec_ctx) {
        !          1957:                set_secctx_in_proposal(iph2, spidx);
        !          1958:        }
        !          1959: #endif /* HAVE_SECCTX */
        !          1960: 
        !          1961:        insph2(iph2);
        !          1962: 
        !          1963:        /* start isakmp initiation by using ident exchange */
        !          1964:        /* XXX should be looped if there are multiple phase 2 handler. */
        !          1965:        if (isakmp_post_acquire(iph2, NULL, TRUE) < 0) {
        !          1966:                plog(LLV_ERROR, LOCATION, NULL,
        !          1967:                        "failed to begin ipsec sa negotication.\n");
        !          1968:                remph2(iph2);
        !          1969:                delph2(iph2);
        !          1970:                return -1;
        !          1971:        }
        !          1972: 
        !          1973:        return 0;
        !          1974: }
        !          1975: 
        !          1976: static int
        !          1977: pk_recvdelete(mhp)
        !          1978:        caddr_t *mhp;
        !          1979: {
        !          1980:        struct sadb_msg *msg;
        !          1981:        struct sadb_sa *sa;
        !          1982:        struct sockaddr *src, *dst;
        !          1983:        struct ph2handle *iph2 = NULL;
        !          1984:        u_int proto_id;
        !          1985: 
        !          1986:        /* ignore this message because of local test mode. */
        !          1987:        if (f_local)
        !          1988:                return 0;
        !          1989: 
        !          1990:        /* sanity check */
        !          1991:        if (mhp[0] == NULL
        !          1992:         || mhp[SADB_EXT_SA] == NULL
        !          1993:         || mhp[SADB_EXT_ADDRESS_SRC] == NULL
        !          1994:         || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
        !          1995:                plog(LLV_ERROR, LOCATION, NULL,
        !          1996:                        "inappropriate sadb delete message passed.\n");
        !          1997:                return -1;
        !          1998:        }
        !          1999:        msg = (struct sadb_msg *)mhp[0];
        !          2000:        sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
        !          2001:        pk_fixup_sa_addresses(mhp);
        !          2002:        src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
        !          2003:        dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
        !          2004: 
        !          2005:        /* the message has to be processed or not ? */
        !          2006:        if (msg->sadb_msg_pid == getpid()) {
        !          2007:                plog(LLV_DEBUG, LOCATION, NULL,
        !          2008:                        "%s message is not interesting "
        !          2009:                        "because the message was originated by me.\n",
        !          2010:                        s_pfkey_type(msg->sadb_msg_type));
        !          2011:                return -1;
        !          2012:        }
        !          2013: 
        !          2014:        proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
        !          2015:        if (proto_id == ~0) {
        !          2016:                plog(LLV_ERROR, LOCATION, NULL,
        !          2017:                        "invalid proto_id %d\n", msg->sadb_msg_satype);
        !          2018:                return -1;
        !          2019:        }
        !          2020: 
        !          2021:        iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
        !          2022:        if (iph2 == NULL) {
        !          2023:                /* ignore */
        !          2024:                plog(LLV_ERROR, LOCATION, NULL,
        !          2025:                        "no iph2 found: %s\n",
        !          2026:                        sadbsecas2str(src, dst, msg->sadb_msg_satype,
        !          2027:                                sa->sadb_sa_spi, IPSEC_MODE_ANY));
        !          2028:                return 0;
        !          2029:        }
        !          2030: 
        !          2031:        plog(LLV_ERROR, LOCATION, NULL,
        !          2032:                "pfkey DELETE received: %s\n",
        !          2033:                sadbsecas2str(src, dst,
        !          2034:                        msg->sadb_msg_satype, sa->sadb_sa_spi, IPSEC_MODE_ANY));
        !          2035: 
        !          2036:        /* send delete information */
        !          2037:        if (iph2->status == PHASE2ST_ESTABLISHED)
        !          2038:                isakmp_info_send_d2(iph2);
        !          2039: 
        !          2040:        remph2(iph2);
        !          2041:        delph2(iph2);
        !          2042: 
        !          2043:        return 0;
        !          2044: }
        !          2045: 
        !          2046: static int
        !          2047: pk_recvflush(mhp)
        !          2048:        caddr_t *mhp;
        !          2049: {
        !          2050:        /* ignore this message because of local test mode. */
        !          2051:        if (f_local)
        !          2052:                return 0;
        !          2053: 
        !          2054:        /* sanity check */
        !          2055:        if (mhp[0] == NULL) {
        !          2056:                plog(LLV_ERROR, LOCATION, NULL,
        !          2057:                        "inappropriate sadb flush message passed.\n");
        !          2058:                return -1;
        !          2059:        }
        !          2060: 
        !          2061:        flushph2();
        !          2062: 
        !          2063:        return 0;
        !          2064: }
        !          2065: 
        !          2066: static int
        !          2067: getsadbpolicy(policy0, policylen0, type, iph2)
        !          2068:        caddr_t *policy0;
        !          2069:        int *policylen0, type;
        !          2070:        struct ph2handle *iph2;
        !          2071: {
        !          2072:        struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen;
        !          2073:        struct sockaddr *src = NULL, *dst = NULL;
        !          2074:        struct sadb_x_policy *xpl;
        !          2075:        struct sadb_x_ipsecrequest *xisr;
        !          2076:        struct saproto *pr;
        !          2077:        struct saproto **pr_rlist;
        !          2078:        int rlist_len = 0;
        !          2079:        caddr_t policy, p;
        !          2080:        int policylen;
        !          2081:        int xisrlen;
        !          2082:        u_int satype, mode;
        !          2083:        int len = 0;
        !          2084: #ifdef HAVE_SECCTX
        !          2085:        int ctxlen = 0;
        !          2086: #endif /* HAVE_SECCTX */
        !          2087: 
        !          2088: 
        !          2089:        /* get policy buffer size */
        !          2090:        policylen = sizeof(struct sadb_x_policy);
        !          2091:        if (type != SADB_X_SPDDELETE) {
        !          2092:                if (iph2->sa_src && iph2->sa_dst) {
        !          2093:                        src = iph2->sa_src; /* MIPv6: Use SA addresses, */
        !          2094:                        dst = iph2->sa_dst; /* not IKE ones             */
        !          2095:                } else {
        !          2096:                        src = iph2->src; /* Common case: SA addresses */
        !          2097:                        dst = iph2->dst; /* and IKE ones are the same */
        !          2098:                }
        !          2099: 
        !          2100:                for (pr = iph2->approval->head; pr; pr = pr->next) {
        !          2101:                        xisrlen = sizeof(*xisr);
        !          2102:                        if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL) {
        !          2103:                                xisrlen += (sysdep_sa_len(src) +
        !          2104:                                            sysdep_sa_len(dst));
        !          2105:                        }
        !          2106: 
        !          2107:                        policylen += PFKEY_ALIGN8(xisrlen);
        !          2108:                }
        !          2109:        }
        !          2110: 
        !          2111: #ifdef HAVE_SECCTX
        !          2112:        if (*spidx->sec_ctx.ctx_str) {
        !          2113:                ctxlen = sizeof(struct sadb_x_sec_ctx)
        !          2114:                                + PFKEY_ALIGN8(spidx->sec_ctx.ctx_strlen);
        !          2115:                policylen += ctxlen;
        !          2116:        }
        !          2117: #endif /* HAVE_SECCTX */
        !          2118: 
        !          2119:        /* make policy structure */
        !          2120:        policy = racoon_malloc(policylen);
        !          2121:        memset((void*)policy, 0xcd, policylen);
        !          2122:        if (!policy) {
        !          2123:                plog(LLV_ERROR, LOCATION, NULL,
        !          2124:                        "buffer allocation failed.\n");
        !          2125:                return -1;
        !          2126:        }
        !          2127: 
        !          2128:        xpl = (struct sadb_x_policy *)policy;
        !          2129:        xpl->sadb_x_policy_len = PFKEY_UNIT64(policylen);
        !          2130:        xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
        !          2131:        xpl->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
        !          2132:        xpl->sadb_x_policy_dir = spidx->dir;
        !          2133:        xpl->sadb_x_policy_id = 0;
        !          2134: #ifdef HAVE_PFKEY_POLICY_PRIORITY
        !          2135:        xpl->sadb_x_policy_priority = PRIORITY_DEFAULT;
        !          2136: #endif
        !          2137:        len++;
        !          2138: 
        !          2139: #ifdef HAVE_SECCTX
        !          2140:        if (*spidx->sec_ctx.ctx_str) {
        !          2141:                struct sadb_x_sec_ctx *p;
        !          2142: 
        !          2143:                p = (struct sadb_x_sec_ctx *)(xpl + len);
        !          2144:                memset(p, 0, ctxlen);
        !          2145:                p->sadb_x_sec_len = PFKEY_UNIT64(ctxlen);
        !          2146:                p->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
        !          2147:                p->sadb_x_ctx_len = spidx->sec_ctx.ctx_strlen;
        !          2148:                p->sadb_x_ctx_doi = spidx->sec_ctx.ctx_doi;
        !          2149:                p->sadb_x_ctx_alg = spidx->sec_ctx.ctx_alg;
        !          2150: 
        !          2151:                memcpy(p + 1,spidx->sec_ctx.ctx_str,spidx->sec_ctx.ctx_strlen);
        !          2152:                len += ctxlen;
        !          2153:        }
        !          2154: #endif /* HAVE_SECCTX */
        !          2155: 
        !          2156:        /* no need to append policy information any more if type is SPDDELETE */
        !          2157:        if (type == SADB_X_SPDDELETE)
        !          2158:                goto end;
        !          2159: 
        !          2160:        xisr = (struct sadb_x_ipsecrequest *)(xpl + len);
        !          2161: 
        !          2162:        /* The order of things is reversed for use in add policy messages */
        !          2163:        for (pr = iph2->approval->head; pr; pr = pr->next) rlist_len++;
        !          2164:        pr_rlist = racoon_malloc((rlist_len+1)*sizeof(struct saproto*));
        !          2165:        if (!pr_rlist) {
        !          2166:                plog(LLV_ERROR, LOCATION, NULL,
        !          2167:                        "buffer allocation failed.\n");
        !          2168:                return -1;
        !          2169:        }
        !          2170:        pr_rlist[rlist_len--] = NULL;
        !          2171:        for (pr = iph2->approval->head; pr; pr = pr->next) pr_rlist[rlist_len--] = pr;
        !          2172:        rlist_len = 0;
        !          2173: 
        !          2174:        for (pr = pr_rlist[rlist_len++]; pr; pr = pr_rlist[rlist_len++]) {
        !          2175: 
        !          2176:                satype = doi2ipproto(pr->proto_id);
        !          2177:                if (satype == ~0) {
        !          2178:                        plog(LLV_ERROR, LOCATION, NULL,
        !          2179:                                "invalid proto_id %d\n", pr->proto_id);
        !          2180:                        goto err;
        !          2181:                }
        !          2182:                mode = ipsecdoi2pfkey_mode(pr->encmode);
        !          2183:                if (mode == ~0) {
        !          2184:                        plog(LLV_ERROR, LOCATION, NULL,
        !          2185:                                "invalid encmode %d\n", pr->encmode);
        !          2186:                        goto err;
        !          2187:                }
        !          2188: 
        !          2189:                /*
        !          2190:                 * the policy level cannot be unique because the policy
        !          2191:                 * is defined later than SA, so req_id cannot be bound to SA.
        !          2192:                 */
        !          2193:                xisr->sadb_x_ipsecrequest_proto = satype;
        !          2194:                xisr->sadb_x_ipsecrequest_mode = mode;
        !          2195:                if(iph2->proposal->head->reqid_in > 0){
        !          2196:                        xisr->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE;
        !          2197:                        xisr->sadb_x_ipsecrequest_reqid = iph2->proposal->head->reqid_in;
        !          2198:                }else{
        !          2199:                        xisr->sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE;
        !          2200:                        xisr->sadb_x_ipsecrequest_reqid = 0;
        !          2201:                }
        !          2202:                p = (caddr_t)(xisr + 1);
        !          2203: 
        !          2204:                xisrlen = sizeof(*xisr);
        !          2205: 
        !          2206:                if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL) {
        !          2207:                        int src_len, dst_len;
        !          2208: 
        !          2209:                        src_len = sysdep_sa_len(src);
        !          2210:                        dst_len = sysdep_sa_len(dst);
        !          2211:                        xisrlen += src_len + dst_len;
        !          2212: 
        !          2213:                        memcpy(p, src, src_len);
        !          2214:                        p += src_len;
        !          2215: 
        !          2216:                        memcpy(p, dst, dst_len);
        !          2217:                        p += dst_len;
        !          2218:                }
        !          2219: 
        !          2220:                xisr->sadb_x_ipsecrequest_len = PFKEY_ALIGN8(xisrlen);
        !          2221:                xisr = (struct sadb_x_ipsecrequest *)p;
        !          2222: 
        !          2223:        }
        !          2224:        racoon_free(pr_rlist);
        !          2225: 
        !          2226: end:
        !          2227:        *policy0 = policy;
        !          2228:        *policylen0 = policylen;
        !          2229: 
        !          2230:        return 0;
        !          2231: 
        !          2232: err:
        !          2233:        if (policy)
        !          2234:                racoon_free(policy);
        !          2235:        if (pr_rlist) racoon_free(pr_rlist);
        !          2236: 
        !          2237:        return -1;
        !          2238: }
        !          2239: 
        !          2240: int
        !          2241: pk_sendspdupdate2(iph2)
        !          2242:        struct ph2handle *iph2;
        !          2243: {
        !          2244:        struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen;
        !          2245:        caddr_t policy = NULL;
        !          2246:        int policylen = 0;
        !          2247:        u_int64_t ltime, vtime;
        !          2248: 
        !          2249:        ltime = iph2->approval->lifetime;
        !          2250:        vtime = 0;
        !          2251: 
        !          2252:        if (getsadbpolicy(&policy, &policylen, SADB_X_SPDUPDATE, iph2)) {
        !          2253:                plog(LLV_ERROR, LOCATION, NULL,
        !          2254:                        "getting sadb policy failed.\n");
        !          2255:                return -1;
        !          2256:        }
        !          2257: 
        !          2258:        if (pfkey_send_spdupdate2(
        !          2259:                        lcconf->sock_pfkey,
        !          2260:                        (struct sockaddr *)&spidx->src,
        !          2261:                        spidx->prefs,
        !          2262:                        (struct sockaddr *)&spidx->dst,
        !          2263:                        spidx->prefd,
        !          2264:                        spidx->ul_proto,
        !          2265:                        ltime, vtime,
        !          2266:                        policy, policylen, 0) < 0) {
        !          2267:                plog(LLV_ERROR, LOCATION, NULL,
        !          2268:                        "libipsec failed send spdupdate2 (%s)\n",
        !          2269:                        ipsec_strerror());
        !          2270:                goto end;
        !          2271:        }
        !          2272:        plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_spdupdate2\n");
        !          2273: 
        !          2274: end:
        !          2275:        if (policy)
        !          2276:                racoon_free(policy);
        !          2277: 
        !          2278:        return 0;
        !          2279: }
        !          2280: 
        !          2281: static int
        !          2282: pk_recvspdupdate(mhp)
        !          2283:        caddr_t *mhp;
        !          2284: {
        !          2285:        struct sadb_address *saddr, *daddr;
        !          2286:        struct sadb_x_policy *xpl;
        !          2287:        struct sadb_lifetime *lt;
        !          2288:        struct policyindex spidx;
        !          2289:        struct secpolicy *sp;
        !          2290:        struct sockaddr *local=NULL, *remote=NULL;
        !          2291:        u_int64_t created;
        !          2292:        int ret;
        !          2293: 
        !          2294:        /* sanity check */
        !          2295:        if (mhp[0] == NULL
        !          2296:         || mhp[SADB_EXT_ADDRESS_SRC] == NULL
        !          2297:         || mhp[SADB_EXT_ADDRESS_DST] == NULL
        !          2298:         || mhp[SADB_X_EXT_POLICY] == NULL) {
        !          2299:                plog(LLV_ERROR, LOCATION, NULL,
        !          2300:                        "inappropriate sadb spdupdate message passed.\n");
        !          2301:                return -1;
        !          2302:        }
        !          2303:        saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
        !          2304:        daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
        !          2305:        xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
        !          2306:        lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
        !          2307:        if(lt != NULL)
        !          2308:                created = lt->sadb_lifetime_addtime;
        !          2309:        else
        !          2310:                created = 0;
        !          2311: 
        !          2312: #ifdef HAVE_PFKEY_POLICY_PRIORITY
        !          2313:        KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
        !          2314:                        saddr + 1,
        !          2315:                        daddr + 1,
        !          2316:                        saddr->sadb_address_prefixlen,
        !          2317:                        daddr->sadb_address_prefixlen,
        !          2318:                        saddr->sadb_address_proto,
        !          2319:                        xpl->sadb_x_policy_priority,
        !          2320:                        created,
        !          2321:                        &spidx);
        !          2322: #else
        !          2323:        KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
        !          2324:                        saddr + 1,
        !          2325:                        daddr + 1,
        !          2326:                        saddr->sadb_address_prefixlen,
        !          2327:                        daddr->sadb_address_prefixlen,
        !          2328:                        saddr->sadb_address_proto,
        !          2329:                        created,
        !          2330:                        &spidx);
        !          2331: #endif
        !          2332: 
        !          2333: #ifdef HAVE_SECCTX
        !          2334:        if (mhp[SADB_X_EXT_SEC_CTX] != NULL) {
        !          2335:                struct sadb_x_sec_ctx *ctx;
        !          2336: 
        !          2337:                ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
        !          2338:                spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg;
        !          2339:                spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi;
        !          2340:                spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len;
        !          2341:                memcpy(spidx.sec_ctx.ctx_str, ctx + 1, ctx->sadb_x_ctx_len);
        !          2342:        }
        !          2343: #endif /* HAVE_SECCTX */
        !          2344: 
        !          2345:        sp = getsp(&spidx);
        !          2346:        if (sp == NULL) {
        !          2347:                plog(LLV_DEBUG, LOCATION, NULL,
        !          2348:                        "this policy did not exist for removal: \"%s\"\n",
        !          2349:                        spidx2str(&spidx));
        !          2350:        } else {
        !          2351:                /* preserve hints before deleting the SP */
        !          2352:                local = sp->local;
        !          2353:                remote = sp->remote;
        !          2354:                sp->local = NULL;
        !          2355:                sp->remote = NULL;
        !          2356: 
        !          2357:                remsp(sp);
        !          2358:                delsp(sp);
        !          2359:        }
        !          2360: 
        !          2361:        /* Add new SP (with old hints) */
        !          2362:        ret = addnewsp(mhp, local, remote);
        !          2363: 
        !          2364:        if (local != NULL)
        !          2365:                racoon_free(local);
        !          2366:        if (remote != NULL)
        !          2367:                racoon_free(remote);
        !          2368: 
        !          2369:        if (ret < 0)
        !          2370:                return -1;
        !          2371: 
        !          2372:        return 0;
        !          2373: }
        !          2374: 
        !          2375: /*
        !          2376:  * this function has to be used by responder side.
        !          2377:  */
        !          2378: int
        !          2379: pk_sendspdadd2(iph2)
        !          2380:        struct ph2handle *iph2;
        !          2381: {
        !          2382:        struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen;
        !          2383:        caddr_t policy = NULL;
        !          2384:        int policylen = 0;
        !          2385:        u_int64_t ltime, vtime;
        !          2386: 
        !          2387:        ltime = iph2->approval->lifetime;
        !          2388:        vtime = 0;
        !          2389: 
        !          2390:        if (getsadbpolicy(&policy, &policylen, SADB_X_SPDADD, iph2)) {
        !          2391:                plog(LLV_ERROR, LOCATION, NULL,
        !          2392:                        "getting sadb policy failed.\n");
        !          2393:                return -1;
        !          2394:        }
        !          2395: 
        !          2396:        if (pfkey_send_spdadd2(
        !          2397:                        lcconf->sock_pfkey,
        !          2398:                        (struct sockaddr *)&spidx->src,
        !          2399:                        spidx->prefs,
        !          2400:                        (struct sockaddr *)&spidx->dst,
        !          2401:                        spidx->prefd,
        !          2402:                        spidx->ul_proto,
        !          2403:                        ltime, vtime,
        !          2404:                        policy, policylen, 0) < 0) {
        !          2405:                plog(LLV_ERROR, LOCATION, NULL,
        !          2406:                        "libipsec failed send spdadd2 (%s)\n",
        !          2407:                        ipsec_strerror());
        !          2408:                goto end;
        !          2409:        }
        !          2410:        plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_spdadd2\n");
        !          2411: 
        !          2412: end:
        !          2413:        if (policy)
        !          2414:                racoon_free(policy);
        !          2415: 
        !          2416:        return 0;
        !          2417: }
        !          2418: 
        !          2419: static int
        !          2420: pk_recvspdadd(mhp)
        !          2421:        caddr_t *mhp;
        !          2422: {
        !          2423:        struct sadb_address *saddr, *daddr;
        !          2424:        struct sadb_x_policy *xpl;
        !          2425:        struct sadb_lifetime *lt;
        !          2426:        struct policyindex spidx;
        !          2427:        struct secpolicy *sp;
        !          2428:        struct sockaddr *local = NULL, *remote = NULL;
        !          2429:        u_int64_t created;
        !          2430:        int ret;
        !          2431: 
        !          2432:        /* sanity check */
        !          2433:        if (mhp[0] == NULL
        !          2434:         || mhp[SADB_EXT_ADDRESS_SRC] == NULL
        !          2435:         || mhp[SADB_EXT_ADDRESS_DST] == NULL
        !          2436:         || mhp[SADB_X_EXT_POLICY] == NULL) {
        !          2437:                plog(LLV_ERROR, LOCATION, NULL,
        !          2438:                        "inappropriate sadb spdadd message passed.\n");
        !          2439:                return -1;
        !          2440:        }
        !          2441:        saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
        !          2442:        daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
        !          2443:        xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
        !          2444:        lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
        !          2445:        if(lt != NULL)
        !          2446:                created = lt->sadb_lifetime_addtime;
        !          2447:        else
        !          2448:                created = 0;
        !          2449: 
        !          2450: #ifdef HAVE_PFKEY_POLICY_PRIORITY
        !          2451:        KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
        !          2452:                        saddr + 1,
        !          2453:                        daddr + 1,
        !          2454:                        saddr->sadb_address_prefixlen,
        !          2455:                        daddr->sadb_address_prefixlen,
        !          2456:                        saddr->sadb_address_proto,
        !          2457:                        xpl->sadb_x_policy_priority,
        !          2458:                        created,
        !          2459:                        &spidx);
        !          2460: #else
        !          2461:        KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
        !          2462:                        saddr + 1,
        !          2463:                        daddr + 1,
        !          2464:                        saddr->sadb_address_prefixlen,
        !          2465:                        daddr->sadb_address_prefixlen,
        !          2466:                        saddr->sadb_address_proto,
        !          2467:                        created,
        !          2468:                        &spidx);
        !          2469: #endif
        !          2470: 
        !          2471: #ifdef HAVE_SECCTX
        !          2472:        if (mhp[SADB_X_EXT_SEC_CTX] != NULL) {
        !          2473:                struct sadb_x_sec_ctx *ctx;
        !          2474: 
        !          2475:                ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
        !          2476:                spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg;
        !          2477:                spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi;
        !          2478:                spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len;
        !          2479:                memcpy(spidx.sec_ctx.ctx_str, ctx + 1, ctx->sadb_x_ctx_len);
        !          2480:        }
        !          2481: #endif /* HAVE_SECCTX */
        !          2482: 
        !          2483:        sp = getsp(&spidx);
        !          2484:        if (sp != NULL) {
        !          2485:                plog(LLV_ERROR, LOCATION, NULL,
        !          2486:                        "such policy already exists. "
        !          2487:                        "anyway replace it: %s\n",
        !          2488:                        spidx2str(&spidx));
        !          2489: 
        !          2490:                /* preserve hints before deleting the SP */
        !          2491:                local = sp->local;
        !          2492:                remote = sp->remote;
        !          2493:                sp->local = NULL;
        !          2494:                sp->remote = NULL;
        !          2495: 
        !          2496:                remsp(sp);
        !          2497:                delsp(sp);
        !          2498:        }
        !          2499: 
        !          2500:        /* Add new SP (with old hints) */
        !          2501:        ret = addnewsp(mhp, local, remote);
        !          2502: 
        !          2503:        if (local != NULL)
        !          2504:                racoon_free(local);
        !          2505:        if (remote != NULL)
        !          2506:                racoon_free(remote);
        !          2507: 
        !          2508:        if (ret < 0)
        !          2509:                return -1;
        !          2510: 
        !          2511:        return 0;
        !          2512: }
        !          2513: 
        !          2514: /*
        !          2515:  * this function has to be used by responder side.
        !          2516:  */
        !          2517: int
        !          2518: pk_sendspddelete(iph2)
        !          2519:        struct ph2handle *iph2;
        !          2520: {
        !          2521:        struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen;
        !          2522:        caddr_t policy = NULL;
        !          2523:        int policylen;
        !          2524: 
        !          2525:        if (getsadbpolicy(&policy, &policylen, SADB_X_SPDDELETE, iph2)) {
        !          2526:                plog(LLV_ERROR, LOCATION, NULL,
        !          2527:                        "getting sadb policy failed.\n");
        !          2528:                return -1;
        !          2529:        }
        !          2530: 
        !          2531:        if (pfkey_send_spddelete(
        !          2532:                        lcconf->sock_pfkey,
        !          2533:                        (struct sockaddr *)&spidx->src,
        !          2534:                        spidx->prefs,
        !          2535:                        (struct sockaddr *)&spidx->dst,
        !          2536:                        spidx->prefd,
        !          2537:                        spidx->ul_proto,
        !          2538:                        policy, policylen, 0) < 0) {
        !          2539:                plog(LLV_ERROR, LOCATION, NULL,
        !          2540:                        "libipsec failed send spddelete (%s)\n",
        !          2541:                        ipsec_strerror());
        !          2542:                goto end;
        !          2543:        }
        !          2544:        plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_spddelete\n");
        !          2545: 
        !          2546: end:
        !          2547:        if (policy)
        !          2548:                racoon_free(policy);
        !          2549: 
        !          2550:        return 0;
        !          2551: }
        !          2552: 
        !          2553: static int
        !          2554: pk_recvspddelete(mhp)
        !          2555:        caddr_t *mhp;
        !          2556: {
        !          2557:        struct sadb_address *saddr, *daddr;
        !          2558:        struct sadb_x_policy *xpl;
        !          2559:        struct sadb_lifetime *lt;
        !          2560:        struct policyindex spidx;
        !          2561:        struct secpolicy *sp;
        !          2562:        u_int64_t created;
        !          2563: 
        !          2564:        /* sanity check */
        !          2565:        if (mhp[0] == NULL
        !          2566:         || mhp[SADB_EXT_ADDRESS_SRC] == NULL
        !          2567:         || mhp[SADB_EXT_ADDRESS_DST] == NULL
        !          2568:         || mhp[SADB_X_EXT_POLICY] == NULL) {
        !          2569:                plog(LLV_ERROR, LOCATION, NULL,
        !          2570:                        "inappropriate sadb spddelete message passed.\n");
        !          2571:                return -1;
        !          2572:        }
        !          2573:        saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
        !          2574:        daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
        !          2575:        xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
        !          2576:        lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
        !          2577:        if(lt != NULL)
        !          2578:                created = lt->sadb_lifetime_addtime;
        !          2579:        else
        !          2580:                created = 0;
        !          2581: 
        !          2582: #ifdef HAVE_PFKEY_POLICY_PRIORITY
        !          2583:        KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
        !          2584:                        saddr + 1,
        !          2585:                        daddr + 1,
        !          2586:                        saddr->sadb_address_prefixlen,
        !          2587:                        daddr->sadb_address_prefixlen,
        !          2588:                        saddr->sadb_address_proto,
        !          2589:                        xpl->sadb_x_policy_priority,
        !          2590:                        created,
        !          2591:                        &spidx);
        !          2592: #else
        !          2593:        KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
        !          2594:                        saddr + 1,
        !          2595:                        daddr + 1,
        !          2596:                        saddr->sadb_address_prefixlen,
        !          2597:                        daddr->sadb_address_prefixlen,
        !          2598:                        saddr->sadb_address_proto,
        !          2599:                        created,
        !          2600:                        &spidx);
        !          2601: #endif
        !          2602: 
        !          2603: #ifdef HAVE_SECCTX
        !          2604:        if (mhp[SADB_X_EXT_SEC_CTX] != NULL) {
        !          2605:                struct sadb_x_sec_ctx *ctx;
        !          2606: 
        !          2607:                ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
        !          2608:                spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg;
        !          2609:                spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi;
        !          2610:                spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len;
        !          2611:                memcpy(spidx.sec_ctx.ctx_str, ctx + 1, ctx->sadb_x_ctx_len);
        !          2612:        }
        !          2613: #endif /* HAVE_SECCTX */
        !          2614: 
        !          2615:        sp = getsp(&spidx);
        !          2616:        if (sp == NULL) {
        !          2617:                plog(LLV_ERROR, LOCATION, NULL,
        !          2618:                        "no policy found: %s\n",
        !          2619:                        spidx2str(&spidx));
        !          2620:                return -1;
        !          2621:        }
        !          2622: 
        !          2623:        remsp(sp);
        !          2624:        delsp(sp);
        !          2625: 
        !          2626:        return 0;
        !          2627: }
        !          2628: 
        !          2629: static int
        !          2630: pk_recvspdexpire(mhp)
        !          2631:        caddr_t *mhp;
        !          2632: {
        !          2633:        struct sadb_address *saddr, *daddr;
        !          2634:        struct sadb_x_policy *xpl;
        !          2635:        struct sadb_lifetime *lt;
        !          2636:        struct policyindex spidx;
        !          2637:        struct secpolicy *sp;
        !          2638:        u_int64_t created;
        !          2639: 
        !          2640:        /* sanity check */
        !          2641:        if (mhp[0] == NULL
        !          2642:         || mhp[SADB_EXT_ADDRESS_SRC] == NULL
        !          2643:         || mhp[SADB_EXT_ADDRESS_DST] == NULL
        !          2644:         || mhp[SADB_X_EXT_POLICY] == NULL) {
        !          2645:                plog(LLV_ERROR, LOCATION, NULL,
        !          2646:                        "inappropriate sadb spdexpire message passed.\n");
        !          2647:                return -1;
        !          2648:        }
        !          2649:        saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
        !          2650:        daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
        !          2651:        xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
        !          2652:        lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
        !          2653:        if(lt != NULL)
        !          2654:                created = lt->sadb_lifetime_addtime;
        !          2655:        else
        !          2656:                created = 0;
        !          2657: 
        !          2658: #ifdef HAVE_PFKEY_POLICY_PRIORITY
        !          2659:        KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
        !          2660:                        saddr + 1,
        !          2661:                        daddr + 1,
        !          2662:                        saddr->sadb_address_prefixlen,
        !          2663:                        daddr->sadb_address_prefixlen,
        !          2664:                        saddr->sadb_address_proto,
        !          2665:                        xpl->sadb_x_policy_priority,
        !          2666:                        created,
        !          2667:                        &spidx);
        !          2668: #else
        !          2669:        KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
        !          2670:                        saddr + 1,
        !          2671:                        daddr + 1,
        !          2672:                        saddr->sadb_address_prefixlen,
        !          2673:                        daddr->sadb_address_prefixlen,
        !          2674:                        saddr->sadb_address_proto,
        !          2675:                        created,
        !          2676:                        &spidx);
        !          2677: #endif
        !          2678: 
        !          2679: #ifdef HAVE_SECCTX
        !          2680:        if (mhp[SADB_X_EXT_SEC_CTX] != NULL) {
        !          2681:                struct sadb_x_sec_ctx *ctx;
        !          2682: 
        !          2683:                ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
        !          2684:                spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg;
        !          2685:                spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi;
        !          2686:                spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len;
        !          2687:                memcpy(spidx.sec_ctx.ctx_str, ctx + 1, ctx->sadb_x_ctx_len);
        !          2688:        }
        !          2689: #endif /* HAVE_SECCTX */
        !          2690: 
        !          2691:        sp = getsp(&spidx);
        !          2692:        if (sp == NULL) {
        !          2693:                plog(LLV_ERROR, LOCATION, NULL,
        !          2694:                        "no policy found: %s\n",
        !          2695:                        spidx2str(&spidx));
        !          2696:                return -1;
        !          2697:        }
        !          2698: 
        !          2699:        remsp(sp);
        !          2700:        delsp(sp);
        !          2701: 
        !          2702:        return 0;
        !          2703: }
        !          2704: 
        !          2705: static int
        !          2706: pk_recvspdget(mhp)
        !          2707:        caddr_t *mhp;
        !          2708: {
        !          2709:        /* sanity check */
        !          2710:        if (mhp[0] == NULL) {
        !          2711:                plog(LLV_ERROR, LOCATION, NULL,
        !          2712:                        "inappropriate sadb spdget message passed.\n");
        !          2713:                return -1;
        !          2714:        }
        !          2715: 
        !          2716:        return 0;
        !          2717: }
        !          2718: 
        !          2719: static int
        !          2720: pk_recvspddump(mhp)
        !          2721:        caddr_t *mhp;
        !          2722: {
        !          2723:        struct sadb_msg *msg;
        !          2724:        struct sadb_address *saddr, *daddr;
        !          2725:        struct sadb_x_policy *xpl;
        !          2726:        struct sadb_lifetime *lt;
        !          2727:        struct policyindex spidx;
        !          2728:        struct secpolicy *sp;
        !          2729:        struct sockaddr *local=NULL, *remote=NULL;
        !          2730:        u_int64_t created;
        !          2731:        int ret;
        !          2732: 
        !          2733:        /* sanity check */
        !          2734:        if (mhp[0] == NULL) {
        !          2735:                plog(LLV_ERROR, LOCATION, NULL,
        !          2736:                        "inappropriate sadb spddump message passed.\n");
        !          2737:                return -1;
        !          2738:        }
        !          2739:        msg = (struct sadb_msg *)mhp[0];
        !          2740:        saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
        !          2741:        daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
        !          2742:        xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
        !          2743:        lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
        !          2744:        if(lt != NULL)
        !          2745:                created = lt->sadb_lifetime_addtime;
        !          2746:        else
        !          2747:                created = 0;
        !          2748: 
        !          2749:        if (saddr == NULL || daddr == NULL || xpl == NULL) {
        !          2750:                plog(LLV_ERROR, LOCATION, NULL,
        !          2751:                        "inappropriate sadb spddump message passed.\n");
        !          2752:                return -1;
        !          2753:        }
        !          2754: 
        !          2755: #ifdef HAVE_PFKEY_POLICY_PRIORITY
        !          2756:        KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
        !          2757:                        saddr + 1,
        !          2758:                        daddr + 1,
        !          2759:                        saddr->sadb_address_prefixlen,
        !          2760:                        daddr->sadb_address_prefixlen,
        !          2761:                        saddr->sadb_address_proto,
        !          2762:                        xpl->sadb_x_policy_priority,
        !          2763:                        created,
        !          2764:                        &spidx);
        !          2765: #else
        !          2766:        KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
        !          2767:                        saddr + 1,
        !          2768:                        daddr + 1,
        !          2769:                        saddr->sadb_address_prefixlen,
        !          2770:                        daddr->sadb_address_prefixlen,
        !          2771:                        saddr->sadb_address_proto,
        !          2772:                        created,
        !          2773:                        &spidx);
        !          2774: #endif
        !          2775: 
        !          2776: #ifdef HAVE_SECCTX
        !          2777:        if (mhp[SADB_X_EXT_SEC_CTX] != NULL) {
        !          2778:                struct sadb_x_sec_ctx *ctx;
        !          2779: 
        !          2780:                ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
        !          2781:                spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg;
        !          2782:                spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi;
        !          2783:                spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len;
        !          2784:                memcpy(spidx.sec_ctx.ctx_str, ctx + 1, ctx->sadb_x_ctx_len);
        !          2785:        }
        !          2786: #endif /* HAVE_SECCTX */
        !          2787: 
        !          2788:        sp = getsp(&spidx);
        !          2789:        if (sp != NULL) {
        !          2790:                plog(LLV_ERROR, LOCATION, NULL,
        !          2791:                        "such policy already exists. "
        !          2792:                        "anyway replace it: %s\n",
        !          2793:                        spidx2str(&spidx));
        !          2794: 
        !          2795:                /* preserve hints before deleting the SP */
        !          2796:                local = sp->local;
        !          2797:                remote = sp->remote;
        !          2798:                sp->local = NULL;
        !          2799:                sp->remote = NULL;
        !          2800: 
        !          2801:                remsp(sp);
        !          2802:                delsp(sp);
        !          2803:        }
        !          2804: 
        !          2805:        /* Add new SP (with old hints) */
        !          2806:        ret = addnewsp(mhp, local, remote);
        !          2807: 
        !          2808:        if (local != NULL)
        !          2809:                racoon_free(local);
        !          2810:        if (remote != NULL)
        !          2811:                racoon_free(remote);
        !          2812: 
        !          2813:        if (ret < 0)
        !          2814:                return -1;
        !          2815: 
        !          2816:        return 0;
        !          2817: }
        !          2818: 
        !          2819: static int
        !          2820: pk_recvspdflush(mhp)
        !          2821:        caddr_t *mhp;
        !          2822: {
        !          2823:        /* sanity check */
        !          2824:        if (mhp[0] == NULL) {
        !          2825:                plog(LLV_ERROR, LOCATION, NULL,
        !          2826:                        "inappropriate sadb spdflush message passed.\n");
        !          2827:                return -1;
        !          2828:        }
        !          2829: 
        !          2830:        flushsp();
        !          2831: 
        !          2832:        return 0;
        !          2833: }
        !          2834: 
        !          2835: #if defined(SADB_X_MIGRATE) && defined(SADB_X_EXT_KMADDRESS)
        !          2836: 
        !          2837: /* MIGRATE support (pk_recvmigrate() is the handler of MIGRATE message).
        !          2838:  *
        !          2839:  * pk_recvmigrate()
        !          2840:  *   1) some preprocessing and checks
        !          2841:  *   2) parsing of sadb_x_kmaddress extension
        !          2842:  *   3) SP lookup using selectors and content of policy extension from MIGRATE
        !          2843:  *   4) resolution of current local and remote IKE addresses
        !          2844:  *   5) Use of addresses to get Phase 1 handler if any
        !          2845:  *   6) Update of IKE addresses in Phase 1 (iph1->local and iph1->remote)
        !          2846:  *   7) Update of IKE addresses in Phase 2 (iph2->src and iph2->dst)
        !          2847:  *   8) Update of IKE addresses in SP (sp->local and sp->remote)
        !          2848:  *   9) Loop on sadb_x_ipsecrequests pairs from MIGRATE
        !          2849:  *      - update of associated ipsecrequests entries in sp->req (should be
        !          2850:  *        only one as racoon does not support bundles), i.e. update of
        !          2851:  *        tunnel endpoints when required.
        !          2852:  *      - If tunnel mode endpoints have been updated, lookup of associated
        !          2853:  *        Phase 2 handle to also update sa_src and sa_dst entries
        !          2854:  *
        !          2855:  * XXX Note that we do not support yet the update of SA addresses for transport
        !          2856:  *     mode, but only the update of SA addresses for tunnel mode (endpoints).
        !          2857:  *     Reasons are:
        !          2858:  *      - there is no initial need for MIPv6
        !          2859:  *      - racoon does not support bundles
        !          2860:  *      - this would imply more work to deal with sainfo update (if feasible).
        !          2861:  */
        !          2862: 
        !          2863: /* Generic argument structure for migration callbacks */
        !          2864: struct migrate_args {
        !          2865:        struct sockaddr *local;
        !          2866:        struct sockaddr *remote;
        !          2867: };
        !          2868: 
        !          2869: /*
        !          2870:  * Update local and remote addresses of given Phase 1. Schedule removal
        !          2871:  * if negotiation was going on and restart a one from updated address.
        !          2872:  *
        !          2873:  * -1 is returned on error. 0 if everything went right.
        !          2874:  */
        !          2875: static int
        !          2876: migrate_ph1_ike_addresses(iph1, arg)
        !          2877:         struct ph1handle *iph1;
        !          2878:         void *arg;
        !          2879: {
        !          2880:        struct migrate_args *ma = (struct migrate_args *) arg;
        !          2881:        struct remoteconf *rmconf;
        !          2882:        u_int16_t port;
        !          2883: 
        !          2884:        /* Already up-to-date? */
        !          2885:        if (cmpsaddr(iph1->local, ma->local) == CMPSADDR_MATCH &&
        !          2886:            cmpsaddr(iph1->remote, ma->remote) == CMPSADDR_MATCH)
        !          2887:                return 0;
        !          2888: 
        !          2889:        if (iph1->status < PHASE1ST_ESTABLISHED) {
        !          2890:                /* Bad luck! We received a MIGRATE *while* negotiating
        !          2891:                 * Phase 1 (i.e. it was not established yet). If we act as
        !          2892:                 * initiator we need to restart the negotiation. As
        !          2893:                 * responder, our best bet is to update our addresses
        !          2894:                 * and wait for the initiator to do something */
        !          2895:                plog(LLV_WARNING, LOCATION, NULL, "MIGRATE received *during* "
        !          2896:                     "Phase 1 negotiation (%s).\n",
        !          2897:                     saddr2str_fromto("%s => %s", ma->local, ma->remote));
        !          2898: 
        !          2899:                /* If we are not acting as initiator, let's just leave and
        !          2900:                 * let the remote peer handle the restart */
        !          2901:                rmconf = getrmconf(ma->remote, 0);
        !          2902:                if (rmconf == NULL || !rmconf->passive) {
        !          2903:                        iph1->status = PHASE1ST_EXPIRED;
        !          2904:                        isakmp_ph1delete(iph1);
        !          2905: 
        !          2906:                        /* This is unlikely, but let's just check if a Phase 1
        !          2907:                         * for the new addresses already exist */
        !          2908:                        if (getph1byaddr(ma->local, ma->remote, 0)) {
        !          2909:                                plog(LLV_WARNING, LOCATION, NULL, "No need "
        !          2910:                                     "to start a new Phase 1 negotiation. One "
        !          2911:                                     "already exists.\n");
        !          2912:                                return 0;
        !          2913:                        }
        !          2914: 
        !          2915:                        plog(LLV_WARNING, LOCATION, NULL, "As initiator, "
        !          2916:                             "restarting it.\n");
        !          2917:                         /* Note that the insertion of the new Phase 1 will not
        !          2918:                          * interfere with the fact we are called from enumph1,
        !          2919:                          * because it is inserted as first element. --arno */
        !          2920:                        isakmp_ph1begin_i(rmconf, ma->local, ma->remote);
        !          2921: 
        !          2922:                        return 0;
        !          2923:                }
        !          2924:        }
        !          2925: 
        !          2926:        if (iph1->local != NULL) {
        !          2927:                plog(LLV_DEBUG, LOCATION, NULL, "Migrating Phase 1 local "
        !          2928:                     "address from %s\n",
        !          2929:                     saddr2str_fromto("%s to %s", iph1->local, ma->local));
        !          2930:                port = extract_port(iph1->local);
        !          2931:                racoon_free(iph1->local);
        !          2932:        } else
        !          2933:                port = 0;
        !          2934: 
        !          2935:        iph1->local = dupsaddr(ma->local);
        !          2936:        if (iph1->local == NULL) {
        !          2937:                plog(LLV_ERROR, LOCATION, NULL, "unable to allocate "
        !          2938:                     "Phase 1 local address.\n");
        !          2939:                return -1;
        !          2940:        }
        !          2941:        set_port(iph1->local, port);
        !          2942: 
        !          2943:        if (iph1->remote != NULL) {
        !          2944:                plog(LLV_DEBUG, LOCATION, NULL, "Migrating Phase 1 remote "
        !          2945:                     "address from %s\n",
        !          2946:                     saddr2str_fromto("%s to %s", iph1->remote, ma->remote));
        !          2947:                port = extract_port(iph1->remote);
        !          2948:                racoon_free(iph1->remote);
        !          2949:        } else
        !          2950:                port = 0;
        !          2951: 
        !          2952:        iph1->remote = dupsaddr(ma->remote);
        !          2953:        if (iph1->remote == NULL) {
        !          2954:                plog(LLV_ERROR, LOCATION, NULL, "unable to allocate "
        !          2955:                     "Phase 1 remote address.\n");
        !          2956:                return -1;
        !          2957:        }
        !          2958:        set_port(iph1->remote, port);
        !          2959: 
        !          2960:        return 0;
        !          2961: }
        !          2962: 
        !          2963: /* Update src and dst of all current Phase 2 handles.
        !          2964:  * with provided local and remote addresses.
        !          2965:  * Our intent is NOT to modify IPsec SA endpoints but IKE
        !          2966:  * addresses so we need to take care to separate those if
        !          2967:  * they are different. -1 is returned on error. 0 if everything
        !          2968:  * went right.
        !          2969:  *
        !          2970:  * Note: we do not maintain port information as it is not
        !          2971:  *       expected to be meaningful --arno
        !          2972:  */
        !          2973: static int
        !          2974: migrate_ph2_ike_addresses(iph2, arg)
        !          2975:        struct ph2handle *iph2;
        !          2976:        void *arg;
        !          2977: {
        !          2978:        struct migrate_args *ma = (struct migrate_args *) arg;
        !          2979:        struct ph1handle *iph1;
        !          2980: 
        !          2981:        /* If Phase 2 has an associated Phase 1, migrate addresses */
        !          2982:        if (iph2->ph1)
        !          2983:                migrate_ph1_ike_addresses(iph2->ph1, arg);
        !          2984: 
        !          2985:        /* Already up-to-date? */
        !          2986:        if (cmpsaddr(iph2->src, ma->local) == CMPSADDR_MATCH &&
        !          2987:            cmpsaddr(iph2->dst, ma->remote) == CMPSADDR_MATCH)
        !          2988:                return 0;
        !          2989: 
        !          2990:        /* save src/dst as sa_src/sa_dst before rewriting */
        !          2991:        if (iph2->sa_src == NULL && iph2->sa_dst == NULL) {
        !          2992:                iph2->sa_src = iph2->src;
        !          2993:                iph2->sa_dst = iph2->dst;
        !          2994:                iph2->src = NULL;
        !          2995:                iph2->dst = NULL;
        !          2996:        }
        !          2997: 
        !          2998:        if (iph2->src != NULL)
        !          2999:                racoon_free(iph2->src);
        !          3000:        iph2->src = dupsaddr(ma->local);
        !          3001:        if (iph2->src == NULL) {
        !          3002:                plog(LLV_ERROR, LOCATION, NULL,
        !          3003:                     "unable to allocate Phase 2 src address.\n");
        !          3004:                return -1;
        !          3005:        }
        !          3006: 
        !          3007:        if (iph2->dst != NULL)
        !          3008:                racoon_free(iph2->dst);
        !          3009:        iph2->dst = dupsaddr(ma->remote);
        !          3010:        if (iph2->dst == NULL) {
        !          3011:                plog(LLV_ERROR, LOCATION, NULL,
        !          3012:                     "unable to allocate Phase 2 dst address.\n");
        !          3013:                return -1;
        !          3014:        }
        !          3015: 
        !          3016:        return 0;
        !          3017: }
        !          3018: 
        !          3019: /* Consider existing Phase 2 handles with given spid and update their source
        !          3020:  * and destination addresses for SA. As racoon does not support bundles, if
        !          3021:  * we modify multiple occurrences, this probably imply rekeying has happened.
        !          3022:  *
        !          3023:  * Both addresses passed to the function are expected not to be NULL and of
        !          3024:  * same family. -1 is returned on error. 0 if everything went right.
        !          3025:  *
        !          3026:  * Specific care is needed to support Phase 2 for which negotiation has
        !          3027:  * already started but are which not yet established.
        !          3028:  */
        !          3029: static int
        !          3030: migrate_ph2_sa_addresses(iph2, args)
        !          3031:        struct ph2handle *iph2;
        !          3032:        void *args;
        !          3033: {
        !          3034:        struct migrate_args *ma = (struct migrate_args *) args;
        !          3035: 
        !          3036:        if (iph2->sa_src != NULL) {
        !          3037:                racoon_free(iph2->sa_src);
        !          3038:                iph2->sa_src = NULL;
        !          3039:        }
        !          3040: 
        !          3041:        if (iph2->sa_dst != NULL) {
        !          3042:                racoon_free(iph2->sa_dst);
        !          3043:                iph2->sa_dst = NULL;
        !          3044:        }
        !          3045: 
        !          3046:        iph2->sa_src = dupsaddr(ma->local);
        !          3047:        if (iph2->sa_src == NULL) {
        !          3048:                plog(LLV_ERROR, LOCATION, NULL,
        !          3049:                     "unable to allocate Phase 2 sa_src address.\n");
        !          3050:                return -1;
        !          3051:        }
        !          3052: 
        !          3053:        iph2->sa_dst = dupsaddr(ma->remote);
        !          3054:        if (iph2->sa_dst == NULL) {
        !          3055:                plog(LLV_ERROR, LOCATION, NULL,
        !          3056:                     "unable to allocate Phase 2 sa_dst address.\n");
        !          3057:                return -1;
        !          3058:        }
        !          3059: 
        !          3060:        if (iph2->status < PHASE2ST_ESTABLISHED) {
        !          3061:                struct remoteconf *rmconf;
        !          3062:                /* We were negotiating for that SA when we received the MIGRATE.
        !          3063:                 * We cannot simply update the addresses and let the exchange
        !          3064:                 * go on. We have to restart the whole negotiation if we are
        !          3065:                 * the initiator. Otherwise (acting as responder), we just need
        !          3066:                 * to delete our ph2handle and wait for the initiator to start
        !          3067:                 * a new negotiation. */
        !          3068: 
        !          3069:                if (iph2->ph1 && iph2->ph1->rmconf)
        !          3070:                        rmconf = iph2->ph1->rmconf;
        !          3071:                else
        !          3072:                        rmconf = getrmconf(iph2->dst, 0);
        !          3073: 
        !          3074:                if (rmconf && !rmconf->passive) {
        !          3075:                        struct ph1handle *iph1hint;
        !          3076: 
        !          3077:                        plog(LLV_WARNING, LOCATION, iph2->dst, "MIGRATE received "
        !          3078:                             "*during* IPsec SA negotiation. As initiator, "
        !          3079:                             "restarting it.\n");
        !          3080: 
        !          3081:                        /* Turn off expiration timer ...*/
        !          3082:                        sched_cancel(&iph2->sce);
        !          3083:                        iph2->status = PHASE2ST_EXPIRED;
        !          3084: 
        !          3085:                        /* ... clean Phase 2 handle ... */
        !          3086:                        iph1hint = iph2->ph1;
        !          3087:                        initph2(iph2);
        !          3088:                        iph2->status = PHASE2ST_STATUS2;
        !          3089: 
        !          3090:                        /* and start a new negotiation */
        !          3091:                        if (isakmp_post_acquire(iph2, iph1hint, FALSE) < 0) {
        !          3092:                                plog(LLV_ERROR, LOCATION, iph2->dst, "failed "
        !          3093:                                     "to begin IPsec SA renegotiation after "
        !          3094:                                     "MIGRATE reception.\n");
        !          3095:                                remph2(iph2);
        !          3096:                                delph2(iph2);
        !          3097:                                return -1;
        !          3098:                        }
        !          3099:                } else {
        !          3100:                        plog(LLV_WARNING, LOCATION, iph2->dst, "MIGRATE received "
        !          3101:                             "*during* IPsec SA negotiation. As responder, let's"
        !          3102:                             "wait for the initiator to act.\n");
        !          3103: 
        !          3104:                        /* Simply schedule deletion */
        !          3105:                        isakmp_ph2expire(iph2);
        !          3106:                }
        !          3107:        }
        !          3108: 
        !          3109:        return 0;
        !          3110: }
        !          3111: 
        !          3112: /* Update SP hints (local and remote addresses) for future IKE
        !          3113:  * negotiations of SA associated with that SP. -1 is returned
        !          3114:  * on error. 0 if everything went right.
        !          3115:  *
        !          3116:  * Note: we do not maintain port information as it is not
        !          3117:  *       expected to be meaningful --arno
        !          3118:  */
        !          3119: static int
        !          3120: migrate_sp_ike_addresses(sp, local, remote)
        !          3121:         struct secpolicy *sp;
        !          3122:         struct sockaddr *local, *remote;
        !          3123: {
        !          3124:        if (sp == NULL || local == NULL || remote == NULL)
        !          3125:                return -1;
        !          3126: 
        !          3127:        if (sp->local != NULL)
        !          3128:                racoon_free(sp->local);
        !          3129: 
        !          3130:        sp->local = dupsaddr(local);
        !          3131:        if (sp->local == NULL) {
        !          3132:                plog(LLV_ERROR, LOCATION, NULL, "unable to allocate "
        !          3133:                     "local hint for SP.\n");
        !          3134:                return -1;
        !          3135:        }
        !          3136: 
        !          3137:        if (sp->remote != NULL)
        !          3138:                racoon_free(sp->remote);
        !          3139: 
        !          3140:        sp->remote = dupsaddr(remote);
        !          3141:        if (sp->remote == NULL) {
        !          3142:                plog(LLV_ERROR, LOCATION, NULL, "unable to allocate "
        !          3143:                     "remote hint for SP.\n");
        !          3144:                return -1;
        !          3145:        }
        !          3146: 
        !          3147:        return 0;
        !          3148: }
        !          3149: 
        !          3150: /* Given current ipsecrequest (isr_cur) to be migrated in considered
        !          3151:    tree, the function first checks that it matches the expected one
        !          3152:    (xisr_old) provided in MIGRATE message and then updates the addresses
        !          3153:    if it is tunnel mode (with content of xisr_new). Various other checks
        !          3154:    are performed. For transport mode, structures are not modified, only
        !          3155:    the checks are done. -1 is returned on error. */
        !          3156: static int
        !          3157: migrate_ph2_one_isr(spid, isr_cur, xisr_old, xisr_new)
        !          3158:         u_int32_t spid;
        !          3159:         struct ipsecrequest *isr_cur;
        !          3160:        struct sadb_x_ipsecrequest *xisr_old, *xisr_new;
        !          3161: {
        !          3162:        struct secasindex *saidx = &isr_cur->saidx;
        !          3163:        struct sockaddr *osaddr, *odaddr, *nsaddr, *ndaddr;
        !          3164:        struct ph2selector ph2sel;
        !          3165:        struct migrate_args ma;
        !          3166: 
        !          3167:        /* First, check that mode and proto do match */
        !          3168:        if (xisr_old->sadb_x_ipsecrequest_proto != saidx->proto ||
        !          3169:            xisr_old->sadb_x_ipsecrequest_mode != saidx->mode ||
        !          3170:            xisr_new->sadb_x_ipsecrequest_proto != saidx->proto ||
        !          3171:            xisr_new->sadb_x_ipsecrequest_mode != saidx->mode)
        !          3172:                return -1;
        !          3173: 
        !          3174:        /* Then, verify reqid if necessary */
        !          3175:        if (isr_cur->saidx.reqid &&
        !          3176:            (xisr_old->sadb_x_ipsecrequest_reqid != IPSEC_LEVEL_UNIQUE ||
        !          3177:             xisr_new->sadb_x_ipsecrequest_reqid != IPSEC_LEVEL_UNIQUE ||
        !          3178:             isr_cur->saidx.reqid != xisr_old->sadb_x_ipsecrequest_reqid ||
        !          3179:             isr_cur->saidx.reqid != xisr_new->sadb_x_ipsecrequest_reqid))
        !          3180:                return -1;
        !          3181: 
        !          3182:        /* If not tunnel mode, our work is over */
        !          3183:        if (saidx->mode != IPSEC_MODE_TUNNEL) {
        !          3184:                plog(LLV_DEBUG, LOCATION, NULL, "SADB_X_MIGRATE: "
        !          3185:                     "non tunnel mode isr, skipping SA address migration.\n");
        !          3186:                return 0;
        !          3187:        }
        !          3188: 
        !          3189:        /* Tunnel mode: let's check addresses do match and then update them. */
        !          3190:        osaddr = (struct sockaddr *)(xisr_old + 1);
        !          3191:        odaddr = (struct sockaddr *)(((u_int8_t *)osaddr) + sysdep_sa_len(osaddr));
        !          3192:        nsaddr = (struct sockaddr *)(xisr_new + 1);
        !          3193:        ndaddr = (struct sockaddr *)(((u_int8_t *)nsaddr) + sysdep_sa_len(nsaddr));
        !          3194: 
        !          3195:        /* Check family does match */
        !          3196:        if (osaddr->sa_family != odaddr->sa_family ||
        !          3197:            nsaddr->sa_family != ndaddr->sa_family)
        !          3198:                return -1;
        !          3199: 
        !          3200:        /* Check family does match */
        !          3201:        if (saidx->src.ss_family != osaddr->sa_family)
        !          3202:                return -1;
        !          3203: 
        !          3204:        /* We log IPv4 to IPv6 and IPv6 to IPv4 switches */
        !          3205:        if (nsaddr->sa_family != osaddr->sa_family)
        !          3206:                plog(LLV_INFO, LOCATION, NULL, "SADB_X_MIGRATE: "
        !          3207:                     "changing address families (%d to %d) for endpoints.\n",
        !          3208:                     osaddr->sa_family, nsaddr->sa_family);
        !          3209: 
        !          3210:        if (cmpsaddr(osaddr, (struct sockaddr *) &saidx->src) != CMPSADDR_MATCH ||
        !          3211:            cmpsaddr(odaddr, (struct sockaddr *) &saidx->dst) != CMPSADDR_MATCH) {
        !          3212:                plog(LLV_DEBUG, LOCATION, NULL, "SADB_X_MIGRATE: "
        !          3213:                     "mismatch of addresses in saidx and xisr.\n");
        !          3214:                return -1;
        !          3215:        }
        !          3216: 
        !          3217:        /* Excellent. Let's grab associated Phase 2 handle (if any)
        !          3218:         * and update its sa_src and sa_dst entries.  Note that we
        !          3219:         * make the assumption that racoon does not support bundles
        !          3220:         * and make the lookup using spid: we blindly update
        !          3221:         * sa_src and sa_dst for _all_ found Phase 2 handles */
        !          3222:        memset(&ph2sel, 0, sizeof(ph2sel));
        !          3223:        ph2sel.spid = spid;
        !          3224: 
        !          3225:        memset(&ma, 0, sizeof(ma));
        !          3226:        ma.local = nsaddr;
        !          3227:        ma.remote = ndaddr;
        !          3228: 
        !          3229:        if (enumph2(&ph2sel, migrate_ph2_sa_addresses, &ma) < 0)
        !          3230:                return -1;
        !          3231: 
        !          3232:        /* Now we can do the update of endpoints in secasindex */
        !          3233:        memcpy(&saidx->src, nsaddr, sysdep_sa_len(nsaddr));
        !          3234:        memcpy(&saidx->dst, ndaddr, sysdep_sa_len(ndaddr));
        !          3235: 
        !          3236:        return 0;
        !          3237: }
        !          3238: 
        !          3239: /* Process the raw (unparsed yet) list of sadb_x_ipsecrequests of MIGRATE
        !          3240:  * message. For each sadb_x_ipsecrequest pair (old followed by new),
        !          3241:  * the corresponding ipsecrequest entry in the SP is updated. Associated
        !          3242:  * existing Phase 2 handle is also updated (if any) */
        !          3243: static int
        !          3244: migrate_sp_isr_list(sp, xisr_list, xisr_list_len)
        !          3245:         struct secpolicy *sp;
        !          3246:        struct sadb_x_ipsecrequest *xisr_list;
        !          3247:        int xisr_list_len;
        !          3248: {
        !          3249:        struct sadb_x_ipsecrequest *xisr_new, *xisr_old = xisr_list;
        !          3250:        int xisr_old_len, xisr_new_len;
        !          3251:        struct ipsecrequest *isr_cur;
        !          3252: 
        !          3253:        isr_cur = sp->req; /* ipsecrequest list from from sp */
        !          3254: 
        !          3255:        while (xisr_list_len > 0 && isr_cur != NULL) {
        !          3256:                /* Get old xisr (length field is in bytes) */
        !          3257:                xisr_old_len = xisr_old->sadb_x_ipsecrequest_len;
        !          3258:                if (xisr_old_len < sizeof(*xisr_old) ||
        !          3259:                    xisr_old_len + sizeof(*xisr_new) > xisr_list_len) {
        !          3260:                        plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: "
        !          3261:                             "invalid ipsecrequest length. Exiting.\n");
        !          3262:                        return -1;
        !          3263:                }
        !          3264: 
        !          3265:                /* Get new xisr with updated info */
        !          3266:                xisr_new = (struct sadb_x_ipsecrequest *)(((u_int8_t *)xisr_old) + xisr_old_len);
        !          3267:                xisr_new_len = xisr_new->sadb_x_ipsecrequest_len;
        !          3268:                if (xisr_new_len < sizeof(*xisr_new) ||
        !          3269:                    xisr_new_len + xisr_old_len > xisr_list_len) {
        !          3270:                        plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: "
        !          3271:                             "invalid ipsecrequest length. Exiting.\n");
        !          3272:                        return -1;
        !          3273:                }
        !          3274: 
        !          3275:                /* Start by migrating current ipsecrequest from SP */
        !          3276:                if (migrate_ph2_one_isr(sp->id, isr_cur, xisr_old, xisr_new) == -1) {
        !          3277:                        plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: "
        !          3278:                             "Unable to match and migrate isr. Exiting.\n");
        !          3279:                        return -1;
        !          3280:                }
        !          3281: 
        !          3282:                /* Update pointers for next round */
        !          3283:                xisr_list_len -= xisr_old_len + xisr_new_len;
        !          3284:                xisr_old = (struct sadb_x_ipsecrequest *)(((u_int8_t *)xisr_new) +
        !          3285:                                                          xisr_new_len);
        !          3286: 
        !          3287:                isr_cur = isr_cur->next; /* Get next ipsecrequest from SP */
        !          3288:        }
        !          3289: 
        !          3290:        /* Check we had the same amount of pairs in the MIGRATE
        !          3291:           as the number of ipsecrequests in the SP */
        !          3292:        if ((xisr_list_len != 0) || isr_cur != NULL) {
        !          3293:                plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: "
        !          3294:                     "number of ipsecrequest does not match the one in SP.\n");
        !          3295:                return -1;
        !          3296:        }
        !          3297: 
        !          3298:        return 0;
        !          3299: }
        !          3300: 
        !          3301: /* Parse sadb_x_kmaddress extension and make local and remote
        !          3302:  * parameters point to the new addresses (zero copy). -1 is
        !          3303:  * returned on error, meaning that addresses are not usable */
        !          3304: static int
        !          3305: parse_kmaddress(kmaddr, local, remote)
        !          3306:         struct sadb_x_kmaddress *kmaddr;
        !          3307:        struct sockaddr **local, **remote;
        !          3308: {
        !          3309:        int addrslen, local_len=0;
        !          3310:        struct ph1handle *iph1;
        !          3311: 
        !          3312:        if (kmaddr == NULL)
        !          3313:                return -1;
        !          3314: 
        !          3315:        /* Grab addresses in sadb_x_kmaddress extension */
        !          3316:        addrslen = PFKEY_EXTLEN(kmaddr) - sizeof(*kmaddr);
        !          3317:        if (addrslen < sizeof(struct sockaddr))
        !          3318:                return -1;
        !          3319: 
        !          3320:        *local = (struct sockaddr *)(kmaddr + 1);
        !          3321: 
        !          3322:        switch ((*local)->sa_family) {
        !          3323:        case AF_INET:
        !          3324:                local_len = sizeof(struct sockaddr_in);
        !          3325:                break;
        !          3326: #ifdef INET6
        !          3327:        case AF_INET6:
        !          3328:                local_len = sizeof(struct sockaddr_in6);
        !          3329:                break;
        !          3330: #endif
        !          3331:        default:
        !          3332:                return -1;
        !          3333:        }
        !          3334: 
        !          3335:        if (addrslen != PFKEY_ALIGN8(2*local_len))
        !          3336:                return -1;
        !          3337: 
        !          3338:        *remote = (struct sockaddr *)(((u_int8_t *)(*local)) + local_len);
        !          3339: 
        !          3340:        if ((*local)->sa_family != (*remote)->sa_family)
        !          3341:                return -1;
        !          3342: 
        !          3343:        return 0;
        !          3344: }
        !          3345: 
        !          3346: /* Handler of PF_KEY MIGRATE message. Helpers are above */
        !          3347: static int
        !          3348: pk_recvmigrate(mhp)
        !          3349:        caddr_t *mhp;
        !          3350: {
        !          3351:        struct sadb_address *saddr, *daddr;
        !          3352:        struct sockaddr *old_saddr, *new_saddr;
        !          3353:        struct sockaddr *old_daddr, *new_daddr;
        !          3354:        struct sockaddr *old_local, *old_remote;
        !          3355:        struct sockaddr *local, *remote;
        !          3356:        struct sadb_x_kmaddress *kmaddr;
        !          3357:        struct sadb_x_policy *xpl;
        !          3358:        struct sadb_x_ipsecrequest *xisr_list;
        !          3359:        struct sadb_lifetime *lt;
        !          3360:        struct policyindex spidx;
        !          3361:        struct secpolicy *sp;
        !          3362:        struct ipsecrequest *isr_cur;
        !          3363:        struct secasindex *oldsaidx;
        !          3364:        struct ph2handle *iph2;
        !          3365:        struct ph1handle *iph1;
        !          3366:        struct ph2selector ph2sel;
        !          3367:        struct ph1selector ph1sel;
        !          3368:        u_int32_t spid;
        !          3369:        u_int64_t created;
        !          3370:        int xisr_list_len;
        !          3371:        int ulproto;
        !          3372:        struct migrate_args ma;
        !          3373: 
        !          3374:        /* Some sanity checks */
        !          3375: 
        !          3376:        if (mhp[0] == NULL
        !          3377:         || mhp[SADB_EXT_ADDRESS_SRC] == NULL
        !          3378:         || mhp[SADB_EXT_ADDRESS_DST] == NULL
        !          3379:         || mhp[SADB_X_EXT_KMADDRESS] == NULL
        !          3380:         || mhp[SADB_X_EXT_POLICY] == NULL) {
        !          3381:                plog(LLV_ERROR, LOCATION, NULL,
        !          3382:                        "SADB_X_MIGRATE: invalid MIGRATE message received.\n");
        !          3383:                return -1;
        !          3384:        }
        !          3385:        kmaddr = (struct sadb_x_kmaddress *)mhp[SADB_X_EXT_KMADDRESS];
        !          3386:        saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
        !          3387:        daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
        !          3388:        xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
        !          3389:        lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
        !          3390:        if (lt != NULL)
        !          3391:                created = lt->sadb_lifetime_addtime;
        !          3392:        else
        !          3393:                created = 0;
        !          3394: 
        !          3395:        if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) {
        !          3396:                plog(LLV_WARNING, LOCATION, NULL,"SADB_X_MIGRATE: "
        !          3397:                     "found non IPsec policy in MIGRATE message. Exiting.\n");
        !          3398:                return -1;
        !          3399:        }
        !          3400: 
        !          3401:        if (PFKEY_EXTLEN(xpl) < sizeof(*xpl)) {
        !          3402:                plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: "
        !          3403:                     "invalid size for sadb_x_policy. Exiting.\n");
        !          3404:                return -1;
        !          3405:        }
        !          3406: 
        !          3407:        /* Some logging to help debbugging */
        !          3408:        if (xpl->sadb_x_policy_dir == IPSEC_DIR_OUTBOUND)
        !          3409:                plog(LLV_DEBUG, LOCATION, NULL,
        !          3410:                     "SADB_X_MIGRATE: Outbound SA being migrated.\n");
        !          3411:        else
        !          3412:                plog(LLV_DEBUG, LOCATION, NULL,
        !          3413:                     "SADB_X_MIGRATE: Inbound SA being migrated.\n");
        !          3414: 
        !          3415:        /* validity check */
        !          3416:        xisr_list = (struct sadb_x_ipsecrequest *)(xpl + 1);
        !          3417:        xisr_list_len = PFKEY_EXTLEN(xpl) - sizeof(*xpl);
        !          3418:        if (xisr_list_len < sizeof(*xisr_list)) {
        !          3419:                plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: "
        !          3420:                     "invalid sadb_x_policy message length. Exiting.\n");
        !          3421:                return -1;
        !          3422:        }
        !          3423: 
        !          3424:        if (parse_kmaddress(kmaddr, &local, &remote) == -1) {
        !          3425:                plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: "
        !          3426:                     "invalid sadb_x_kmaddress extension. Exiting.\n");
        !          3427:                return -1;
        !          3428:        }
        !          3429: 
        !          3430:        /* 0 means ANY */
        !          3431:        if (saddr->sadb_address_proto == 0)
        !          3432:                ulproto = IPSEC_ULPROTO_ANY;
        !          3433:        else
        !          3434:                ulproto = saddr->sadb_address_proto;
        !          3435: 
        !          3436: #ifdef HAVE_PFKEY_POLICY_PRIORITY
        !          3437:        KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
        !          3438:                        saddr + 1,
        !          3439:                        daddr + 1,
        !          3440:                        saddr->sadb_address_prefixlen,
        !          3441:                        daddr->sadb_address_prefixlen,
        !          3442:                        ulproto,
        !          3443:                        xpl->sadb_x_policy_priority,
        !          3444:                        created,
        !          3445:                        &spidx);
        !          3446: #else
        !          3447:        KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
        !          3448:                        saddr + 1,
        !          3449:                        daddr + 1,
        !          3450:                        saddr->sadb_address_prefixlen,
        !          3451:                        daddr->sadb_address_prefixlen,
        !          3452:                        ulproto,
        !          3453:                        created,
        !          3454:                        &spidx);
        !          3455: #endif
        !          3456: 
        !          3457:        /* Everything seems ok, let's get the SP.
        !          3458:         *
        !          3459:         * XXX We could also do the lookup using the spid from xpl.
        !          3460:         *     I don't know which one is better.  --arno */
        !          3461:        sp = getsp(&spidx);
        !          3462:        if (sp == NULL) {
        !          3463:                plog(LLV_ERROR, LOCATION, NULL,
        !          3464:                        "SADB_X_MIGRATE: Passed policy does not exist: %s\n",
        !          3465:                        spidx2str(&spidx));
        !          3466:                return -1;
        !          3467:        }
        !          3468: 
        !          3469:        /* Get the best source and destination addresses used for IKE
        !          3470:         * negotiation, to find and migrate existing Phase 1 */
        !          3471:        if (sp->local && sp->remote) {
        !          3472:                /* hints available, let's use them */
        !          3473:                old_local  = (struct sockaddr *)sp->local;
        !          3474:                old_remote = (struct sockaddr *)sp->remote;
        !          3475:        } else if (sp->req && sp->req->saidx.mode == IPSEC_MODE_TUNNEL) {
        !          3476:                /* Tunnel mode and no hint, use endpoints */
        !          3477:                old_local  = (struct sockaddr *)&sp->req->saidx.src;
        !          3478:                old_remote = (struct sockaddr *)&sp->req->saidx.dst;
        !          3479:        } else {
        !          3480:                /* default, use selectors as fallback */
        !          3481:                old_local  = (struct sockaddr *)&sp->spidx.src;
        !          3482:                old_remote = (struct sockaddr *)&sp->spidx.dst;
        !          3483:        }
        !          3484: 
        !          3485:        /* We migrate all Phase 1 that match our old local and remote
        !          3486:         * addresses (no matter their state).
        !          3487:         *
        !          3488:         * XXX In fact, we should probably havea special treatment for
        !          3489:         * Phase 1 that are being established when we receive a MIGRATE.
        !          3490:         * This can happen if a movement occurs during the initial IKE
        !          3491:         * negotiation. In that case, I wonder if should restart the
        !          3492:         * negotiation from the new address or just update things like
        !          3493:         * we do it now.
        !          3494:         *
        !          3495:         * XXX while looking at getph1byaddr(), the comment at the
        !          3496:         * beginning of the function expects comparison to happen
        !          3497:         * without ports considerations but it uses CMPSADDR() which
        !          3498:         * relies either on cmpsaddrstrict() or cmpsaddrwop() based
        !          3499:         * on NAT-T support being activated. That make me wonder if I
        !          3500:         * should force ports to 0 (ANY) in local and remote values
        !          3501:         * used below.
        !          3502:         *
        !          3503:         * -- arno */
        !          3504: 
        !          3505:        /* Apply callback data ...*/
        !          3506:        memset(&ma, 0, sizeof(ma));
        !          3507:        ma.local = local;
        !          3508:        ma.remote = remote;
        !          3509: 
        !          3510:        /* Fill phase1 match criteria ... */
        !          3511:        memset(&ph1sel, 0, sizeof(ph1sel));
        !          3512:        ph1sel.local = old_local;
        !          3513:        ph1sel.remote = old_remote;
        !          3514: 
        !          3515: 
        !          3516:        /* Have matching Phase 1 found and addresses updated. As this is a
        !          3517:         * time consuming task on a busy responder, and MIGRATE messages
        !          3518:         * are always sent for *both* inbound and outbound (and possibly
        !          3519:         * forward), we only do that for outbound SP. */
        !          3520:        if (xpl->sadb_x_policy_dir == IPSEC_DIR_OUTBOUND &&
        !          3521:            enumph1(&ph1sel, migrate_ph1_ike_addresses, &ma) < 0) {
        !          3522:                plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: Unable "
        !          3523:                     "to migrate Phase 1 addresses.\n");
        !          3524:                return -1;
        !          3525:        }
        !          3526: 
        !          3527:        /* We can now update IKE addresses in Phase 2 handle. */
        !          3528:        memset(&ph2sel, 0, sizeof(ph2sel));
        !          3529:        ph2sel.spid = sp->id;
        !          3530:        if (enumph2(&ph2sel, migrate_ph2_ike_addresses, &ma) < 0) {
        !          3531:                plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: Unable "
        !          3532:                     "to migrate Phase 2 IKE addresses.\n");
        !          3533:                return -1;
        !          3534:        }
        !          3535: 
        !          3536:        /* and _then_ in SP. */
        !          3537:        if (migrate_sp_ike_addresses(sp, local, remote) < 0) {
        !          3538:                plog(LLV_ERROR, LOCATION, NULL,
        !          3539:                     "SADB_X_MIGRATE: Unable to migrate SP IKE addresses.\n");
        !          3540:                return -1;
        !          3541:        }
        !          3542: 
        !          3543:        /* Loop on sadb_x_ipsecrequest list to possibly update sp->req
        !          3544:         * entries and associated live Phase 2 handles (their sa_src
        !          3545:         * and sa_dst) */
        !          3546:        if (migrate_sp_isr_list(sp, xisr_list, xisr_list_len) < 0) {
        !          3547:                plog(LLV_ERROR, LOCATION, NULL,
        !          3548:                     "SADB_X_MIGRATE: Unable to migrate isr list.\n");
        !          3549:                return -1;
        !          3550:        }
        !          3551: 
        !          3552:        return 0;
        !          3553: }
        !          3554: #endif
        !          3555: 
        !          3556: /*
        !          3557:  * send error against acquire message to kernel.
        !          3558:  */
        !          3559: int
        !          3560: pk_sendeacquire(iph2)
        !          3561:        struct ph2handle *iph2;
        !          3562: {
        !          3563:        struct sadb_msg *newmsg;
        !          3564:        int len;
        !          3565: 
        !          3566:        len = sizeof(struct sadb_msg);
        !          3567:        newmsg = racoon_calloc(1, len);
        !          3568:        if (newmsg == NULL) {
        !          3569:                plog(LLV_ERROR, LOCATION, NULL,
        !          3570:                        "failed to get buffer to send acquire.\n");
        !          3571:                return -1;
        !          3572:        }
        !          3573: 
        !          3574:        memset(newmsg, 0, len);
        !          3575:        newmsg->sadb_msg_version = PF_KEY_V2;
        !          3576:        newmsg->sadb_msg_type = SADB_ACQUIRE;
        !          3577:        newmsg->sadb_msg_errno = ENOENT;        /* XXX */
        !          3578:        newmsg->sadb_msg_satype = iph2->satype;
        !          3579:        newmsg->sadb_msg_len = PFKEY_UNIT64(len);
        !          3580:        newmsg->sadb_msg_reserved = 0;
        !          3581:        newmsg->sadb_msg_seq = iph2->seq;
        !          3582:        newmsg->sadb_msg_pid = (u_int32_t)getpid();
        !          3583: 
        !          3584:        /* send message */
        !          3585:        len = pfkey_send(lcconf->sock_pfkey, newmsg, len);
        !          3586: 
        !          3587:        racoon_free(newmsg);
        !          3588: 
        !          3589:        return 0;
        !          3590: }
        !          3591: 
        !          3592: /*
        !          3593:  * check if the algorithm is supported or not.
        !          3594:  * OUT  0: ok
        !          3595:  *     -1: ng
        !          3596:  */
        !          3597: int
        !          3598: pk_checkalg(class, calg, keylen)
        !          3599:        int class, calg, keylen;
        !          3600: {
        !          3601:        int sup, error;
        !          3602:        u_int alg;
        !          3603:        struct sadb_alg alg0;
        !          3604: 
        !          3605:        switch (algclass2doi(class)) {
        !          3606:        case IPSECDOI_PROTO_IPSEC_ESP:
        !          3607:                sup = SADB_EXT_SUPPORTED_ENCRYPT;
        !          3608:                break;
        !          3609:        case IPSECDOI_ATTR_AUTH:
        !          3610:                sup = SADB_EXT_SUPPORTED_AUTH;
        !          3611:                break;
        !          3612:        case IPSECDOI_PROTO_IPCOMP:
        !          3613:                plog(LLV_DEBUG, LOCATION, NULL,
        !          3614:                        "no check of compression algorithm; "
        !          3615:                        "not supported in sadb message.\n");
        !          3616:                return 0;
        !          3617:        default:
        !          3618:                plog(LLV_ERROR, LOCATION, NULL,
        !          3619:                        "invalid algorithm class.\n");
        !          3620:                return -1;
        !          3621:        }
        !          3622:        alg = ipsecdoi2pfkey_alg(algclass2doi(class), algtype2doi(class, calg));
        !          3623:        if (alg == ~0)
        !          3624:                return -1;
        !          3625: 
        !          3626:        if (keylen == 0) {
        !          3627:                if (ipsec_get_keylen(sup, alg, &alg0)) {
        !          3628:                        plog(LLV_ERROR, LOCATION, NULL,
        !          3629:                                "%s.\n", ipsec_strerror());
        !          3630:                        return -1;
        !          3631:                }
        !          3632:                keylen = alg0.sadb_alg_minbits;
        !          3633:        }
        !          3634: 
        !          3635:        error = ipsec_check_keylen(sup, alg, keylen);
        !          3636:        if (error)
        !          3637:                plog(LLV_ERROR, LOCATION, NULL,
        !          3638:                        "%s.\n", ipsec_strerror());
        !          3639: 
        !          3640:        return error;
        !          3641: }
        !          3642: 
        !          3643: /*
        !          3644:  * differences with pfkey_recv() in libipsec/pfkey.c:
        !          3645:  * - never performs busy wait loop.
        !          3646:  * - returns NULL and set *lenp to negative on fatal failures
        !          3647:  * - returns NULL and set *lenp to non-negative on non-fatal failures
        !          3648:  * - returns non-NULL on success
        !          3649:  */
        !          3650: static struct sadb_msg *
        !          3651: pk_recv(so, lenp)
        !          3652:        int so;
        !          3653:        int *lenp;
        !          3654: {
        !          3655:        struct sadb_msg buf, *newmsg;
        !          3656:        int reallen;
        !          3657:        int retry = 0;
        !          3658: 
        !          3659:        *lenp = -1;
        !          3660:        do
        !          3661:        {
        !          3662:            plog(LLV_DEBUG, LOCATION, NULL, "pk_recv: retry[%d] recv() \n", retry );
        !          3663:            *lenp = recv(so, (caddr_t)&buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT);
        !          3664:            retry++;
        !          3665:        }
        !          3666:        while (*lenp < 0 && errno == EAGAIN && retry < 3);
        !          3667: 
        !          3668:        if (*lenp < 0)
        !          3669:                return NULL;    /*fatal*/
        !          3670: 
        !          3671:        else if (*lenp < sizeof(buf))
        !          3672:                return NULL;
        !          3673: 
        !          3674:        reallen = PFKEY_UNUNIT64(buf.sadb_msg_len);
        !          3675:        if (reallen < sizeof(buf)) {
        !          3676:                *lenp = -1;
        !          3677:                errno = EIO;
        !          3678:                return NULL;    /*fatal*/
        !          3679:        }
        !          3680:        if ((newmsg = racoon_calloc(1, reallen)) == NULL)
        !          3681:                return NULL;
        !          3682: 
        !          3683:        *lenp = recv(so, (caddr_t)newmsg, reallen, MSG_PEEK);
        !          3684:        if (*lenp < 0) {
        !          3685:                racoon_free(newmsg);
        !          3686:                return NULL;    /*fatal*/
        !          3687:        } else if (*lenp != reallen) {
        !          3688:                racoon_free(newmsg);
        !          3689:                return NULL;
        !          3690:        }
        !          3691: 
        !          3692:        *lenp = recv(so, (caddr_t)newmsg, reallen, 0);
        !          3693:        if (*lenp < 0) {
        !          3694:                racoon_free(newmsg);
        !          3695:                return NULL;    /*fatal*/
        !          3696:        } else if (*lenp != reallen) {
        !          3697:                racoon_free(newmsg);
        !          3698:                return NULL;
        !          3699:        }
        !          3700: 
        !          3701:        return newmsg;
        !          3702: }
        !          3703: 
        !          3704: /* see handler.h */
        !          3705: u_int32_t
        !          3706: pk_getseq()
        !          3707: {
        !          3708:        return eay_random();
        !          3709: }
        !          3710: 
        !          3711: static int
        !          3712: addnewsp(mhp, local, remote)
        !          3713:        caddr_t *mhp;
        !          3714:        struct sockaddr *local, *remote;
        !          3715: {
        !          3716:        struct secpolicy *new = NULL;
        !          3717:        struct sadb_address *saddr, *daddr;
        !          3718:        struct sadb_x_policy *xpl;
        !          3719:        struct sadb_lifetime *lt;
        !          3720:        u_int64_t created;
        !          3721: 
        !          3722:        /* sanity check */
        !          3723:        if (mhp[SADB_EXT_ADDRESS_SRC] == NULL
        !          3724:         || mhp[SADB_EXT_ADDRESS_DST] == NULL
        !          3725:         || mhp[SADB_X_EXT_POLICY] == NULL) {
        !          3726:                plog(LLV_ERROR, LOCATION, NULL,
        !          3727:                        "inappropriate sadb spd management message passed.\n");
        !          3728:                goto bad;
        !          3729:        }
        !          3730: 
        !          3731:        saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
        !          3732:        daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
        !          3733:        xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
        !          3734:        lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
        !          3735:        if(lt != NULL)
        !          3736:                created = lt->sadb_lifetime_addtime;
        !          3737:        else
        !          3738:                created = 0;
        !          3739:        lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
        !          3740:        if(lt != NULL)
        !          3741:                created = lt->sadb_lifetime_addtime;
        !          3742:        else
        !          3743:                created = 0;
        !          3744: 
        !          3745: #ifdef __linux__
        !          3746:        /* bsd skips over per-socket policies because there will be no
        !          3747:         * src and dst extensions in spddump messages. On Linux the only
        !          3748:         * way to achieve the same is check for policy id.
        !          3749:         */
        !          3750:        if (xpl->sadb_x_policy_id % 8 >= 3) return 0;
        !          3751: #endif
        !          3752: 
        !          3753:        new = newsp();
        !          3754:        if (new == NULL) {
        !          3755:                plog(LLV_ERROR, LOCATION, NULL,
        !          3756:                        "failed to allocate buffer\n");
        !          3757:                goto bad;
        !          3758:        }
        !          3759: 
        !          3760:        new->spidx.dir = xpl->sadb_x_policy_dir;
        !          3761:        new->id = xpl->sadb_x_policy_id;
        !          3762:        new->policy = xpl->sadb_x_policy_type;
        !          3763:        new->req = NULL;
        !          3764: 
        !          3765:        /* check policy */
        !          3766:        switch (xpl->sadb_x_policy_type) {
        !          3767:        case IPSEC_POLICY_DISCARD:
        !          3768:        case IPSEC_POLICY_NONE:
        !          3769:        case IPSEC_POLICY_ENTRUST:
        !          3770:        case IPSEC_POLICY_BYPASS:
        !          3771:                break;
        !          3772: 
        !          3773:        case IPSEC_POLICY_IPSEC:
        !          3774:            {
        !          3775:                int tlen;
        !          3776:                struct sadb_x_ipsecrequest *xisr;
        !          3777:                struct ipsecrequest **p_isr = &new->req;
        !          3778: 
        !          3779:                /* validity check */
        !          3780:                if (PFKEY_EXTLEN(xpl) < sizeof(*xpl)) {
        !          3781:                        plog(LLV_ERROR, LOCATION, NULL,
        !          3782:                                "invalid msg length.\n");
        !          3783:                        goto bad;
        !          3784:                }
        !          3785: 
        !          3786:                tlen = PFKEY_EXTLEN(xpl) - sizeof(*xpl);
        !          3787:                xisr = (struct sadb_x_ipsecrequest *)(xpl + 1);
        !          3788: 
        !          3789:                while (tlen > 0) {
        !          3790: 
        !          3791:                        /* length check */
        !          3792:                        if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr)) {
        !          3793:                                plog(LLV_ERROR, LOCATION, NULL,
        !          3794:                                        "invalid msg length.\n");
        !          3795:                                goto bad;
        !          3796:                        }
        !          3797: 
        !          3798:                        /* allocate request buffer */
        !          3799:                        *p_isr = newipsecreq();
        !          3800:                        if (*p_isr == NULL) {
        !          3801:                                plog(LLV_ERROR, LOCATION, NULL,
        !          3802:                                        "failed to get new ipsecreq.\n");
        !          3803:                                goto bad;
        !          3804:                        }
        !          3805: 
        !          3806:                        /* set values */
        !          3807:                        (*p_isr)->next = NULL;
        !          3808: 
        !          3809:                        switch (xisr->sadb_x_ipsecrequest_proto) {
        !          3810:                        case IPPROTO_ESP:
        !          3811:                        case IPPROTO_AH:
        !          3812:                        case IPPROTO_IPCOMP:
        !          3813:                                break;
        !          3814:                        default:
        !          3815:                                plog(LLV_ERROR, LOCATION, NULL,
        !          3816:                                        "invalid proto type: %u\n",
        !          3817:                                        xisr->sadb_x_ipsecrequest_proto);
        !          3818:                                goto bad;
        !          3819:                        }
        !          3820:                        (*p_isr)->saidx.proto = xisr->sadb_x_ipsecrequest_proto;
        !          3821: 
        !          3822:                        switch (xisr->sadb_x_ipsecrequest_mode) {
        !          3823:                        case IPSEC_MODE_TRANSPORT:
        !          3824:                        case IPSEC_MODE_TUNNEL:
        !          3825:                                break;
        !          3826:                        case IPSEC_MODE_ANY:
        !          3827:                        default:
        !          3828:                                plog(LLV_ERROR, LOCATION, NULL,
        !          3829:                                        "invalid mode: %u\n",
        !          3830:                                        xisr->sadb_x_ipsecrequest_mode);
        !          3831:                                goto bad;
        !          3832:                        }
        !          3833:                        (*p_isr)->saidx.mode = xisr->sadb_x_ipsecrequest_mode;
        !          3834: 
        !          3835:                        switch (xisr->sadb_x_ipsecrequest_level) {
        !          3836:                        case IPSEC_LEVEL_DEFAULT:
        !          3837:                        case IPSEC_LEVEL_USE:
        !          3838:                        case IPSEC_LEVEL_REQUIRE:
        !          3839:                                break;
        !          3840:                        case IPSEC_LEVEL_UNIQUE:
        !          3841:                                (*p_isr)->saidx.reqid =
        !          3842:                                        xisr->sadb_x_ipsecrequest_reqid;
        !          3843:                                break;
        !          3844: 
        !          3845:                        default:
        !          3846:                                plog(LLV_ERROR, LOCATION, NULL,
        !          3847:                                        "invalid level: %u\n",
        !          3848:                                        xisr->sadb_x_ipsecrequest_level);
        !          3849:                                goto bad;
        !          3850:                        }
        !          3851:                        (*p_isr)->level = xisr->sadb_x_ipsecrequest_level;
        !          3852: 
        !          3853:                        /* set IP addresses if there */
        !          3854:                        if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
        !          3855:                                struct sockaddr *paddr;
        !          3856: 
        !          3857:                                paddr = (struct sockaddr *)(xisr + 1);
        !          3858:                                bcopy(paddr, &(*p_isr)->saidx.src,
        !          3859:                                        sysdep_sa_len(paddr));
        !          3860: 
        !          3861:                                paddr = (struct sockaddr *)((caddr_t)paddr
        !          3862:                                                        + sysdep_sa_len(paddr));
        !          3863:                                bcopy(paddr, &(*p_isr)->saidx.dst,
        !          3864:                                        sysdep_sa_len(paddr));
        !          3865:                        }
        !          3866: 
        !          3867:                        (*p_isr)->sp = new;
        !          3868: 
        !          3869:                        /* initialization for the next. */
        !          3870:                        p_isr = &(*p_isr)->next;
        !          3871:                        tlen -= xisr->sadb_x_ipsecrequest_len;
        !          3872: 
        !          3873:                        /* validity check */
        !          3874:                        if (tlen < 0) {
        !          3875:                                plog(LLV_ERROR, LOCATION, NULL,
        !          3876:                                        "becoming tlen < 0\n");
        !          3877:                        }
        !          3878: 
        !          3879:                        xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xisr
        !          3880:                                         + xisr->sadb_x_ipsecrequest_len);
        !          3881:                }
        !          3882:            }
        !          3883:                break;
        !          3884:        default:
        !          3885:                plog(LLV_ERROR, LOCATION, NULL,
        !          3886:                        "invalid policy type.\n");
        !          3887:                goto bad;
        !          3888:        }
        !          3889: 
        !          3890: #ifdef HAVE_PFKEY_POLICY_PRIORITY
        !          3891:        KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
        !          3892:                        saddr + 1,
        !          3893:                        daddr + 1,
        !          3894:                        saddr->sadb_address_prefixlen,
        !          3895:                        daddr->sadb_address_prefixlen,
        !          3896:                        saddr->sadb_address_proto,
        !          3897:                        xpl->sadb_x_policy_priority,
        !          3898:                        created,
        !          3899:                        &new->spidx);
        !          3900: #else
        !          3901:        KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
        !          3902:                        saddr + 1,
        !          3903:                        daddr + 1,
        !          3904:                        saddr->sadb_address_prefixlen,
        !          3905:                        daddr->sadb_address_prefixlen,
        !          3906:                        saddr->sadb_address_proto,
        !          3907:                        created,
        !          3908:                        &new->spidx);
        !          3909: #endif
        !          3910: 
        !          3911: #ifdef HAVE_SECCTX
        !          3912:        if (mhp[SADB_X_EXT_SEC_CTX] != NULL) {
        !          3913:                struct sadb_x_sec_ctx *ctx;
        !          3914: 
        !          3915:                ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
        !          3916:                new->spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg;
        !          3917:                new->spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi;
        !          3918:                new->spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len;
        !          3919:                memcpy(new->spidx.sec_ctx.ctx_str,ctx + 1,ctx->sadb_x_ctx_len);
        !          3920:        }
        !          3921: #endif /* HAVE_SECCTX */
        !          3922: 
        !          3923:        /* Set local and remote hints for that SP, if available */
        !          3924:        if (local && remote) {
        !          3925:                new->local = dupsaddr(local);
        !          3926:                new->remote = dupsaddr(remote);
        !          3927:        }
        !          3928: 
        !          3929:        inssp(new);
        !          3930: 
        !          3931:        return 0;
        !          3932: bad:
        !          3933:        if (new != NULL) {
        !          3934:                if (new->req != NULL)
        !          3935:                        racoon_free(new->req);
        !          3936:                racoon_free(new);
        !          3937:        }
        !          3938:        return -1;
        !          3939: }
        !          3940: 
        !          3941: /* proto/mode/src->dst spi */
        !          3942: const char *
        !          3943: sadbsecas2str(src, dst, proto, spi, mode)
        !          3944:        struct sockaddr *src, *dst;
        !          3945:        int proto;
        !          3946:        u_int32_t spi;
        !          3947:        int mode;
        !          3948: {
        !          3949:        static char buf[256];
        !          3950:        u_int doi_proto, doi_mode = 0;
        !          3951:        char *p;
        !          3952:        int blen, i;
        !          3953: 
        !          3954:        doi_proto = pfkey2ipsecdoi_proto(proto);
        !          3955:        if (doi_proto == ~0)
        !          3956:                return NULL;
        !          3957:        if (mode) {
        !          3958:                doi_mode = pfkey2ipsecdoi_mode(mode);
        !          3959:                if (doi_mode == ~0)
        !          3960:                        return NULL;
        !          3961:        }
        !          3962: 
        !          3963:        blen = sizeof(buf) - 1;
        !          3964:        p = buf;
        !          3965: 
        !          3966:        i = snprintf(p, blen, "%s%s%s ",
        !          3967:                s_ipsecdoi_proto(doi_proto),
        !          3968:                mode ? "/" : "",
        !          3969:                mode ? s_ipsecdoi_encmode(doi_mode) : "");
        !          3970:        if (i < 0 || i >= blen)
        !          3971:                return NULL;
        !          3972:        p += i;
        !          3973:        blen -= i;
        !          3974: 
        !          3975:        i = snprintf(p, blen, "%s->", saddr2str(src));
        !          3976:        if (i < 0 || i >= blen)
        !          3977:                return NULL;
        !          3978:        p += i;
        !          3979:        blen -= i;
        !          3980: 
        !          3981:        i = snprintf(p, blen, "%s ", saddr2str(dst));
        !          3982:        if (i < 0 || i >= blen)
        !          3983:                return NULL;
        !          3984:        p += i;
        !          3985:        blen -= i;
        !          3986: 
        !          3987:        if (spi) {
        !          3988:                snprintf(p, blen, "spi=%lu(0x%lx)", (unsigned long)ntohl(spi),
        !          3989:                    (unsigned long)ntohl(spi));
        !          3990:        }
        !          3991: 
        !          3992:        return buf;
        !          3993: }

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