attribute_manager supports attribute_handler's to handle configuration attributes...
[strongswan.git] / src / charon / config / 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 * $Id$
16 */
17
18 #include "attribute_manager.h"
19
20 #include <daemon.h>
21 #include <utils/linked_list.h>
22 #include <utils/mutex.h>
23
24 typedef struct private_attribute_manager_t private_attribute_manager_t;
25
26 /**
27 * private data of attribute_manager
28 */
29 struct private_attribute_manager_t {
30
31 /**
32 * public functions
33 */
34 attribute_manager_t public;
35
36 /**
37 * list of registered providers
38 */
39 linked_list_t *providers;
40
41 /**
42 * list of registered handlers
43 */
44 linked_list_t *handlers;
45
46 /**
47 * rwlock provider list
48 */
49 rwlock_t *lock;
50 };
51
52 /**
53 * Implementation of attribute_manager_t.acquire_address.
54 */
55 static host_t* acquire_address(private_attribute_manager_t *this,
56 char *pool, identification_t *id,
57 host_t *requested)
58 {
59 enumerator_t *enumerator;
60 attribute_provider_t *current;
61 host_t *host = NULL;
62
63 this->lock->read_lock(this->lock);
64 enumerator = this->providers->create_enumerator(this->providers);
65 while (enumerator->enumerate(enumerator, &current))
66 {
67 host = current->acquire_address(current, pool, id, requested);
68 if (host)
69 {
70 break;
71 }
72 }
73 enumerator->destroy(enumerator);
74 this->lock->unlock(this->lock);
75
76 if (!host)
77 {
78 DBG1(DBG_CFG, "acquiring address from pool '%s' failed", pool);
79 }
80 return host;
81 }
82
83 /**
84 * Implementation of attribute_manager_t.release_address.
85 */
86 static void release_address(private_attribute_manager_t *this,
87 char *pool, host_t *address, identification_t *id)
88 {
89 enumerator_t *enumerator;
90 attribute_provider_t *current;
91 bool found = FALSE;
92
93 this->lock->read_lock(this->lock);
94 enumerator = this->providers->create_enumerator(this->providers);
95 while (enumerator->enumerate(enumerator, &current))
96 {
97 if (current->release_address(current, pool, address, id))
98 {
99 found = TRUE;
100 break;
101 }
102 }
103 enumerator->destroy(enumerator);
104 this->lock->unlock(this->lock);
105
106 if (!found)
107 {
108 DBG1(DBG_CFG, "releasing address to pool '%s' failed", pool);
109 }
110 }
111
112 /**
113 * inner enumerator constructor for attributes
114 */
115 static enumerator_t *attrib_enum_create(attribute_provider_t *provider,
116 identification_t *id)
117 {
118 return provider->create_attribute_enumerator(provider, id);
119 }
120
121 /**
122 * Implementation of attribute_manager_t.create_attribute_enumerator
123 */
124 static enumerator_t* create_attribute_enumerator(
125 private_attribute_manager_t *this, identification_t *id)
126 {
127 this->lock->read_lock(this->lock);
128 return enumerator_create_cleaner(
129 enumerator_create_nested(
130 this->providers->create_enumerator(this->providers),
131 (void*)attrib_enum_create, id, NULL),
132 (void*)this->lock->unlock, this->lock);
133 }
134
135 /**
136 * Implementation of attribute_manager_t.add_provider.
137 */
138 static void add_provider(private_attribute_manager_t *this,
139 attribute_provider_t *provider)
140 {
141 this->lock->write_lock(this->lock);
142 this->providers->insert_last(this->providers, provider);
143 this->lock->unlock(this->lock);
144 }
145
146 /**
147 * Implementation of attribute_manager_t.remove_provider.
148 */
149 static void remove_provider(private_attribute_manager_t *this,
150 attribute_provider_t *provider)
151 {
152 this->lock->write_lock(this->lock);
153 this->providers->remove(this->providers, provider, NULL);
154 this->lock->unlock(this->lock);
155 }
156
157 /**
158 * Implementation of attribute_manager_t.handle
159 */
160 static attribute_handler_t* handle(private_attribute_manager_t *this,
161 ike_sa_t *ike_sa, configuration_attribute_type_t type,
162 chunk_t data)
163 {
164 enumerator_t *enumerator;
165 attribute_handler_t *current, *handled = NULL;
166
167 this->lock->read_lock(this->lock);
168 enumerator = this->handlers->create_enumerator(this->handlers);
169 while (enumerator->enumerate(enumerator, &current))
170 {
171 if (current->handle(current, ike_sa, type, data))
172 {
173 handled = current;
174 break;
175 }
176 }
177 enumerator->destroy(enumerator);
178 this->lock->unlock(this->lock);
179
180 if (!handled)
181 {
182 DBG1(DBG_CFG, "handling %N attribute failed",
183 configuration_attribute_type_names, type);
184 }
185 return handled;
186 }
187
188 /**
189 * Implementation of attribute_manager_t.release
190 */
191 static void release(private_attribute_manager_t *this,
192 attribute_handler_t *handler, ike_sa_t *ike_sa,
193 configuration_attribute_type_t type, chunk_t data)
194 {
195 enumerator_t *enumerator;
196 attribute_handler_t *current;
197
198 this->lock->read_lock(this->lock);
199 enumerator = this->handlers->create_enumerator(this->handlers);
200 while (enumerator->enumerate(enumerator, &current))
201 {
202 if (current == handler)
203 {
204 current->release(current, ike_sa, type, data);
205 break;
206 }
207 }
208 enumerator->destroy(enumerator);
209 this->lock->unlock(this->lock);
210 }
211
212 /**
213 * Implementation of attribute_manager_t.add_handler
214 */
215 static void add_handler(private_attribute_manager_t *this,
216 attribute_handler_t *handler)
217 {
218 this->lock->write_lock(this->lock);
219 this->handlers->insert_last(this->handlers, handler);
220 this->lock->unlock(this->lock);
221 }
222
223 /**
224 * Implementation of attribute_manager_t.remove_handler
225 */
226 static void remove_handler(private_attribute_manager_t *this,
227 attribute_handler_t *handler)
228 {
229 this->lock->write_lock(this->lock);
230 this->handlers->remove(this->handlers, handler, NULL);
231 this->lock->unlock(this->lock);
232 }
233
234 /**
235 * Implementation of attribute_manager_t.destroy
236 */
237 static void destroy(private_attribute_manager_t *this)
238 {
239 this->providers->destroy(this->providers);
240 this->handlers->destroy(this->handlers);
241 this->lock->destroy(this->lock);
242 free(this);
243 }
244
245 /*
246 * see header file
247 */
248 attribute_manager_t *attribute_manager_create()
249 {
250 private_attribute_manager_t *this = malloc_thing(private_attribute_manager_t);
251
252 this->public.acquire_address = (host_t*(*)(attribute_manager_t*, char*, identification_t*,host_t*))acquire_address;
253 this->public.release_address = (void(*)(attribute_manager_t*, char *, host_t*, identification_t*))release_address;
254 this->public.create_attribute_enumerator = (enumerator_t*(*)(attribute_manager_t*, identification_t *id))create_attribute_enumerator;
255 this->public.add_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))add_provider;
256 this->public.remove_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))remove_provider;
257 this->public.handle = (attribute_handler_t*(*)(attribute_manager_t*, ike_sa_t *ike_sa, configuration_attribute_type_t type, chunk_t data))handle;
258 this->public.release = (void(*)(attribute_manager_t*, attribute_handler_t *handler, ike_sa_t *ike_sa, configuration_attribute_type_t type, chunk_t data))release;
259 this->public.add_handler = (void(*)(attribute_manager_t*, attribute_handler_t *handler))add_handler;
260 this->public.remove_handler = (void(*)(attribute_manager_t*, attribute_handler_t *handler))remove_handler;
261 this->public.destroy = (void(*)(attribute_manager_t*))destroy;
262
263 this->providers = linked_list_create();
264 this->handlers = linked_list_create();
265 this->lock = rwlock_create(RWLOCK_DEFAULT);
266
267 return &this->public;
268 }
269