Annotation of embedaddon/strongswan/src/libcharon/sa/child_sa_manager.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2014 Martin Willi
        !             3:  * Copyright (C) 2014 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: #include "child_sa_manager.h"
        !            17: 
        !            18: #include <daemon.h>
        !            19: #include <threading/mutex.h>
        !            20: #include <collections/hashtable.h>
        !            21: 
        !            22: typedef struct private_child_sa_manager_t private_child_sa_manager_t;
        !            23: 
        !            24: /**
        !            25:  * Private data of an child_sa_manager_t object.
        !            26:  */
        !            27: struct private_child_sa_manager_t {
        !            28: 
        !            29:        /**
        !            30:         * Public child_sa_manager_t interface.
        !            31:         */
        !            32:        child_sa_manager_t public;
        !            33: 
        !            34:        /**
        !            35:         * CHILD_SAs by inbound SPI/dst, child_entry_t => child_entry_t
        !            36:         */
        !            37:        hashtable_t *in;
        !            38: 
        !            39:        /**
        !            40:         * CHILD_SAs by outbound SPI/dst, child_entry_t => child_entry_t
        !            41:         */
        !            42:        hashtable_t *out;
        !            43: 
        !            44:        /**
        !            45:         * CHILD_SAs by unique ID, child_entry_t => child_entry_t
        !            46:         */
        !            47:        hashtable_t *ids;
        !            48: 
        !            49:        /**
        !            50:         * Mutex to access any hashtable
        !            51:         */
        !            52:        mutex_t *mutex;
        !            53: };
        !            54: 
        !            55: /**
        !            56:  * Hashtable entry for a known CHILD_SA
        !            57:  */
        !            58: typedef struct {
        !            59:        /** the associated IKE_SA */
        !            60:        ike_sa_id_t *ike_id;
        !            61:        /** unique CHILD_SA identifier */
        !            62:        uint32_t unique_id;
        !            63:        /** inbound SPI */
        !            64:        uint32_t spi_in;
        !            65:        /** outbound SPI */
        !            66:        uint32_t spi_out;
        !            67:        /** inbound host address */
        !            68:        host_t *host_in;
        !            69:        /** outbound host address and port */
        !            70:        host_t *host_out;
        !            71:        /** IPsec protocol, AH|ESP */
        !            72:        protocol_id_t proto;
        !            73: } child_entry_t;
        !            74: 
        !            75: /**
        !            76:  * Destroy a CHILD_SA entry
        !            77:  */
        !            78: static void child_entry_destroy(child_entry_t *entry)
        !            79: {
        !            80:        entry->ike_id->destroy(entry->ike_id);
        !            81:        entry->host_in->destroy(entry->host_in);
        !            82:        entry->host_out->destroy(entry->host_out);
        !            83:        free(entry);
        !            84: }
        !            85: 
        !            86: /**
        !            87:  * Hashtable hash function for inbound SAs
        !            88:  */
        !            89: static u_int hash_in(child_entry_t *entry)
        !            90: {
        !            91:        return chunk_hash_inc(chunk_from_thing(entry->spi_in),
        !            92:                        chunk_hash_inc(entry->host_in->get_address(entry->host_in),
        !            93:                         chunk_hash(chunk_from_thing(entry->proto))));
        !            94: }
        !            95: 
        !            96: /**
        !            97:  * Hashtable equals function for inbound SAs
        !            98:  */
        !            99: static bool equals_in(child_entry_t *a, child_entry_t *b)
        !           100: {
        !           101:        return a->spi_in == b->spi_in &&
        !           102:                   a->proto == b->proto &&
        !           103:                   a->host_in->ip_equals(a->host_in, b->host_in);
        !           104: }
        !           105: 
        !           106: /**
        !           107:  * Hashtable hash function for outbound SAs
        !           108:  */
        !           109: static u_int hash_out(child_entry_t *entry)
        !           110: {
        !           111:        return chunk_hash_inc(chunk_from_thing(entry->spi_out),
        !           112:                        chunk_hash_inc(entry->host_out->get_address(entry->host_out),
        !           113:                         chunk_hash(chunk_from_thing(entry->proto))));
        !           114: }
        !           115: 
        !           116: /**
        !           117:  * Hashtable equals function for outbound SAs
        !           118:  */
        !           119: static bool equals_out(child_entry_t *a, child_entry_t *b)
        !           120: {
        !           121:        return a->spi_out == b->spi_out &&
        !           122:                   a->proto == b->proto &&
        !           123:                   a->host_out->ip_equals(a->host_out, b->host_out);
        !           124: }
        !           125: 
        !           126: /**
        !           127:  * Hashtable hash function for SAs by unique ID
        !           128:  */
        !           129: static u_int hash_id(child_entry_t *entry)
        !           130: {
        !           131:        return chunk_hash(chunk_from_thing(entry->unique_id));
        !           132: }
        !           133: 
        !           134: /**
        !           135:  * Hashtable equals function for SAs by unique ID
        !           136:  */
        !           137: static bool equals_id(child_entry_t *a, child_entry_t *b)
        !           138: {
        !           139:        return a->unique_id == b->unique_id;
        !           140: }
        !           141: 
        !           142: METHOD(child_sa_manager_t, add, void,
        !           143:        private_child_sa_manager_t *this, child_sa_t *child_sa, ike_sa_t *ike_sa)
        !           144: {
        !           145:        child_entry_t *entry;
        !           146:        host_t *in, *out;
        !           147:        ike_sa_id_t *id;
        !           148: 
        !           149:        id = ike_sa->get_id(ike_sa);
        !           150:        in = ike_sa->get_my_host(ike_sa);
        !           151:        out = ike_sa->get_other_host(ike_sa);
        !           152: 
        !           153:        INIT(entry,
        !           154:                .ike_id = id->clone(id),
        !           155:                .unique_id = child_sa->get_unique_id(child_sa),
        !           156:                .proto = child_sa->get_protocol(child_sa),
        !           157:                .spi_in = child_sa->get_spi(child_sa, TRUE),
        !           158:                .spi_out = child_sa->get_spi(child_sa, FALSE),
        !           159:                .host_in = in->clone(in),
        !           160:                .host_out = out->clone(out),
        !           161:        );
        !           162: 
        !           163:        this->mutex->lock(this->mutex);
        !           164:        if (!this->in->get(this->in, entry) &&
        !           165:                !this->out->get(this->out, entry))
        !           166:        {
        !           167:                this->in->put(this->in, entry, entry);
        !           168:                this->out->put(this->out, entry, entry);
        !           169:                entry = this->ids->put(this->ids, entry, entry);
        !           170:        }
        !           171:        this->mutex->unlock(this->mutex);
        !           172: 
        !           173:        if (entry)
        !           174:        {
        !           175:                child_entry_destroy(entry);
        !           176:        }
        !           177: }
        !           178: 
        !           179: METHOD(child_sa_manager_t, remove_, void,
        !           180:        private_child_sa_manager_t *this, child_sa_t *child_sa)
        !           181: {
        !           182:        child_entry_t *entry, key = {
        !           183:                .unique_id = child_sa->get_unique_id(child_sa),
        !           184:        };
        !           185: 
        !           186:        this->mutex->lock(this->mutex);
        !           187:        entry = this->ids->remove(this->ids, &key);
        !           188:        if (entry)
        !           189:        {
        !           190:                this->in->remove(this->in, entry);
        !           191:                this->out->remove(this->out, entry);
        !           192:        }
        !           193:        this->mutex->unlock(this->mutex);
        !           194: 
        !           195:        if (entry)
        !           196:        {
        !           197:                child_entry_destroy(entry);
        !           198:        }
        !           199: }
        !           200: 
        !           201: /**
        !           202:  * Check out an IKE_SA for a given CHILD_SA
        !           203:  */
        !           204: static ike_sa_t *checkout_ikesa(private_child_sa_manager_t *this,
        !           205:                                        ike_sa_id_t *id, uint32_t unique_id, child_sa_t **child_sa)
        !           206: {
        !           207:        enumerator_t *enumerator;
        !           208:        child_sa_t *current;
        !           209:        ike_sa_t *ike_sa;
        !           210:        bool found = FALSE;
        !           211: 
        !           212:        ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id);
        !           213:        id->destroy(id);
        !           214:        if (ike_sa)
        !           215:        {
        !           216:                enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
        !           217:                while (enumerator->enumerate(enumerator, &current))
        !           218:                {
        !           219:                        found = current->get_unique_id(current) == unique_id;
        !           220:                        if (found)
        !           221:                        {
        !           222:                                if (child_sa)
        !           223:                                {
        !           224:                                        *child_sa = current;
        !           225:                                }
        !           226:                                break;
        !           227:                        }
        !           228:                }
        !           229:                enumerator->destroy(enumerator);
        !           230: 
        !           231:                if (found)
        !           232:                {
        !           233:                        return ike_sa;
        !           234:                }
        !           235:                charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
        !           236:        }
        !           237:        return NULL;
        !           238: }
        !           239: 
        !           240: METHOD(child_sa_manager_t, checkout_by_id, ike_sa_t*,
        !           241:        private_child_sa_manager_t *this, uint32_t unique_id,
        !           242:        child_sa_t **child_sa)
        !           243: {
        !           244:        ike_sa_id_t *id;
        !           245:        child_entry_t *entry, key = {
        !           246:                .unique_id = unique_id,
        !           247:        };
        !           248: 
        !           249:        this->mutex->lock(this->mutex);
        !           250:        entry = this->ids->get(this->ids, &key);
        !           251:        if (entry)
        !           252:        {
        !           253:                id = entry->ike_id->clone(entry->ike_id);
        !           254:        }
        !           255:        this->mutex->unlock(this->mutex);
        !           256: 
        !           257:        if (entry)
        !           258:        {
        !           259:                return checkout_ikesa(this, id, unique_id, child_sa);
        !           260:        }
        !           261:        return NULL;
        !           262: }
        !           263: 
        !           264: METHOD(child_sa_manager_t, checkout, ike_sa_t*,
        !           265:        private_child_sa_manager_t *this, protocol_id_t protocol, uint32_t spi,
        !           266:        host_t *dst, child_sa_t **child_sa)
        !           267: {
        !           268:        ike_sa_id_t *id;
        !           269:        uint32_t unique_id;
        !           270:        child_entry_t *entry, key = {
        !           271:                .spi_in = spi,
        !           272:                .spi_out = spi,
        !           273:                .host_in = dst,
        !           274:                .host_out = dst,
        !           275:                .proto = protocol,
        !           276:        };
        !           277: 
        !           278:        this->mutex->lock(this->mutex);
        !           279:        entry = this->in->get(this->in, &key);
        !           280:        if (!entry)
        !           281:        {
        !           282:                entry = this->out->get(this->out, &key);
        !           283:        }
        !           284:        if (entry)
        !           285:        {
        !           286:                unique_id = entry->unique_id;
        !           287:                id = entry->ike_id->clone(entry->ike_id);
        !           288:        }
        !           289:        this->mutex->unlock(this->mutex);
        !           290: 
        !           291:        if (entry)
        !           292:        {
        !           293:                return checkout_ikesa(this, id, unique_id, child_sa);
        !           294:        }
        !           295:        return NULL;
        !           296: }
        !           297: 
        !           298: METHOD(child_sa_manager_t, destroy, void,
        !           299:        private_child_sa_manager_t *this)
        !           300: {
        !           301:        this->in->destroy(this->in);
        !           302:        this->out->destroy(this->out);
        !           303:        this->ids->destroy(this->ids);
        !           304:        this->mutex->destroy(this->mutex);
        !           305:        free(this);
        !           306: }
        !           307: 
        !           308: /**
        !           309:  * See header
        !           310:  */
        !           311: child_sa_manager_t *child_sa_manager_create()
        !           312: {
        !           313:        private_child_sa_manager_t *this;
        !           314: 
        !           315:        INIT(this,
        !           316:                .public = {
        !           317:                        .add = _add,
        !           318:                        .remove = _remove_,
        !           319:                        .checkout = _checkout,
        !           320:                        .checkout_by_id = _checkout_by_id,
        !           321:                        .destroy = _destroy,
        !           322:                },
        !           323:                .in = hashtable_create((hashtable_hash_t)hash_in,
        !           324:                                                           (hashtable_equals_t)equals_in, 8),
        !           325:                .out = hashtable_create((hashtable_hash_t)hash_out,
        !           326:                                                           (hashtable_equals_t)equals_out, 8),
        !           327:                .ids = hashtable_create((hashtable_hash_t)hash_id,
        !           328:                                                           (hashtable_equals_t)equals_id, 8),
        !           329:                .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
        !           330:        );
        !           331: 
        !           332:        return &this->public;
        !           333: }

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