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