Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/tasks/quick_delete.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2011 Martin Willi
        !             3:  * Copyright (C) 2011 revosec AG
        !             4:  *
        !             5:  * This program is free software; you can redistribute it and/or modify it
        !             6:  * under the terms of the GNU General Public License as published by the
        !             7:  * Free Software Foundation; either version 2 of the License, or (at your
        !             8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !             9:  *
        !            10:  * This program is distributed in the hope that it will be useful, but
        !            11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            13:  * for more details.
        !            14:  */
        !            15: /*
        !            16:  * Copyright (C) 2013 Oliver Smith
        !            17:  *
        !            18:  * Permission is hereby granted, free of charge, to any person obtaining a copy
        !            19:  * of this software and associated documentation files (the "Software"), to deal
        !            20:  * in the Software without restriction, including without limitation the rights
        !            21:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        !            22:  * copies of the Software, and to permit persons to whom the Software is
        !            23:  * furnished to do so, subject to the following conditions:
        !            24:  *
        !            25:  * The above copyright notice and this permission notice shall be included in
        !            26:  * all copies or substantial portions of the Software.
        !            27:  *
        !            28:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        !            29:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        !            30:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        !            31:  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        !            32:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        !            33:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        !            34:  * THE SOFTWARE.
        !            35:  */
        !            36: 
        !            37: #include "quick_delete.h"
        !            38: 
        !            39: #include <daemon.h>
        !            40: #include <encoding/payloads/delete_payload.h>
        !            41: #include <sa/ikev1/task_manager_v1.h>
        !            42: 
        !            43: typedef struct private_quick_delete_t private_quick_delete_t;
        !            44: 
        !            45: /**
        !            46:  * Private members of a quick_delete_t task.
        !            47:  */
        !            48: struct private_quick_delete_t {
        !            49: 
        !            50:        /**
        !            51:         * Public methods and task_t interface.
        !            52:         */
        !            53:        quick_delete_t public;
        !            54: 
        !            55:        /**
        !            56:         * Assigned IKE_SA.
        !            57:         */
        !            58:        ike_sa_t *ike_sa;
        !            59: 
        !            60:        /**
        !            61:         * Are we the initiator?
        !            62:         */
        !            63:        bool initiator;
        !            64: 
        !            65:        /**
        !            66:         * Protocol of CHILD_SA to delete
        !            67:         */
        !            68:        protocol_id_t protocol;
        !            69: 
        !            70:        /**
        !            71:         * Inbound SPI of CHILD_SA to delete
        !            72:         */
        !            73:        uint32_t spi;
        !            74: 
        !            75:        /**
        !            76:         * Send delete even if SA does not exist
        !            77:         */
        !            78:        bool force;
        !            79: 
        !            80:        /**
        !            81:         * SA already expired?
        !            82:         */
        !            83:        bool expired;
        !            84: };
        !            85: 
        !            86: /**
        !            87:  * Delete the specified CHILD_SA, if found
        !            88:  */
        !            89: static bool delete_child(private_quick_delete_t *this, protocol_id_t protocol,
        !            90:                                                 uint32_t spi, bool remote_close)
        !            91: {
        !            92:        uint64_t bytes_in, bytes_out;
        !            93:        child_sa_t *child_sa;
        !            94:        linked_list_t *my_ts, *other_ts;
        !            95:        child_cfg_t *child_cfg;
        !            96:        bool rekeyed;
        !            97: 
        !            98:        child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol, spi, TRUE);
        !            99:        if (!child_sa)
        !           100:        {       /* fallback and check for outbound SA */
        !           101:                child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol, spi, FALSE);
        !           102:                if (!child_sa)
        !           103:                {
        !           104:                        return FALSE;
        !           105:                }
        !           106:                this->spi = spi = child_sa->get_spi(child_sa, TRUE);
        !           107:        }
        !           108: 
        !           109:        rekeyed = child_sa->get_state(child_sa) == CHILD_REKEYED;
        !           110:        if (!rekeyed)
        !           111:        {
        !           112:                rekeyed = ikev1_child_sa_is_redundant(this->ike_sa, child_sa, NULL);
        !           113:        }
        !           114:        child_sa->set_state(child_sa, CHILD_DELETING);
        !           115: 
        !           116:        my_ts = linked_list_create_from_enumerator(
        !           117:                                                        child_sa->create_ts_enumerator(child_sa, TRUE));
        !           118:        other_ts = linked_list_create_from_enumerator(
        !           119:                                                        child_sa->create_ts_enumerator(child_sa, FALSE));
        !           120:        if (this->expired)
        !           121:        {
        !           122:                DBG0(DBG_IKE, "closing expired CHILD_SA %s{%d} "
        !           123:                         "with SPIs %.8x_i %.8x_o and TS %#R === %#R",
        !           124:                         child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa),
        !           125:                         ntohl(child_sa->get_spi(child_sa, TRUE)),
        !           126:                         ntohl(child_sa->get_spi(child_sa, FALSE)), my_ts, other_ts);
        !           127:        }
        !           128:        else
        !           129:        {
        !           130:                child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in, NULL);
        !           131:                child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out, NULL);
        !           132: 
        !           133:                DBG0(DBG_IKE, "closing CHILD_SA %s{%d} with SPIs "
        !           134:                         "%.8x_i (%llu bytes) %.8x_o (%llu bytes) and TS %#R === %#R",
        !           135:                         child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa),
        !           136:                         ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in,
        !           137:                         ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out,
        !           138:                         my_ts, other_ts);
        !           139:        }
        !           140:        my_ts->destroy(my_ts);
        !           141:        other_ts->destroy(other_ts);
        !           142: 
        !           143:        child_sa->set_state(child_sa, CHILD_DELETED);
        !           144:        if (!rekeyed)
        !           145:        {
        !           146:                charon->bus->child_updown(charon->bus, child_sa, FALSE);
        !           147: 
        !           148:                if (remote_close)
        !           149:                {
        !           150:                        child_cfg = child_sa->get_config(child_sa);
        !           151:                        child_cfg->get_ref(child_cfg);
        !           152: 
        !           153:                        switch (child_sa->get_close_action(child_sa))
        !           154:                        {
        !           155:                                case ACTION_RESTART:
        !           156:                                        child_cfg->get_ref(child_cfg);
        !           157:                                        this->ike_sa->initiate(this->ike_sa, child_cfg,
        !           158:                                                                        child_sa->get_reqid(child_sa), NULL, NULL);
        !           159:                                        break;
        !           160:                                case ACTION_ROUTE:
        !           161:                                        charon->traps->install(charon->traps,
        !           162:                                                                        this->ike_sa->get_peer_cfg(this->ike_sa),
        !           163:                                                                        child_cfg);
        !           164:                                        break;
        !           165:                                default:
        !           166:                                        break;
        !           167:                        }
        !           168:                        child_cfg->destroy(child_cfg);
        !           169:                }
        !           170:        }
        !           171:        this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi);
        !           172: 
        !           173:        return TRUE;
        !           174: }
        !           175: 
        !           176: METHOD(task_t, build_i, status_t,
        !           177:        private_quick_delete_t *this, message_t *message)
        !           178: {
        !           179:        if (delete_child(this, this->protocol, this->spi, FALSE) || this->force)
        !           180:        {
        !           181:                delete_payload_t *delete_payload;
        !           182: 
        !           183:                DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x",
        !           184:                         protocol_id_names, this->protocol, ntohl(this->spi));
        !           185: 
        !           186:                delete_payload = delete_payload_create(PLV1_DELETE, this->protocol);
        !           187:                delete_payload->add_spi(delete_payload, this->spi);
        !           188:                message->add_payload(message, &delete_payload->payload_interface);
        !           189: 
        !           190:                return SUCCESS;
        !           191:        }
        !           192:        this->ike_sa->flush_queue(this->ike_sa, TASK_QUEUE_ACTIVE);
        !           193:        return ALREADY_DONE;
        !           194: }
        !           195: 
        !           196: METHOD(task_t, process_i, status_t,
        !           197:        private_quick_delete_t *this, message_t *message)
        !           198: {
        !           199:        return FAILED;
        !           200: }
        !           201: 
        !           202: METHOD(task_t, process_r, status_t,
        !           203:        private_quick_delete_t *this, message_t *message)
        !           204: {
        !           205:        enumerator_t *payloads, *spis;
        !           206:        payload_t *payload;
        !           207:        delete_payload_t *delete_payload;
        !           208:        protocol_id_t protocol;
        !           209:        uint32_t spi;
        !           210: 
        !           211:        payloads = message->create_payload_enumerator(message);
        !           212:        while (payloads->enumerate(payloads, &payload))
        !           213:        {
        !           214:                if (payload->get_type(payload) == PLV1_DELETE)
        !           215:                {
        !           216:                        delete_payload = (delete_payload_t*)payload;
        !           217:                        protocol = delete_payload->get_protocol_id(delete_payload);
        !           218:                        if (protocol != PROTO_ESP && protocol != PROTO_AH)
        !           219:                        {
        !           220:                                continue;
        !           221:                        }
        !           222:                        spis = delete_payload->create_spi_enumerator(delete_payload);
        !           223:                        while (spis->enumerate(spis, &spi))
        !           224:                        {
        !           225:                                DBG1(DBG_IKE, "received DELETE for %N CHILD_SA with SPI %.8x",
        !           226:                                         protocol_id_names, protocol, ntohl(spi));
        !           227:                                if (!delete_child(this, protocol, spi, TRUE))
        !           228:                                {
        !           229:                                        DBG1(DBG_IKE, "CHILD_SA not found, ignored");
        !           230:                                        continue;
        !           231:                                }
        !           232:                        }
        !           233:                        spis->destroy(spis);
        !           234:                }
        !           235:        }
        !           236:        payloads->destroy(payloads);
        !           237: 
        !           238:        return SUCCESS;
        !           239: }
        !           240: 
        !           241: METHOD(task_t, build_r, status_t,
        !           242:        private_quick_delete_t *this, message_t *message)
        !           243: {
        !           244:        return FAILED;
        !           245: }
        !           246: 
        !           247: METHOD(task_t, get_type, task_type_t,
        !           248:        private_quick_delete_t *this)
        !           249: {
        !           250:        return TASK_QUICK_DELETE;
        !           251: }
        !           252: 
        !           253: METHOD(task_t, migrate, void,
        !           254:        private_quick_delete_t *this, ike_sa_t *ike_sa)
        !           255: {
        !           256:        this->ike_sa = ike_sa;
        !           257: }
        !           258: 
        !           259: METHOD(task_t, destroy, void,
        !           260:        private_quick_delete_t *this)
        !           261: {
        !           262:        free(this);
        !           263: }
        !           264: 
        !           265: /*
        !           266:  * Described in header.
        !           267:  */
        !           268: quick_delete_t *quick_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
        !           269:                                                                        uint32_t spi, bool force, bool expired)
        !           270: {
        !           271:        private_quick_delete_t *this;
        !           272: 
        !           273:        INIT(this,
        !           274:                .public = {
        !           275:                        .task = {
        !           276:                                .get_type = _get_type,
        !           277:                                .migrate = _migrate,
        !           278:                                .destroy = _destroy,
        !           279:                        },
        !           280:                },
        !           281:                .ike_sa = ike_sa,
        !           282:                .protocol = protocol,
        !           283:                .spi = spi,
        !           284:                .force = force,
        !           285:                .expired = expired,
        !           286:        );
        !           287: 
        !           288:        if (protocol != PROTO_NONE)
        !           289:        {
        !           290:                this->public.task.build = _build_i;
        !           291:                this->public.task.process = _process_i;
        !           292:        }
        !           293:        else
        !           294:        {
        !           295:                this->public.task.build = _build_r;
        !           296:                this->public.task.process = _process_r;
        !           297:        }
        !           298:        return &this->public;
        !           299: }

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