2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
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>.
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
18 #include "stroke_attribute.h"
21 #include <utils/linked_list.h>
22 #include <utils/mutex.h>
26 typedef struct private_stroke_attribute_t private_stroke_attribute_t
;
29 * private data of stroke_attribute
31 struct private_stroke_attribute_t
{
36 stroke_attribute_t
public;
39 * list of pools, contains pool_t
44 * mutex to lock access to pools
50 /** name of the pool */
52 /** base address of the pool */
54 /** number of entries in the pool */
56 /** array of in-use flags, TODO: use bit fields */
63 static void pool_destroy(pool_t
*this)
65 DESTROY_IF(this->base
);
74 static pool_t
*find_pool(private_stroke_attribute_t
*this, char *name
)
76 enumerator_t
*enumerator
;
77 pool_t
*current
, *found
= NULL
;
79 enumerator
= this->pools
->create_enumerator(this->pools
);
80 while (enumerator
->enumerate(enumerator
, ¤t
))
82 if (streq(name
, current
->name
))
88 enumerator
->destroy(enumerator
);
93 * convert an pool offset to an address
95 host_t
* offset2host(pool_t
*pool
, int offset
)
101 if (offset
> pool
->count
)
106 addr
= chunk_clone(pool
->base
->get_address(pool
->base
));
107 if (pool
->base
->get_family(pool
->base
) == AF_INET6
)
109 pos
= (u_int32_t
*)(addr
.ptr
+ 12);
113 pos
= (u_int32_t
*)addr
.ptr
;
115 *pos
= htonl(offset
+ ntohl(*pos
));
116 host
= host_create_from_chunk(pool
->base
->get_family(pool
->base
), addr
, 0);
122 * convert a host to a pool offset
124 int host2offset(pool_t
*pool
, host_t
*addr
)
127 u_int32_t hosti
, basei
;
129 if (addr
->get_family(addr
) != pool
->base
->get_family(pool
->base
))
133 host
= addr
->get_address(addr
);
134 base
= pool
->base
->get_address(pool
->base
);
135 if (addr
->get_family(addr
) == AF_INET6
)
137 /* only look at last /32 block */
138 if (!memeq(host
.ptr
, base
.ptr
, 12))
142 host
= chunk_skip(host
, 12);
143 base
= chunk_skip(base
, 12);
145 hosti
= ntohl(*(u_int32_t
*)(host
.ptr
));
146 basei
= ntohl(*(u_int32_t
*)(base
.ptr
));
147 if (hosti
> basei
+ pool
->count
)
151 return hosti
- basei
;
155 * Implementation of attribute_provider_t.acquire_address
157 static host_t
* acquire_address(private_stroke_attribute_t
*this,
158 char *name
, identification_t
*id
,
159 auth_info_t
*auth
, host_t
*requested
)
165 this->mutex
->lock(this->mutex
);
166 pool
= find_pool(this, name
);
169 if (requested
&& !requested
->is_anyaddr(requested
))
171 if (pool
->count
== 0)
172 { /* %config, give any */
173 host
= requested
->clone(requested
);
177 i
= host2offset(pool
, requested
);
178 if (i
>= 0 && !pool
->in_use
[i
])
180 pool
->in_use
[i
] = TRUE
;
181 host
= requested
->clone(requested
);
187 for (i
= 0; i
< pool
->count
; i
++)
189 if (!pool
->in_use
[i
])
191 pool
->in_use
[i
] = TRUE
;
192 host
= offset2host(pool
, i
);
198 this->mutex
->unlock(this->mutex
);
203 * Implementation of attribute_provider_t.release_address
205 static bool release_address(private_stroke_attribute_t
*this,
206 char *name
, host_t
*address
)
212 this->mutex
->lock(this->mutex
);
213 pool
= find_pool(this, name
);
216 if (pool
->count
!= 0)
218 i
= host2offset(pool
, address
);
219 if (i
>= 0 && pool
->in_use
[i
])
221 pool
->in_use
[i
] = FALSE
;
226 this->mutex
->unlock(this->mutex
);
231 * Implementation of stroke_attribute_t.add_pool.
233 static void add_pool(private_stroke_attribute_t
*this, stroke_msg_t
*msg
)
235 if (msg
->add_conn
.other
.sourceip_size
)
239 if (msg
->add_conn
.other
.sourceip
)
244 DBG1(DBG_CFG
, "adding virtual IP address pool '%s': %s/%d",
245 msg
->add_conn
.name
, msg
->add_conn
.other
.sourceip
,
246 msg
->add_conn
.other
.sourceip_size
);
248 pool
= malloc_thing(pool_t
);
249 pool
->base
= host_create_from_string(msg
->add_conn
.other
.sourceip
, 0);
253 DBG1(DBG_CFG
, "virtual IP address invalid, discarded");
256 pool
->name
= strdup(msg
->add_conn
.name
);
257 family
= pool
->base
->get_family(pool
->base
);
258 bits
= (family
== AF_INET ?
32 : 128) - msg
->add_conn
.other
.sourceip_size
;
259 if (bits
> POOL_LIMIT
)
262 DBG1(DBG_CFG
, "virtual IP pool to large, limiting to %s/%d",
263 msg
->add_conn
.other
.sourceip
,
264 (family
== AF_INET ?
32 : 128) - bits
);
266 pool
->count
= 1 << (bits
);
267 pool
->in_use
= calloc(pool
->count
, sizeof(u_int8_t
));
270 { /* do not use first and last addresses of a block */
271 pool
->in_use
[0] = TRUE
;
272 pool
->in_use
[pool
->count
-1] = TRUE
;
276 { /* %config, add an empty pool */
277 pool
= malloc_thing(pool_t
);
278 pool
->name
= strdup(msg
->add_conn
.name
);
283 this->mutex
->lock(this->mutex
);
284 this->pools
->insert_last(this->pools
, pool
);
285 this->mutex
->unlock(this->mutex
);
290 * Implementation of stroke_attribute_t.del_pool.
292 static void del_pool(private_stroke_attribute_t
*this, stroke_msg_t
*msg
)
294 enumerator_t
*enumerator
;
297 this->mutex
->lock(this->mutex
);
298 enumerator
= this->pools
->create_enumerator(this->pools
);
299 while (enumerator
->enumerate(enumerator
, &pool
))
301 if (streq(msg
->del_conn
.name
, pool
->name
))
303 this->pools
->remove_at(this->pools
, enumerator
);
308 enumerator
->destroy(enumerator
);
309 this->mutex
->unlock(this->mutex
);
313 * Implementation of stroke_attribute_t.destroy
315 static void destroy(private_stroke_attribute_t
*this)
317 this->mutex
->destroy(this->mutex
);
318 this->pools
->destroy_function(this->pools
, (void*)pool_destroy
);
325 stroke_attribute_t
*stroke_attribute_create()
327 private_stroke_attribute_t
*this = malloc_thing(private_stroke_attribute_t
);
329 this->public.provider
.acquire_address
= (host_t
*(*)(attribute_provider_t
*this, char*, identification_t
*,auth_info_t
*, host_t
*))acquire_address
;
330 this->public.provider
.release_address
= (bool(*)(attribute_provider_t
*this, char*,host_t
*))release_address
;
331 this->public.add_pool
= (void(*)(stroke_attribute_t
*, stroke_msg_t
*msg
))add_pool
;
332 this->public.del_pool
= (void(*)(stroke_attribute_t
*, stroke_msg_t
*msg
))del_pool
;
333 this->public.destroy
= (void(*)(stroke_attribute_t
*))destroy
;
335 this->pools
= linked_list_create();
336 this->mutex
= mutex_create(MUTEX_DEFAULT
);
338 return &this->public;