Annotation of embedaddon/strongswan/src/libcharon/tests/utils/mock_ipsec.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:  * Copyright (C) 2016-2017 Tobias Brunner
                      3:  * Copyright (C) 2008 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 "mock_ipsec.h"
                     18: 
                     19: #include <daemon.h>
                     20: #include <collections/hashtable.h>
                     21: #include <collections/array.h>
                     22: 
                     23: #include <assert.h>
                     24: 
                     25: typedef struct private_kernel_ipsec_t private_kernel_ipsec_t;
                     26: 
                     27: /**
                     28:  * Private data
                     29:  */
                     30: struct private_kernel_ipsec_t {
                     31: 
                     32:        /**
                     33:         * Public interface
                     34:         */
                     35:        kernel_ipsec_t public;
                     36: 
                     37:        /**
                     38:         * Rekey listener
                     39:         */
                     40:        listener_t listener;
                     41: 
                     42:        /**
                     43:         * Allocated SPI
                     44:         */
                     45:        refcount_t spi;
                     46: 
                     47:        /**
                     48:         * Installed SAs
                     49:         */
                     50:        hashtable_t *sas;
                     51: };
                     52: 
                     53: /**
                     54:  * Global instance
                     55:  */
                     56: static private_kernel_ipsec_t *instance;
                     57: 
                     58: /**
                     59:  * Data about installed IPsec SAs
                     60:  */
                     61: typedef struct {
                     62:        /**
                     63:         * SPI of the SA
                     64:         */
                     65:        uint32_t spi;
                     66: 
                     67:        /**
                     68:         * Associated IKE_SA
                     69:         */
                     70:        ike_sa_t *ike_sa;
                     71: 
                     72:        /**
                     73:         * TRUE if this was an allocated SPI
                     74:         */
                     75:        bool alloc;
                     76: 
                     77: } entry_t;
                     78: 
                     79: /**
                     80:  * Hash an IPsec SA entry
                     81:  */
                     82: static u_int entry_hash(const void *key)
                     83: {
                     84:        entry_t *entry = (entry_t*)key;
                     85:        return chunk_hash_inc(chunk_from_thing(entry->spi),
                     86:                                                  chunk_hash(chunk_from_thing(entry->ike_sa)));
                     87: }
                     88: 
                     89: /**
                     90:  * Compare an IPsec SA entry
                     91:  */
                     92: static bool entry_equals(const void *key, const void *other_key)
                     93: {
                     94:        entry_t *a = (entry_t*)key, *b = (entry_t*)other_key;
                     95:        return a->spi == b->spi && a->ike_sa == b->ike_sa;
                     96: }
                     97: 
                     98: METHOD(kernel_ipsec_t, get_spi, status_t,
                     99:        private_kernel_ipsec_t *this, host_t *src, host_t *dst, uint8_t protocol,
                    100:        uint32_t *spi)
                    101: {
                    102:        entry_t *entry;
                    103: 
                    104:        *spi = (uint32_t)ref_get(&this->spi);
                    105:        INIT(entry,
                    106:                .spi = *spi,
                    107:                .ike_sa = charon->bus->get_sa(charon->bus),
                    108:                .alloc = TRUE,
                    109:        );
                    110:        entry = this->sas->put(this->sas, entry, entry);
                    111:        assert(!entry);
                    112:        return SUCCESS;
                    113: }
                    114: 
                    115: METHOD(kernel_ipsec_t, get_cpi, status_t,
                    116:        private_kernel_ipsec_t *this, host_t *src, host_t *dst, uint16_t *cpi)
                    117: {
                    118:        return FAILED;
                    119: }
                    120: 
                    121: METHOD(kernel_ipsec_t, add_sa, status_t,
                    122:        private_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
                    123:        kernel_ipsec_add_sa_t *data)
                    124: {
                    125:        entry_t *entry;
                    126: 
                    127:        INIT(entry,
                    128:                .spi = id->spi,
                    129:                .ike_sa = charon->bus->get_sa(charon->bus),
                    130:        );
                    131:        if (data->inbound)
                    132:        {
                    133:                entry = this->sas->put(this->sas, entry, entry);
                    134:                assert(entry && entry->alloc);
                    135:                free(entry);
                    136:        }
                    137:        else
                    138:        {
                    139:                entry = this->sas->put(this->sas, entry, entry);
                    140:                assert(!entry);
                    141:        }
                    142:        return SUCCESS;
                    143: }
                    144: 
                    145: METHOD(kernel_ipsec_t, update_sa, status_t,
                    146:        private_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
                    147:        kernel_ipsec_update_sa_t *data)
                    148: {
                    149:        return SUCCESS;
                    150: }
                    151: 
                    152: METHOD(kernel_ipsec_t, query_sa, status_t,
                    153:        private_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
                    154:        kernel_ipsec_query_sa_t *data, uint64_t *bytes, uint64_t *packets,
                    155:        time_t *time)
                    156: {
                    157:        return NOT_SUPPORTED;
                    158: }
                    159: 
                    160: METHOD(kernel_ipsec_t, del_sa, status_t,
                    161:        private_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
                    162:        kernel_ipsec_del_sa_t *data)
                    163: {
                    164:        entry_t *entry, lookup = {
                    165:                .spi = id->spi,
                    166:                .ike_sa = charon->bus->get_sa(charon->bus),
                    167:        };
                    168: 
                    169:        entry = this->sas->remove(this->sas, &lookup);
                    170:        assert(entry);
                    171:        free(entry);
                    172:        return SUCCESS;
                    173: }
                    174: 
                    175: METHOD(listener_t, ike_rekey, bool,
                    176:        listener_t *listener, ike_sa_t *old, ike_sa_t *new)
                    177: {
                    178:        enumerator_t *enumerator;
                    179:        array_t *sas = NULL;
                    180:        entry_t *entry;
                    181: 
                    182:        enumerator = instance->sas->create_enumerator(instance->sas);
                    183:        while (enumerator->enumerate(enumerator, &entry, NULL))
                    184:        {
                    185:                if (entry->ike_sa == old)
                    186:                {
                    187:                        instance->sas->remove_at(instance->sas, enumerator);
                    188:                        array_insert_create(&sas, ARRAY_TAIL, entry);
                    189:                }
                    190:        }
                    191:        enumerator->destroy(enumerator);
                    192:        enumerator = array_create_enumerator(sas);
                    193:        while (enumerator->enumerate(enumerator, &entry))
                    194:        {
                    195:                array_remove_at(sas, enumerator);
                    196:                entry->ike_sa = new;
                    197:                entry = instance->sas->put(instance->sas, entry, entry);
                    198:                assert(!entry);
                    199:        }
                    200:        enumerator->destroy(enumerator);
                    201:        array_destroy(sas);
                    202:        return TRUE;
                    203: }
                    204: 
                    205: METHOD(kernel_ipsec_t, add_policy, status_t,
                    206:        private_kernel_ipsec_t *this, kernel_ipsec_policy_id_t *id,
                    207:        kernel_ipsec_manage_policy_t *data)
                    208: {
                    209:        return SUCCESS;
                    210: }
                    211: 
                    212: METHOD(kernel_ipsec_t, query_policy, status_t,
                    213:        private_kernel_ipsec_t *this, kernel_ipsec_policy_id_t *id,
                    214:        kernel_ipsec_query_policy_t *data, time_t *use_time)
                    215: {
                    216:        *use_time = 1;
                    217:        return SUCCESS;
                    218: }
                    219: 
                    220: METHOD(kernel_ipsec_t, del_policy, status_t,
                    221:        private_kernel_ipsec_t *this, kernel_ipsec_policy_id_t *id,
                    222:        kernel_ipsec_manage_policy_t *data)
                    223: {
                    224:        return SUCCESS;
                    225: }
                    226: 
