Annotation of embedaddon/strongswan/src/libcharon/sa/child_sa_manager.c, revision 1.1.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>