stroke: Allow specifying the ipsec.secrets location in strongswan.conf
[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 <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, &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 /**
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)
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);
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, identification_t *id,
124 host_t *requested)
125 {
126 host_t *addr;
127
128 this->lock->read_lock(this->lock);
129
130 addr = find_addr(this, pools, id, requested, MEM_POOL_EXISTING);
131 if (!addr)
132 {
133 addr = find_addr(this, pools, id, requested, MEM_POOL_NEW);
134 if (!addr)
135 {
136 addr = find_addr(this, pools, id, requested, MEM_POOL_REASSIGN);
137 }
138 }
139
140 this->lock->unlock(this->lock);
141
142 return addr;
143 }
144
145 METHOD(attribute_provider_t, release_address, bool,
146 private_stroke_attribute_t *this, linked_list_t *pools, host_t *address,
147 identification_t *id)
148 {
149 enumerator_t *enumerator;
150 mem_pool_t *pool;
151 bool found = FALSE;
152 char *name;
153
154 enumerator = pools->create_enumerator(pools);
155 this->lock->read_lock(this->lock);
156 while (enumerator->enumerate(enumerator, &name))
157 {
158 pool = find_pool(this, name);
159 if (pool)
160 {
161 found = pool->release_address(pool, address, id);
162 if (found)
163 {
164 break;
165 }
166 }
167 }
168 this->lock->unlock(this->lock);
169 enumerator->destroy(enumerator);
170
171 return found;
172 }
173
174 /**
175 * Filter function to convert host to DNS configuration attributes
176 */
177 static bool attr_filter(void *lock, host_t **in,
178 configuration_attribute_type_t *type,
179 void *dummy, chunk_t *data)
180 {
181 host_t *host = *in;
182
183 switch (host->get_family(host))
184 {
185 case AF_INET:
186 *type = INTERNAL_IP4_DNS;
187 break;
188 case AF_INET6:
189 *type = INTERNAL_IP6_DNS;
190 break;
191 default:
192 return FALSE;
193 }
194 *data = host->get_address(host);
195 return TRUE;
196 }
197
198 METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
199 private_stroke_attribute_t *this, linked_list_t *pools,
200 identification_t *id, linked_list_t *vips)
201 {
202 ike_sa_t *ike_sa;
203 peer_cfg_t *peer_cfg;
204 enumerator_t *enumerator;
205 attributes_t *attr;
206
207 ike_sa = charon->bus->get_sa(charon->bus);
208 if (ike_sa)
209 {
210 peer_cfg = ike_sa->get_peer_cfg(ike_sa);
211 this->lock->read_lock(this->lock);
212 enumerator = this->attrs->create_enumerator(this->attrs);
213 while (enumerator->enumerate(enumerator, &attr))
214 {
215 if (streq(attr->name, peer_cfg->get_name(peer_cfg)))
216 {
217 enumerator->destroy(enumerator);
218 return enumerator_create_filter(
219 attr->dns->create_enumerator(attr->dns),
220 (void*)attr_filter, this->lock,
221 (void*)this->lock->unlock);
222 }
223 }
224 enumerator->destroy(enumerator);
225 this->lock->unlock(this->lock);
226 }
227 return enumerator_create_empty();
228 }
229
230 METHOD(stroke_attribute_t, add_pool, void,
231 private_stroke_attribute_t *this, mem_pool_t *pool)
232 {
233 enumerator_t *enumerator;
234 mem_pool_t *current;
235 host_t *base;
236 int size;
237
238 base = pool->get_base(pool);
239 size = pool->get_size(pool);
240
241 this->lock->write_lock(this->lock);
242
243 enumerator = this->pools->create_enumerator(this->pools);
244 while (enumerator->enumerate(enumerator, &current))
245 {
246 if (base && current->get_base(current) &&
247 base->ip_equals(base, current->get_base(current)) &&
248 size == current->get_size(current))
249 {
250 DBG1(DBG_CFG, "reusing virtual IP address pool %s",
251 current->get_name(current));
252 pool->destroy(pool);
253 pool = NULL;
254 break;
255 }
256 }
257 enumerator->destroy(enumerator);
258
259 if (pool)
260 {
261 if (base)
262 {
263 DBG1(DBG_CFG, "adding virtual IP address pool %s",
264 pool->get_name(pool));
265 }
266 this->pools->insert_last(this->pools, pool);
267 }
268
269 this->lock->unlock(this->lock);
270 }
271
272 METHOD(stroke_attribute_t, add_dns, void,
273 private_stroke_attribute_t *this, stroke_msg_t *msg)
274 {
275 if (msg->add_conn.other.dns)
276 {
277 enumerator_t *enumerator;
278 attributes_t *attr = NULL;
279 host_t *host;
280 char *token;
281
282 enumerator = enumerator_create_token(msg->add_conn.other.dns, ",", " ");
283 while (enumerator->enumerate(enumerator, &token))
284 {
285 host = host_create_from_string(token, 0);
286 if (host)
287 {
288 if (!attr)
289 {
290 INIT(attr,
291 .name = strdup(msg->add_conn.name),
292 .dns = linked_list_create(),
293 );
294 }
295 attr->dns->insert_last(attr->dns, host);
296 }
297 else
298 {
299 DBG1(DBG_CFG, "ignoring invalid DNS address '%s'", token);
300 }
301 }
302 enumerator->destroy(enumerator);
303 if (attr)
304 {
305 this->lock->write_lock(this->lock);
306 this->attrs->insert_last(this->attrs, attr);
307 this->lock->unlock(this->lock);
308 }
309 }
310 }
311
312 METHOD(stroke_attribute_t, del_dns, void,
313 private_stroke_attribute_t *this, stroke_msg_t *msg)
314 {
315 enumerator_t *enumerator;
316 attributes_t *attr;
317
318 this->lock->write_lock(this->lock);
319
320 enumerator = this->attrs->create_enumerator(this->attrs);
321 while (enumerator->enumerate(enumerator, &attr))
322 {
323 if (streq(msg->del_conn.name, attr->name))
324 {
325 this->attrs->remove_at(this->attrs, enumerator);
326 attributes_destroy(attr);
327 break;
328 }
329 }
330 enumerator->destroy(enumerator);
331
332 this->lock->unlock(this->lock);
333 }
334
335 /**
336 * Pool enumerator filter function, converts pool_t to name, size, ...
337 */
338 static bool pool_filter(void *lock, mem_pool_t **poolp, const char **name,
339 void *d1, u_int *size, void *d2, u_int *online,
340 void *d3, u_int *offline)
341 {
342 mem_pool_t *pool = *poolp;
343
344 if (pool->get_size(pool) == 0)
345 {
346 return FALSE;
347 }
348 *name = pool->get_name(pool);
349 *size = pool->get_size(pool);
350 *online = pool->get_online(pool);
351 *offline = pool->get_offline(pool);
352 return TRUE;
353 }
354
355 METHOD(stroke_attribute_t, create_pool_enumerator, enumerator_t*,
356 private_stroke_attribute_t *this)
357 {
358 this->lock->read_lock(this->lock);
359 return enumerator_create_filter(this->pools->create_enumerator(this->pools),
360 (void*)pool_filter,
361 this->lock, (void*)this->lock->unlock);
362 }
363
364 METHOD(stroke_attribute_t, create_lease_enumerator, enumerator_t*,
365 private_stroke_attribute_t *this, char *name)
366 {
367 mem_pool_t *pool;
368 this->lock->read_lock(this->lock);
369 pool = find_pool(this, name);
370 if (!pool)
371 {
372 this->lock->unlock(this->lock);
373 return NULL;
374 }
375 return enumerator_create_cleaner(pool->create_lease_enumerator(pool),
376 (void*)this->lock->unlock, this->lock);
377 }
378
379 METHOD(stroke_attribute_t, destroy, void,
380 private_stroke_attribute_t *this)
381 {
382 this->lock->destroy(this->lock);
383 this->pools->destroy_offset(this->pools, offsetof(mem_pool_t, destroy));
384 this->attrs->destroy_function(this->attrs, (void*)attributes_destroy);
385 free(this);
386 }
387
388 /*
389 * see header file
390 */
391 stroke_attribute_t *stroke_attribute_create()
392 {
393 private_stroke_attribute_t *this;
394
395 INIT(this,
396 .public = {
397 .provider = {
398 .acquire_address = _acquire_address,
399 .release_address = _release_address,
400 .create_attribute_enumerator = _create_attribute_enumerator,
401 },
402 .add_pool = _add_pool,
403 .add_dns = _add_dns,
404 .del_dns = _del_dns,
405 .create_pool_enumerator = _create_pool_enumerator,
406 .create_lease_enumerator = _create_lease_enumerator,
407 .destroy = _destroy,
408 },
409 .pools = linked_list_create(),
410 .attrs = linked_list_create(),
411 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
412 );
413
414 return &this->public;
415 }
416