Annotation of embedaddon/strongswan/src/libcharon/plugins/stroke/stroke_attribute.c, revision 1.1.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>