Annotation of embedaddon/strongswan/src/libcharon/sa/ikev2/tasks/child_delete.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2009-2016 Tobias Brunner
        !             3:  * Copyright (C) 2006-2007 Martin Willi
        !             4:  * HSR Hochschule fuer Technik Rapperswil
        !             5:  *
        !             6:  * This program is free software; you can redistribute it and/or modify it
        !             7:  * under the terms of the GNU General Public License as published by the
        !             8:  * Free Software Foundation; either version 2 of the License, or (at your
        !             9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !            10:  *
        !            11:  * This program is distributed in the hope that it will be useful, but
        !            12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            14:  * for more details.
        !            15:  */
        !            16: 
        !            17: #include "child_delete.h"
        !            18: 
        !            19: #include <daemon.h>
        !            20: #include <encoding/payloads/delete_payload.h>
        !            21: #include <processing/jobs/delete_child_sa_job.h>
        !            22: #include <sa/ikev2/tasks/child_create.h>
        !            23: #include <sa/ikev2/tasks/child_rekey.h>
        !            24: 
        !            25: #ifndef DELETE_REKEYED_DELAY
        !            26: #define DELETE_REKEYED_DELAY 5
        !            27: #endif
        !            28: 
        !            29: typedef struct private_child_delete_t private_child_delete_t;
        !            30: 
        !            31: /**
        !            32:  * Private members of a child_delete_t task.
        !            33:  */
        !            34: struct private_child_delete_t {
        !            35: 
        !            36:        /**
        !            37:         * Public methods and task_t interface.
        !            38:         */
        !            39:        child_delete_t public;
        !            40: 
        !            41:        /**
        !            42:         * Assigned IKE_SA.
        !            43:         */
        !            44:        ike_sa_t *ike_sa;
        !            45: 
        !            46:        /**
        !            47:         * Whether we are the initiator of the exchange
        !            48:         */
        !            49:        bool initiator;
        !            50: 
        !            51:        /**
        !            52:         * Protocol of CHILD_SA to delete (as initiator)
        !            53:         */
        !            54:        protocol_id_t protocol;
        !            55: 
        !            56:        /**
        !            57:         * Inbound SPI of CHILD_SA to delete (as initiator)
        !            58:         */
        !            59:        uint32_t spi;
        !            60: 
        !            61:        /**
        !            62:         * CHILD_SA already expired (as initiator)
        !            63:         */
        !            64:        bool expired;
        !            65: 
        !            66:        /**
        !            67:         * CHILD_SAs which get deleted, entry_t*
        !            68:         */
        !            69:        linked_list_t *child_sas;
        !            70: };
        !            71: 
        !            72: /**
        !            73:  * Information about a deleted CHILD_SA
        !            74:  */
        !            75: typedef struct {
        !            76:        /** Deleted CHILD_SA */
        !            77:        child_sa_t *child_sa;
        !            78:        /** Whether the CHILD_SA was rekeyed */
        !            79:        bool rekeyed;
        !            80:        /** Whether to enforce any delete action policy */
        !            81:        bool check_delete_action;
        !            82: } entry_t;
        !            83: 
        !            84: CALLBACK(match_child, bool,
        !            85:        entry_t *entry, va_list args)
        !            86: {
        !            87:        child_sa_t *child_sa;
        !            88: 
        !            89:        VA_ARGS_VGET(args, child_sa);
        !            90:        return entry->child_sa == child_sa;
        !            91: }
        !            92: 
        !            93: /**
        !            94:  * build the delete payloads from the listed child_sas
        !            95:  */
        !            96: static void build_payloads(private_child_delete_t *this, message_t *message)
        !            97: {
        !            98:        delete_payload_t *ah = NULL, *esp = NULL;
        !            99:        enumerator_t *enumerator;
        !           100:        entry_t *entry;
        !           101:        protocol_id_t protocol;
        !           102:        uint32_t spi;
        !           103: 
        !           104:        enumerator = this->child_sas->create_enumerator(this->child_sas);
        !           105:        while (enumerator->enumerate(enumerator, (void**)&entry))
        !           106:        {
        !           107:                protocol = entry->child_sa->get_protocol(entry->child_sa);
        !           108:                spi = entry->child_sa->get_spi(entry->child_sa, TRUE);
        !           109: 
        !           110:                switch (protocol)
        !           111:                {
        !           112:                        case PROTO_ESP:
        !           113:                                if (!esp)
        !           114:                                {
        !           115:                                        esp = delete_payload_create(PLV2_DELETE, PROTO_ESP);
        !           116:                                        message->add_payload(message, (payload_t*)esp);
        !           117:                                }
        !           118:                                esp->add_spi(esp, spi);
        !           119:                                DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x",
        !           120:                                         protocol_id_names, protocol, ntohl(spi));
        !           121:                                break;
        !           122:                        case PROTO_AH:
        !           123:                                if (ah == NULL)
        !           124:                                {
        !           125:                                        ah = delete_payload_create(PLV2_DELETE, PROTO_AH);
        !           126:                                        message->add_payload(message, (payload_t*)ah);
        !           127:                                }
        !           128:                                ah->add_spi(ah, spi);
        !           129:                                DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x",
        !           130:                                         protocol_id_names, protocol, ntohl(spi));
        !           131:                                break;
        !           132:                        default:
        !           133:                                break;
        !           134:                }
        !           135:                entry->child_sa->set_state(entry->child_sa, CHILD_DELETING);
        !           136:        }
        !           137:        enumerator->destroy(enumerator);
        !           138: }
        !           139: 
        !           140: /**
        !           141:  * Check if the given CHILD_SA is the redundant SA created in a rekey collision.
        !           142:  */
        !           143: static bool is_redundant(private_child_delete_t *this, child_sa_t *child)
        !           144: {
        !           145:        enumerator_t *tasks;
        !           146:        task_t *task;
        !           147: 
        !           148:        tasks = this->ike_sa->create_task_enumerator(this->ike_sa,
        !           149:                                                                                                 TASK_QUEUE_ACTIVE);
        !           150:        while (tasks->enumerate(tasks, &task))
        !           151:        {
        !           152:                if (task->get_type(task) == TASK_CHILD_REKEY)
        !           153:                {
        !           154:                        child_rekey_t *rekey = (child_rekey_t*)task;
        !           155: 
        !           156:                        if (rekey->is_redundant(rekey, child))
        !           157:                        {
        !           158:                                tasks->destroy(tasks);
        !           159:                                return TRUE;
        !           160:                        }
        !           161:                }
        !           162:        }
        !           163:        tasks->destroy(tasks);
        !           164:        return FALSE;
        !           165: }
        !           166: 
        !           167: /**
        !           168:  * Install the outbound CHILD_SA with the given SPI
        !           169:  */
        !           170: static void install_outbound(private_child_delete_t *this,
        !           171:                                                         protocol_id_t protocol, uint32_t spi)
        !           172: {
        !           173:        child_sa_t *child_sa;
        !           174:        linked_list_t *my_ts, *other_ts;
        !           175:        status_t status;
        !           176: 
        !           177:        if (!spi)
        !           178:        {
        !           179:                return;
        !           180:        }
        !           181: 
        !           182:        child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol,
        !           183:                                                                                  spi, FALSE);
        !           184:        if (!child_sa)
        !           185:        {
        !           186:                DBG1(DBG_IKE, "CHILD_SA not found after rekeying");
        !           187:                return;
        !           188:        }
        !           189:        if (this->initiator && is_redundant(this, child_sa))
        !           190:        {       /* if we won the rekey collision we don't want to install the
        !           191:                 * redundant SA created by the peer */
        !           192:                return;
        !           193:        }
        !           194: 
        !           195:        status = child_sa->install_outbound(child_sa);
        !           196:        if (status != SUCCESS)
        !           197:        {
        !           198:                DBG1(DBG_IKE, "unable to install outbound IPsec SA (SAD) in kernel");
        !           199:                charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_SA_FAILED,
        !           200:                                                   child_sa);
        !           201:                /* FIXME: delete the new child_sa? */
        !           202:                return;
        !           203:        }
        !           204: 
        !           205:        my_ts = linked_list_create_from_enumerator(
        !           206:                                                        child_sa->create_ts_enumerator(child_sa, TRUE));
        !           207:        other_ts = linked_list_create_from_enumerator(
        !           208:                                                        child_sa->create_ts_enumerator(child_sa, FALSE));
        !           209: 
        !           210:        DBG0(DBG_IKE, "outbound CHILD_SA %s{%d} established "
        !           211:                 "with SPIs %.8x_i %.8x_o and TS %#R === %#R",
        !           212:                 child_sa->get_name(child_sa),
        !           213:                 child_sa->get_unique_id(child_sa),
        !           214:                 ntohl(child_sa->get_spi(child_sa, TRUE)),
        !           215:                 ntohl(child_sa->get_spi(child_sa, FALSE)),
        !           216:                 my_ts, other_ts);
        !           217: 
        !           218:        my_ts->destroy(my_ts);
        !           219:        other_ts->destroy(other_ts);
        !           220: }
        !           221: 
        !           222: /**
        !           223:  * read in payloads and find the children to delete
        !           224:  */
        !           225: static void process_payloads(private_child_delete_t *this, message_t *message)
        !           226: {
        !           227:        enumerator_t *payloads, *spis;
        !           228:        payload_t *payload;
        !           229:        delete_payload_t *delete_payload;
        !           230:        uint32_t spi;
        !           231:        protocol_id_t protocol;
        !           232:        child_sa_t *child_sa;
        !           233:        entry_t *entry;
        !           234: 
        !           235:        payloads = message->create_payload_enumerator(message);
        !           236:        while (payloads->enumerate(payloads, &payload))
        !           237:        {
        !           238:                if (payload->get_type(payload) == PLV2_DELETE)
        !           239:                {
        !           240:                        delete_payload = (delete_payload_t*)payload;
        !           241:                        protocol = delete_payload->get_protocol_id(delete_payload);
        !           242:                        if (protocol != PROTO_ESP && protocol != PROTO_AH)
        !           243:                        {
        !           244:                                continue;
        !           245:                        }
        !           246:                        spis = delete_payload->create_spi_enumerator(delete_payload);
        !           247:                        while (spis->enumerate(spis, &spi))
        !           248:                        {
        !           249:                                child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol,
        !           250:                                                                                                          spi, FALSE);
        !           251:                                if (!child_sa)
        !           252:                                {
        !           253:                                        DBG1(DBG_IKE, "received DELETE for unknown %N CHILD_SA with"
        !           254:                                                 " SPI %.8x", protocol_id_names, protocol, ntohl(spi));
        !           255:                                        continue;
        !           256:                                }
        !           257:                                DBG1(DBG_IKE, "received DELETE for %N CHILD_SA with SPI %.8x",
        !           258:                                         protocol_id_names, protocol, ntohl(spi));
        !           259: 
        !           260:                                if (this->child_sas->find_first(this->child_sas, match_child,
        !           261:                                                                                                NULL, child_sa))
        !           262:                                {
        !           263:                                        continue;
        !           264:                                }
        !           265:                                INIT(entry,
        !           266:                                        .child_sa = child_sa
        !           267:                                );
        !           268:                                switch (child_sa->get_state(child_sa))
        !           269:                                {
        !           270:                                        case CHILD_REKEYED:
        !           271:                                                entry->rekeyed = TRUE;
        !           272:                                                break;
        !           273:                                        case CHILD_DELETED:
        !           274:                                                /* already deleted but not yet destroyed, ignore */
        !           275:                                        case CHILD_DELETING:
        !           276:                                                /* we don't send back a delete if we already initiated
        !           277:                                                 * a delete ourself */
        !           278:                                                if (!this->initiator)
        !           279:                                                {
        !           280:                                                        free(entry);
        !           281:                                                        continue;
        !           282:                                                }
        !           283:                                                break;
        !           284:                                        case CHILD_REKEYING:
        !           285:                                                /* we reply as usual, rekeying will fail */
        !           286:                                        case CHILD_INSTALLED:
        !           287:                                                if (!this->initiator)
        !           288:                                                {
        !           289:                                                        if (is_redundant(this, child_sa))
        !           290:                                                        {
        !           291:                                                                entry->rekeyed = TRUE;
        !           292:                                                        }
        !           293:                                                        else
        !           294:                                                        {
        !           295:                                                                entry->check_delete_action = TRUE;
        !           296:                                                        }
        !           297:                                                }
        !           298:                                                break;
        !           299:                                        default:
        !           300:                                                break;
        !           301:                                }
        !           302:                                this->child_sas->insert_last(this->child_sas, entry);
        !           303:                        }
        !           304:                        spis->destroy(spis);
        !           305:                }
        !           306:        }
        !           307:        payloads->destroy(payloads);
        !           308: }
        !           309: 
        !           310: /**
        !           311:  * destroy the children listed in this->child_sas, reestablish by policy
        !           312:  */
        !           313: static status_t destroy_and_reestablish(private_child_delete_t *this)
        !           314: {
        !           315:        enumerator_t *enumerator;
        !           316:        entry_t *entry;
        !           317:        child_sa_t *child_sa;
        !           318:        child_cfg_t *child_cfg;
        !           319:        protocol_id_t protocol;
        !           320:        uint32_t spi, reqid;
        !           321:        action_t action;
        !           322:        status_t status = SUCCESS;
        !           323:        time_t now, expire;
        !           324:        u_int delay;
        !           325: 
        !           326:        now = time_monotonic(NULL);
        !           327:        delay = lib->settings->get_int(lib->settings, "%s.delete_rekeyed_delay",
        !           328:                                                                   DELETE_REKEYED_DELAY, lib->ns);
        !           329: 
        !           330:        enumerator = this->child_sas->create_enumerator(this->child_sas);
        !           331:        while (enumerator->enumerate(enumerator, (void**)&entry))
        !           332:        {
        !           333:                child_sa = entry->child_sa;
        !           334:                child_sa->set_state(child_sa, CHILD_DELETED);
        !           335:                /* signal child down event if we weren't rekeying */
        !           336:                protocol = child_sa->get_protocol(child_sa);
        !           337:                if (!entry->rekeyed)
        !           338:                {
        !           339:                        charon->bus->child_updown(charon->bus, child_sa, FALSE);
        !           340:                }
        !           341:                else
        !           342:                {
        !           343:                        install_outbound(this, protocol, child_sa->get_rekey_spi(child_sa));
        !           344:                        /* for rekeyed CHILD_SAs we uninstall the outbound SA but don't
        !           345:                         * immediately destroy it, by default, so we can process delayed
        !           346:                         * packets */
        !           347:                        child_sa->remove_outbound(child_sa);
        !           348:                        expire = child_sa->get_lifetime(child_sa, TRUE);
        !           349:                        if (delay && (!expire || ((now + delay) < expire)))
        !           350:                        {
        !           351:                                lib->scheduler->schedule_job(lib->scheduler,
        !           352:                                        (job_t*)delete_child_sa_job_create_id(
        !           353:                                                                        child_sa->get_unique_id(child_sa)), delay);
        !           354:                                continue;
        !           355:                        }
        !           356:                        else if (now < expire)
        !           357:                        {       /* let it expire naturally */
        !           358:                                continue;
        !           359:                        }
        !           360:                        /* no delay and no lifetime, destroy it immediately */
        !           361:                }
        !           362:                spi = child_sa->get_spi(child_sa, TRUE);
        !           363:                reqid = child_sa->get_reqid(child_sa);
        !           364:                child_cfg = child_sa->get_config(child_sa);
        !           365:                child_cfg->get_ref(child_cfg);
        !           366:                action = child_sa->get_close_action(child_sa);
        !           367: 
        !           368:                this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi);
        !           369: 
        !           370:                if (entry->check_delete_action)
        !           371:                {       /* enforce child_cfg policy if deleted passively */
        !           372:                        switch (action)
        !           373:                        {
        !           374:                                case ACTION_RESTART:
        !           375:                                        child_cfg->get_ref(child_cfg);
        !           376:                                        status = this->ike_sa->initiate(this->ike_sa, child_cfg,
        !           377:                                                                                                        reqid, NULL, NULL);
        !           378:                                        break;
        !           379:                                case ACTION_ROUTE:
        !           380:                                        charon->traps->install(charon->traps,
        !           381:                                                                        this->ike_sa->get_peer_cfg(this->ike_sa),
        !           382:                                                                        child_cfg);
        !           383:                                        break;
        !           384:                                default:
        !           385:                                        break;
        !           386:                        }
        !           387:                }
        !           388:                child_cfg->destroy(child_cfg);
        !           389:                if (status != SUCCESS)
        !           390:                {
        !           391:                        break;
        !           392:                }
        !           393:        }
        !           394:        enumerator->destroy(enumerator);
        !           395:        return status;
        !           396: }
        !           397: 
        !           398: /**
        !           399:  * send closing signals for all CHILD_SAs over the bus
        !           400:  */
        !           401: static void log_children(private_child_delete_t *this)
        !           402: {
        !           403:        linked_list_t *my_ts, *other_ts;
        !           404:        enumerator_t *enumerator;
        !           405:        entry_t *entry;
        !           406:        child_sa_t *child_sa;
        !           407:        uint64_t bytes_in, bytes_out;
        !           408: 
        !           409:        enumerator = this->child_sas->create_enumerator(this->child_sas);
        !           410:        while (enumerator->enumerate(enumerator, (void**)&entry))
        !           411:        {
        !           412:                child_sa = entry->child_sa;
        !           413:                my_ts = linked_list_create_from_enumerator(
        !           414:                                                        child_sa->create_ts_enumerator(child_sa, TRUE));
        !           415:                other_ts = linked_list_create_from_enumerator(
        !           416:                                                        child_sa->create_ts_enumerator(child_sa, FALSE));
        !           417:                if (this->expired)
        !           418:                {
        !           419:                        DBG0(DBG_IKE, "closing expired CHILD_SA %s{%d} "
        !           420:                                 "with SPIs %.8x_i %.8x_o and TS %#R === %#R",
        !           421:                                 child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa),
        !           422:                                 ntohl(child_sa->get_spi(child_sa, TRUE)),
        !           423:                                 ntohl(child_sa->get_spi(child_sa, FALSE)), my_ts, other_ts);
        !           424:                }
        !           425:                else
        !           426:                {
        !           427:                        child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in, NULL);
        !           428:                        child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out, NULL);
        !           429: 
        !           430:                        DBG0(DBG_IKE, "closing CHILD_SA %s{%d} with SPIs %.8x_i "
        !           431:                                 "(%llu bytes) %.8x_o (%llu bytes) and TS %#R === %#R",
        !           432:                                 child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa),
        !           433:                                 ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in,
        !           434:                                 ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out,
        !           435:                                 my_ts, other_ts);
        !           436:                }
        !           437:                my_ts->destroy(my_ts);
        !           438:                other_ts->destroy(other_ts);
        !           439:        }
        !           440:        enumerator->destroy(enumerator);
        !           441: }
        !           442: 
        !           443: METHOD(task_t, build_i, status_t,
        !           444:        private_child_delete_t *this, message_t *message)
        !           445: {
        !           446:        child_sa_t *child_sa;
        !           447:        entry_t *entry;
        !           448: 
        !           449:        child_sa = this->ike_sa->get_child_sa(this->ike_sa, this->protocol,
        !           450:                                                                                  this->spi, TRUE);
        !           451:        if (!child_sa)
        !           452:        {       /* check if it is an outbound sa */
        !           453:                child_sa = this->ike_sa->get_child_sa(this->ike_sa, this->protocol,
        !           454:                                                                                          this->spi, FALSE);
        !           455:                if (!child_sa)
        !           456:                {       /* child does not exist anymore */
        !           457:                        return SUCCESS;
        !           458:                }
        !           459:                /* we work only with the inbound SPI */
        !           460:                this->spi = child_sa->get_spi(child_sa, TRUE);
        !           461:        }
        !           462: 
        !           463:        if (this->expired && child_sa->get_state(child_sa) == CHILD_REKEYED)
        !           464:        {       /* the peer was expected to delete this SA, but if we send a DELETE
        !           465:                 * we might cause a collision there if the CREATE_CHILD_SA response
        !           466:                 * is delayed (the peer wouldn't know if we deleted this SA due to an
        !           467:                 * expire or because of a forced delete by the user and might then
        !           468:                 * ignore the CREATE_CHILD_SA response once it arrives) */
        !           469:                child_sa->set_state(child_sa, CHILD_DELETED);
        !           470:                install_outbound(this, this->protocol,
        !           471:                                                 child_sa->get_rekey_spi(child_sa));
        !           472:        }
        !           473: 
        !           474:        if (child_sa->get_state(child_sa) == CHILD_DELETED)
        !           475:        {       /* DELETEs for this CHILD_SA were already exchanged, but it was not yet
        !           476:                 * destroyed to allow delayed packets to get processed */
        !           477:                this->ike_sa->destroy_child_sa(this->ike_sa, this->protocol, this->spi);
        !           478:                message->set_exchange_type(message, EXCHANGE_TYPE_UNDEFINED);
        !           479:                return SUCCESS;
        !           480:        }
        !           481: 
        !           482:        INIT(entry,
        !           483:                .child_sa = child_sa,
        !           484:                .rekeyed = child_sa->get_state(child_sa) == CHILD_REKEYED,
        !           485:        );
        !           486:        this->child_sas->insert_last(this->child_sas, entry);
        !           487:        log_children(this);
        !           488:        build_payloads(this, message);
        !           489: 
        !           490:        if (!entry->rekeyed && this->expired)
        !           491:        {
        !           492:                child_cfg_t *child_cfg;
        !           493: 
        !           494:                DBG1(DBG_IKE, "scheduling CHILD_SA recreate after hard expire");
        !           495:                child_cfg = child_sa->get_config(child_sa);
        !           496:                this->ike_sa->queue_task(this->ike_sa, (task_t*)
        !           497:                                child_create_create(this->ike_sa, child_cfg->get_ref(child_cfg),
        !           498:                                                                        FALSE, NULL, NULL));
        !           499:        }
        !           500:        return NEED_MORE;
        !           501: }
        !           502: 
        !           503: METHOD(task_t, process_i, status_t,
        !           504:        private_child_delete_t *this, message_t *message)
        !           505: {
        !           506:        process_payloads(this, message);
        !           507:        DBG1(DBG_IKE, "CHILD_SA closed");
        !           508:        return destroy_and_reestablish(this);
        !           509: }
        !           510: 
        !           511: METHOD(task_t, process_r, status_t,
        !           512:        private_child_delete_t *this, message_t *message)
        !           513: {
        !           514:        process_payloads(this, message);
        !           515:        log_children(this);
        !           516:        return NEED_MORE;
        !           517: }
        !           518: 
        !           519: METHOD(task_t, build_r, status_t,
        !           520:        private_child_delete_t *this, message_t *message)
        !           521: {
        !           522:        build_payloads(this, message);
        !           523:        DBG1(DBG_IKE, "CHILD_SA closed");
        !           524:        return destroy_and_reestablish(this);
        !           525: }
        !           526: 
        !           527: METHOD(task_t, get_type, task_type_t,
        !           528:        private_child_delete_t *this)
        !           529: {
        !           530:        return TASK_CHILD_DELETE;
        !           531: }
        !           532: 
        !           533: METHOD(child_delete_t , get_child, child_sa_t*,
        !           534:        private_child_delete_t *this)
        !           535: {
        !           536:        child_sa_t *child_sa = NULL;
        !           537:        entry_t *entry;
        !           538: 
        !           539:        if (this->child_sas->get_first(this->child_sas, (void**)&entry) == SUCCESS)
        !           540:        {
        !           541:                child_sa = entry->child_sa;
        !           542:        }
        !           543:        return child_sa;
        !           544: }
        !           545: 
        !           546: METHOD(task_t, migrate, void,
        !           547:        private_child_delete_t *this, ike_sa_t *ike_sa)
        !           548: {
        !           549:        this->ike_sa = ike_sa;
        !           550: 
        !           551:        this->child_sas->destroy_function(this->child_sas, free);
        !           552:        this->child_sas = linked_list_create();
        !           553: }
        !           554: 
        !           555: METHOD(task_t, destroy, void,
        !           556:        private_child_delete_t *this)
        !           557: {
        !           558:        this->child_sas->destroy_function(this->child_sas, free);
        !           559:        free(this);
        !           560: }
        !           561: 
        !           562: /*
        !           563:  * Described in header.
        !           564:  */
        !           565: child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
        !           566:                                                                        uint32_t spi, bool expired)
        !           567: {
        !           568:        private_child_delete_t *this;
        !           569: 
        !           570:        INIT(this,
        !           571:                .public = {
        !           572:                        .task = {
        !           573:                                .get_type = _get_type,
        !           574:                                .migrate = _migrate,
        !           575:                                .destroy = _destroy,
        !           576:                        },
        !           577:                        .get_child = _get_child,
        !           578:                },
        !           579:                .ike_sa = ike_sa,
        !           580:                .child_sas = linked_list_create(),
        !           581:                .protocol = protocol,
        !           582:                .spi = spi,
        !           583:                .expired = expired,
        !           584:        );
        !           585: 
        !           586:        if (protocol != PROTO_NONE)
        !           587:        {
        !           588:                this->public.task.build = _build_i;
        !           589:                this->public.task.process = _process_i;
        !           590:                this->initiator = TRUE;
        !           591:        }
        !           592:        else
        !           593:        {
        !           594:                this->public.task.build = _build_r;
        !           595:                this->public.task.process = _process_r;
        !           596:                this->initiator = FALSE;
        !           597:        }
        !           598:        return &this->public;
        !           599: }

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