Annotation of embedaddon/strongswan/src/libcharon/attributes/attribute_manager.c, revision 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>