Print the name of mem pools instead of the confusing <base>/<size>
[strongswan.git] / src / libcharon / plugins / stroke / stroke_attribute.c
1 /*
2 * Copyright (C) 2010 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * 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 <utils/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, &current))
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 METHOD(attribute_provider_t, acquire_address, host_t*,
93 private_stroke_attribute_t *this, char *name, identification_t *id,
94 host_t *requested)
95 {
96 mem_pool_t *pool;
97 host_t *addr = NULL;
98
99 this->lock->read_lock(this->lock);
100 pool = find_pool(this, name);
101 if (pool)
102 {
103 addr = pool->acquire_address(pool, id, requested);
104 }
105 this->lock->unlock(this->lock);
106 return addr;
107 }
108
109 METHOD(attribute_provider_t, release_address, bool,
110 private_stroke_attribute_t *this, char *name, host_t *address,
111 identification_t *id)
112 {
113 mem_pool_t *pool;
114 bool found = FALSE;
115
116 this->lock->read_lock(this->lock);
117 pool = find_pool(this, name);
118 if (pool)
119 {
120 found = pool->release_address(pool, address, id);
121 }
122 this->lock->unlock(this->lock);
123 return found;
124 }
125
126 /**
127 * Filter function to convert host to DNS configuration attributes
128 */
129 static bool attr_filter(void *lock, host_t **in,
130 configuration_attribute_type_t *type,
131 void *dummy, chunk_t *data)
132 {
133 host_t *host = *in;
134
135 switch (host->get_family(host))
136 {
137 case AF_INET:
138 *type = INTERNAL_IP4_DNS;
139 break;
140 case AF_INET6:
141 *type = INTERNAL_IP6_DNS;
142 break;
143 default:
144 return FALSE;
145 }
146 *data = host->get_address(host);
147 return TRUE;
148 }
149
150 METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
151 private_stroke_attribute_t *this, linked_list_t *pools,
152 identification_t *id, linked_list_t *vips)
153 {
154 ike_sa_t *ike_sa;
155 peer_cfg_t *peer_cfg;
156 enumerator_t *enumerator;
157 attributes_t *attr;
158
159 ike_sa = charon->bus->get_sa(charon->bus);
160 if (ike_sa)
161 {
162 peer_cfg = ike_sa->get_peer_cfg(ike_sa);
163 this->lock->read_lock(this->lock);
164 enumerator = this->attrs->create_enumerator(this->attrs);
165 while (enumerator->enumerate(enumerator, &attr))
166 {
167 if (streq(attr->name, peer_cfg->get_name(peer_cfg)))
168 {
169 enumerator->destroy(enumerator);
170 return enumerator_create_filter(
171 attr->dns->create_enumerator(attr->dns),
172 (void*)attr_filter, this->lock,
173 (void*)this->lock->unlock);
174 }
175 }
176 enumerator->destroy(enumerator);
177 this->lock->unlock(this->lock);
178 }
179 return enumerator_create_empty();
180 }
181
182 METHOD(stroke_attribute_t, add_pool, void,
183 private_stroke_attribute_t *this, mem_pool_t *pool)
184 {
185 enumerator_t *enumerator;
186 mem_pool_t *current;
187 host_t *base;
188 int size;
189
190 base = pool->get_base(pool);
191 size = pool->get_size(pool);
192
193 this->lock->write_lock(this->lock);
194
195 enumerator = this->pools->create_enumerator(this->pools);
196 while (enumerator->enumerate(enumerator, &current))
197 {
198 if (base && current->get_base(current) &&
199 base->ip_equals(base, current->get_base(current)) &&
200 size == current->get_size(current))
201 {
202 DBG1(DBG_CFG, "reusing virtual IP address pool %s",
203 current->get_name(current));
204 pool->destroy(pool);
205 pool = NULL;
206 break;
207 }
208 }
209 enumerator->destroy(enumerator);
210
211 if (pool)
212 {
213 if (base)
214 {
215 DBG1(DBG_CFG, "adding virtual IP address pool %s",
216 pool->get_name(pool));
217 }
218 this->pools->insert_last(this->pools, pool);
219 }
220
221 this->lock->unlock(this->lock);
222 }
223
224 METHOD(stroke_attribute_t, add_dns, void,
225 private_stroke_attribute_t *this, stroke_msg_t *msg)
226 {
227 if (msg->add_conn.other.dns)
228 {
229 enumerator_t *enumerator;
230 attributes_t *attr = NULL;
231 host_t *host;
232 char *token;
233
234 enumerator = enumerator_create_token(msg->add_conn.other.dns, ",", " ");
235 while (enumerator->enumerate(enumerator, &token))
236 {
237 host = host_create_from_string(token, 0);
238 if (host)
239 {
240 if (!attr)
241 {
242 INIT(attr,
243 .name = strdup(msg->add_conn.name),
244 .dns = linked_list_create(),
245 );
246 }
247 attr->dns->insert_last(attr->dns, host);
248 }
249 else
250 {
251 DBG1(DBG_CFG, "ignoring invalid DNS address '%s'", token);
252 }
253 }
254 enumerator->destroy(enumerator);
255 if (attr)
256 {
257 this->lock->write_lock(this->lock);
258 this->attrs->insert_last(this->attrs, attr);
259 this->lock->unlock(this->lock);
260 }
261 }
262 }
263
264 METHOD(stroke_attribute_t, del_dns, void,
265 private_stroke_attribute_t *this, stroke_msg_t *msg)
266 {
267 enumerator_t *enumerator;
268 attributes_t *attr;
269
270 this->lock->write_lock(this->lock);
271
272 enumerator = this->attrs->create_enumerator(this->attrs);
273 while (enumerator->enumerate(enumerator, &attr))
274 {
275 if (streq(msg->del_conn.name, attr->name))
276 {
277 this->attrs->remove_at(this->attrs, enumerator);
278 attributes_destroy(attr);
279 break;
280 }
281 }
282 enumerator->destroy(enumerator);
283
284 this->lock->unlock(this->lock);
285 }
286
287 /**
288 * Pool enumerator filter function, converts pool_t to name, size, ...
289 */
290 static bool pool_filter(void *lock, mem_pool_t **poolp, const char **name,
291 void *d1, u_int *size, void *d2, u_int *online,
292 void *d3, u_int *offline)
293 {
294 mem_pool_t *pool = *poolp;
295
296 if (pool->get_size(pool) == 0)
297 {
298 return FALSE;
299 }
300 *name = pool->get_name(pool);
301 *size = pool->get_size(pool);
302 *online = pool->get_online(pool);
303 *offline = pool->get_offline(pool);
304 return TRUE;
305 }
306
307 METHOD(stroke_attribute_t, create_pool_enumerator, enumerator_t*,
308 private_stroke_attribute_t *this)
309 {
310 this->lock->read_lock(this->lock);
311 return enumerator_create_filter(this->pools->create_enumerator(this->pools),
312 (void*)pool_filter,
313 this->lock, (void*)this->lock->unlock);
314 }
315
316 METHOD(stroke_attribute_t, create_lease_enumerator, enumerator_t*,
317 private_stroke_attribute_t *this, char *name)
318 {
319 mem_pool_t *pool;
320 this->lock->read_lock(this->lock);
321 pool = find_pool(this, name);
322 if (!pool)
323 {
324 this->lock->unlock(this->lock);
325 return NULL;
326 }
327 return enumerator_create_cleaner(pool->create_lease_enumerator(pool),
328 (void*)this->lock->unlock, this->lock);
329 }
330
331 METHOD(stroke_attribute_t, destroy, void,
332 private_stroke_attribute_t *this)
333 {
334 this->lock->destroy(this->lock);
335 this->pools->destroy_offset(this->pools, offsetof(mem_pool_t, destroy));
336 this->attrs->destroy_function(this->attrs, (void*)attributes_destroy);
337 free(this);
338 }
339
340 /*
341 * see header file
342 */
343 stroke_attribute_t *stroke_attribute_create()
344 {
345 private_stroke_attribute_t *this;
346
347 INIT(this,
348 .public = {
349 .provider = {
350 .acquire_address = _acquire_address,
351 .release_address = _release_address,
352 .create_attribute_enumerator = _create_attribute_enumerator,
353 },
354 .add_pool = _add_pool,
355 .add_dns = _add_dns,
356 .del_dns = _del_dns,
357 .create_pool_enumerator = _create_pool_enumerator,
358 .create_lease_enumerator = _create_lease_enumerator,
359 .destroy = _destroy,
360 },
361 .pools = linked_list_create(),
362 .attrs = linked_list_create(),
363 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
364 );
365
366 return &this->public;
367 }
368