Annotation of embedaddon/strongswan/src/libcharon/plugins/dhcp/dhcp_provider.c, revision 1.1.1.1
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>