Adding a whack_attribute class which manages in-memory pools in pluto and is very...
[strongswan.git] / src / pluto / whack_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 "whack_attribute.h"
18
19 #include "log.h"
20
21 /* these are defined as constants in constant.h but redefined as enum values in
22 * attributes/attributes.h */
23 #undef INTERNAL_IP4_SERVER
24 #undef INTERNAL_IP6_SERVER
25
26 #include <hydra.h>
27 #include <attributes/mem_pool.h>
28 #include <utils/linked_list.h>
29 #include <threading/rwlock.h>
30
31 typedef struct private_whack_attribute_t private_whack_attribute_t;
32
33 /**
34 * private data of whack_attribute
35 */
36 struct private_whack_attribute_t {
37
38 /**
39 * public functions
40 */
41 whack_attribute_t public;
42
43 /**
44 * list of pools, contains mem_pool_t
45 */
46 linked_list_t *pools;
47
48 /**
49 * rwlock to lock access to pools
50 */
51 rwlock_t *lock;
52 };
53
54 /**
55 * global object
56 */
57 whack_attribute_t *whack_attr;
58
59 /**
60 * compare pools by name
61 */
62 static bool pool_match(mem_pool_t *current, char *name)
63 {
64 return name && streq(name, current->get_name(current));
65 }
66
67 /**
68 * find a pool by name
69 */
70 static mem_pool_t *find_pool(private_whack_attribute_t *this, char *name)
71 {
72 mem_pool_t *found;
73 if (this->pools->find_first(this->pools, (linked_list_match_t)pool_match,
74 (void**)&found, name) == SUCCESS)
75 {
76 return found;
77 }
78 return NULL;
79 }
80
81 METHOD(attribute_provider_t, acquire_address, host_t*,
82 private_whack_attribute_t *this, char *name, identification_t *id,
83 host_t *requested)
84 {
85 mem_pool_t *pool;
86 host_t *addr = NULL;
87 this->lock->read_lock(this->lock);
88 pool = find_pool(this, name);
89 if (pool)
90 {
91 addr = pool->acquire_address(pool, id, requested);
92 }
93 this->lock->unlock(this->lock);
94 return addr;
95 }
96
97 METHOD(attribute_provider_t, release_address, bool,
98 private_whack_attribute_t *this, char *name, host_t *address,
99 identification_t *id)
100 {
101 mem_pool_t *pool;
102 bool found = FALSE;
103 this->lock->read_lock(this->lock);
104 pool = find_pool(this, name);
105 if (pool)
106 {
107 found = pool->release_address(pool, address, id);
108 }
109 this->lock->unlock(this->lock);
110 return found;
111 }
112
113 METHOD(whack_attribute_t, add_pool, bool,
114 private_whack_attribute_t *this, const char *name,
115 const whack_end_t *right)
116 {
117 mem_pool_t *pool;
118 host_t *base = NULL;
119 u_int32_t bits = 0;
120
121 /* named pool */
122 if (right->sourceip_mask <= 0)
123 {
124 return FALSE;
125 }
126
127 /* if %config, add an empty pool, otherwise */
128 if (right->sourceip)
129 {
130 DBG(DBG_CONTROL,
131 DBG_log("adding virtual IP address pool '%s': %s/%d",
132 name, right->sourceip, right->sourceip_mask);
133 );
134 base = host_create_from_string(right->sourceip, 0);
135 if (!base)
136 {
137 loglog(RC_LOG_SERIOUS, "virtual IP address invalid, discarded");
138 return FALSE;
139 }
140 bits = right->sourceip_mask;
141 }
142 pool = mem_pool_create((char*)name, base, bits);
143 DESTROY_IF(base);
144
145 this->lock->write_lock(this->lock);
146 this->pools->insert_last(this->pools, pool);
147 this->lock->unlock(this->lock);
148 return TRUE;
149 }
150
151 METHOD(whack_attribute_t, del_pool, void,
152 private_whack_attribute_t *this, char *name)
153 {
154 enumerator_t *enumerator;
155 mem_pool_t *pool;
156
157 this->lock->write_lock(this->lock);
158 enumerator = this->pools->create_enumerator(this->pools);
159 while (enumerator->enumerate(enumerator, &pool))
160 {
161 if (streq(name, pool->get_name(pool)))
162 {
163 this->pools->remove_at(this->pools, enumerator);
164 pool->destroy(pool);
165 break;
166 }
167 }
168 enumerator->destroy(enumerator);
169 this->lock->unlock(this->lock);
170 }
171
172 /**
173 * Pool enumerator filter function, converts pool_t to name, size, ...
174 */
175 static bool pool_filter(void *lock, mem_pool_t **poolp, const char **name,
176 void *d1, u_int *size, void *d2, u_int *online,
177 void *d3, u_int *offline)
178 {
179 mem_pool_t *pool = *poolp;
180 *name = pool->get_name(pool);
181 *size = pool->get_size(pool);
182 *online = pool->get_online(pool);
183 *offline = pool->get_offline(pool);
184 return TRUE;
185 }
186
187 METHOD(whack_attribute_t, create_pool_enumerator, enumerator_t*,
188 private_whack_attribute_t *this)
189 {
190 this->lock->read_lock(this->lock);
191 return enumerator_create_filter(this->pools->create_enumerator(this->pools),
192 (void*)pool_filter,
193 this->lock, (void*)this->lock->unlock);
194 }
195
196 METHOD(whack_attribute_t, create_lease_enumerator, enumerator_t*,
197 private_whack_attribute_t *this, char *name)
198 {
199 mem_pool_t *pool;
200 this->lock->read_lock(this->lock);
201 pool = find_pool(this, name);
202 if (!pool)
203 {
204 this->lock->unlock(this->lock);
205 return NULL;
206 }
207 return enumerator_create_cleaner(pool->create_lease_enumerator(pool),
208 (void*)this->lock->unlock, this->lock);
209 }
210
211 /**
212 * see header file
213 */
214 void whack_attribute_finalize()
215 {
216 private_whack_attribute_t *this = (private_whack_attribute_t*)whack_attr;
217 hydra->attributes->remove_provider(hydra->attributes,
218 &this->public.provider);
219 this->lock->destroy(this->lock);
220 this->pools->destroy_offset(this->pools, offsetof(mem_pool_t, destroy));
221 free(this);
222 }
223
224 /**
225 * see header file
226 */
227 void whack_attribute_initialize()
228 {
229 private_whack_attribute_t *this;
230
231 INIT(this,
232 .public = {
233 .provider = {
234 .acquire_address = _acquire_address,
235 .release_address = _release_address,
236 .create_attribute_enumerator = enumerator_create_empty,
237 },
238 .add_pool = _add_pool,
239 .del_pool = _del_pool,
240 .create_pool_enumerator = _create_pool_enumerator,
241 .create_lease_enumerator = _create_lease_enumerator,
242 },
243 .pools = linked_list_create(),
244 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
245 );
246
247 hydra->attributes->add_provider(hydra->attributes, &this->public.provider);
248
249 whack_attr = &this->public;
250 }
251