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

1.1     ! misho       1: /*     $NetBSD: isakmp_inf.c,v 1.47 2011/03/15 13:20:14 vanhu Exp $    */
        !             2: 
        !             3: /* Id: isakmp_inf.c,v 1.44 2006/05/06 20:45:52 manubsd 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 <sys/types.h>
        !            37: #include <sys/param.h>
        !            38: #include <sys/socket.h>
        !            39: 
        !            40: #include <net/pfkeyv2.h>
        !            41: #include <netinet/in.h>
        !            42: #include <sys/queue.h>
        !            43: #include PATH_IPSEC_H
        !            44: 
        !            45: #include <stdlib.h>
        !            46: #include <stdio.h>
        !            47: #include <string.h>
        !            48: #include <errno.h>
        !            49: #if TIME_WITH_SYS_TIME
        !            50: # include <sys/time.h>
        !            51: # include <time.h>
        !            52: #else
        !            53: # if HAVE_SYS_TIME_H
        !            54: #  include <sys/time.h>
        !            55: # else
        !            56: #  include <time.h>
        !            57: # endif
        !            58: #endif
        !            59: #ifdef ENABLE_HYBRID
        !            60: #include <resolv.h>
        !            61: #endif
        !            62: 
        !            63: #include "libpfkey.h"
        !            64: 
        !            65: #include "var.h"
        !            66: #include "vmbuf.h"
        !            67: #include "schedule.h"
        !            68: #include "str2val.h"
        !            69: #include "misc.h"
        !            70: #include "plog.h"
        !            71: #include "debug.h"
        !            72: 
        !            73: #include "localconf.h"
        !            74: #include "remoteconf.h"
        !            75: #include "sockmisc.h"
        !            76: #include "handler.h"
        !            77: #include "policy.h"
        !            78: #include "proposal.h"
        !            79: #include "isakmp_var.h"
        !            80: #include "evt.h"
        !            81: #include "isakmp.h"
        !            82: #ifdef ENABLE_HYBRID
        !            83: #include "isakmp_xauth.h"
        !            84: #include "isakmp_unity.h"
        !            85: #include "isakmp_cfg.h" 
        !            86: #endif
        !            87: #include "isakmp_inf.h"
        !            88: #include "oakley.h"
        !            89: #include "ipsec_doi.h"
        !            90: #include "crypto_openssl.h"
        !            91: #include "pfkey.h"
        !            92: #include "policy.h"
        !            93: #include "algorithm.h"
        !            94: #include "proposal.h"
        !            95: #include "admin.h"
        !            96: #include "strnames.h"
        !            97: #ifdef ENABLE_NATT
        !            98: #include "nattraversal.h"
        !            99: #endif
        !           100: 
        !           101: /* information exchange */
        !           102: static int isakmp_info_recv_n (struct ph1handle *, struct isakmp_pl_n *, u_int32_t, int);
        !           103: static int isakmp_info_recv_d (struct ph1handle *, struct isakmp_pl_d *, u_int32_t, int);
        !           104: 
        !           105: #ifdef ENABLE_DPD
        !           106: static int isakmp_info_recv_r_u __P((struct ph1handle *,
        !           107:        struct isakmp_pl_ru *, u_int32_t));
        !           108: static int isakmp_info_recv_r_u_ack __P((struct ph1handle *,
        !           109:        struct isakmp_pl_ru *, u_int32_t));
        !           110: static void isakmp_info_send_r_u __P((struct sched *));
        !           111: #endif
        !           112: 
        !           113: static void purge_isakmp_spi __P((int, isakmp_index *, size_t));
        !           114: 
        !           115: /* %%%
        !           116:  * Information Exchange
        !           117:  */
        !           118: /*
        !           119:  * receive Information
        !           120:  */
        !           121: int
        !           122: isakmp_info_recv(iph1, msg0)
        !           123:        struct ph1handle *iph1;
        !           124:        vchar_t *msg0;
        !           125: {
        !           126:        vchar_t *msg = NULL;
        !           127:        vchar_t *pbuf = NULL;
        !           128:        u_int32_t msgid = 0;
        !           129:        int error = -1;
        !           130:        struct isakmp *isakmp;
        !           131:        struct isakmp_gen *gen;
        !           132:        struct isakmp_parse_t *pa, *pap;
        !           133:        void *p;
        !           134:        vchar_t *hash, *payload;
        !           135:        struct isakmp_gen *nd;
        !           136:        u_int8_t np;
        !           137:        int encrypted;
        !           138: 
        !           139:        plog(LLV_DEBUG, LOCATION, NULL, "receive Information.\n");
        !           140: 
        !           141:        encrypted = ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E);
        !           142:        msgid = ((struct isakmp *)msg0->v)->msgid;
        !           143: 
        !           144:        /* Use new IV to decrypt Informational message. */
        !           145:        if (encrypted) {
        !           146:                struct isakmp_ivm *ivm;
        !           147: 
        !           148:                if (iph1->ivm == NULL) {
        !           149:                        plog(LLV_ERROR, LOCATION, NULL, "iph1->ivm == NULL\n");
        !           150:                        return -1;
        !           151:                }
        !           152: 
        !           153:                /* compute IV */
        !           154:                ivm = oakley_newiv2(iph1, ((struct isakmp *)msg0->v)->msgid);
        !           155:                if (ivm == NULL)
        !           156:                        return -1;
        !           157: 
        !           158:                msg = oakley_do_decrypt(iph1, msg0, ivm->iv, ivm->ive);
        !           159:                oakley_delivm(ivm);
        !           160:                if (msg == NULL)
        !           161:                        return -1;
        !           162: 
        !           163:        } else
        !           164:                msg = vdup(msg0);
        !           165: 
        !           166:        /* Safety check */
        !           167:        if (msg->l < sizeof(*isakmp) + sizeof(*gen)) {
        !           168:                plog(LLV_ERROR, LOCATION, NULL, 
        !           169:                        "ignore information because the "
        !           170:                        "message is way too short - %zu byte(s).\n",
        !           171:                        msg->l);
        !           172:                goto end;
        !           173:        }
        !           174: 
        !           175:        isakmp = (struct isakmp *)msg->v;
        !           176:        gen = (struct isakmp_gen *)((caddr_t)isakmp + sizeof(struct isakmp));
        !           177:        np = gen->np;
        !           178: 
        !           179:        if (encrypted) {
        !           180:                if (isakmp->np != ISAKMP_NPTYPE_HASH) {
        !           181:                        plog(LLV_ERROR, LOCATION, NULL,
        !           182:                            "ignore information because the "
        !           183:                            "message has no hash payload.\n");
        !           184:                        goto end;
        !           185:                }
        !           186: 
        !           187:                if (iph1->status != PHASE1ST_ESTABLISHED &&
        !           188:                    iph1->status != PHASE1ST_DYING) {
        !           189:                        plog(LLV_ERROR, LOCATION, NULL,
        !           190:                            "ignore information because ISAKMP-SA "
        !           191:                            "has not been established yet.\n");
        !           192:                        goto end;
        !           193:                }
        !           194:                
        !           195:                /* Safety check */
        !           196:                if (msg->l < sizeof(*isakmp) + ntohs(gen->len) + sizeof(*nd)) {
        !           197:                        plog(LLV_ERROR, LOCATION, NULL, 
        !           198:                                "ignore information because the "
        !           199:                                "message is too short - %zu byte(s).\n",
        !           200:                                msg->l);
        !           201:                        goto end;
        !           202:                }
        !           203: 
        !           204:                p = (caddr_t) gen + sizeof(struct isakmp_gen);
        !           205:                nd = (struct isakmp_gen *) ((caddr_t) gen + ntohs(gen->len));
        !           206: 
        !           207:                /* nd length check */
        !           208:                if (ntohs(nd->len) > msg->l - (sizeof(struct isakmp) +
        !           209:                    ntohs(gen->len))) {
        !           210:                        plog(LLV_ERROR, LOCATION, NULL,
        !           211:                                 "too long payload length (broken message?)\n");
        !           212:                        goto end;
        !           213:                }
        !           214: 
        !           215:                if (ntohs(nd->len) < sizeof(*nd)) {
        !           216:                        plog(LLV_ERROR, LOCATION, NULL,
        !           217:                                "too short payload length (broken message?)\n");
        !           218:                        goto end;
        !           219:                }
        !           220: 
        !           221:                payload = vmalloc(ntohs(nd->len));
        !           222:                if (payload == NULL) {
        !           223:                        plog(LLV_ERROR, LOCATION, NULL,
        !           224:                            "cannot allocate memory\n");
        !           225:                        goto end;
        !           226:                }
        !           227: 
        !           228:                memcpy(payload->v, (caddr_t) nd, ntohs(nd->len));
        !           229: 
        !           230:                /* compute HASH */
        !           231:                hash = oakley_compute_hash1(iph1, isakmp->msgid, payload);
        !           232:                if (hash == NULL) {
        !           233:                        plog(LLV_ERROR, LOCATION, NULL,
        !           234:                            "cannot compute hash\n");
        !           235: 
        !           236:                        vfree(payload);
        !           237:                        goto end;
        !           238:                }
        !           239:                
        !           240:                if (ntohs(gen->len) - sizeof(struct isakmp_gen) != hash->l) {
        !           241:                        plog(LLV_ERROR, LOCATION, NULL,
        !           242:                            "ignore information due to hash length mismatch\n");
        !           243: 
        !           244:                        vfree(hash);
        !           245:                        vfree(payload);
        !           246:                        goto end;
        !           247:                }
        !           248: 
        !           249:                if (memcmp(p, hash->v, hash->l) != 0) {
        !           250:                        plog(LLV_ERROR, LOCATION, NULL,
        !           251:                            "ignore information due to hash mismatch\n");
        !           252: 
        !           253:                        vfree(hash);
        !           254:                        vfree(payload);
        !           255:                        goto end;
        !           256:                }
        !           257: 
        !           258:                plog(LLV_DEBUG, LOCATION, NULL, "hash validated.\n");
        !           259: 
        !           260:                vfree(hash);
        !           261:                vfree(payload);
        !           262:        } else {
        !           263:                /* make sure the packet was encrypted after the beginning of phase 1. */
        !           264:                switch (iph1->etype) {
        !           265:                case ISAKMP_ETYPE_AGG:
        !           266:                case ISAKMP_ETYPE_BASE:
        !           267:                case ISAKMP_ETYPE_IDENT:
        !           268:                        if ((iph1->side == INITIATOR && iph1->status < PHASE1ST_MSG3SENT)
        !           269:                         || (iph1->side == RESPONDER && iph1->status < PHASE1ST_MSG2SENT)) {
        !           270:                                break;
        !           271:                        }
        !           272:                        /*FALLTHRU*/
        !           273:                default:
        !           274:                        plog(LLV_ERROR, LOCATION, iph1->remote,
        !           275:                                "%s message must be encrypted\n",
        !           276:                                s_isakmp_nptype(np));
        !           277:                        error = 0;
        !           278:                        goto end;
        !           279:                }
        !           280:        }
        !           281: 
        !           282:        if (!(pbuf = isakmp_parse(msg))) {
        !           283:                error = -1;
        !           284:                goto end;
        !           285:        }
        !           286: 
        !           287:        error = 0;
        !           288:        for (pa = (struct isakmp_parse_t *)pbuf->v; pa->type; pa++) {
        !           289:                switch (pa->type) {
        !           290:                case ISAKMP_NPTYPE_HASH:
        !           291:                        /* Handled above */
        !           292:                        break;
        !           293:                case ISAKMP_NPTYPE_N:
        !           294:                        error = isakmp_info_recv_n(iph1,
        !           295:                                (struct isakmp_pl_n *)pa->ptr,
        !           296:                                msgid, encrypted);
        !           297:                        break;
        !           298:                case ISAKMP_NPTYPE_D:
        !           299:                        error = isakmp_info_recv_d(iph1,
        !           300:                                (struct isakmp_pl_d *)pa->ptr,
        !           301:                                msgid, encrypted);
        !           302:                        break;
        !           303:                case ISAKMP_NPTYPE_NONCE:
        !           304:                        /* XXX to be 6.4.2 ike-01.txt */
        !           305:                        /* XXX IV is to be synchronized. */
        !           306:                        plog(LLV_ERROR, LOCATION, iph1->remote,
        !           307:                                "ignore Acknowledged Informational\n");
        !           308:                        break;
        !           309:                default:
        !           310:                        /* don't send information, see isakmp_ident_r1() */
        !           311:                        error = 0;
        !           312:                        plog(LLV_ERROR, LOCATION, iph1->remote,
        !           313:                                "reject the packet, "
        !           314:                                "received unexpected payload type %s.\n",
        !           315:                                s_isakmp_nptype(gen->np));
        !           316:                }
        !           317:                if (error < 0)
        !           318:                        break;
        !           319:        }
        !           320:     end:
        !           321:        if (msg != NULL)
        !           322:                vfree(msg);
        !           323:        if (pbuf != NULL)
        !           324:                vfree(pbuf);
        !           325:        return error;
        !           326: }
        !           327: 
        !           328: 
        !           329: /*
        !           330:  * log unhandled / unallowed Notification payload
        !           331:  */
        !           332: int
        !           333: isakmp_log_notify(iph1, notify, exchange)
        !           334:        struct ph1handle *iph1;
        !           335:        struct isakmp_pl_n *notify;
        !           336:        const char *exchange;
        !           337: {
        !           338:        u_int type;
        !           339:        char *nraw, *ndata, *nhex;
        !           340:        size_t l;
        !           341: 
        !           342:        type = ntohs(notify->type);
        !           343:        if (ntohs(notify->h.len) < sizeof(*notify) + notify->spi_size) {
        !           344:                plog(LLV_ERROR, LOCATION, iph1->remote,
        !           345:                        "invalid spi_size in %s notification in %s.\n",
        !           346:                        s_isakmp_notify_msg(type), exchange);
        !           347:                return -1;
        !           348:        }
        !           349: 
        !           350:        plog(LLV_ERROR, LOCATION, iph1->remote,
        !           351:                "notification %s received in %s.\n",
        !           352:                s_isakmp_notify_msg(type), exchange);
        !           353: 
        !           354:        nraw = ((char*) notify) + sizeof(*notify) + notify->spi_size;
        !           355:        l = ntohs(notify->h.len) - sizeof(*notify) - notify->spi_size;
        !           356:        if (l > 0) {
        !           357:                if (type >= ISAKMP_NTYPE_MINERROR &&
        !           358:                    type <= ISAKMP_NTYPE_MAXERROR) {
        !           359:                        ndata = binsanitize(nraw, l);
        !           360:                        if (ndata != NULL) {
        !           361:                                plog(LLV_ERROR, LOCATION, iph1->remote,
        !           362:                                        "error message: '%s'.\n",
        !           363:                                        ndata);
        !           364:                                racoon_free(ndata);
        !           365:                        } else {
        !           366:                                plog(LLV_ERROR, LOCATION, iph1->remote,
        !           367:                                        "Cannot allocate memory\n");
        !           368:                        }
        !           369:                } else {
        !           370:                        nhex = val2str(nraw, l);
        !           371:                        if (nhex != NULL) {
        !           372:                                plog(LLV_ERROR, LOCATION, iph1->remote,
        !           373:                                        "notification payload: %s.\n",
        !           374:                                        nhex);
        !           375:                                racoon_free(nhex);
        !           376:                        } else {
        !           377:                                plog(LLV_ERROR, LOCATION, iph1->remote,
        !           378:                                        "Cannot allocate memory\n");
        !           379:                        }
        !           380:                }
        !           381:        }
        !           382: 
        !           383:        return 0;
        !           384: }
        !           385: 
        !           386: 
        !           387: /*
        !           388:  * handling of Notification payload
        !           389:  */
        !           390: static int
        !           391: isakmp_info_recv_n(iph1, notify, msgid, encrypted)
        !           392:        struct ph1handle *iph1;
        !           393:        struct isakmp_pl_n *notify;
        !           394:        u_int32_t msgid;
        !           395:        int encrypted;
        !           396: {
        !           397:        u_int type;
        !           398: 
        !           399:        type = ntohs(notify->type);
        !           400:        switch (type) {
        !           401:        case ISAKMP_NTYPE_CONNECTED:
        !           402:        case ISAKMP_NTYPE_RESPONDER_LIFETIME:
        !           403:        case ISAKMP_NTYPE_REPLAY_STATUS:
        !           404: #ifdef ENABLE_HYBRID
        !           405:        case ISAKMP_NTYPE_UNITY_HEARTBEAT:
        !           406: #endif
        !           407:                /* do something */
        !           408:                break;
        !           409:        case ISAKMP_NTYPE_INITIAL_CONTACT:
        !           410:                if (encrypted)
        !           411:                        return isakmp_info_recv_initialcontact(iph1, NULL);
        !           412:                break;
        !           413: #ifdef ENABLE_DPD
        !           414:        case ISAKMP_NTYPE_R_U_THERE:
        !           415:                if (encrypted)
        !           416:                        return isakmp_info_recv_r_u(iph1,
        !           417:                                (struct isakmp_pl_ru *)notify, msgid);
        !           418:                break;
        !           419:        case ISAKMP_NTYPE_R_U_THERE_ACK:
        !           420:                if (encrypted)
        !           421:                        return isakmp_info_recv_r_u_ack(iph1,
        !           422:                                (struct isakmp_pl_ru *)notify, msgid);
        !           423:                break;
        !           424: #endif
        !           425:        }
        !           426: 
        !           427:        /* If we receive a error notification we should delete the related
        !           428:         * phase1 / phase2 handle, and send an event to racoonctl.
        !           429:         * However, since phase1 error notifications are not encrypted and
        !           430:         * can not be authenticated, it would allow a DoS attack possibility
        !           431:         * to handle them.
        !           432:         * Phase2 error notifications should be encrypted, so we could handle
        !           433:         * those, but it needs implementing (the old code didn't implement
        !           434:         * that either).
        !           435:         * So we are good to just log the messages here.
        !           436:         */
        !           437:        if (encrypted)
        !           438:                isakmp_log_notify(iph1, notify, "informational exchange");
        !           439:        else
        !           440:                isakmp_log_notify(iph1, notify, "unencrypted informational exchange");
        !           441: 
        !           442:        return 0;
        !           443: }
        !           444: 
        !           445: /*
        !           446:  * handling of Deletion payload
        !           447:  */
        !           448: static int
        !           449: isakmp_info_recv_d(iph1, delete, msgid, encrypted)
        !           450:        struct ph1handle *iph1;
        !           451:        struct isakmp_pl_d *delete;
        !           452:        u_int32_t msgid;
        !           453:        int encrypted;
        !           454: {
        !           455:        int tlen, num_spi;
        !           456:        vchar_t *pbuf;
        !           457:        int protected = 0;
        !           458:        struct ph1handle *del_ph1;
        !           459:        struct ph2handle *iph2;
        !           460:        union {
        !           461:                u_int32_t spi32;
        !           462:                u_int16_t spi16[2];
        !           463:        } spi;
        !           464: 
        !           465:        if (ntohl(delete->doi) != IPSEC_DOI) {
        !           466:                plog(LLV_ERROR, LOCATION, iph1->remote,
        !           467:                        "delete payload with invalid doi:%d.\n",
        !           468:                        ntohl(delete->doi));
        !           469: #ifdef ENABLE_HYBRID
        !           470:                /*
        !           471:                 * At deconnexion time, Cisco VPN client does this
        !           472:                 * with a zero DOI. Don't give up in that situation.
        !           473:                 */
        !           474:                if (((iph1->mode_cfg->flags &
        !           475:                    ISAKMP_CFG_VENDORID_UNITY) == 0) || (delete->doi != 0))
        !           476:                        return 0;
        !           477: #else
        !           478:                return 0;
        !           479: #endif
        !           480:        }
        !           481: 
        !           482:        num_spi = ntohs(delete->num_spi);
        !           483:        tlen = ntohs(delete->h.len) - sizeof(struct isakmp_pl_d);
        !           484: 
        !           485:        if (tlen != num_spi * delete->spi_size) {
        !           486:                plog(LLV_ERROR, LOCATION, iph1->remote,
        !           487:                        "deletion payload with invalid length.\n");
        !           488:                return 0;
        !           489:        }
        !           490: 
        !           491:        plog(LLV_DEBUG, LOCATION, iph1->remote,
        !           492:                "delete payload for protocol %s\n",
        !           493:                s_ipsecdoi_proto(delete->proto_id));
        !           494: 
        !           495:        if(!iph1->rmconf->weak_phase1_check && !encrypted) {
        !           496:                plog(LLV_WARNING, LOCATION, iph1->remote,
        !           497:                        "Ignoring unencrypted delete payload "
        !           498:                        "(check the weak_phase1_check option)\n");
        !           499:                return 0;
        !           500:        }
        !           501: 
        !           502:        switch (delete->proto_id) {
        !           503:        case IPSECDOI_PROTO_ISAKMP:
        !           504:                if (delete->spi_size != sizeof(isakmp_index)) {
        !           505:                        plog(LLV_ERROR, LOCATION, iph1->remote,
        !           506:                                "delete payload with strange spi "
        !           507:                                "size %d(proto_id:%d)\n",
        !           508:                                delete->spi_size, delete->proto_id);
        !           509:                        return 0;
        !           510:                }
        !           511: 
        !           512:                del_ph1=getph1byindex((isakmp_index *)(delete + 1));
        !           513:                if(del_ph1 != NULL){
        !           514: 
        !           515:                        evt_phase1(iph1, EVT_PHASE1_PEER_DELETED, NULL);
        !           516:                        sched_cancel(&del_ph1->scr);
        !           517: 
        !           518:                        /*
        !           519:                         * Delete also IPsec-SAs if rekeying is enabled.
        !           520:                         */
        !           521:                        if (ph1_rekey_enabled(del_ph1))
        !           522:                                purge_remote(del_ph1);
        !           523:                        else
        !           524:                                isakmp_ph1expire(del_ph1);
        !           525:                }
        !           526:                break;
        !           527: 
        !           528:        case IPSECDOI_PROTO_IPSEC_AH:
        !           529:        case IPSECDOI_PROTO_IPSEC_ESP:
        !           530:                if (delete->spi_size != sizeof(u_int32_t)) {
        !           531:                        plog(LLV_ERROR, LOCATION, iph1->remote,
        !           532:                                "delete payload with strange spi "
        !           533:                                "size %d(proto_id:%d)\n",
        !           534:                                delete->spi_size, delete->proto_id);
        !           535:                        return 0;
        !           536:                }
        !           537:                purge_ipsec_spi(iph1->remote, delete->proto_id,
        !           538:                    (u_int32_t *)(delete + 1), num_spi);
        !           539:                break;
        !           540: 
        !           541:        case IPSECDOI_PROTO_IPCOMP:
        !           542:                /* need to handle both 16bit/32bit SPI */
        !           543:                memset(&spi, 0, sizeof(spi));
        !           544:                if (delete->spi_size == sizeof(spi.spi16[1])) {
        !           545:                        memcpy(&spi.spi16[1], delete + 1,
        !           546:                            sizeof(spi.spi16[1]));
        !           547:                } else if (delete->spi_size == sizeof(spi.spi32))
        !           548:                        memcpy(&spi.spi32, delete + 1, sizeof(spi.spi32));
        !           549:                else {
        !           550:                        plog(LLV_ERROR, LOCATION, iph1->remote,
        !           551:                                "delete payload with strange spi "
        !           552:                                "size %d(proto_id:%d)\n",
        !           553:                                delete->spi_size, delete->proto_id);
        !           554:                        return 0;
        !           555:                }
        !           556:                purge_ipsec_spi(iph1->remote, delete->proto_id,
        !           557:                    &spi.spi32, num_spi);
        !           558:                break;
        !           559: 
        !           560:        default:
        !           561:                plog(LLV_ERROR, LOCATION, iph1->remote,
        !           562:                        "deletion message received, "
        !           563:                        "invalid proto_id: %d\n",
        !           564:                        delete->proto_id);
        !           565:                return 0;
        !           566:        }
        !           567: 
        !           568:        plog(LLV_DEBUG, LOCATION, NULL, "purged SAs.\n");
        !           569: 
        !           570:        return 0;
        !           571: }
        !           572: 
        !           573: /*
        !           574:  * send Delete payload (for ISAKMP SA) in Informational exchange.
        !           575:  */
        !           576: int
        !           577: isakmp_info_send_d1(iph1)
        !           578:        struct ph1handle *iph1;
        !           579: {
        !           580:        struct isakmp_pl_d *d;
        !           581:        vchar_t *payload = NULL;
        !           582:        int tlen;
        !           583:        int error = 0;
        !           584: 
        !           585:        if (iph1->status != PHASE2ST_ESTABLISHED)
        !           586:                return 0;
        !           587: 
        !           588:        /* create delete payload */
        !           589: 
        !           590:        /* send SPIs of inbound SAs. */
        !           591:        /* XXX should send outbound SAs's ? */
        !           592:        tlen = sizeof(*d) + sizeof(isakmp_index);
        !           593:        payload = vmalloc(tlen);
        !           594:        if (payload == NULL) {
        !           595:                plog(LLV_ERROR, LOCATION, NULL, 
        !           596:                        "failed to get buffer for payload.\n");
        !           597:                return errno;
        !           598:        }
        !           599: 
        !           600:        d = (struct isakmp_pl_d *)payload->v;
        !           601:        d->h.np = ISAKMP_NPTYPE_NONE;
        !           602:        d->h.len = htons(tlen);
        !           603:        d->doi = htonl(IPSEC_DOI);
        !           604:        d->proto_id = IPSECDOI_PROTO_ISAKMP;
        !           605:        d->spi_size = sizeof(isakmp_index);
        !           606:        d->num_spi = htons(1);
        !           607:        memcpy(d + 1, &iph1->index, sizeof(isakmp_index));
        !           608: 
        !           609:        error = isakmp_info_send_common(iph1, payload,
        !           610:                                        ISAKMP_NPTYPE_D, 0);
        !           611:        vfree(payload);
        !           612: 
        !           613:        return error;
        !           614: }
        !           615: 
        !           616: /*
        !           617:  * send Delete payload (for IPsec SA) in Informational exchange, based on
        !           618:  * pfkey msg.  It sends always single SPI.
        !           619:  */
        !           620: int
        !           621: isakmp_info_send_d2(iph2)
        !           622:        struct ph2handle *iph2;
        !           623: {
        !           624:        struct ph1handle *iph1;
        !           625:        struct saproto *pr;
        !           626:        struct isakmp_pl_d *d;
        !           627:        vchar_t *payload = NULL;
        !           628:        int tlen;
        !           629:        int error = 0;
        !           630:        u_int8_t *spi;
        !           631: 
        !           632:        if (iph2->status != PHASE2ST_ESTABLISHED)
        !           633:                return 0;
        !           634: 
        !           635:        /*
        !           636:         * don't send delete information if there is no phase 1 handler.
        !           637:         * It's nonsensical to negotiate phase 1 to send the information.
        !           638:         */
        !           639:        iph1 = getph1byaddr(iph2->src, iph2->dst, 0); 
        !           640:        if (iph1 == NULL){
        !           641:                plog(LLV_DEBUG2, LOCATION, NULL,
        !           642:                         "No ph1 handler found, could not send DELETE_SA\n");
        !           643:                return 0;
        !           644:        }
        !           645: 
        !           646:        /* create delete payload */
        !           647:        for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
        !           648: 
        !           649:                /* send SPIs of inbound SAs. */
        !           650:                /*
        !           651:                 * XXX should I send outbound SAs's ?
        !           652:                 * I send inbound SAs's SPI only at the moment because I can't
        !           653:                 * decode any more if peer send encoded packet without aware of
        !           654:                 * deletion of SA.  Outbound SAs don't come under the situation.
        !           655:                 */
        !           656:                tlen = sizeof(*d) + pr->spisize;
        !           657:                payload = vmalloc(tlen);
        !           658:                if (payload == NULL) {
        !           659:                        plog(LLV_ERROR, LOCATION, NULL, 
        !           660:                                "failed to get buffer for payload.\n");
        !           661:                        return errno;
        !           662:                }
        !           663: 
        !           664:                d = (struct isakmp_pl_d *)payload->v;
        !           665:                d->h.np = ISAKMP_NPTYPE_NONE;
        !           666:                d->h.len = htons(tlen);
        !           667:                d->doi = htonl(IPSEC_DOI);
        !           668:                d->proto_id = pr->proto_id;
        !           669:                d->spi_size = pr->spisize;
        !           670:                d->num_spi = htons(1);
        !           671:                /*
        !           672:                 * XXX SPI bits are left-filled, for use with IPComp.
        !           673:                 * we should be switching to variable-length spi field...
        !           674:                 */
        !           675:                spi = (u_int8_t *)&pr->spi;
        !           676:                spi += sizeof(pr->spi);
        !           677:                spi -= pr->spisize;
        !           678:                memcpy(d + 1, spi, pr->spisize);
        !           679: 
        !           680:                error = isakmp_info_send_common(iph1, payload,
        !           681:                                                ISAKMP_NPTYPE_D, 0);
        !           682:                vfree(payload);
        !           683:        }
        !           684: 
        !           685:        return error;
        !           686: }
        !           687: 
        !           688: /*
        !           689:  * send Notification payload (for without ISAKMP SA) in Informational exchange
        !           690:  */
        !           691: int
        !           692: isakmp_info_send_nx(isakmp, remote, local, type, data)
        !           693:        struct isakmp *isakmp;
        !           694:        struct sockaddr *remote, *local;
        !           695:        int type;
        !           696:        vchar_t *data;
        !           697: {
        !           698:        struct ph1handle *iph1 = NULL;
        !           699:        vchar_t *payload = NULL;
        !           700:        int tlen;
        !           701:        int error = -1;
        !           702:        struct isakmp_pl_n *n;
        !           703:        int spisiz = 0;         /* see below */
        !           704: 
        !           705:        /* add new entry to isakmp status table. */
        !           706:        iph1 = newph1();
        !           707:        if (iph1 == NULL)
        !           708:                return -1;
        !           709: 
        !           710:        memcpy(&iph1->index.i_ck, &isakmp->i_ck, sizeof(cookie_t));
        !           711:        isakmp_newcookie((char *)&iph1->index.r_ck, remote, local);
        !           712:        iph1->status = PHASE1ST_START;
        !           713:        iph1->side = INITIATOR;
        !           714:        iph1->version = isakmp->v;
        !           715:        iph1->flags = 0;
        !           716:        iph1->msgid = 0;        /* XXX */
        !           717: #ifdef ENABLE_HYBRID
        !           718:        if ((iph1->mode_cfg = isakmp_cfg_mkstate()) == NULL)
        !           719:                goto end;
        !           720: #endif
        !           721: #ifdef ENABLE_FRAG
        !           722:        iph1->frag = 0;
        !           723:        iph1->frag_chain = NULL;
        !           724: #endif
        !           725: 
        !           726:        /* copy remote address */
        !           727:        if (copy_ph1addresses(iph1, NULL, remote, local) < 0)
        !           728:                goto end;
        !           729: 
        !           730:        tlen = sizeof(*n) + spisiz;
        !           731:        if (data)
        !           732:                tlen += data->l;
        !           733:        payload = vmalloc(tlen);
        !           734:        if (payload == NULL) { 
        !           735:                plog(LLV_ERROR, LOCATION, NULL,
        !           736:                        "failed to get buffer to send.\n");
        !           737:                goto end;
        !           738:        }
        !           739: 
        !           740:        n = (struct isakmp_pl_n *)payload->v;
        !           741:        n->h.np = ISAKMP_NPTYPE_NONE;
        !           742:        n->h.len = htons(tlen);
        !           743:        n->doi = htonl(IPSEC_DOI);
        !           744:        n->proto_id = IPSECDOI_KEY_IKE;
        !           745:        n->spi_size = spisiz;
        !           746:        n->type = htons(type);
        !           747:        if (spisiz)
        !           748:                memset(n + 1, 0, spisiz);       /* XXX spisiz is always 0 */
        !           749:        if (data)
        !           750:                memcpy((caddr_t)(n + 1) + spisiz, data->v, data->l);
        !           751: 
        !           752:        error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, 0);
        !           753:        vfree(payload);
        !           754: 
        !           755:     end:
        !           756:        if (iph1 != NULL)
        !           757:                delph1(iph1);
        !           758: 
        !           759:        return error;
        !           760: }
        !           761: 
        !           762: /*
        !           763:  * send Notification payload (for ISAKMP SA) in Informational exchange
        !           764:  */
        !           765: int
        !           766: isakmp_info_send_n1(iph1, type, data)
        !           767:        struct ph1handle *iph1;
        !           768:        int type;
        !           769:        vchar_t *data;
        !           770: {
        !           771:        vchar_t *payload = NULL;
        !           772:        int tlen;
        !           773:        int error = 0;
        !           774:        struct isakmp_pl_n *n;
        !           775:        int spisiz;
        !           776: 
        !           777:        /*
        !           778:         * note on SPI size: which description is correct?  I have chosen
        !           779:         * this to be 0.
        !           780:         *
        !           781:         * RFC2408 3.1, 2nd paragraph says: ISAKMP SA is identified by
        !           782:         * Initiator/Responder cookie and SPI has no meaning, SPI size = 0.
        !           783:         * RFC2408 3.1, first paragraph on page 40: ISAKMP SA is identified
        !           784:         * by cookie and SPI has no meaning, 0 <= SPI size <= 16.
        !           785:         * RFC2407 4.6.3.3, INITIAL-CONTACT is required to set to 16.
        !           786:         */
        !           787:        if (type == ISAKMP_NTYPE_INITIAL_CONTACT)
        !           788:                spisiz = sizeof(isakmp_index);
        !           789:        else
        !           790:                spisiz = 0;
        !           791: 
        !           792:        tlen = sizeof(*n) + spisiz;
        !           793:        if (data)
        !           794:                tlen += data->l;
        !           795:        payload = vmalloc(tlen);
        !           796:        if (payload == NULL) { 
        !           797:                plog(LLV_ERROR, LOCATION, NULL,
        !           798:                        "failed to get buffer to send.\n");
        !           799:                return errno;
        !           800:        }
        !           801: 
        !           802:        n = (struct isakmp_pl_n *)payload->v;
        !           803:        n->h.np = ISAKMP_NPTYPE_NONE;
        !           804:        n->h.len = htons(tlen);
        !           805:        n->doi = htonl(iph1->rmconf->doitype);
        !           806:        n->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX to be configurable ? */
        !           807:        n->spi_size = spisiz;
        !           808:        n->type = htons(type);
        !           809:        if (spisiz)
        !           810:                memcpy(n + 1, &iph1->index, sizeof(isakmp_index));
        !           811:        if (data)
        !           812:                memcpy((caddr_t)(n + 1) + spisiz, data->v, data->l);
        !           813: 
        !           814:        error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, iph1->flags);
        !           815:        vfree(payload);
        !           816: 
        !           817:        return error;
        !           818: }
        !           819: 
        !           820: /*
        !           821:  * send Notification payload (for IPsec SA) in Informational exchange
        !           822:  */
        !           823: int
        !           824: isakmp_info_send_n2(iph2, type, data)
        !           825:        struct ph2handle *iph2;
        !           826:        int type;
        !           827:        vchar_t *data;
        !           828: {
        !           829:        struct ph1handle *iph1 = iph2->ph1;
        !           830:        vchar_t *payload = NULL;
        !           831:        int tlen;
        !           832:        int error = 0;
        !           833:        struct isakmp_pl_n *n;
        !           834:        struct saproto *pr;
        !           835: 
        !           836:        if (!iph2->approval)
        !           837:                return EINVAL;
        !           838: 
        !           839:        pr = iph2->approval->head;
        !           840: 
        !           841:        /* XXX must be get proper spi */
        !           842:        tlen = sizeof(*n) + pr->spisize;
        !           843:        if (data)
        !           844:                tlen += data->l;
        !           845:        payload = vmalloc(tlen);
        !           846:        if (payload == NULL) { 
        !           847:                plog(LLV_ERROR, LOCATION, NULL,
        !           848:                        "failed to get buffer to send.\n");
        !           849:                return errno;
        !           850:        }
        !           851: 
        !           852:        n = (struct isakmp_pl_n *)payload->v;
        !           853:        n->h.np = ISAKMP_NPTYPE_NONE;
        !           854:        n->h.len = htons(tlen);
        !           855:        n->doi = htonl(IPSEC_DOI);              /* IPSEC DOI (1) */
        !           856:        n->proto_id = pr->proto_id;             /* IPSEC AH/ESP/whatever*/
        !           857:        n->spi_size = pr->spisize;
        !           858:        n->type = htons(type);
        !           859:        *(u_int32_t *)(n + 1) = pr->spi;
        !           860:        if (data)
        !           861:                memcpy((caddr_t)(n + 1) + pr->spisize, data->v, data->l);
        !           862: 
        !           863:        iph2->flags |= ISAKMP_FLAG_E;   /* XXX Should we do FLAG_A ? */
        !           864:        error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, iph2->flags);
        !           865:        vfree(payload);
        !           866: 
        !           867:        return error;
        !           868: }
        !           869: 
        !           870: /*
        !           871:  * send Information
        !           872:  * When ph1->skeyid_a == NULL, send message without encoding.
        !           873:  */
        !           874: int
        !           875: isakmp_info_send_common(iph1, payload, np, flags)
        !           876:        struct ph1handle *iph1;
        !           877:        vchar_t *payload;
        !           878:        u_int32_t np;
        !           879:        int flags;
        !           880: {
        !           881:        struct ph2handle *iph2 = NULL;
        !           882:        vchar_t *hash = NULL;
        !           883:        struct isakmp *isakmp;
        !           884:        struct isakmp_gen *gen;
        !           885:        char *p;
        !           886:        int tlen;
        !           887:        int error = -1;
        !           888: 
        !           889:        /* add new entry to isakmp status table */
        !           890:        iph2 = newph2();
        !           891:        if (iph2 == NULL)
        !           892:                goto end;
        !           893: 
        !           894:        iph2->dst = dupsaddr(iph1->remote);
        !           895:        if (iph2->dst == NULL) {
        !           896:                delph2(iph2);
        !           897:                goto end;
        !           898:        }
        !           899:        iph2->src = dupsaddr(iph1->local);
        !           900:        if (iph2->src == NULL) {
        !           901:                delph2(iph2);
        !           902:                goto end;
        !           903:        }
        !           904:        iph2->side = INITIATOR;
        !           905:        iph2->status = PHASE2ST_START;
        !           906:        iph2->msgid = isakmp_newmsgid2(iph1);
        !           907: 
        !           908:        /* get IV and HASH(1) if skeyid_a was generated. */
        !           909:        if (iph1->skeyid_a != NULL) {
        !           910:                iph2->ivm = oakley_newiv2(iph1, iph2->msgid);
        !           911:                if (iph2->ivm == NULL) {
        !           912:                        delph2(iph2);
        !           913:                        goto end;
        !           914:                }
        !           915: 
        !           916:                /* generate HASH(1) */
        !           917:                hash = oakley_compute_hash1(iph1, iph2->msgid, payload);
        !           918:                if (hash == NULL) {
        !           919:                        delph2(iph2);
        !           920:                        goto end;
        !           921:                }
        !           922: 
        !           923:                /* initialized total buffer length */
        !           924:                tlen = hash->l;
        !           925:                tlen += sizeof(*gen);
        !           926:        } else {
        !           927:                /* IKE-SA is not established */
        !           928:                hash = NULL;
        !           929: 
        !           930:                /* initialized total buffer length */
        !           931:                tlen = 0;
        !           932:        }
        !           933:        if ((flags & ISAKMP_FLAG_A) == 0)
        !           934:                iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_E);
        !           935:        else
        !           936:                iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_A);
        !           937: 
        !           938:        insph2(iph2);
        !           939:        bindph12(iph1, iph2);
        !           940: 
        !           941:        tlen += sizeof(*isakmp) + payload->l;
        !           942: 
        !           943:        /* create buffer for isakmp payload */
        !           944:        iph2->sendbuf = vmalloc(tlen);
        !           945:        if (iph2->sendbuf == NULL) { 
        !           946:                plog(LLV_ERROR, LOCATION, NULL,
        !           947:                        "failed to get buffer to send.\n");
        !           948:                goto err;
        !           949:        }
        !           950: 
        !           951:        /* create isakmp header */
        !           952:        isakmp = (struct isakmp *)iph2->sendbuf->v;
        !           953:        memcpy(&isakmp->i_ck, &iph1->index.i_ck, sizeof(cookie_t));
        !           954:        memcpy(&isakmp->r_ck, &iph1->index.r_ck, sizeof(cookie_t));
        !           955:        isakmp->np = hash == NULL ? (np & 0xff) : ISAKMP_NPTYPE_HASH;
        !           956:        isakmp->v = iph1->version;
        !           957:        isakmp->etype = ISAKMP_ETYPE_INFO;
        !           958:        isakmp->flags = iph2->flags;
        !           959:        memcpy(&isakmp->msgid, &iph2->msgid, sizeof(isakmp->msgid));
        !           960:        isakmp->len   = htonl(tlen);
        !           961:        p = (char *)(isakmp + 1);
        !           962: 
        !           963:        /* create HASH payload */
        !           964:        if (hash != NULL) {
        !           965:                gen = (struct isakmp_gen *)p;
        !           966:                gen->np = np & 0xff;
        !           967:                gen->len = htons(sizeof(*gen) + hash->l);
        !           968:                p += sizeof(*gen);
        !           969:                memcpy(p, hash->v, hash->l);
        !           970:                p += hash->l;
        !           971:        }
        !           972: 
        !           973:        /* add payload */
        !           974:        memcpy(p, payload->v, payload->l);
        !           975:        p += payload->l;
        !           976: 
        !           977: #ifdef HAVE_PRINT_ISAKMP_C
        !           978:        isakmp_printpacket(iph2->sendbuf, iph1->local, iph1->remote, 1);
        !           979: #endif
        !           980: 
        !           981:        /* encoding */
        !           982:        if (ISSET(isakmp->flags, ISAKMP_FLAG_E)) {
        !           983:                vchar_t *tmp;
        !           984: 
        !           985:                tmp = oakley_do_encrypt(iph2->ph1, iph2->sendbuf, iph2->ivm->ive,
        !           986:                                iph2->ivm->iv);
        !           987:                VPTRINIT(iph2->sendbuf);
        !           988:                if (tmp == NULL)
        !           989:                        goto err;
        !           990:                iph2->sendbuf = tmp;
        !           991:        }
        !           992: 
        !           993:        /* HDR*, HASH(1), N */
        !           994:        if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0) {
        !           995:                VPTRINIT(iph2->sendbuf);
        !           996:                goto err;
        !           997:        }
        !           998: 
        !           999:        plog(LLV_DEBUG, LOCATION, NULL,
        !          1000:                "sendto Information %s.\n", s_isakmp_nptype(np));
        !          1001: 
        !          1002:        /*
        !          1003:         * don't resend notify message because peer can use Acknowledged
        !          1004:         * Informational if peer requires the reply of the notify message.
        !          1005:         */
        !          1006: 
        !          1007:        /* XXX If Acknowledged Informational required, don't delete ph2handle */
        !          1008:        error = 0;
        !          1009:        VPTRINIT(iph2->sendbuf);
        !          1010:        goto err;       /* XXX */
        !          1011: 
        !          1012: end:
        !          1013:        if (hash)
        !          1014:                vfree(hash);
        !          1015:        return error;
        !          1016: 
        !          1017: err:
        !          1018:        remph2(iph2);
        !          1019:        delph2(iph2);
        !          1020:        goto end;
        !          1021: }
        !          1022: 
        !          1023: /*
        !          1024:  * add a notify payload to buffer by reallocating buffer.
        !          1025:  * If buf == NULL, the function only create a notify payload.
        !          1026:  *
        !          1027:  * XXX Which is SPI to be included, inbound or outbound ?
        !          1028:  */
        !          1029: vchar_t *
        !          1030: isakmp_add_pl_n(buf0, np_p, type, pr, data)
        !          1031:        vchar_t *buf0;
        !          1032:        u_int8_t **np_p;
        !          1033:        int type;
        !          1034:        struct saproto *pr;
        !          1035:        vchar_t *data;
        !          1036: {
        !          1037:        vchar_t *buf = NULL;
        !          1038:        struct isakmp_pl_n *n;
        !          1039:        int tlen;
        !          1040:        int oldlen = 0;
        !          1041: 
        !          1042:        if (*np_p)
        !          1043:                **np_p = ISAKMP_NPTYPE_N;
        !          1044: 
        !          1045:        tlen = sizeof(*n) + pr->spisize;
        !          1046: 
        !          1047:        if (data)
        !          1048:                tlen += data->l;
        !          1049:        if (buf0) {
        !          1050:                oldlen = buf0->l;
        !          1051:                buf = vrealloc(buf0, buf0->l + tlen);
        !          1052:        } else
        !          1053:                buf = vmalloc(tlen);
        !          1054:        if (!buf) {
        !          1055:                plog(LLV_ERROR, LOCATION, NULL,
        !          1056:                        "failed to get a payload buffer.\n");
        !          1057:                return NULL;
        !          1058:        }
        !          1059: 
        !          1060:        n = (struct isakmp_pl_n *)(buf->v + oldlen);
        !          1061:        n->h.np = ISAKMP_NPTYPE_NONE;
        !          1062:        n->h.len = htons(tlen);
        !          1063:        n->doi = htonl(IPSEC_DOI);              /* IPSEC DOI (1) */
        !          1064:        n->proto_id = pr->proto_id;             /* IPSEC AH/ESP/whatever*/
        !          1065:        n->spi_size = pr->spisize;
        !          1066:        n->type = htons(type);
        !          1067:        *(u_int32_t *)(n + 1) = pr->spi;        /* XXX */
        !          1068:        if (data)
        !          1069:                memcpy((caddr_t)(n + 1) + pr->spisize, data->v, data->l);
        !          1070: 
        !          1071:        /* save the pointer of next payload type */
        !          1072:        *np_p = &n->h.np;
        !          1073: 
        !          1074:        return buf;
        !          1075: }
        !          1076: 
        !          1077: static void
        !          1078: purge_isakmp_spi(proto, spi, n)
        !          1079:        int proto;
        !          1080:        isakmp_index *spi;      /*network byteorder*/
        !          1081:        size_t n;
        !          1082: {
        !          1083:        struct ph1handle *iph1;
        !          1084:        size_t i;
        !          1085: 
        !          1086:        for (i = 0; i < n; i++) {
        !          1087:                iph1 = getph1byindex(&spi[i]);
        !          1088:                if (!iph1)
        !          1089:                        continue;
        !          1090: 
        !          1091:                plog(LLV_INFO, LOCATION, NULL,
        !          1092:                        "purged ISAKMP-SA proto_id=%s spi=%s.\n",
        !          1093:                        s_ipsecdoi_proto(proto),
        !          1094:                        isakmp_pindex(&spi[i], 0));
        !          1095: 
        !          1096:                iph1->status = PHASE1ST_EXPIRED;
        !          1097:                isakmp_ph1delete(iph1);
        !          1098:        }
        !          1099: }
        !          1100: 
        !          1101: 
        !          1102: 
        !          1103: void
        !          1104: purge_ipsec_spi(dst0, proto, spi, n)
        !          1105:        struct sockaddr *dst0;
        !          1106:        int proto;
        !          1107:        u_int32_t *spi; /*network byteorder*/
        !          1108:        size_t n;
        !          1109: {
        !          1110:        vchar_t *buf = NULL;
        !          1111:        struct sadb_msg *msg, *next, *end;
        !          1112:        struct sadb_sa *sa;
        !          1113:        struct sadb_lifetime *lt;
        !          1114:        struct sockaddr *src, *dst;
        !          1115:        struct ph2handle *iph2;
        !          1116:        u_int64_t created;
        !          1117:        size_t i;
        !          1118:        caddr_t mhp[SADB_EXT_MAX + 1];
        !          1119: 
        !          1120:        plog(LLV_DEBUG2, LOCATION, NULL,
        !          1121:                 "purge_ipsec_spi:\n");
        !          1122:        plog(LLV_DEBUG2, LOCATION, NULL, "dst0: %s\n", saddr2str(dst0));
        !          1123:        plog(LLV_DEBUG2, LOCATION, NULL, "SPI: %08X\n", ntohl(spi[0]));
        !          1124: 
        !          1125:        buf = pfkey_dump_sadb(ipsecdoi2pfkey_proto(proto));
        !          1126:        if (buf == NULL) {
        !          1127:                plog(LLV_DEBUG, LOCATION, NULL,
        !          1128:                        "pfkey_dump_sadb returned nothing.\n");
        !          1129:                return;
        !          1130:        }
        !          1131: 
        !          1132:        msg = (struct sadb_msg *)buf->v;
        !          1133:        end = (struct sadb_msg *)(buf->v + buf->l);
        !          1134: 
        !          1135:        while (msg < end) {
        !          1136:                if ((msg->sadb_msg_len << 3) < sizeof(*msg))
        !          1137:                        break;
        !          1138:                next = (struct sadb_msg *)((caddr_t)msg + (msg->sadb_msg_len << 3));
        !          1139:                if (msg->sadb_msg_type != SADB_DUMP) {
        !          1140:                        msg = next;
        !          1141:                        continue;
        !          1142:                }
        !          1143: 
        !          1144:                if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
        !          1145:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1146:                                "pfkey_check (%s)\n", ipsec_strerror());
        !          1147:                        msg = next;
        !          1148:                        continue;
        !          1149:                }
        !          1150: 
        !          1151:                sa = (struct sadb_sa *)(mhp[SADB_EXT_SA]);
        !          1152:                if (!sa
        !          1153:                 || !mhp[SADB_EXT_ADDRESS_SRC]
        !          1154:                 || !mhp[SADB_EXT_ADDRESS_DST]) {
        !          1155:                        msg = next;
        !          1156:                        continue;
        !          1157:                }
        !          1158:                pk_fixup_sa_addresses(mhp);
        !          1159:                src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
        !          1160:                dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
        !          1161:                lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
        !          1162:                if(lt != NULL)
        !          1163:                        created = lt->sadb_lifetime_addtime;
        !          1164:                else
        !          1165:                        created = 0;
        !          1166: 
        !          1167:                if (sa->sadb_sa_state != SADB_SASTATE_MATURE
        !          1168:                 && sa->sadb_sa_state != SADB_SASTATE_DYING) {
        !          1169:                        msg = next;
        !          1170:                        continue;
        !          1171:                }
        !          1172: 
        !          1173:                plog(LLV_DEBUG2, LOCATION, NULL, "src: %s\n", saddr2str(src));
        !          1174:                plog(LLV_DEBUG2, LOCATION, NULL, "dst: %s\n", saddr2str(dst));
        !          1175: 
        !          1176:                /* XXX n^2 algorithm, inefficient */
        !          1177: 
        !          1178:                /* don't delete inbound SAs at the moment */
        !          1179:                /* XXX should we remove SAs with opposite direction as well? */
        !          1180:                if (cmpsaddr(dst0, dst) != CMPSADDR_MATCH) {
        !          1181:                        msg = next;
        !          1182:                        continue;
        !          1183:                }
        !          1184: 
        !          1185:                for (i = 0; i < n; i++) {
        !          1186:                        plog(LLV_DEBUG, LOCATION, NULL,
        !          1187:                                "check spi(packet)=%u spi(db)=%u.\n",
        !          1188:                                ntohl(spi[i]), ntohl(sa->sadb_sa_spi));
        !          1189:                        if (spi[i] != sa->sadb_sa_spi)
        !          1190:                                continue;
        !          1191: 
        !          1192:                        pfkey_send_delete(lcconf->sock_pfkey,
        !          1193:                                msg->sadb_msg_satype,
        !          1194:                                IPSEC_MODE_ANY,
        !          1195:                                src, dst, sa->sadb_sa_spi);
        !          1196: 
        !          1197:                        /*
        !          1198:                         * delete a relative phase 2 handler.
        !          1199:                         * continue to process if no relative phase 2 handler
        !          1200:                         * exists.
        !          1201:                         */
        !          1202:                        iph2 = getph2bysaidx(src, dst, proto, spi[i]);
        !          1203:                        if(iph2 != NULL){
        !          1204:                                delete_spd(iph2, created);
        !          1205:                                remph2(iph2);
        !          1206:                                delph2(iph2);
        !          1207:                        }
        !          1208: 
        !          1209:                        plog(LLV_INFO, LOCATION, NULL,
        !          1210:                                "purged IPsec-SA proto_id=%s spi=%u.\n",
        !          1211:                                s_ipsecdoi_proto(proto),
        !          1212:                                ntohl(spi[i]));
        !          1213:                }
        !          1214: 
        !          1215:                msg = next;
        !          1216:        }
        !          1217: 
        !          1218:        if (buf)
        !          1219:                vfree(buf);
        !          1220: }
        !          1221: 
        !          1222: /*
        !          1223:  * delete all phase2 sa relatived to the destination address
        !          1224:  * (except the phase2 within which the INITIAL-CONTACT was received).
        !          1225:  * Don't delete Phase 1 handlers on INITIAL-CONTACT, and don't ignore
        !          1226:  * an INITIAL-CONTACT if we have contacted the peer.  This matches the
        !          1227:  * Sun IKE behavior, and makes rekeying work much better when the peer
        !          1228:  * restarts.
        !          1229:  */
        !          1230: int
        !          1231: isakmp_info_recv_initialcontact(iph1, protectedph2)
        !          1232:        struct ph1handle *iph1;
        !          1233:        struct ph2handle *protectedph2;
        !          1234: {
        !          1235:        vchar_t *buf = NULL;
        !          1236:        struct sadb_msg *msg, *next, *end;
        !          1237:        struct sadb_sa *sa;
        !          1238:        struct sockaddr *src, *dst;
        !          1239:        caddr_t mhp[SADB_EXT_MAX + 1];
        !          1240:        int proto_id, i;
        !          1241:        struct ph2handle *iph2;
        !          1242: #if 0
        !          1243:        char *loc, *rem;
        !          1244: #endif
        !          1245: 
        !          1246:        plog(LLV_INFO, LOCATION, iph1->remote, "received INITIAL-CONTACT\n");
        !          1247: 
        !          1248:        if (f_local)
        !          1249:                return 0;
        !          1250: 
        !          1251: #if 0
        !          1252:        loc = racoon_strdup(saddrwop2str(iph1->local));
        !          1253:        rem = racoon_strdup(saddrwop2str(iph1->remote));
        !          1254:        STRDUP_FATAL(loc);
        !          1255:        STRDUP_FATAL(rem);
        !          1256: 
        !          1257:        /*
        !          1258:         * Purge all IPSEC-SAs for the peer.  We can do this
        !          1259:         * the easy way (using a PF_KEY SADB_DELETE extension)
        !          1260:         * or we can do it the hard way.
        !          1261:         */
        !          1262:        for (i = 0; i < pfkey_nsatypes; i++) {
        !          1263:                proto_id = pfkey2ipsecdoi_proto(pfkey_satypes[i].ps_satype);
        !          1264: 
        !          1265:                plog(LLV_INFO, LOCATION, NULL,
        !          1266:                    "purging %s SAs for %s -> %s\n",
        !          1267:                    pfkey_satypes[i].ps_name, loc, rem);
        !          1268:                if (pfkey_send_delete_all(lcconf->sock_pfkey,
        !          1269:                    pfkey_satypes[i].ps_satype, IPSEC_MODE_ANY,
        !          1270:                    iph1->local, iph1->remote) == -1) {
        !          1271:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1272:                            "delete_all %s -> %s failed for %s (%s)\n",
        !          1273:                            loc, rem,
        !          1274:                            pfkey_satypes[i].ps_name, ipsec_strerror());
        !          1275:                        goto the_hard_way;
        !          1276:                }
        !          1277: 
        !          1278:                deleteallph2(iph1->local, iph1->remote, proto_id);
        !          1279: 
        !          1280:                plog(LLV_INFO, LOCATION, NULL,
        !          1281:                    "purging %s SAs for %s -> %s\n",
        !          1282:                    pfkey_satypes[i].ps_name, rem, loc);
        !          1283:                if (pfkey_send_delete_all(lcconf->sock_pfkey,
        !          1284:                    pfkey_satypes[i].ps_satype, IPSEC_MODE_ANY,
        !          1285:                    iph1->remote, iph1->local) == -1) {
        !          1286:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1287:                            "delete_all %s -> %s failed for %s (%s)\n",
        !          1288:                            rem, loc,
        !          1289:                            pfkey_satypes[i].ps_name, ipsec_strerror());
        !          1290:                        goto the_hard_way;
        !          1291:                }
        !          1292: 
        !          1293:                deleteallph2(iph1->remote, iph1->local, proto_id);
        !          1294:        }
        !          1295: 
        !          1296:        racoon_free(loc);
        !          1297:        racoon_free(rem);
        !          1298:        return 0;
        !          1299: 
        !          1300:  the_hard_way:
        !          1301:        racoon_free(loc);
        !          1302:        racoon_free(rem);
        !          1303: #endif
        !          1304: 
        !          1305:        buf = pfkey_dump_sadb(SADB_SATYPE_UNSPEC);
        !          1306:        if (buf == NULL) {
        !          1307:                plog(LLV_DEBUG, LOCATION, NULL,
        !          1308:                        "pfkey_dump_sadb returned nothing.\n");
        !          1309:                return 0;
        !          1310:        }
        !          1311: 
        !          1312:        msg = (struct sadb_msg *)buf->v;
        !          1313:        end = (struct sadb_msg *)(buf->v + buf->l);
        !          1314: 
        !          1315:        for (; msg < end; msg = next) {
        !          1316:                if ((msg->sadb_msg_len << 3) < sizeof(*msg))
        !          1317:                        break;
        !          1318: 
        !          1319:                next = (struct sadb_msg *)((caddr_t)msg + (msg->sadb_msg_len << 3));
        !          1320:                if (msg->sadb_msg_type != SADB_DUMP)
        !          1321:                        continue;
        !          1322: 
        !          1323:                if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
        !          1324:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1325:                                "pfkey_check (%s)\n", ipsec_strerror());
        !          1326:                        continue;
        !          1327:                }
        !          1328: 
        !          1329:                if (mhp[SADB_EXT_SA] == NULL
        !          1330:                 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
        !          1331:                 || mhp[SADB_EXT_ADDRESS_DST] == NULL)
        !          1332:                        continue;
        !          1333: 
        !          1334:                sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
        !          1335:                pk_fixup_sa_addresses(mhp);
        !          1336:                src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
        !          1337:                dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
        !          1338: 
        !          1339:                if (sa->sadb_sa_state != SADB_SASTATE_MATURE
        !          1340:                 && sa->sadb_sa_state != SADB_SASTATE_DYING)
        !          1341:                        continue;
        !          1342: 
        !          1343:                /*
        !          1344:                 * RFC2407 4.6.3.3 INITIAL-CONTACT is the message that
        !          1345:                 * announces the sender of the message was rebooted.
        !          1346:                 * it is interpreted to delete all SAs which source address
        !          1347:                 * is the sender of the message.
        !          1348:                 * racoon only deletes SA which is matched both the
        !          1349:                 * source address and the destination accress.
        !          1350:                 */
        !          1351: 
        !          1352:                /*
        !          1353:                 * Check that the IP and port match. But this is not optimal,
        !          1354:                 * since NAT-T can make the peer have multiple different
        !          1355:                 * ports. Correct thing to do is delete all entries with
        !          1356:                  * same identity. -TT
        !          1357:                  */
        !          1358:                if ((cmpsaddr(iph1->local, src) != CMPSADDR_MATCH ||
        !          1359:                     cmpsaddr(iph1->remote, dst) != CMPSADDR_MATCH) &&
        !          1360:                    (cmpsaddr(iph1->local, dst) != CMPSADDR_MATCH ||
        !          1361:                     cmpsaddr(iph1->remote, src) != CMPSADDR_MATCH))
        !          1362:                        continue;
        !          1363: 
        !          1364:                /*
        !          1365:                 * Make sure this is an SATYPE that we manage.
        !          1366:                 * This is gross; too bad we couldn't do it the
        !          1367:                 * easy way.
        !          1368:                 */
        !          1369:                for (i = 0; i < pfkey_nsatypes; i++) {
        !          1370:                        if (pfkey_satypes[i].ps_satype ==
        !          1371:                            msg->sadb_msg_satype)
        !          1372:                                break;
        !          1373:                }
        !          1374:                if (i == pfkey_nsatypes)
        !          1375:                        continue;
        !          1376: 
        !          1377:                plog(LLV_INFO, LOCATION, NULL,
        !          1378:                        "purging spi=%u.\n", ntohl(sa->sadb_sa_spi));
        !          1379:                pfkey_send_delete(lcconf->sock_pfkey,
        !          1380:                        msg->sadb_msg_satype,
        !          1381:                        IPSEC_MODE_ANY, src, dst, sa->sadb_sa_spi);
        !          1382: 
        !          1383:                /*
        !          1384:                 * delete a relative phase 2 handler.
        !          1385:                 * continue to process if no relative phase 2 handler
        !          1386:                 * exists.
        !          1387:                 */
        !          1388:                proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
        !          1389:                iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
        !          1390:                if (iph2 && iph2 != protectedph2) {
        !          1391:                        delete_spd(iph2, 0);
        !          1392:                        remph2(iph2);
        !          1393:                        delph2(iph2);
        !          1394:                }
        !          1395:        }
        !          1396: 
        !          1397:        vfree(buf);
        !          1398:        return 0;
        !          1399: }
        !          1400: 
        !          1401: 
        !          1402: #ifdef ENABLE_DPD
        !          1403: static int
        !          1404: isakmp_info_recv_r_u (iph1, ru, msgid)
        !          1405:        struct ph1handle *iph1;
        !          1406:        struct isakmp_pl_ru *ru;
        !          1407:        u_int32_t msgid;
        !          1408: {
        !          1409:        struct isakmp_pl_ru *ru_ack;
        !          1410:        vchar_t *payload = NULL;
        !          1411:        int tlen;
        !          1412:        int error = 0;
        !          1413: 
        !          1414:        plog(LLV_DEBUG, LOCATION, iph1->remote,
        !          1415:                 "DPD R-U-There received\n");
        !          1416: 
        !          1417:        /* XXX should compare cookies with iph1->index?
        !          1418:           Or is this already done by calling function?  */
        !          1419:        tlen = sizeof(*ru_ack);
        !          1420:        payload = vmalloc(tlen);
        !          1421:        if (payload == NULL) { 
        !          1422:                plog(LLV_ERROR, LOCATION, NULL,
        !          1423:                        "failed to get buffer to send.\n");
        !          1424:                return errno;
        !          1425:        }
        !          1426: 
        !          1427:        ru_ack = (struct isakmp_pl_ru *)payload->v;
        !          1428:        ru_ack->h.np = ISAKMP_NPTYPE_NONE;
        !          1429:        ru_ack->h.len = htons(tlen);
        !          1430:        ru_ack->doi = htonl(IPSEC_DOI);
        !          1431:        ru_ack->type = htons(ISAKMP_NTYPE_R_U_THERE_ACK);
        !          1432:        ru_ack->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX ? */
        !          1433:        ru_ack->spi_size = sizeof(isakmp_index);
        !          1434:        memcpy(ru_ack->i_ck, ru->i_ck, sizeof(cookie_t));
        !          1435:        memcpy(ru_ack->r_ck, ru->r_ck, sizeof(cookie_t));       
        !          1436:        ru_ack->data = ru->data;
        !          1437: 
        !          1438:        /* XXX Should we do FLAG_A ?  */
        !          1439:        error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N,
        !          1440:                                        ISAKMP_FLAG_E);
        !          1441:        vfree(payload);
        !          1442: 
        !          1443:        plog(LLV_DEBUG, LOCATION, NULL, "received a valid R-U-THERE, ACK sent\n");
        !          1444: 
        !          1445:        /* Should we mark tunnel as active ? */
        !          1446:        return error;
        !          1447: }
        !          1448: 
        !          1449: static int
        !          1450: isakmp_info_recv_r_u_ack (iph1, ru, msgid)
        !          1451:        struct ph1handle *iph1;
        !          1452:        struct isakmp_pl_ru *ru;
        !          1453:        u_int32_t msgid;
        !          1454: {
        !          1455:        u_int32_t seq;
        !          1456: 
        !          1457:        plog(LLV_DEBUG, LOCATION, iph1->remote,
        !          1458:                 "DPD R-U-There-Ack received\n");
        !          1459: 
        !          1460:        seq = ntohl(ru->data);
        !          1461:        if (seq <= iph1->dpd_last_ack || seq > iph1->dpd_seq) {
        !          1462:                plog(LLV_ERROR, LOCATION, iph1->remote,
        !          1463:                         "Wrong DPD sequence number (%d; last_ack=%d, seq=%d).\n", 
        !          1464:                         seq, iph1->dpd_last_ack, iph1->dpd_seq);
        !          1465:                return 0;
        !          1466:        }
        !          1467: 
        !          1468:        if (memcmp(ru->i_ck, iph1->index.i_ck, sizeof(cookie_t)) ||
        !          1469:            memcmp(ru->r_ck, iph1->index.r_ck, sizeof(cookie_t))) {
        !          1470:                plog(LLV_ERROR, LOCATION, iph1->remote,
        !          1471:                         "Cookie mismatch in DPD ACK!.\n");
        !          1472:                return 0;
        !          1473:        }
        !          1474: 
        !          1475:        iph1->dpd_fails = 0;
        !          1476:        iph1->dpd_last_ack = seq;
        !          1477:        sched_cancel(&iph1->dpd_r_u);
        !          1478:        isakmp_sched_r_u(iph1, 0);
        !          1479: 
        !          1480:        plog(LLV_DEBUG, LOCATION, NULL, "received an R-U-THERE-ACK\n");
        !          1481: 
        !          1482:        return 0;
        !          1483: }
        !          1484: 
        !          1485: 
        !          1486: 
        !          1487: 
        !          1488: /*
        !          1489:  * send DPD R-U-THERE payload in Informational exchange.
        !          1490:  */
        !          1491: static void
        !          1492: isakmp_info_send_r_u(sc)
        !          1493:        struct sched *sc;
        !          1494: {
        !          1495:        struct ph1handle *iph1 = container_of(sc, struct ph1handle, dpd_r_u);
        !          1496: 
        !          1497:        /* create R-U-THERE payload */
        !          1498:        struct isakmp_pl_ru *ru;
        !          1499:        vchar_t *payload = NULL;
        !          1500:        int tlen;
        !          1501:        int error = 0;
        !          1502: 
        !          1503:        plog(LLV_DEBUG, LOCATION, iph1->remote, "DPD monitoring....\n");
        !          1504: 
        !          1505:        if (iph1->status == PHASE1ST_EXPIRED) {
        !          1506:                /* This can happen after removing tunnels from the
        !          1507:                 * config file and then reloading.
        !          1508:                 * Such iph1 have rmconf=NULL, so return before the if
        !          1509:                 * block below.
        !          1510:                 */
        !          1511:                return;
        !          1512:        }
        !          1513: 
        !          1514:        if (iph1->dpd_fails >= iph1->rmconf->dpd_maxfails) {
        !          1515: 
        !          1516:                plog(LLV_INFO, LOCATION, iph1->remote,
        !          1517:                        "DPD: remote (ISAKMP-SA spi=%s) seems to be dead.\n",
        !          1518:                        isakmp_pindex(&iph1->index, 0));
        !          1519: 
        !          1520:                script_hook(iph1, SCRIPT_PHASE1_DEAD);
        !          1521:                evt_phase1(iph1, EVT_PHASE1_DPD_TIMEOUT, NULL);
        !          1522:                purge_remote(iph1);
        !          1523: 
        !          1524:                /* Do not reschedule here: phase1 is deleted,
        !          1525:                 * DPD will be reactivated when a new ph1 will be negociated
        !          1526:                 */
        !          1527:                return;
        !          1528:        }
        !          1529: 
        !          1530:        /* TODO: check recent activity to avoid useless sends... */
        !          1531: 
        !          1532:        tlen = sizeof(*ru);
        !          1533:        payload = vmalloc(tlen);
        !          1534:        if (payload == NULL) {
        !          1535:                plog(LLV_ERROR, LOCATION, NULL, 
        !          1536:                         "failed to get buffer for payload.\n");
        !          1537:                return;
        !          1538:        }
        !          1539:        ru = (struct isakmp_pl_ru *)payload->v;
        !          1540:        ru->h.np = ISAKMP_NPTYPE_NONE;
        !          1541:        ru->h.len = htons(tlen);
        !          1542:        ru->doi = htonl(IPSEC_DOI);
        !          1543:        ru->type = htons(ISAKMP_NTYPE_R_U_THERE);
        !          1544:        ru->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX ?*/
        !          1545:        ru->spi_size = sizeof(isakmp_index);
        !          1546: 
        !          1547:        memcpy(ru->i_ck, iph1->index.i_ck, sizeof(cookie_t));
        !          1548:        memcpy(ru->r_ck, iph1->index.r_ck, sizeof(cookie_t));
        !          1549: 
        !          1550:        if (iph1->dpd_seq == 0) {
        !          1551:                /* generate a random seq which is not too big */
        !          1552:                iph1->dpd_seq = iph1->dpd_last_ack = rand() & 0x0fff;
        !          1553:        }
        !          1554: 
        !          1555:        iph1->dpd_seq++;
        !          1556:        iph1->dpd_fails++;
        !          1557:        ru->data = htonl(iph1->dpd_seq);
        !          1558: 
        !          1559:        error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, 0);
        !          1560:        vfree(payload);
        !          1561: 
        !          1562:        plog(LLV_DEBUG, LOCATION, iph1->remote,
        !          1563:                 "DPD R-U-There sent (%d)\n", error);
        !          1564: 
        !          1565:        /* Reschedule the r_u_there with a short delay,
        !          1566:         * will be deleted/rescheduled if ACK received before */
        !          1567:        isakmp_sched_r_u(iph1, 1);
        !          1568: 
        !          1569:        plog(LLV_DEBUG, LOCATION, iph1->remote,
        !          1570:                 "rescheduling send_r_u (%d).\n", iph1->rmconf->dpd_retry);
        !          1571: }
        !          1572: 
        !          1573: /* Schedule a new R-U-THERE */
        !          1574: int
        !          1575: isakmp_sched_r_u(iph1, retry)
        !          1576:        struct ph1handle *iph1;
        !          1577:        int retry;
        !          1578: {
        !          1579:        if(iph1 == NULL ||
        !          1580:           iph1->rmconf == NULL)
        !          1581:                return 1;
        !          1582: 
        !          1583: 
        !          1584:        if(iph1->dpd_support == 0 ||
        !          1585:           iph1->rmconf->dpd_interval == 0)
        !          1586:                return 0;
        !          1587: 
        !          1588:        if(retry)
        !          1589:                sched_schedule(&iph1->dpd_r_u, iph1->rmconf->dpd_retry,
        !          1590:                               isakmp_info_send_r_u);
        !          1591:        else
        !          1592:                sched_schedule(&iph1->dpd_r_u, iph1->rmconf->dpd_interval,
        !          1593:                               isakmp_info_send_r_u);
        !          1594: 
        !          1595:        return 0;
        !          1596: }
        !          1597: #endif

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