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, ¤t))
! 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, ¤t))
! 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, ¤t))
! 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, ¤t))
! 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, ¤t))
! 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>