Annotation of embedaddon/strongswan/src/libcharon/attributes/attribute_manager.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2008 Martin Willi
3: * HSR Hochschule fuer Technik Rapperswil
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 "attribute_manager.h"
17:
18: #include <utils/debug.h>
19: #include <collections/linked_list.h>
20: #include <threading/rwlock.h>
21:
22: typedef struct private_attribute_manager_t private_attribute_manager_t;
23:
24: /**
25: * private data of attribute_manager
26: */
27: struct private_attribute_manager_t {
28:
29: /**
30: * public functions
31: */
32: attribute_manager_t public;
33:
34: /**
35: * list of registered providers
36: */
37: linked_list_t *providers;
38:
39: /**
40: * list of registered handlers
41: */
42: linked_list_t *handlers;
43:
44: /**
45: * rwlock provider list
46: */
47: rwlock_t *lock;
48: };
49:
50: /**
51: * Data to pass to enumerator filters
52: */
53: typedef struct {
54: /** attribute group pools */
55: linked_list_t *pools;
56: /** associated IKE_SA */
57: ike_sa_t *ike_sa;
58: /** requesting/assigned virtual IPs */
59: linked_list_t *vips;
60: } enum_data_t;
61:
62: METHOD(attribute_manager_t, acquire_address, host_t*,
63: private_attribute_manager_t *this, linked_list_t *pools,
64: ike_sa_t *ike_sa, host_t *requested)
65: {
66: enumerator_t *enumerator;
67: attribute_provider_t *current;
68: host_t *host = NULL;
69:
70: this->lock->read_lock(this->lock);
71: enumerator = this->providers->create_enumerator(this->providers);
72: while (enumerator->enumerate(enumerator, ¤t))
73: {
74: host = current->acquire_address(current, pools, ike_sa, requested);
75: if (host)
76: {
77: break;
78: }
79: }
80: enumerator->destroy(enumerator);
81: this->lock->unlock(this->lock);
82:
83: return host;
84: }
85:
86: METHOD(attribute_manager_t, release_address, bool,
87: private_attribute_manager_t *this, linked_list_t *pools, host_t *address,
88: ike_sa_t *ike_sa)
89: {
90: enumerator_t *enumerator;
91: attribute_provider_t *current;
92: bool found = FALSE;
93:
94: this->lock->read_lock(this->lock);
95: enumerator = this->providers->create_enumerator(this->providers);
96: while (enumerator->enumerate(enumerator, ¤t))
97: {
98: if (current->release_address(current, pools, address, ike_sa))
99: {
100: found = TRUE;
101: break;
102: }
103: }
104: enumerator->destroy(enumerator);
105: this->lock->unlock(this->lock);
106:
107: return found;
108: }
109:
110: /**
111: * inner enumerator constructor for responder attributes
112: */
113: static enumerator_t *responder_enum_create(attribute_provider_t *provider,
114: enum_data_t *data)
115: {
116: return provider->create_attribute_enumerator(provider, data->pools,
117: data->ike_sa, data->vips);
118: }
119:
120: METHOD(attribute_manager_t, create_responder_enumerator, enumerator_t*,
121: private_attribute_manager_t *this, linked_list_t *pools,
122: ike_sa_t *ike_sa, linked_list_t *vips)
123: {
124: enum_data_t *data;
125:
126: INIT(data,
127: .pools = pools,
128: .ike_sa = ike_sa,
129: .vips = vips,
130: );
131: this->lock->read_lock(this->lock);
132: return enumerator_create_cleaner(
133: enumerator_create_nested(
134: this->providers->create_enumerator(this->providers),
135: (void*)responder_enum_create, data, free),
136: (void*)this->lock->unlock, this->lock);
137: }
138:
139: METHOD(attribute_manager_t, add_provider, void,
140: private_attribute_manager_t *this, attribute_provider_t *provider)
141: {
142: this->lock->write_lock(this->lock);
143: this->providers->insert_last(this->providers, provider);
144: this->lock->unlock(this->lock);
145: }
146:
147: METHOD(attribute_manager_t, remove_provider, void,
148: private_attribute_manager_t *this, attribute_provider_t *provider)
149: {
150: this->lock->write_lock(this->lock);
151: this->providers->remove(this->providers, provider, NULL);
152: this->lock->unlock(this->lock);
153: }
154:
155: METHOD(attribute_manager_t, handle, attribute_handler_t*,
156: private_attribute_manager_t *this, ike_sa_t *ike_sa,
157: attribute_handler_t *handler, configuration_attribute_type_t type,
158: chunk_t data)
159: {
160: enumerator_t *enumerator;
161: attribute_handler_t *current, *handled = NULL;
162:
163: this->lock->read_lock(this->lock);
164:
165: /* try to find the passed handler */
166: enumerator = this->handlers->create_enumerator(this->handlers);
167: while (enumerator->enumerate(enumerator, ¤t))
168: {
169: if (current == handler && current->handle(current, ike_sa, type, data))
170: {
171: handled = current;
172: break;
173: }
174: }
175: enumerator->destroy(enumerator);
176: if (!handled)
177: { /* handler requesting this attribute not found, try any other */
178: enumerator = this->handlers->create_enumerator(this->handlers);
179: while (enumerator->enumerate(enumerator, ¤t))
180: {
181: if (current->handle(current, ike_sa, type, data))
182: {
183: handled = current;
184: break;
185: }
186: }
187: enumerator->destroy(enumerator);
188: }
189: this->lock->unlock(this->lock);
190:
191: if (!handled)
192: {
193: DBG1(DBG_CFG, "handling %N attribute failed",
194: configuration_attribute_type_names, type);
195: }
196: return handled;
197: }
198:
199: METHOD(attribute_manager_t, release, void,
200: private_attribute_manager_t *this, attribute_handler_t *handler,
201: ike_sa_t *ike_sa, configuration_attribute_type_t type, chunk_t data)
202: {
203: enumerator_t *enumerator;
204: attribute_handler_t *current;
205:
206: this->lock->read_lock(this->lock);
207: enumerator = this->handlers->create_enumerator(this->handlers);
208: while (enumerator->enumerate(enumerator, ¤t))
209: {
210: if (current == handler)
211: {
212: current->release(current, ike_sa, type, data);
213: break;
214: }
215: }
216: enumerator->destroy(enumerator);
217: this->lock->unlock(this->lock);
218: }
219:
220: /**
221: * Enumerator implementation to enumerate nested initiator attributes
222: */
223: typedef struct {
224: /** implements enumerator_t */
225: enumerator_t public;
226: /** back ref */
227: private_attribute_manager_t *this;
228: /** currently processing handler */
229: attribute_handler_t *handler;
230: /** outer enumerator over handlers */
231: enumerator_t *outer;
232: /** inner enumerator over current handlers attributes */
233: enumerator_t *inner;
234: /** IKE_SA to request attributes for */
235: ike_sa_t *ike_sa;
236: /** virtual IPs we are requesting along with attributes */
237: linked_list_t *vips;
238: } initiator_enumerator_t;
239:
240: METHOD(enumerator_t, initiator_enumerate, bool,
241: initiator_enumerator_t *this, va_list args)
242: {
243: configuration_attribute_type_t *type;
244: attribute_handler_t **handler;
245: chunk_t *value;
246:
247: VA_ARGS_VGET(args, handler, type, value);
248: /* enumerate inner attributes using outer handler enumerator */
249: while (!this->inner || !this->inner->enumerate(this->inner, type, value))
250: {
251: if (!this->outer->enumerate(this->outer, &this->handler))
252: {
253: return FALSE;
254: }
255: DESTROY_IF(this->inner);
256: this->inner = this->handler->create_attribute_enumerator(this->handler,
257: this->ike_sa, this->vips);
258: }
259: /* inject the handler as additional attribute */
260: *handler = this->handler;
261: return TRUE;
262: }
263:
264: METHOD(enumerator_t, initiator_destroy, void,
265: initiator_enumerator_t *this)
266: {
267: this->this->lock->unlock(this->this->lock);
268: this->outer->destroy(this->outer);
269: DESTROY_IF(this->inner);
270: free(this);
271: }
272:
273: METHOD(attribute_manager_t, create_initiator_enumerator, enumerator_t*,
274: private_attribute_manager_t *this, ike_sa_t *ike_sa, linked_list_t *vips)
275: {
276: initiator_enumerator_t *enumerator;
277:
278: this->lock->read_lock(this->lock);
279:
280: INIT(enumerator,
281: .public = {
282: .enumerate = enumerator_enumerate_default,
283: .venumerate = _initiator_enumerate,
284: .destroy = _initiator_destroy,
285: },
286: .this = this,
287: .ike_sa = ike_sa,
288: .vips = vips,
289: .outer = this->handlers->create_enumerator(this->handlers),
290: );
291: return &enumerator->public;
292: }
293:
294: METHOD(attribute_manager_t, add_handler, void,
295: private_attribute_manager_t *this, attribute_handler_t *handler)
296: {
297: this->lock->write_lock(this->lock);
298: this->handlers->insert_last(this->handlers, handler);
299: this->lock->unlock(this->lock);
300: }
301:
302: METHOD(attribute_manager_t, remove_handler, void,
303: private_attribute_manager_t *this, attribute_handler_t *handler)
304: {
305: this->lock->write_lock(this->lock);
306: this->handlers->remove(this->handlers, handler, NULL);
307: this->lock->unlock(this->lock);
308: }
309:
310: METHOD(attribute_manager_t, destroy, void,
311: private_attribute_manager_t *this)
312: {
313: this->providers->destroy(this->providers);
314: this->handlers->destroy(this->handlers);
315: this->lock->destroy(this->lock);
316: free(this);
317: }
318:
319: /*
320: * see header file
321: */
322: attribute_manager_t *attribute_manager_create()
323: {
324: private_attribute_manager_t *this;
325:
326: INIT(this,
327: .public = {
328: .acquire_address = _acquire_address,
329: .release_address = _release_address,
330: .create_responder_enumerator = _create_responder_enumerator,
331: .add_provider = _add_provider,
332: .remove_provider = _remove_provider,
333: .handle = _handle,
334: .release = _release,
335: .create_initiator_enumerator = _create_initiator_enumerator,
336: .add_handler = _add_handler,
337: .remove_handler = _remove_handler,
338: .destroy = _destroy,
339: },
340: .providers = linked_list_create(),
341: .handlers = linked_list_create(),
342: .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
343: );
344:
345: return &this->public;
346: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>