Return to stroke_attribute.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / stroke |
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: }