0ee45746e0cb01bf4ecab0f172e40aebf3c992ce
[strongswan.git] / src / libcharon / plugins / stroke / stroke_attribute.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 "stroke_attribute.h"
17
18 #include <daemon.h>
19 #include <attributes/mem_pool.h>
20 #include <utils/linked_list.h>
21 #include <threading/mutex.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 * mutex to lock access to pools
42 */
43 mutex_t *mutex;
44 };
45
46 /**
47 * find a pool by name
48 */
49 static mem_pool_t *find_pool(private_stroke_attribute_t *this, char *name)
50 {
51 enumerator_t *enumerator;
52 mem_pool_t *current, *found = NULL;
53
54 enumerator = this->pools->create_enumerator(this->pools);
55 while (enumerator->enumerate(enumerator, &current))
56 {
57 if (streq(name, current->get_name(current)))
58 {
59 found = current;
60 break;
61 }
62 }
63 enumerator->destroy(enumerator);
64 return found;
65 }
66
67 /**
68 * Implementation of attribute_provider_t.acquire_address
69 */
70 static host_t* acquire_address(private_stroke_attribute_t *this,
71 char *name, identification_t *id,
72 host_t *requested)
73 {
74 mem_pool_t *pool;
75 host_t *addr = NULL;
76 this->mutex->lock(this->mutex);
77 pool = find_pool(this, name);
78 if (pool)
79 {
80 addr = pool->acquire_address(pool, id, requested);
81 }
82 this->mutex->unlock(this->mutex);
83 return addr;
84 }
85
86 /**
87 * Implementation of attribute_provider_t.release_address
88 */
89 static bool release_address(private_stroke_attribute_t *this,
90 char *name, host_t *address, identification_t *id)
91 {
92 mem_pool_t *pool;
93 bool found = FALSE;
94 this->mutex->lock(this->mutex);
95 pool = find_pool(this, name);
96 if (pool)
97 {
98 found = pool->release_address(pool, address, id);
99 }
100 this->mutex->unlock(this->mutex);
101 return found;
102 }
103
104 /**
105 * Implementation of stroke_attribute_t.add_pool.
106 */
107 static void add_pool(private_stroke_attribute_t *this, stroke_msg_t *msg)
108 {
109 if (msg->add_conn.other.sourceip_mask)
110 {
111 mem_pool_t *pool;
112 host_t *base = NULL;
113 u_int32_t bits = 0;
114
115 /* if %config, add an empty pool, otherwise */
116 if (msg->add_conn.other.sourceip)
117 {
118 DBG1(DBG_CFG, "adding virtual IP address pool '%s': %s/%d",
119 msg->add_conn.name, msg->add_conn.other.sourceip,
120 msg->add_conn.other.sourceip_mask);
121 base = host_create_from_string(msg->add_conn.other.sourceip, 0);
122 if (!base)
123 {
124 DBG1(DBG_CFG, "virtual IP address invalid, discarded");
125 return;
126 }
127 bits = msg->add_conn.other.sourceip_mask;
128 }
129 pool = mem_pool_create(msg->add_conn.name, base, bits);
130 DESTROY_IF(base);
131
132 this->mutex->lock(this->mutex);
133 this->pools->insert_last(this->pools, pool);
134 this->mutex->unlock(this->mutex);
135 }
136 }
137
138 /**
139 * Implementation of stroke_attribute_t.del_pool.
140 */
141 static void del_pool(private_stroke_attribute_t *this, stroke_msg_t *msg)
142 {
143 enumerator_t *enumerator;
144 mem_pool_t *pool;
145
146 this->mutex->lock(this->mutex);
147 enumerator = this->pools->create_enumerator(this->pools);
148 while (enumerator->enumerate(enumerator, &pool))
149 {
150 if (streq(msg->del_conn.name, pool->get_name(pool)))
151 {
152 this->pools->remove_at(this->pools, enumerator);
153 pool->destroy(pool);
154 break;
155 }
156 }
157 enumerator->destroy(enumerator);
158 this->mutex->unlock(this->mutex);
159 }
160
161 /**
162 * Pool enumerator filter function, converts pool_t to name, size, ...
163 */
164 static bool pool_filter(void *mutex, mem_pool_t **poolp, const char **name,
165 void *d1, u_int *size, void *d2, u_int *online,
166 void *d3, u_int *offline)
167 {
168 mem_pool_t *pool = *poolp;
169 *name = pool->get_name(pool);
170 *size = pool->get_size(pool);
171 *online = pool->get_online(pool);
172 *offline = pool->get_offline(pool);
173 return TRUE;
174 }
175
176 /**
177 * Implementation of stroke_attribute_t.create_pool_enumerator
178 */
179 static enumerator_t* create_pool_enumerator(private_stroke_attribute_t *this)
180 {
181 this->mutex->lock(this->mutex);
182 return enumerator_create_filter(this->pools->create_enumerator(this->pools),
183 (void*)pool_filter,
184 this->mutex, (void*)this->mutex->unlock);
185 }
186
187 /**
188 * Implementation of stroke_attribute_t.create_lease_enumerator
189 */
190 static enumerator_t* create_lease_enumerator(private_stroke_attribute_t *this,
191 char *name)
192 {
193 mem_pool_t *pool;
194 this->mutex->lock(this->mutex);
195 pool = find_pool(this, name);
196 if (!pool)
197 {
198 this->mutex->unlock(this->mutex);
199 return NULL;
200 }
201 return enumerator_create_cleaner(pool->create_lease_enumerator(pool),
202 (void*)this->mutex->unlock, this->mutex);
203 }
204
205 /**
206 * Implementation of stroke_attribute_t.destroy
207 */
208 static void destroy(private_stroke_attribute_t *this)
209 {
210 this->mutex->destroy(this->mutex);
211 this->pools->destroy_offset(this->pools, offsetof(mem_pool_t, destroy));
212 free(this);
213 }
214
215 /*
216 * see header file
217 */
218 stroke_attribute_t *stroke_attribute_create()
219 {
220 private_stroke_attribute_t *this = malloc_thing(private_stroke_attribute_t);
221
222 this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *,host_t *))acquire_address;
223 this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_t*))release_address;
224 this->public.provider.create_attribute_enumerator = (enumerator_t*(*)(attribute_provider_t*, identification_t *id, host_t *vip))enumerator_create_empty;
225 this->public.add_pool = (void(*)(stroke_attribute_t*, stroke_msg_t *msg))add_pool;
226 this->public.del_pool = (void(*)(stroke_attribute_t*, stroke_msg_t *msg))del_pool;
227 this->public.create_pool_enumerator = (enumerator_t*(*)(stroke_attribute_t*))create_pool_enumerator;
228 this->public.create_lease_enumerator = (enumerator_t*(*)(stroke_attribute_t*, char *pool))create_lease_enumerator;
229 this->public.destroy = (void(*)(stroke_attribute_t*))destroy;
230
231 this->pools = linked_list_create();
232 this->mutex = mutex_create(MUTEX_TYPE_RECURSIVE);
233
234 return &this->public;
235 }
236