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

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:  */
1.1.1.2 ! misho      89: static status_t delete_child(private_quick_delete_t *this,
        !            90:                                                         protocol_id_t protocol, uint32_t spi,
        !            91:                                                         bool remote_close)
1.1       misho      92: {
                     93:        uint64_t bytes_in, bytes_out;
                     94:        child_sa_t *child_sa;
                     95:        linked_list_t *my_ts, *other_ts;
                     96:        child_cfg_t *child_cfg;
1.1.1.2 ! misho      97:        status_t status = SUCCESS;
1.1       misho      98:        bool rekeyed;
                     99: 
                    100:        child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol, spi, TRUE);
                    101:        if (!child_sa)
                    102:        {       /* fallback and check for outbound SA */
                    103:                child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol, spi, FALSE);
                    104:                if (!child_sa)
                    105:                {
1.1.1.2 ! misho     106:                        return NOT_FOUND;
1.1       misho     107:                }
                    108:                this->spi = spi = child_sa->get_spi(child_sa, TRUE);
                    109:        }
                    110: 
                    111:        rekeyed = child_sa->get_state(child_sa) == CHILD_REKEYED;
                    112:        if (!rekeyed)
                    113:        {
                    114:                rekeyed = ikev1_child_sa_is_redundant(this->ike_sa, child_sa, NULL);
                    115:        }
                    116:        child_sa->set_state(child_sa, CHILD_DELETING);
                    117: 
                    118:        my_ts = linked_list_create_from_enumerator(
                    119:                                                        child_sa->create_ts_enumerator(child_sa, TRUE));
                    120:        other_ts = linked_list_create_from_enumerator(
                    121:                                                        child_sa->create_ts_enumerator(child_sa, FALSE));
                    122:        if (this->expired)
                    123:        {
                    124:                DBG0(DBG_IKE, "closing expired CHILD_SA %s{%d} "
                    125:                         "with SPIs %.8x_i %.8x_o and TS %#R === %#R",
                    126:                         child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa),
                    127:                         ntohl(child_sa->get_spi(child_sa, TRUE)),
                    128:                         ntohl(child_sa->get_spi(child_sa, FALSE)), my_ts, other_ts);
                    129:        }
                    130:        else
                    131:        {
                    132:                child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in, NULL);
                    133:                child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out, NULL);
                    134: 
                    135:                DBG0(DBG_IKE, "closing CHILD_SA %s{%d} with SPIs "
                    136:                         "%.8x_i (%llu bytes) %.8x_o (%llu bytes) and TS %#R === %#R",
                    137:                         child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa),
                    138:                         ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in,
                    139:                         ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out,
                    140:                         my_ts, other_ts);
                    141:        }
                    142:        my_ts->destroy(my_ts);
                    143:        other_ts->destroy(other_ts);
                    144: 
                    145:        child_sa->set_state(child_sa, CHILD_DELETED);
                    146:        if (!rekeyed)
                    147:        {
                    148:                charon->bus->child_updown(charon->bus, child_sa, FALSE);
                    149: 
                    150:                if (remote_close)
                    151:                {
                    152:                        child_cfg = child_sa->get_config(child_sa);
                    153:                        child_cfg->get_ref(child_cfg);
                    154: 
                    155:                        switch (child_sa->get_close_action(child_sa))
                    156:                        {
                    157:                                case ACTION_RESTART:
                    158:                                        child_cfg->get_ref(child_cfg);
1.1.1.2 ! misho     159:                                        status = this->ike_sa->initiate(this->ike_sa, child_cfg,
1.1       misho     160:                                                                        child_sa->get_reqid(child_sa), NULL, NULL);
                    161:                                        break;
                    162:                                case ACTION_ROUTE:
                    163:                                        charon->traps->install(charon->traps,
                    164:                                                                        this->ike_sa->get_peer_cfg(this->ike_sa),
                    165:                                                                        child_cfg);
                    166:                                        break;
                    167:                                default:
                    168:                                        break;
                    169:                        }
                    170:                        child_cfg->destroy(child_cfg);
                    171:                }
                    172:        }
1.1.1.2 ! misho     173:        if (status == SUCCESS)
        !           174:        {
        !           175:                this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi);
        !           176:        }
        !           177:        return status;
