Return to dhcp_provider.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / dhcp |
1.1 misho 1: /* 2: * Copyright (C) 2010 Martin Willi 3: * Copyright (C) 2010 revosec AG 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 "dhcp_provider.h" 17: 18: #include <collections/hashtable.h> 19: #include <threading/mutex.h> 20: 21: typedef struct private_dhcp_provider_t private_dhcp_provider_t; 22: 23: /** 24: * Private data of an dhcp_provider_t object. 25: */ 26: struct private_dhcp_provider_t { 27: 28: /** 29: * Public dhcp_provider_t interface. 30: */ 31: dhcp_provider_t public; 32: 33: /** 34: * Completed DHCP transactions 35: */ 36: hashtable_t *transactions; 37: 38: /** 39: * Lock for transactions 40: */ 41: mutex_t *mutex; 42: 43: /** 44: * DHCP communication socket 45: */ 46: dhcp_socket_t *socket; 47: }; 48: 49: /** 50: * Hash ID and host to a key 51: */ 52: static uintptr_t hash_id_host(identification_t *id, host_t *host) 53: { 54: return chunk_hash_inc(id->get_encoding(id), 55: chunk_hash(host->get_address(host))); 56: } 57: 58: /** 59: * Hash a DHCP transaction to a key, using address and id 60: */ 61: static uintptr_t hash_transaction(dhcp_transaction_t *transaction) 62: { 63: return hash_id_host(transaction->get_identity(transaction), 64: transaction->get_address(transaction)); 65: } 66: 67: METHOD(attribute_provider_t, acquire_address, host_t*, 68: private_dhcp_provider_t *this, linked_list_t *pools, 69: ike_sa_t *ike_sa, host_t *requested) 70: { 71: dhcp_transaction_t *transaction, *old; 72: enumerator_t *enumerator; 73: identification_t *id; 74: char *pool; 75: host_t *vip = NULL; 76: 77: if (requested->get_family(requested) != AF_INET) 78: { 79: return NULL; 80: } 81: id = ike_sa->get_other_eap_id(ike_sa); 82: enumerator = pools->create_enumerator(pools); 83: while (enumerator->enumerate(enumerator, &pool)) 84: { 85: if (!streq(pool, "dhcp")) 86: { 87: continue; 88: } 89: transaction = this->socket->enroll(this->socket, id); 90: if (!transaction) 91: { 92: continue; 93: } 94: vip = transaction->get_address(transaction); 95: vip = vip->clone(vip); 96: this->mutex->lock(this->mutex); 97: old = this->transactions->put(this->transactions, 98: (void*)hash_transaction(transaction), transaction); 99: this->mutex->unlock(this->mutex); 100: DESTROY_IF(old); 101: break; 102: } 103: enumerator->destroy(enumerator); 104: return vip; 105: } 106: 107: METHOD(attribute_provider_t, release_address, bool, 108: private_dhcp_provider_t *this, linked_list_t *pools, 109: host_t *address, ike_sa_t *ike_sa) 110: { 111: dhcp_transaction_t *transaction; 112: enumerator_t *enumerator; 113: identification_t *id; 114: bool found = FALSE; 115: char *pool; 116: 117: if (address->get_family(address) != AF_INET) 118: { 119: return FALSE; 120: } 121: id = ike_sa->get_other_eap_id(ike_sa); 122: enumerator = pools->create_enumerator(pools); 123: while (enumerator->enumerate(enumerator, &pool)) 124: { 125: if (!streq(pool, "dhcp")) 126: { 127: continue; 128: } 129: this->mutex->lock(this->mutex); 130: transaction = this->transactions->remove(this->transactions, 131: (void*)hash_id_host(id, address)); 132: this->mutex->unlock(this->mutex); 133: if (transaction) 134: { 135: this->socket->release(this->socket, transaction); 136: transaction->destroy(transaction); 137: found = TRUE; 138: break; 139: } 140: } 141: enumerator->destroy(enumerator); 142: return found; 143: } 144: 145: METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, 146: private_dhcp_provider_t *this, linked_list_t *pools, ike_sa_t *ike_sa, 147: linked_list_t *vips) 148: { 149: dhcp_transaction_t *transaction = NULL; 150: enumerator_t *enumerator; 151: identification_t *id; 152: host_t *vip; 153: 154: if (!pools->find_first(pools, linked_list_match_str, NULL, "dhcp")) 155: { 156: return NULL; 157: } 158: 159: id = ike_sa->get_other_eap_id(ike_sa); 160: this->mutex->lock(this->mutex); 161: enumerator = vips->create_enumerator(vips); 162: while (enumerator->enumerate(enumerator, &vip)) 163: { 164: transaction = this->transactions->get(this->transactions, 165: (void*)hash_id_host(id, vip)); 166: if (transaction) 167: { 168: break; 169: } 170: } 171: enumerator->destroy(enumerator); 172: if (!transaction) 173: { 174: this->mutex->unlock(this->mutex); 175: return NULL; 176: } 177: return enumerator_create_cleaner( 178: transaction->create_attribute_enumerator(transaction), 179: (void*)this->mutex->unlock, this->mutex); 180: } 181: 182: METHOD(dhcp_provider_t, destroy, void, 183: private_dhcp_provider_t *this) 184: { 185: enumerator_t *enumerator; 186: dhcp_transaction_t *value; 187: void *key; 188: 189: enumerator = this->transactions->create_enumerator(this->transactions); 190: while (enumerator->enumerate(enumerator, &key, &value)) 191: { 192: value->destroy(value); 193: } 194: enumerator->destroy(enumerator); 195: this->transactions->destroy(this->transactions); 196: this->mutex->destroy(this->mutex); 197: free(this); 198: } 199: 200: /** 201: * See header 202: */ 203: dhcp_provider_t *dhcp_provider_create(dhcp_socket_t *socket) 204: { 205: private_dhcp_provider_t *this; 206: 207: INIT(this, 208: .public = { 209: .provider = { 210: .acquire_address = _acquire_address, 211: .release_address = _release_address, 212: .create_attribute_enumerator = _create_attribute_enumerator, 213: }, 214: .destroy = _destroy, 215: }, 216: .socket = socket, 217: .mutex = mutex_create(MUTEX_TYPE_DEFAULT), 218: .transactions = hashtable_create(hashtable_hash_ptr, 219: hashtable_equals_ptr, 8), 220: ); 221: 222: return &this->public; 223: }