management of any attribute by ipsec pool
[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 /**
65 * Implementation of attribute_provider_t.create_attribute_enumerator
66 */
67 static enumerator_t* create_attribute_enumerator(private_attr_provider_t *this,
68 identification_t *id, host_t *vip)
69 {
70 if (vip)
71 {
72 return enumerator_create_filter(
73 this->attributes->create_enumerator(this->attributes),
74 (void*)attr_enum_filter, NULL, NULL);
75 }
76 return enumerator_create_empty();
77 }
78
79 /**
80 * Implementation of attr_provider_t.destroy
81 */
82 static void destroy(private_attr_provider_t *this)
83 {
84 attribute_entry_t *entry;
85
86 while (this->attributes->remove_last(this->attributes,
87 (void**)&entry) == SUCCESS)
88 {
89 free(entry->value.ptr);
90 free(entry);
91 }
92 this->attributes->destroy(this->attributes);
93 free(this);
94 }
95
96 /**
97 * Add an attribute entry to the list
98 */
99 static void add_legacy_entry(private_attr_provider_t *this, char *key, int nr,
100 configuration_attribute_type_t type)
101 {
102 attribute_entry_t *entry;
103 host_t *host;
104 char *str;
105
106 str = lib->settings->get_str(lib->settings, "%s.%s%d", NULL, hydra->daemon,
107 key, nr);
108 if (str)
109 {
110 host = host_create_from_string(str, 0);
111 if (host)
112 {
113 entry = malloc_thing(attribute_entry_t);
114
115 if (host->get_family(host) == AF_INET6)
116 {
117 switch (type)
118 {
119 case INTERNAL_IP4_DNS:
120 type = INTERNAL_IP6_DNS;
121 break;
122 case INTERNAL_IP4_NBNS:
123 type = INTERNAL_IP6_NBNS;
124 break;
125 default:
126 break;
127 }
128 }
129 entry->type = type;
130 entry->value = chunk_clone(host->get_address(host));
131 host->destroy(host);
132 this->attributes->insert_last(this->attributes, entry);
133 }
134 }
135 }
136
137 /**
138 * Key to attribute type mappings, for v4 and v6 attributes
139 */
140 static struct {
141 char *name;
142 configuration_attribute_type_t v4;
143 configuration_attribute_type_t v6;
144 } keys[] = {
145 {"address", INTERNAL_IP4_ADDRESS, INTERNAL_IP6_ADDRESS},
146 {"dns", INTERNAL_IP4_DNS, INTERNAL_IP6_DNS},
147 {"nbns", INTERNAL_IP4_NBNS, INTERNAL_IP6_NBNS},
148 {"dhcp", INTERNAL_IP4_DHCP, INTERNAL_IP6_DHCP},
149 {"netmask", INTERNAL_IP4_NETMASK, INTERNAL_IP6_NETMASK},
150 {"server", INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER},
151 };
152
153 /**
154 * Load (numerical) entries from the plugins.attr namespace
155 */
156 static void load_entries(private_attr_provider_t *this)
157 {
158 enumerator_t *enumerator, *tokens;
159 char *key, *value, *token;
160
161 enumerator = lib->settings->create_key_value_enumerator(lib->settings,
162 "%s.plugins.attr", hydra->daemon);
163 while (enumerator->enumerate(enumerator, &key, &value))
164 {
165 configuration_attribute_type_t type;
166 attribute_entry_t *entry;
167 host_t *host;
168 int i;
169
170 type = atoi(key);
171 tokens = enumerator_create_token(value, ",", " ");
172 while (tokens->enumerate(tokens, &token))
173 {
174 host = host_create_from_string(token, 0);
175 if (!host)
176 {
177 DBG1(DBG_CFG, "invalid host in key %s: %s", key, token);
178 continue;
179 }
180 if (!type)
181 {
182 for (i = 0; i < countof(keys); i++)
183 {
184 if (streq(key, keys[i].name))
185 {
186 if (host->get_family(host) == AF_INET)
187 {
188 type = keys[i].v4;
189 }
190 else
191 {
192 type = keys[i].v6;
193 }
194 }
195 }
196 if (!type)
197 {
198 DBG1(DBG_CFG, "mapping attribute type %s failed", key);
199 break;
200 }
201 }
202 entry = malloc_thing(attribute_entry_t);
203 entry->type = type;
204 entry->value = chunk_clone(host->get_address(host));
205 host->destroy(host);
206 this->attributes->insert_last(this->attributes, entry);
207 }
208 tokens->destroy(tokens);
209 }
210 enumerator->destroy(enumerator);
211 }
212
213 /*
214 * see header file
215 */
216 attr_provider_t *attr_provider_create(database_t *db)
217 {
218 private_attr_provider_t *this;
219 int i;
220
221 this = malloc_thing(private_attr_provider_t);
222
223 this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *, host_t *))return_null;
224 this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_t*))return_false;
225 this->public.provider.create_attribute_enumerator = (enumerator_t*(*)(attribute_provider_t*, identification_t *id, host_t *vip))create_attribute_enumerator;
226 this->public.destroy = (void(*)(attr_provider_t*))destroy;
227
228 this->attributes = linked_list_create();
229
230 for (i = 1; i <= SERVER_MAX; i++)
231 {
232 add_legacy_entry(this, "dns", i, INTERNAL_IP4_DNS);
233 add_legacy_entry(this, "nbns", i, INTERNAL_IP4_NBNS);
234 }
235
236 load_entries(this);
237
238 return &this->public;
239 }
240