Fixing Doxygen for libhydra.
[strongswan.git] / src / libstrongswan / attributes / attribute_manager.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * 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 <debug.h>
19 #include <utils/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 /** server/peer identity */
55 identification_t *id;
56 /** requesting/assigned virtual IP */
57 host_t *vip;
58 } enum_data_t;
59
60 /**
61 * Implementation of attribute_manager_t.acquire_address.
62 */
63 static host_t* acquire_address(private_attribute_manager_t *this,
64 char *pool, identification_t *id,
65 host_t *requested)
66 {
67 enumerator_t *enumerator;
68 attribute_provider_t *current;
69 host_t *host = NULL;
70
71 this->lock->read_lock(this->lock);
72 enumerator = this->providers->create_enumerator(this->providers);
73 while (enumerator->enumerate(enumerator, &current))
74 {
75 host = current->acquire_address(current, pool, id, requested);
76 if (host)
77 {
78 break;
79 }
80 }
81 enumerator->destroy(enumerator);
82 this->lock->unlock(this->lock);
83
84 if (!host)
85 {
86 DBG1("acquiring address from pool '%s' failed", pool);
87 }
88 return host;
89 }
90
91 /**
92 * Implementation of attribute_manager_t.release_address.
93 */
94 static void release_address(private_attribute_manager_t *this,
95 char *pool, host_t *address, identification_t *id)
96 {
97 enumerator_t *enumerator;
98 attribute_provider_t *current;
99 bool found = FALSE;
100
101 this->lock->read_lock(this->lock);
102 enumerator = this->providers->create_enumerator(this->providers);
103 while (enumerator->enumerate(enumerator, &current))
104 {
105 if (current->release_address(current, pool, address, id))
106 {
107 found = TRUE;
108 break;
109 }
110 }
111 enumerator->destroy(enumerator);
112 this->lock->unlock(this->lock);
113
114 if (!found)
115 {
116 DBG1("releasing address to pool '%s' failed", pool);
117 }
118 }
119
120 /**
121 * inner enumerator constructor for responder attributes
122 */
123 static enumerator_t *responder_enum_create(attribute_provider_t *provider,
124 enum_data_t *data)
125 {
126 return provider->create_attribute_enumerator(provider, data->id, data->vip);
127 }
128
129 /**
130 * Implementation of attribute_manager_t.create_responder_enumerator
131 */
132 static enumerator_t* create_responder_enumerator(
133 private_attribute_manager_t *this, identification_t *id, host_t *vip)
134 {
135 enum_data_t *data = malloc_thing(enum_data_t);
136
137 data->id = id;
138 data->vip = vip;
139 this->lock->read_lock(this->lock);
140 return enumerator_create_cleaner(
141 enumerator_create_nested(
142 this->providers->create_enumerator(this->providers),
143 (void*)responder_enum_create, data, free),
144 (void*)this->lock->unlock, this->lock);
145 }
146
147 /**
148 * Implementation of attribute_manager_t.add_provider.
149 */
150 static void add_provider(private_attribute_manager_t *this,
151 attribute_provider_t *provider)
152 {
153 this->lock->write_lock(this->lock);
154 this->providers->insert_last(this->providers, provider);
155 this->lock->unlock(this->lock);
156 }
157
158 /**
159 * Implementation of attribute_manager_t.remove_provider.
160 */
161 static void remove_provider(private_attribute_manager_t *this,
162 attribute_provider_t *provider)
163 {
164 this->lock->write_lock(this->lock);
165 this->providers->remove(this->providers, provider, NULL);
166 this->lock->unlock(this->lock);
167 }
168
169 /**
170 * Implementation of attribute_manager_t.handle
171 */
172 static attribute_handler_t* handle(private_attribute_manager_t *this,
173 identification_t *server, attribute_handler_t *handler,
174 configuration_attribute_type_t type, chunk_t data)
175 {
176 enumerator_t *enumerator;
177 attribute_handler_t *current, *handled = NULL;
178
179 this->lock->read_lock(this->lock);
180
181 /* try to find the passed handler */
182 enumerator = this->handlers->create_enumerator(this->handlers);
183 while (enumerator->enumerate(enumerator, &current))
184 {
185 if (current == handler && current->handle(current, server, type, data))
186 {
187 handled = current;
188 break;
189 }
190 }
191 enumerator->destroy(enumerator);
192 if (!handled)
193 { /* handler requesting this attribute not found, try any other */
194 enumerator = this->handlers->create_enumerator(this->handlers);
195 while (enumerator->enumerate(enumerator, &current))
196 {
197 if (current->handle(current, server, type, data))
198 {
199 handled = current;
200 break;
201 }
202 }
203 enumerator->destroy(enumerator);
204 }
205 this->lock->unlock(this->lock);
206
207 if (!handled)
208 {
209 DBG1("handling %N attribute failed",
210 configuration_attribute_type_names, type);
211 }
212 return handled;
213 }
214
215 /**
216 * Implementation of attribute_manager_t.release
217 */
218 static void release(private_attribute_manager_t *this,
219 attribute_handler_t *handler,
220 identification_t *server,
221 configuration_attribute_type_t type, chunk_t data)
222 {
223 enumerator_t *enumerator;
224 attribute_handler_t *current;
225
226 this->lock->read_lock(this->lock);
227 enumerator = this->handlers->create_enumerator(this->handlers);
228 while (enumerator->enumerate(enumerator, &current))
229 {
230 if (current == handler)
231 {
232 current->release(current, server, type, data);
233 break;
234 }
235 }
236 enumerator->destroy(enumerator);
237 this->lock->unlock(this->lock);
238 }
239
240 /**
241 * Enumerator implementation to enumerate nested initiator attributes
242 */
243 typedef struct {
244 /** implements enumerator_t */
245 enumerator_t public;
246 /** back ref */
247 private_attribute_manager_t *this;
248 /** currently processing handler */
249 attribute_handler_t *handler;
250 /** outer enumerator over handlers */
251 enumerator_t *outer;
252 /** inner enumerator over current handlers attributes */
253 enumerator_t *inner;
254 /** server ID we want attributes for */
255 identification_t *id;
256 /** virtual IP we are requesting along with attriubutes */
257 host_t *vip;
258 } initiator_enumerator_t;
259
260 /**
261 * Enumerator implementation for initiator attributes
262 */
263 static bool initiator_enumerate(initiator_enumerator_t *this,
264 attribute_handler_t **handler,
265 configuration_attribute_type_t *type,
266 chunk_t *value)
267 {
268 /* enumerate inner attributes using outer handler enumerator */
269 while (!this->inner || !this->inner->enumerate(this->inner, type, value))
270 {
271 if (!this->outer->enumerate(this->outer, &this->handler))
272 {
273 return FALSE;
274 }
275 DESTROY_IF(this->inner);
276 this->inner = this->handler->create_attribute_enumerator(this->handler,
277 this->id, this->vip);
278 }
279 /* inject the handler as additional attribute */
280 *handler = this->handler;
281 return TRUE;
282 }
283
284 /**
285 * Cleanup function of initiator attribute enumerator
286 */
287 static void initiator_destroy(initiator_enumerator_t *this)
288 {
289 this->this->lock->unlock(this->this->lock);
290 this->outer->destroy(this->outer);
291 DESTROY_IF(this->inner);
292 free(this);
293 }
294
295 /**
296 * Implementation of attribute_manager_t.create_initiator_enumerator
297 */
298 static enumerator_t* create_initiator_enumerator(
299 private_attribute_manager_t *this, identification_t *id, host_t *vip)
300 {
301 initiator_enumerator_t *enumerator = malloc_thing(initiator_enumerator_t);
302
303 this->lock->read_lock(this->lock);
304 enumerator->public.enumerate = (void*)initiator_enumerate;
305 enumerator->public.destroy = (void*)initiator_destroy;
306 enumerator->this = this;
307 enumerator->id = id;
308 enumerator->vip = vip;
309 enumerator->outer = this->handlers->create_enumerator(this->handlers);
310 enumerator->inner = NULL;
311 enumerator->handler = NULL;
312
313 return &enumerator->public;
314 }
315
316 /**
317 * Implementation of attribute_manager_t.add_handler
318 */
319 static void add_handler(private_attribute_manager_t *this,
320 attribute_handler_t *handler)
321 {
322 this->lock->write_lock(this->lock);
323 this->handlers->insert_last(this->handlers, handler);
324 this->lock->unlock(this->lock);
325 }
326
327 /**
328 * Implementation of attribute_manager_t.remove_handler
329 */
330 static void remove_handler(private_attribute_manager_t *this,
331 attribute_handler_t *handler)
332 {
333 this->lock->write_lock(this->lock);
334 this->handlers->remove(this->handlers, handler, NULL);
335 this->lock->unlock(this->lock);
336 }
337
338 /**
339 * Implementation of attribute_manager_t.destroy
340 */
341 static void destroy(private_attribute_manager_t *this)
342 {
343 this->providers->destroy(this->providers);
344 this->handlers->destroy(this->handlers);
345 this->lock->destroy(this->lock);
346 free(this);
347 }
348
349 /*
350 * see header file
351 */
352 attribute_manager_t *attribute_manager_create()
353 {
354 private_attribute_manager_t *this = malloc_thing(private_attribute_manager_t);
355
356 this->public.acquire_address = (host_t*(*)(attribute_manager_t*, char*, identification_t*,host_t*))acquire_address;
357 this->public.release_address = (void(*)(attribute_manager_t*, char *, host_t*, identification_t*))release_address;
358 this->public.create_responder_enumerator = (enumerator_t*(*)(attribute_manager_t*, identification_t*, host_t*))create_responder_enumerator;
359 this->public.add_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))add_provider;
360 this->public.remove_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))remove_provider;
361 this->public.handle = (attribute_handler_t*(*)(attribute_manager_t*,identification_t*, attribute_handler_t*, configuration_attribute_type_t, chunk_t))handle;
362 this->public.release = (void(*)(attribute_manager_t*, attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))release;
363 this->public.create_initiator_enumerator = (enumerator_t*(*)(attribute_manager_t*, identification_t*, host_t*))create_initiator_enumerator;
364 this->public.add_handler = (void(*)(attribute_manager_t*, attribute_handler_t*))add_handler;
365 this->public.remove_handler = (void(*)(attribute_manager_t*, attribute_handler_t*))remove_handler;
366 this->public.destroy = (void(*)(attribute_manager_t*))destroy;
367
368 this->providers = linked_list_create();
369 this->handlers = linked_list_create();
370 this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
371
372 return &this->public;
373 }
374