1.1.1.2 ! misho     227: CALLBACK(destroy_spis, void,
        !           228:        entry_t *entry, const void* key)
        !           229: {
        !           230:        /* only free allocated SPIs, other SAs that were not properly deleted will
        !           231:         * cause a leak */
        !           232:        if (entry->alloc)
        !           233:        {
        !           234:                free(entry);
        !           235:        }
        !           236: }
        !           237: 
1.1       misho     238: METHOD(kernel_ipsec_t, destroy, void,
                    239:        private_kernel_ipsec_t *this)
                    240: {
                    241:        charon->bus->remove_listener(charon->bus, &this->listener);
1.1.1.2 ! misho     242:        this->sas->destroy_function(this->sas, destroy_spis);
1.1       misho     243:        free(this);
                    244: }
                    245: 
                    246: /*
                    247:  * Described in header
                    248:  */
                    249: kernel_ipsec_t *mock_ipsec_create()
                    250: {
                    251:        private_kernel_ipsec_t *this;
                    252: 
                    253:        INIT(this,
                    254:                .public = {
                    255:                        .get_spi = _get_spi,
                    256:                        .get_cpi = _get_cpi,
                    257:                        .add_sa = _add_sa,
                    258:                        .update_sa = _update_sa,
                    259:                        .query_sa = _query_sa,
                    260:                        .del_sa = _del_sa,
                    261:                        .flush_sas = (void*)return_failed,
                    262:                        .add_policy = _add_policy,
                    263:                        .query_policy = _query_policy,
                    264:                        .del_policy = _del_policy,
                    265:                        .flush_policies = (void*)return_failed,
                    266:                        .bypass_socket = (void*)return_true,
                    267:                        .enable_udp_decap = (void*)return_true,
                    268:                        .destroy = _destroy,
                    269:                },
                    270:                .listener = {
                    271:                        .ike_rekey = _ike_rekey,
                    272:                },
                    273:                .sas = hashtable_create(entry_hash, entry_equals, 8),
                    274:        );
                    275: 
                    276:        instance = this;
                    277: 
                    278:        charon->bus->add_listener(charon->bus, &this->listener);
                    279: 
                    280:        return &this->public;
                    281: }
                    282: 
                    283: 
                    284: CALLBACK(filter_sas, bool,
                    285:        void *data, enumerator_t *orig, va_list args)
                    286: {
                    287:        entry_t *entry;
                    288:        ike_sa_t **ike_sa;
                    289:        uint32_t *spi;
                    290: 
                    291:        VA_ARGS_VGET(args, ike_sa, spi);
                    292: 
                    293:        while (orig->enumerate(orig, &entry, NULL))
                    294:        {
                    295:                if (entry->alloc)
                    296:                {
                    297:                        continue;
                    298:                }
                    299:                *ike_sa = entry->ike_sa;
                    300:                *spi = entry->spi;
                    301:                return TRUE;
                    302:        }
                    303:        return FALSE;
                    304: }
                    305: 
                    306: /*
                    307:  * Described in header
                    308:  */
                    309: enumerator_t *mock_ipsec_create_sa_enumerator()
                    310: {
                    311:        return enumerator_create_filter(
                    312:                                                        instance->sas->create_enumerator(instance->sas),
                    313:                                                        filter_sas, NULL, NULL);
                    314: }

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