Annotation of embedaddon/strongswan/src/libcharon/plugins/stroke/stroke_attribute.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2010 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 "stroke_attribute.h"
! 18:
! 19: #include <daemon.h>
! 20: #include <collections/linked_list.h>
! 21: #include <threading/rwlock.h>
! 22:
! 23: typedef struct private_stroke_attribute_t private_stroke_attribute_t;
! 24:
! 25: /**
! 26: * private data of stroke_attribute
! 27: */
! 28: struct private_stroke_attribute_t {
! 29:
! 30: /**
! 31: * public functions
! 32: */
! 33: stroke_attribute_t public;
! 34:
! 35: /**
! 36: * list of pools, contains mem_pool_t
! 37: */
! 38: linked_list_t *pools;
! 39:
! 40: /**
! 41: * List of connection specific attributes, as attributes_t
! 42: */
! 43: linked_list_t *attrs;
! 44:
! 45: /**
! 46: * rwlock to lock access to pools
! 47: */
! 48: rwlock_t *lock;
! 49: };
! 50:
! 51: /**
! 52: * Attributes assigned to a connection
! 53: */
! 54: typedef struct {
! 55: /** name of the connection */
! 56: char *name;
! 57: /** list of DNS attributes, as host_t */
! 58: linked_list_t *dns;
! 59: } attributes_t;
! 60:
! 61: /**
! 62: * Destroy an attributes_t entry
! 63: */
! 64: static void attributes_destroy(attributes_t *this)
! 65: {
! 66: this->dns->destroy_offset(this->dns, offsetof(host_t, destroy));
! 67: free(this->name);
! 68: free(this);
! 69: }
! 70:
! 71: /**
! 72: * find a pool by name
! 73: */
! 74: static mem_pool_t *find_pool(private_stroke_attribute_t *this, char *name)
! 75: {
! 76: enumerator_t *enumerator;
! 77: mem_pool_t *current, *found = NULL;
! 78:
! 79: enumerator = this->pools->create_enumerator(this->pools);
! 80: while (enumerator->enumerate(enumerator, ¤t))
! 81: {
! 82: if (streq(name, current->get_name(current)))
! 83: {
! 84: found = current;
! 85: break;
! 86: }
! 87: }
! 88: enumerator->destroy(enumerator);
! 89: return found;
! 90: }
! 91:
! 92: /**
! 93: * Find an existing or not yet existing lease
! 94: */
! 95: static host_t *find_addr(private_stroke_attribute_t *this, linked_list_t *pools,
! 96: identification_t *id, host_t *requested,
! 97: mem_pool_op_t operation, host_t *peer)
! 98: {
! 99: host_t *addr = NULL;
! 100: enumerator_t *enumerator;
! 101: mem_pool_t *pool;
! 102: char *name;
! 103:
! 104: enumerator = pools->create_enumerator(pools);
! 105: while (enumerator->enumerate(enumerator, &name))
! 106: {
! 107: pool = find_pool(this, name);
! 108: if (pool)
! 109: {
! 110: addr = pool->acquire_address(pool, id, requested, operation, peer);
! 111: if (addr)
! 112: {
! 113: break;
! 114: }
! 115: }
! 116: }
! 117: enumerator->destroy(enumerator);
! 118:
! 119: return addr;
! 120: }
! 121:
! 122: METHOD(attribute_provider_t, acquire_address, host_t*,
! 123: private_stroke_attribute_t *this, linked_list_t *pools, ike_sa_t *ike_sa,
! 124: host_t *requested)
! 125: {
! 126: identification_t *id;
! 127: host_t *addr, *peer;
! 128:
! 129: id = ike_sa->get_other_eap_id(ike_sa);
! 130: peer = ike_sa->get_other_host(ike_sa);
! 131:
! 132: this->lock->read_lock(this->lock);
! 133:
! 134: addr = find_addr(this, pools, id, requested, MEM_POOL_EXISTING, peer);
! 135: if (!addr)
! 136: {
! 137: addr = find_addr(this, pools, id, requested, MEM_POOL_NEW, peer);
! 138: if (!addr)
! 139: {
! 140: addr = find_addr(this, pools, id, requested, MEM_POOL_REASSIGN, peer);
! 141: }
! 142: }
! 143:
! 144: this->lock->unlock(this->lock);
! 145:
! 146: return addr;
! 147: }
! 148:
! 149: METHOD(attribute_provider_t, release_address, bool,
! 150: private_stroke_attribute_t *this, linked_list_t *pools, host_t *address,
! 151: ike_sa_t *ike_sa)
! 152: {
! 153: enumerator_t *enumerator;
! 154: identification_t *id;
! 155: mem_pool_t *pool;
! 156: bool found = FALSE;
! 157: char *name;
! 158:
! 159: id = ike_sa->get_other_eap_id(ike_sa);
! 160:
! 161: enumerator = pools->create_enumerator(pools);
! 162: this->lock->read_lock(this->lock);
! 163: while (enumerator->enumerate(enumerator, &name))
! 164: {
! 165: pool = find_pool(this, name);
! 166: if (pool)
! 167: {
! 168: found = pool->release_address(pool, address, id);
! 169: if (found)
! 170: {
! 171: break;
! 172: }
! 173: }
! 174: }
! 175: this->lock->unlock(this->lock);
! 176: enumerator->destroy(enumerator);
! 177:
! 178: return found;
! 179: }
! 180:
! 181: CALLBACK(attr_filter, bool,
! 182: void *lock, enumerator_t *orig, va_list args)
! 183: {
! 184: configuration_attribute_type_t *type;
! 185: chunk_t *data;
! 186: host_t *host;
! 187:
! 188: VA_ARGS_VGET(args, type, data);
! 189:
! 190: while (orig->enumerate(orig, &host))
! 191: {
! 192: switch (host->get_family(host))
! 193: {
! 194: case AF_INET:
! 195: *type = INTERNAL_IP4_DNS;
! 196: break;
! 197: case AF_INET6:
! 198: *type = INTERNAL_IP6_DNS;
! 199: break;
! 200: default:
! 201: continue;
! 202: }
! 203: *data = host->get_address(host);
! 204: return TRUE;
! 205: }
! 206: return FALSE;
! 207: }
! 208:
! 209: METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
! 210: private_stroke_attribute_t *this, linked_list_t *pools,
! 211: ike_sa_t *ike_sa, linked_list_t *vips)
! 212: {
! 213: peer_cfg_t *peer_cfg;
! 214: enumerator_t *enumerator;
! 215: attributes_t *attr;
! 216:
! 217: ike_sa = charon->bus->get_sa(charon->bus);
! 218: if (ike_sa)
! 219: {
! 220: peer_cfg = ike_sa->get_peer_cfg(ike_sa);
! 221: this->lock->read_lock(this->lock);
! 222: enumerator = this->attrs->create_enumerator(this->attrs);
! 223: while (enumerator->enumerate(enumerator, &attr))
! 224: {
! 225: if (streq(attr->name, peer_cfg->get_name(peer_cfg)))
! 226: {
! 227: enumerator->destroy(enumerator);
! 228: return enumerator_create_filter(
! 229: attr->dns->create_enumerator(attr->dns),
! 230: attr_filter, this->lock,
! 231: (void*)this->lock->unlock);
! 232: }
! 233: }
! 234: enumerator->destroy(enumerator);
! 235: this->lock->unlock(this->lock);
! 236: }
! 237: return enumerator_create_empty();
! 238: }
! 239:
! 240: METHOD(stroke_attribute_t, add_pool, void,
! 241: private_stroke_attribute_t *this, mem_pool_t *pool)
! 242: {
! 243: enumerator_t *enumerator;
! 244: mem_pool_t *current;
! 245: host_t *base;
! 246: int size;
! 247:
! 248: base = pool->get_base(pool);
! 249: size = pool->get_size(pool);
! 250:
! 251: this->lock->write_lock(this->lock);
! 252:
! 253: enumerator = this->pools->create_enumerator(this->pools);
! 254: while (enumerator->enumerate(enumerator, ¤t))
! 255: {
! 256: if (base && current->get_base(current) &&
! 257: base->ip_equals(base, current->get_base(current)) &&
! 258: size == current->get_size(current))
! 259: {
! 260: DBG1(DBG_CFG, "reusing virtual IP address pool %s",
! 261: current->get_name(current));
! 262: pool->destroy(pool);
! 263: pool = NULL;
! 264: break;
! 265: }
! 266: }
! 267: enumerator->destroy(enumerator);
! 268:
! 269: if (pool)
! 270: {
! 271: if (base)
! 272: {
! 273: DBG1(DBG_CFG, "adding virtual IP address pool %s",
! 274: pool->get_name(pool));
! 275: }
! 276: this->pools->insert_last(this->pools, pool);
! 277: }
! 278:
! 279: this->lock->unlock(this->lock);
! 280: }
! 281:
! 282: METHOD(stroke_attribute_t, add_dns, void,
! 283: private_stroke_attribute_t *this, stroke_msg_t *msg)
! 284: {
! 285: if (msg->add_conn.other.dns)
! 286: {
! 287: enumerator_t *enumerator;
! 288: attributes_t *attr = NULL;
! 289: host_t *host;
! 290: char *token;
! 291:
! 292: enumerator = enumerator_create_token(msg->add_conn.other.dns, ",", " ");
! 293: while (enumerator->enumerate(enumerator, &token))
! 294: {
! 295: host = host_create_from_string(token, 0);
! 296: if (host)
! 297: {
! 298: if (!attr)
! 299: {
! 300: INIT(attr,
! 301: .name = strdup(msg->add_conn.name),
! 302: .dns = linked_list_create(),
! 303: );
! 304: }
! 305: attr->dns->insert_last(attr->dns, host);
! 306: }
! 307: else
! 308: {
! 309: DBG1(DBG_CFG, "ignoring invalid DNS address '%s'", token);
! 310: }
! 311: }
! 312: enumerator->destroy(enumerator);
! 313: if (attr)
! 314: {
! 315: this->lock->write_lock(this->lock);
! 316: this->attrs->insert_last(this->attrs, attr);
! 317: this->lock->unlock(this->lock);
! 318: }
! 319: }
! 320: }
! 321:
! 322: METHOD(stroke_attribute_t, del_dns, void,
! 323: private_stroke_attribute_t *this, stroke_msg_t *msg)
! 324: {
! 325: enumerator_t *enumerator;
! 326: attributes_t *attr;
! 327:
! 328: this->lock->write_lock(this->lock);
! 329:
! 330: enumerator = this->attrs->create_enumerator(this->attrs);
! 331: while (enumerator->enumerate(enumerator, &attr))
! 332: {
! 333: if (streq(msg->del_conn.name, attr->name))
! 334: {
! 335: this->attrs->remove_at(this->attrs, enumerator);
! 336: attributes_destroy(attr);
! 337: break;
! 338: }
! 339: }
! 340: enumerator->destroy(enumerator);
! 341:
! 342: this->lock->unlock(this->lock);
! 343: }
! 344:
! 345: CALLBACK(pool_filter, bool,
! 346: void *lock, enumerator_t *orig, va_list args)
! 347: {
! 348: mem_pool_t *pool;
! 349: const char **name;
! 350: u_int *size, *online, *offline;
! 351:
! 352: VA_ARGS_VGET(args, name, size, online, offline);
! 353:
! 354: while (orig->enumerate(orig, &pool))
! 355: {
! 356: if (pool->get_size(pool) == 0)
! 357: {
! 358: continue;
! 359: }
! 360: *name = pool->get_name(pool);
! 361: *size = pool->get_size(pool);
! 362: *online = pool->get_online(pool);
! 363: *offline = pool->get_offline(pool);
! 364: return TRUE;
! 365: }
! 366: return FALSE;
! 367: }
! 368:
! 369: METHOD(stroke_attribute_t, create_pool_enumerator, enumerator_t*,
! 370: private_stroke_attribute_t *this)
! 371: {
! 372: this->lock->read_lock(this->lock);
! 373: return enumerator_create_filter(this->pools->create_enumerator(this->pools),
! 374: pool_filter,
! 375: this->lock, (void*)this->lock->unlock);
! 376: }
! 377:
! 378: METHOD(stroke_attribute_t, create_lease_enumerator, enumerator_t*,
! 379: private_stroke_attribute_t *this, char *name)
! 380: {
! 381: mem_pool_t *pool;
! 382: this->lock->read_lock(this->lock);
! 383: pool = find_pool(this, name);
! 384: if (!pool)
! 385: {
! 386: this->lock->unlock(this->lock);
! 387: return NULL;
! 388: }
! 389: return enumerator_create_cleaner(pool->create_lease_enumerator(pool),
! 390: (void*)this->lock->unlock, this->lock);
! 391: }
! 392:
! 393: METHOD(stroke_attribute_t, destroy, void,
! 394: private_stroke_attribute_t *this)
! 395: {
! 396: this->lock->destroy(this->lock);
! 397: this->pools->destroy_offset(this->pools, offsetof(mem_pool_t, destroy));
! 398: this->attrs->destroy_function(this->attrs, (void*)attributes_destroy);
! 399: free(this);
! 400: }
! 401:
! 402: /*
! 403: * see header file
! 404: */
! 405: stroke_attribute_t *stroke_attribute_create()
! 406: {
! 407: private_stroke_attribute_t *this;
! 408:
! 409: INIT(this,
! 410: .public = {
! 411: .provider = {
! 412: .acquire_address = _acquire_address,
! 413: .release_address = _release_address,
! 414: .create_attribute_enumerator = _create_attribute_enumerator,
! 415: },
! 416: .add_pool = _add_pool,
! 417: .add_dns = _add_dns,
! 418: .del_dns = _del_dns,
! 419: .create_pool_enumerator = _create_pool_enumerator,
! 420: .create_lease_enumerator = _create_lease_enumerator,
! 421: .destroy = _destroy,
! 422: },
! 423: .pools = linked_list_create(),
! 424: .attrs = linked_list_create(),
! 425: .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
! 426: );
! 427:
! 428: return &this->public;
! 429: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>