Annotation of embedaddon/strongswan/src/libcharon/attributes/attribute_manager.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2008 Martin Willi
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      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 "attribute_manager.h"
                     17: 
                     18: #include <utils/debug.h>
                     19: #include <collections/linked_list.h>
                     20: #include <threading/rwlock.h>
                     21: 
                     22: typedef struct private_attribute_manager_t private_attribute_manager_t;
                     23: 
                     24: /**
                     25:  * private data of attribute_manager
                     26:  */
                     27: struct private_attribute_manager_t {
                     28: 
                     29:        /**
                     30:         * public functions
                     31:         */
                     32:        attribute_manager_t public;
                     33: 
                     34:        /**
                     35:         * list of registered providers
                     36:         */
                     37:        linked_list_t *providers;
                     38: 
                     39:        /**
                     40:         * list of registered handlers
                     41:         */
                     42:        linked_list_t *handlers;
                     43: 
                     44:        /**
                     45:         * rwlock provider list
                     46:         */
                     47:        rwlock_t *lock;
                     48: };
                     49: 
                     50: /**
                     51:  * Data to pass to enumerator filters
                     52:  */
                     53: typedef struct {
                     54:        /** attribute group pools */
                     55:        linked_list_t *pools;
                     56:        /** associated IKE_SA */
                     57:        ike_sa_t *ike_sa;
                     58:        /** requesting/assigned virtual IPs */
                     59:        linked_list_t *vips;
                     60: } enum_data_t;
                     61: 
                     62: METHOD(attribute_manager_t, acquire_address, host_t*,
                     63:        private_attribute_manager_t *this, linked_list_t *pools,
                     64:        ike_sa_t *ike_sa, host_t *requested)
                     65: {
                     66:        enumerator_t *enumerator;
                     67:        attribute_provider_t *current;
                     68:        host_t *host = NULL;
                     69: 
                     70:        this->lock->read_lock(this->lock);
                     71:        enumerator = this->providers->create_enumerator(this->providers);
                     72:        while (enumerator->enumerate(enumerator, &current))
                     73:        {
                     74:                host = current->acquire_address(current, pools, ike_sa, requested);
                     75:                if (host)
                     76:                {
                     77:                        break;
                     78:                }
                     79:        }
                     80:        enumerator->destroy(enumerator);
                     81:        this->lock->unlock(this->lock);
                     82: 
                     83:        return host;
                     84: }
                     85: 
                     86: METHOD(attribute_manager_t, release_address, bool,
                     87:        private_attribute_manager_t *this, linked_list_t *pools, host_t *address,
                     88:        ike_sa_t *ike_sa)
                     89: {
                     90:        enumerator_t *enumerator;
                     91:        attribute_provider_t *current;
                     92:        bool found = FALSE;
                     93: 
                     94:        this->lock->read_lock(this->lock);
                     95:        enumerator = this->providers->create_enumerator(this->providers);
                     96:        while (enumerator->enumerate(enumerator, &current))
                     97:        {
                     98:                if (current->release_address(current, pools, address, ike_sa))
                     99:                {
                    100:                        found = TRUE;
                    101:                        break;
                    102:                }
                    103:        }
                    104:        enumerator->destroy(enumerator);
                    105:        this->lock->unlock(this->lock);
                    106: 
                    107:        return found;
                    108: }
                    109: 
                    110: /**
                    111:  * inner enumerator constructor for responder attributes
                    112:  */
                    113: static enumerator_t *responder_enum_create(attribute_provider_t *provider,
                    114:                                                                                   enum_data_t *data)
                    115: {
                    116:        return provider->create_attribute_enumerator(provider, data->pools,
                    117:                                                                                                 data->ike_sa, data->vips);
                    118: }
                    119: 
                    120: METHOD(attribute_manager_t, create_responder_enumerator, enumerator_t*,
                    121:        private_attribute_manager_t *this, linked_list_t *pools,
                    122:        ike_sa_t *ike_sa, linked_list_t *vips)
                    123: {
                    124:        enum_data_t *data;
                    125: 
                    126:        INIT(data,
                    127:                .pools = pools,
                    128:                .ike_sa = ike_sa,
                    129:                .vips = vips,
                    130:        );
                    131:        this->lock->read_lock(this->lock);
                    132:        return enumerator_create_cleaner(
                    133:                                enumerator_create_nested(
                    134:                                        this->providers->create_enumerator(this->providers),
                    135:                                        (void*)responder_enum_create, data, free),
                    136:                                (void*)this->lock->unlock, this->lock);
                    137: }
                    138: 
                    139: METHOD(attribute_manager_t, add_provider, void,
                    140:        private_attribute_manager_t *this, attribute_provider_t *provider)
                    141: {
                    142:        this->lock->write_lock(this->lock);
                    143:        this->providers->insert_last(this->providers, provider);
                    144:        this->lock->unlock(this->lock);
                    145: }
                    146: 
                    147: METHOD(attribute_manager_t, remove_provider, void,
                    148:        private_attribute_manager_t *this, attribute_provider_t *provider)
                    149: {
                    150:        this->lock->write_lock(this->lock);
                    151:        this->providers->remove(this->providers, provider, NULL);
                    152:        this->lock->unlock(this->lock);
                    153: }
                    154: 
                    155: METHOD(attribute_manager_t, handle, attribute_handler_t*,
                    156:        private_attribute_manager_t *this, ike_sa_t *ike_sa,
                    157:        attribute_handler_t *handler, configuration_attribute_type_t type,
                    158:        chunk_t data)
                    159: {
                    160:        enumerator_t *enumerator;
                    161:        attribute_handler_t *current, *handled = NULL;
                    162: 
                    163:        this->lock->read_lock(this->lock);
                    164: 
                    165:        /* try to find the passed handler */
                    166:        enumerator = this->handlers->create_enumerator(this->handlers);
                    167:        while (enumerator->enumerate(enumerator, &current))
                    168:        {
                    169:                if (current == handler && current->handle(current, ike_sa, type, data))
                    170:                {
                    171:                        handled = current;
                    172:                        break;
                    173:                }
                    174:        }
                    175:        enumerator->destroy(enumerator);
                    176:        if (!handled)
                    177:        {       /* handler requesting this attribute not found, try any other */
                    178:                enumerator = this->handlers->create_enumerator(this->handlers);
                    179:                while (enumerator->enumerate(enumerator, &current))
                    180:                {
                    181:                        if (current->handle(current, ike_sa, type, data))
                    182:                        {
                    183:                                handled = current;
                    184:                                break;
                    185:                        }
                    186:                }
                    187:                enumerator->destroy(enumerator);
                    188:        }
                    189:        this->lock->unlock(this->lock);
                    190: 
                    191:        if (!handled)
                    192:        {
                    193:                DBG1(DBG_CFG, "handling %N attribute failed",
                    194:                         configuration_attribute_type_names, type);
                    195:        }
                    196:        return handled;
                    197: }
                    198: 
                    199: METHOD(attribute_manager_t, release, void,
                    200:        private_attribute_manager_t *this, attribute_handler_t *handler,
                    201:        ike_sa_t *ike_sa, configuration_attribute_type_t type, chunk_t data)
                    202: {
                    203:        enumerator_t *enumerator;
                    204:        attribute_handler_t *current;
                    205: 
                    206:        this->lock->read_lock(this->lock);
                    207:        enumerator = this->handlers->create_enumerator(this->handlers);
                    208:        while (enumerator->enumerate(enumerator, &current))
                    209:        {
                    210:                if (current == handler)
                    211:                {
                    212:                        current->release(current, ike_sa, type, data);
                    213:                        break;
                    214:                }
                    215:        }
                    216:        enumerator->destroy(enumerator);
                    217:        this->lock->unlock(this->lock);
                    218: }
                    219: 
                    220: /**
                    221:  * Enumerator implementation to enumerate nested initiator attributes
                    222:  */
                    223: typedef struct {
                    224:        /** implements enumerator_t */
                    225:        enumerator_t public;
                    226:        /** back ref */
                    227:        private_attribute_manager_t *this;
                    228:        /** currently processing handler */
                    229:        attribute_handler_t *handler;
                    230:        /** outer enumerator over handlers */
                    231:        enumerator_t *outer;
                    232:        /** inner enumerator over current handlers attributes */
                    233:        enumerator_t *inner;
                    234:        /** IKE_SA to request attributes for */
                    235:        ike_sa_t *ike_sa;
                    236:        /** virtual IPs we are requesting along with attributes */
                    237:        linked_list_t *vips;
                    238: } initiator_enumerator_t;
                    239: 
                    240: METHOD(enumerator_t, initiator_enumerate, bool,
                    241:        initiator_enumerator_t *this, va_list args)
                    242: {
                    243:        configuration_attribute_type_t *type;
                    244:        attribute_handler_t **handler;
                    245:        chunk_t *value;
                    246: 
                    247:        VA_ARGS_VGET(args, handler, type, value);
                    248:        /* enumerate inner attributes using outer handler enumerator */
                    249:        while (!this->inner || !this->inner->enumerate(this->inner, type, value))
                    250:        {
                    251:                if (!this->outer->enumerate(this->outer, &this->handler))
                    252:                {
                    253:                        return FALSE;
                    254:                }
                    255:                DESTROY_IF(this->inner);
                    256:                this->inner = this->handler->create_attribute_enumerator(this->handler,
                    257:                                                                                                        this->ike_sa, this->vips);
                    258:        }
                    259:        /* inject the handler as additional attribute */
                    260:        *handler = this->handler;
                    261:        return TRUE;
                    262: }
                    263: 
                    264: METHOD(enumerator_t, initiator_destroy, void,
                    265:        initiator_enumerator_t *this)
                    266: {
                    267:        this->this->lock->unlock(this->this->lock);
                    268:        this->outer->destroy(this->outer);
                    269:        DESTROY_IF(this->inner);
                    270:        free(this);
                    271: }
                    272: 
                    273: METHOD(attribute_manager_t, create_initiator_enumerator, enumerator_t*,
                    274:        private_attribute_manager_t *this, ike_sa_t *ike_sa, linked_list_t *vips)
                    275: {
                    276:        initiator_enumerator_t *enumerator;
                    277: 
                    278:        this->lock->read_lock(this->lock);
                    279: 
                    280:        INIT(enumerator,
                    281:                .public = {
                    282:                        .enumerate = enumerator_enumerate_default,
                    283:                        .venumerate = _initiator_enumerate,
                    284:                        .destroy = _initiator_destroy,
                    285:                },
                    286:                .this = this,
                    287:                .ike_sa = ike_sa,
                    288:                .vips = vips,
                    289:                .outer = this->handlers->create_enumerator(this->handlers),
                    290:        );
                    291:        return &enumerator->public;
                    292: }
                    293: 
                    294: METHOD(attribute_manager_t, add_handler, void,
                    295:        private_attribute_manager_t *this, attribute_handler_t *handler)
                    296: {
                    297:        this->lock->write_lock(this->lock);
                    298:        this->handlers->insert_last(this->handlers, handler);
                    299:        this->lock->unlock(this->lock);
                    300: }
                    301: 
                    302: METHOD(attribute_manager_t, remove_handler, void,
                    303:        private_attribute_manager_t *this, attribute_handler_t *handler)
                    304: {
                    305:        this->lock->write_lock(this->lock);
                    306:        this->handlers->remove(this->handlers, handler, NULL);
                    307:        this->lock->unlock(this->lock);
                    308: }
                    309: 
                    310: METHOD(attribute_manager_t, destroy, void,
                    311:        private_attribute_manager_t *this)
                    312: {
                    313:        this->providers->destroy(this->providers);
                    314:        this->handlers->destroy(this->handlers);
                    315:        this->lock->destroy(this->lock);
                    316:        free(this);
                    317: }
                    318: 
                    319: /*
                    320:  * see header file
                    321:  */
                    322: attribute_manager_t *attribute_manager_create()
                    323: {
                    324:        private_attribute_manager_t *this;
                    325: 
                    326:        INIT(this,
                    327:                .public = {
                    328:                        .acquire_address = _acquire_address,
                    329:                        .release_address = _release_address,
                    330:                        .create_responder_enumerator = _create_responder_enumerator,
                    331:                        .add_provider = _add_provider,
                    332:                        .remove_provider = _remove_provider,
                    333:                        .handle = _handle,
                    334:                        .release = _release,
                    335:                        .create_initiator_enumerator = _create_initiator_enumerator,
                    336:                        .add_handler = _add_handler,
                    337:                        .remove_handler = _remove_handler,
                    338:                        .destroy = _destroy,
                    339:                },
                    340:                .providers = linked_list_create(),
                    341:                .handlers = linked_list_create(),
                    342:                .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
                    343:        );
                    344: 
                    345:        return &this->public;
                    346: }

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