Moving charon to libcharon.
[strongswan.git] / src / libcharon / plugins / attr / attr_provider.c
1 /*
2 * Copyright (C) 2009 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 "attr_provider.h"
17
18 #include <time.h>
19
20 #include <daemon.h>
21
22 #define SERVER_MAX 2
23
24 typedef struct private_attr_provider_t private_attr_provider_t;
25 typedef struct attribute_entry_t attribute_entry_t;
26
27 /**
28 * private data of attr_provider
29 */
30 struct private_attr_provider_t {
31
32 /**
33 * public functions
34 */
35 attr_provider_t public;
36
37 /**
38 * List of attributes, attribute_entry_t
39 */
40 linked_list_t *attributes;
41 };
42
43 struct attribute_entry_t {
44 /** type of attribute */
45 configuration_attribute_type_t type;
46 /** attribute value */
47 chunk_t value;
48 };
49
50 /**
51 * convert enumerator value from attribute_entry
52 */
53 static bool attr_enum_filter(void *null, attribute_entry_t **in,
54 configuration_attribute_type_t *type, void* none, chunk_t *value)
55 {
56 *type = (*in)->type;
57 *value = (*in)->value;
58 return TRUE;
59 }
60
61 /**
62 * Implementation of attribute_provider_t.create_attribute_enumerator
63 */
64 static enumerator_t* create_attribute_enumerator(private_attr_provider_t *this,
65 identification_t *id, host_t *vip)
66 {
67 if (vip)
68 {
69 return enumerator_create_filter(
70 this->attributes->create_enumerator(this->attributes),
71 (void*)attr_enum_filter, NULL, NULL);
72 }
73 return enumerator_create_empty();
74 }
75
76 /**
77 * Implementation of attr_provider_t.destroy
78 */
79 static void destroy(private_attr_provider_t *this)
80 {
81 attribute_entry_t *entry;
82
83 while (this->attributes->remove_last(this->attributes,
84 (void**)&entry) == SUCCESS)
85 {
86 free(entry->value.ptr);
87 free(entry);
88 }
89 this->attributes->destroy(this->attributes);
90 free(this);
91 }
92
93 /**
94 * Add an attribute entry to the list
95 */
96 static void add_legacy_entry(private_attr_provider_t *this, char *key, int nr,
97 configuration_attribute_type_t type)
98 {
99 attribute_entry_t *entry;
100 host_t *host;
101 char *str;
102
103 str = lib->settings->get_str(lib->settings, "charon.%s%d", NULL, 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 };
148
149 /**
150 * Load (numerical) entries from the plugins.attr namespace
151 */
152 static void load_entries(private_attr_provider_t *this)
153 {
154 enumerator_t *enumerator, *tokens;
155 char *key, *value, *token;
156
157 enumerator = lib->settings->create_key_value_enumerator(lib->settings,
158 "charon.plugins.attr");
159 while (enumerator->enumerate(enumerator, &key, &value))
160 {
161 configuration_attribute_type_t type;
162 attribute_entry_t *entry;
163 host_t *host;
164 int i;
165
166 type = atoi(key);
167 tokens = enumerator_create_token(value, ",", " ");
168 while (tokens->enumerate(tokens, &token))
169 {
170 host = host_create_from_string(token, 0);
171 if (!host)
172 {
173 DBG1(DBG_CFG, "invalid host in key %s: %s", key, token);
174 continue;
175 }
176 if (!type)
177 {
178 for (i = 0; i < countof(keys); i++)
179 {
180 if (streq(key, keys[i].name))
181 {
182 if (host->get_family(host) == AF_INET)
183 {
184 type = keys[i].v4;
185 }
186 else
187 {
188 type = keys[i].v6;
189 }
190 }
191 }
192 if (!type)
193 {
194 DBG1(DBG_CFG, "mapping attribute type %s failed", key);
195 break;
196 }
197 }
198 entry = malloc_thing(attribute_entry_t);
199 entry->type = type;
200 entry->value = chunk_clone(host->get_address(host));
201 host->destroy(host);
202 this->attributes->insert_last(this->attributes, entry);
203 }
204 tokens->destroy(tokens);
205 }
206 enumerator->destroy(enumerator);
207 }
208
209 /*
210 * see header file
211 */
212 attr_provider_t *attr_provider_create(database_t *db)
213 {
214 private_attr_provider_t *this;
215 int i;
216
217 this = malloc_thing(private_attr_provider_t);
218
219 this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *, host_t *))return_null;
220 this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_t*))return_false;
221 this->public.provider.create_attribute_enumerator = (enumerator_t*(*)(attribute_provider_t*, identification_t *id, host_t *vip))create_attribute_enumerator;
222 this->public.destroy = (void(*)(attr_provider_t*))destroy;
223
224 this->attributes = linked_list_create();
225
226 for (i = 1; i <= SERVER_MAX; i++)
227 {
228 add_legacy_entry(this, "dns", i, INTERNAL_IP4_DNS);
229 add_legacy_entry(this, "nbns", i, INTERNAL_IP4_NBNS);
230 }
231
232 load_entries(this);
233
234 return &this->public;
235 }
236