1.1       misho     178: }
                    179: 
                    180: METHOD(task_t, build_i, status_t,
                    181:        private_quick_delete_t *this, message_t *message)
                    182: {
1.1.1.2 ! misho     183:        if (delete_child(this, this->protocol, this->spi, FALSE) == SUCCESS ||
        !           184:                this->force)
1.1       misho     185:        {
                    186:                delete_payload_t *delete_payload;
                    187: 
                    188:                DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x",
                    189:                         protocol_id_names, this->protocol, ntohl(this->spi));
                    190: 
                    191:                delete_payload = delete_payload_create(PLV1_DELETE, this->protocol);
                    192:                delete_payload->add_spi(delete_payload, this->spi);
                    193:                message->add_payload(message, &delete_payload->payload_interface);
                    194: 
                    195:                return SUCCESS;
                    196:        }
                    197:        this->ike_sa->flush_queue(this->ike_sa, TASK_QUEUE_ACTIVE);
                    198:        return ALREADY_DONE;
                    199: }
                    200: 
                    201: METHOD(task_t, process_i, status_t,
                    202:        private_quick_delete_t *this, message_t *message)
                    203: {
                    204:        return FAILED;
                    205: }
                    206: 
                    207: METHOD(task_t, process_r, status_t,
                    208:        private_quick_delete_t *this, message_t *message)
                    209: {
                    210:        enumerator_t *payloads, *spis;
                    211:        payload_t *payload;
                    212:        delete_payload_t *delete_payload;
                    213:        protocol_id_t protocol;
1.1.1.2 ! misho     214:        status_t status = SUCCESS;
1.1       misho     215:        uint32_t spi;
                    216: 
                    217:        payloads = message->create_payload_enumerator(message);
                    218:        while (payloads->enumerate(payloads, &payload))
                    219:        {
                    220:                if (payload->get_type(payload) == PLV1_DELETE)
                    221:                {
                    222:                        delete_payload = (delete_payload_t*)payload;
                    223:                        protocol = delete_payload->get_protocol_id(delete_payload);
                    224:                        if (protocol != PROTO_ESP && protocol != PROTO_AH)
                    225:                        {
                    226:                                continue;
                    227:                        }
                    228:                        spis = delete_payload->create_spi_enumerator(delete_payload);
                    229:                        while (spis->enumerate(spis, &spi))
                    230:                        {
                    231:                                DBG1(DBG_IKE, "received DELETE for %N CHILD_SA with SPI %.8x",
                    232:                                         protocol_id_names, protocol, ntohl(spi));
1.1.1.2 ! misho     233:                                status = delete_child(this, protocol, spi, TRUE);
        !           234:                                if (status == NOT_FOUND)
1.1       misho     235:                                {
                    236:                                        DBG1(DBG_IKE, "CHILD_SA not found, ignored");
1.1.1.2 ! misho     237:                                        status = SUCCESS;
        !           238:                                }
        !           239:                                if (status != SUCCESS)
        !           240:                                {
        !           241:                                        break;
1.1       misho     242:                                }
                    243:                        }
                    244:                        spis->destroy(spis);
                    245:                }
1.1.1.2 ! misho     246:                if (status != SUCCESS)
        !           247:                {
        !           248:                        break;
        !           249:                }
1.1       misho     250:        }
                    251:        payloads->destroy(payloads);
                    252: 
1.1.1.2 ! misho     253:        return status;
1.1       misho     254: }
                    255: 
                    256: METHOD(task_t, build_r, status_t,
                    257:        private_quick_delete_t *this, message_t *message)
                    258: {
                    259:        return FAILED;
                    260: }
                    261: 
                    262: METHOD(task_t, get_type, task_type_t,
                    263:        private_quick_delete_t *this)
                    264: {
                    265:        return TASK_QUICK_DELETE;
                    266: }
                    267: 
                    268: METHOD(task_t, migrate, void,
                    269:        private_quick_delete_t *this, ike_sa_t *ike_sa)
                    270: {
                    271:        this->ike_sa = ike_sa;
                    272: }
                    273: 
                    274: METHOD(task_t, destroy, void,
                    275:        private_quick_delete_t *this)
                    276: {
                    277:        free(this);
                    278: }
                    279: 
                    280: /*
                    281:  * Described in header.
                    282:  */
                    283: quick_delete_t *quick_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
                    284:                                                                        uint32_t spi, bool force, bool expired)
                    285: {
                    286:        private_quick_delete_t *this;
                    287: 
                    288:        INIT(this,
                    289:                .public = {
                    290:                        .task = {
                    291:                                .get_type = _get_type,
                    292:                                .migrate = _migrate,
                    293:                                .destroy = _destroy,
                    294:                        },
                    295:                },
                    296:                .ike_sa = ike_sa,
                    297:                .protocol = protocol,
                    298:                .spi = spi,
                    299:                .force = force,
                    300:                .expired = expired,
                    301:        );
                    302: 
                    303:        if (protocol != PROTO_NONE)
                    304:        {
                    305:                this->public.task.build = _build_i;
                    306:                this->public.task.process = _process_i;
                    307:        }
                    308:        else
                    309:        {
                    310:                this->public.task.build = _build_r;
                    311:                this->public.task.process = _process_r;
                    312:        }
                    313:        return &this->public;
                    314: }

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