]>
Commit | Line | Data |
---|---|---|
7f56b494 | 1 | /* |
7ac6060e | 2 | * Copyright (C) 2010 Tobias Brunner |
7f56b494 MW |
3 | * Copyright (C) 2009 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. | |
7f56b494 MW |
15 | */ |
16 | ||
17 | #include "attr_provider.h" | |
18 | ||
19 | #include <time.h> | |
20 | ||
7ac6060e TB |
21 | #include <hydra.h> |
22 | #include <debug.h> | |
23 | #include <utils/linked_list.h> | |
96409be3 | 24 | #include <threading/rwlock.h> |
7f56b494 MW |
25 | |
26 | #define SERVER_MAX 2 | |
27 | ||
28 | typedef struct private_attr_provider_t private_attr_provider_t; | |
29 | typedef struct attribute_entry_t attribute_entry_t; | |
30 | ||
31 | /** | |
32 | * private data of attr_provider | |
33 | */ | |
34 | struct private_attr_provider_t { | |
7daf5226 | 35 | |
7f56b494 MW |
36 | /** |
37 | * public functions | |
38 | */ | |
39 | attr_provider_t public; | |
7daf5226 | 40 | |
7f56b494 MW |
41 | /** |
42 | * List of attributes, attribute_entry_t | |
43 | */ | |
44 | linked_list_t *attributes; | |
96409be3 MW |
45 | |
46 | /** | |
47 | * Lock for attribute list | |
48 | */ | |
49 | rwlock_t *lock; | |
7f56b494 MW |
50 | }; |
51 | ||
52 | struct attribute_entry_t { | |
53 | /** type of attribute */ | |
54 | configuration_attribute_type_t type; | |
55 | /** attribute value */ | |
56 | chunk_t value; | |
57 | }; | |
58 | ||
96409be3 MW |
59 | /** |
60 | * Destroy an entry | |
61 | */ | |
62 | static void attribute_destroy(attribute_entry_t *this) | |
63 | { | |
64 | free(this->value.ptr); | |
65 | free(this); | |
66 | } | |
67 | ||
7f56b494 MW |
68 | /** |
69 | * convert enumerator value from attribute_entry | |
70 | */ | |
71 | static bool attr_enum_filter(void *null, attribute_entry_t **in, | |
72 | configuration_attribute_type_t *type, void* none, chunk_t *value) | |
73 | { | |
74 | *type = (*in)->type; | |
75 | *value = (*in)->value; | |
76 | return TRUE; | |
77 | } | |
78 | ||
00b4b4b0 MW |
79 | METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, |
80 | private_attr_provider_t *this, char *pool, | |
81 | identification_t *id, host_t *vip) | |
7f56b494 | 82 | { |
b5a2055f MW |
83 | if (vip) |
84 | { | |
96409be3 | 85 | this->lock->read_lock(this->lock); |
b5a2055f | 86 | return enumerator_create_filter( |
96409be3 MW |
87 | this->attributes->create_enumerator(this->attributes), |
88 | (void*)attr_enum_filter, this->lock, (void*)this->lock->unlock); | |
b5a2055f MW |
89 | } |
90 | return enumerator_create_empty(); | |
7f56b494 MW |
91 | } |
92 | ||
00b4b4b0 MW |
93 | METHOD(attr_provider_t, destroy, void, |
94 | private_attr_provider_t *this) | |
7f56b494 | 95 | { |
96409be3 MW |
96 | this->attributes->destroy_function(this->attributes, |
97 | (void*)attribute_destroy); | |
98 | this->lock->destroy(this->lock); | |
7f56b494 MW |
99 | free(this); |
100 | } | |
101 | ||
102 | /** | |
103 | * Add an attribute entry to the list | |
104 | */ | |
d674c2ac MW |
105 | static void add_legacy_entry(private_attr_provider_t *this, char *key, int nr, |
106 | configuration_attribute_type_t type) | |
7f56b494 MW |
107 | { |
108 | attribute_entry_t *entry; | |
109 | host_t *host; | |
110 | char *str; | |
7daf5226 | 111 | |
5b0bcfb1 MW |
112 | str = lib->settings->get_str(lib->settings, "%s.%s%d", NULL, hydra->daemon, |
113 | key, nr); | |
7f56b494 MW |
114 | if (str) |
115 | { | |
116 | host = host_create_from_string(str, 0); | |
117 | if (host) | |
118 | { | |
119 | entry = malloc_thing(attribute_entry_t); | |
7daf5226 | 120 | |
7f56b494 MW |
121 | if (host->get_family(host) == AF_INET6) |
122 | { | |
123 | switch (type) | |
124 | { | |
125 | case INTERNAL_IP4_DNS: | |
126 | type = INTERNAL_IP6_DNS; | |
127 | break; | |
128 | case INTERNAL_IP4_NBNS: | |
129 | type = INTERNAL_IP6_NBNS; | |
130 | break; | |
131 | default: | |
132 | break; | |
133 | } | |
134 | } | |
135 | entry->type = type; | |
136 | entry->value = chunk_clone(host->get_address(host)); | |
137 | host->destroy(host); | |
96409be3 MW |
138 | DBG2(DBG_CFG, "loaded legacy entry attribute %N: %#B", |
139 | configuration_attribute_type_names, entry->type, &entry->value); | |
7f56b494 MW |
140 | this->attributes->insert_last(this->attributes, entry); |
141 | } | |
142 | } | |
143 | } | |
144 | ||
d674c2ac MW |
145 | /** |
146 | * Key to attribute type mappings, for v4 and v6 attributes | |
147 | */ | |
148 | static struct { | |
149 | char *name; | |
150 | configuration_attribute_type_t v4; | |
151 | configuration_attribute_type_t v6; | |
152 | } keys[] = { | |
153 | {"address", INTERNAL_IP4_ADDRESS, INTERNAL_IP6_ADDRESS}, | |
154 | {"dns", INTERNAL_IP4_DNS, INTERNAL_IP6_DNS}, | |
155 | {"nbns", INTERNAL_IP4_NBNS, INTERNAL_IP6_NBNS}, | |
156 | {"dhcp", INTERNAL_IP4_DHCP, INTERNAL_IP6_DHCP}, | |
157 | {"netmask", INTERNAL_IP4_NETMASK, INTERNAL_IP6_NETMASK}, | |
158 | {"server", INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER}, | |
1e723d73 | 159 | {"subnet", INTERNAL_IP4_SUBNET, INTERNAL_IP6_SUBNET}, |
d674c2ac MW |
160 | }; |
161 | ||
162 | /** | |
163 | * Load (numerical) entries from the plugins.attr namespace | |
164 | */ | |
165 | static void load_entries(private_attr_provider_t *this) | |
166 | { | |
167 | enumerator_t *enumerator, *tokens; | |
168 | char *key, *value, *token; | |
96409be3 MW |
169 | int i; |
170 | ||
171 | for (i = 1; i <= SERVER_MAX; i++) | |
172 | { | |
173 | add_legacy_entry(this, "dns", i, INTERNAL_IP4_DNS); | |
174 | add_legacy_entry(this, "nbns", i, INTERNAL_IP4_NBNS); | |
175 | } | |
d674c2ac MW |
176 | |
177 | enumerator = lib->settings->create_key_value_enumerator(lib->settings, | |
7ac6060e | 178 | "%s.plugins.attr", hydra->daemon); |
d674c2ac MW |
179 | while (enumerator->enumerate(enumerator, &key, &value)) |
180 | { | |
181 | configuration_attribute_type_t type; | |
182 | attribute_entry_t *entry; | |
183 | host_t *host; | |
1e723d73 MW |
184 | char *pos; |
185 | int i, mask = -1; | |
d674c2ac MW |
186 | |
187 | type = atoi(key); | |
188 | tokens = enumerator_create_token(value, ",", " "); | |
189 | while (tokens->enumerate(tokens, &token)) | |
190 | { | |
1e723d73 MW |
191 | pos = strchr(token, '/'); |
192 | if (pos) | |
193 | { | |
194 | *(pos++) = '\0'; | |
195 | mask = atoi(pos); | |
196 | } | |
d674c2ac MW |
197 | host = host_create_from_string(token, 0); |
198 | if (!host) | |
199 | { | |
894936ce | 200 | DBG1(DBG_CFG, "invalid host in key %s: %s", key, token); |
d674c2ac MW |
201 | continue; |
202 | } | |
203 | if (!type) | |
204 | { | |
205 | for (i = 0; i < countof(keys); i++) | |
206 | { | |
207 | if (streq(key, keys[i].name)) | |
208 | { | |
209 | if (host->get_family(host) == AF_INET) | |
210 | { | |
211 | type = keys[i].v4; | |
212 | } | |
213 | else | |
214 | { | |
215 | type = keys[i].v6; | |
216 | } | |
217 | } | |
218 | } | |
219 | if (!type) | |
220 | { | |
894936ce | 221 | DBG1(DBG_CFG, "mapping attribute type %s failed", key); |
d674c2ac MW |
222 | break; |
223 | } | |
224 | } | |
225 | entry = malloc_thing(attribute_entry_t); | |
226 | entry->type = type; | |
1e723d73 MW |
227 | if (mask == -1) |
228 | { | |
229 | entry->value = chunk_clone(host->get_address(host)); | |
230 | } | |
231 | else | |
232 | { | |
233 | if (host->get_family(host) == AF_INET) | |
234 | { /* IPv4 attributes contain a subnet mask */ | |
235 | u_int32_t netmask; | |
236 | ||
237 | mask = 32 - mask; | |
238 | netmask = htonl((0xFFFFFFFF >> mask) << mask); | |
239 | entry->value = chunk_cat("cc", host->get_address(host), | |
240 | chunk_from_thing(netmask)); | |
241 | } | |
242 | else | |
243 | { /* IPv6 addresses the prefix only */ | |
244 | entry->value = chunk_cat("cc", host->get_address(host), | |
245 | chunk_from_chars(mask)); | |
246 | } | |
247 | } | |
d674c2ac | 248 | host->destroy(host); |
96409be3 MW |
249 | DBG2(DBG_CFG, "loaded attribute %N: %#B", |
250 | configuration_attribute_type_names, entry->type, &entry->value); | |
d674c2ac MW |
251 | this->attributes->insert_last(this->attributes, entry); |
252 | } | |
253 | tokens->destroy(tokens); | |
254 | } | |
255 | enumerator->destroy(enumerator); | |
256 | } | |
257 | ||
96409be3 MW |
258 | METHOD(attr_provider_t, reload, void, |
259 | private_attr_provider_t *this) | |
260 | { | |
261 | this->lock->write_lock(this->lock); | |
262 | ||
263 | this->attributes->destroy_function(this->attributes, (void*)attribute_destroy); | |
264 | this->attributes = linked_list_create(); | |
265 | ||
266 | load_entries(this); | |
267 | ||
268 | DBG1(DBG_CFG, "loaded %d entr%s for attr plugin configuration", | |
269 | this->attributes->get_count(this->attributes), | |
270 | this->attributes->get_count(this->attributes) == 1 ? "y" : "ies"); | |
271 | ||
272 | this->lock->unlock(this->lock); | |
273 | } | |
274 | ||
7f56b494 MW |
275 | /* |
276 | * see header file | |
277 | */ | |
278 | attr_provider_t *attr_provider_create(database_t *db) | |
279 | { | |
280 | private_attr_provider_t *this; | |
7daf5226 | 281 | |
00b4b4b0 MW |
282 | INIT(this, |
283 | .public = { | |
284 | .provider = { | |
285 | .acquire_address = (void*)return_null, | |
286 | .release_address = (void*)return_false, | |
287 | .create_attribute_enumerator = _create_attribute_enumerator, | |
288 | }, | |
96409be3 | 289 | .reload = _reload, |
00b4b4b0 MW |
290 | .destroy = _destroy, |
291 | }, | |
292 | .attributes = linked_list_create(), | |
96409be3 | 293 | .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), |
00b4b4b0 | 294 | ); |
7daf5226 | 295 | |
d674c2ac MW |
296 | load_entries(this); |
297 | ||
7f56b494 MW |
298 | return &this->public; |
299 | } | |
300 |