5e06d9eb451a4119b835703820f3fdd31aa0c7b3
[strongswan.git] / src / libcharon / plugins / tnc_imc / tnc_imc_manager.c
1 /*
2 * Copyright (C) 2006 Mike McCauley
3 * Copyright (C) 2010-2011 Andreas Steffen
4 * HSR 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 "tnc_imc_manager.h"
18 #include "tnc_imc.h"
19
20 #include <tncifimc.h>
21
22 #include <utils/linked_list.h>
23 #include <debug.h>
24
25 typedef struct private_tnc_imc_manager_t private_tnc_imc_manager_t;
26
27 /**
28 * Private data of an imc_manager_t object.
29 */
30 struct private_tnc_imc_manager_t {
31
32 /**
33 * Public members of imc_manager_t.
34 */
35 imc_manager_t public;
36
37 /**
38 * Linked list of IMCs
39 */
40 linked_list_t *imcs;
41
42 /**
43 * Next IMC ID to be assigned
44 */
45 TNC_IMCID next_imc_id;
46 };
47
48 METHOD(imc_manager_t, add, bool,
49 private_tnc_imc_manager_t *this, imc_t *imc)
50 {
51 TNC_Version version;
52
53 /* Initialize the module */
54 imc->set_id(imc, this->next_imc_id);
55 if (imc->initialize(imc->get_id(imc), TNC_IFIMC_VERSION_1,
56 TNC_IFIMC_VERSION_1, &version) != TNC_RESULT_SUCCESS)
57 {
58 DBG1(DBG_TNC, "IMC \"%s\" failed to initialize", imc->get_name(imc));
59 return FALSE;
60 }
61 this->imcs->insert_last(this->imcs, imc);
62 this->next_imc_id++;
63
64 if (imc->provide_bind_function(imc->get_id(imc), TNC_TNCC_BindFunction)
65 != TNC_RESULT_SUCCESS)
66 {
67 DBG1(DBG_TNC, "IMC \"%s\" failed to obtain bind function",
68 imc->get_name(imc));
69 this->imcs->remove_last(this->imcs, (void**)&imc);
70 return FALSE;
71 }
72
73 return TRUE;
74 }
75
76 METHOD(imc_manager_t, remove_, imc_t*,
77 private_tnc_imc_manager_t *this, TNC_IMCID id)
78 {
79 enumerator_t *enumerator;
80 imc_t *imc, *removed_imc = NULL;
81
82 enumerator = this->imcs->create_enumerator(this->imcs);
83 while (enumerator->enumerate(enumerator, &imc))
84 {
85 if (id == imc->get_id(imc))
86 {
87 this->imcs->remove_at(this->imcs, enumerator);
88 removed_imc = imc;
89 break;
90 }
91 }
92 enumerator->destroy(enumerator);
93
94 return removed_imc;
95 }
96
97 METHOD(imc_manager_t, load, bool,
98 private_tnc_imc_manager_t *this, char *name, char *path)
99 {
100 imc_t *imc;
101
102 imc = tnc_imc_create(name, path);
103 if (!imc)
104 {
105 free(name);
106 free(path);
107 return FALSE;
108 }
109 if (!add(this, imc))
110 {
111 if (imc->terminate &&
112 imc->terminate(imc->get_id(imc)) != TNC_RESULT_SUCCESS)
113 {
114 DBG1(DBG_TNC, "IMC \"%s\" not terminated successfully",
115 imc->get_name(imc));
116 }
117 imc->destroy(imc);
118 return FALSE;
119 }
120 DBG1(DBG_TNC, "IMC %u \"%s\" loaded from '%s'", imc->get_id(imc), name, path);
121 return TRUE;
122 }
123
124 METHOD(imc_manager_t, is_registered, bool,
125 private_tnc_imc_manager_t *this, TNC_IMCID id)
126 {
127 enumerator_t *enumerator;
128 imc_t *imc;
129 bool found = FALSE;
130
131 enumerator = this->imcs->create_enumerator(this->imcs);
132 while (enumerator->enumerate(enumerator, &imc))
133 {
134 if (imc->has_id(imc, id))
135 {
136 found = TRUE;
137 break;
138 }
139 }
140 enumerator->destroy(enumerator);
141
142 return found;
143 }
144
145 METHOD(imc_manager_t, reserve_id, bool,
146 private_tnc_imc_manager_t *this, TNC_IMCID id, TNC_UInt32 *new_id)
147 {
148 enumerator_t *enumerator;
149 imc_t *imc;
150 bool found = FALSE;
151
152 enumerator = this->imcs->create_enumerator(this->imcs);
153 while (enumerator->enumerate(enumerator, &imc))
154 {
155 if (imc->get_id(imc))
156 {
157 imc->add_id(imc, this->next_imc_id++);
158 found = TRUE;
159 break;
160 }
161 }
162 enumerator->destroy(enumerator);
163
164 return found;
165 }
166
167 METHOD(imc_manager_t, get_preferred_language, char*,
168 private_tnc_imc_manager_t *this)
169 {
170 return lib->settings->get_str(lib->settings,
171 "charon.plugins.tnc-imc.preferred_language", "en");
172 }
173
174 METHOD(imc_manager_t, notify_connection_change, void,
175 private_tnc_imc_manager_t *this, TNC_ConnectionID id,
176 TNC_ConnectionState state)
177 {
178 enumerator_t *enumerator;
179 imc_t *imc;
180
181 enumerator = this->imcs->create_enumerator(this->imcs);
182 while (enumerator->enumerate(enumerator, &imc))
183 {
184 if (imc->notify_connection_change)
185 {
186 imc->notify_connection_change(imc->get_id(imc), id, state);
187 }
188 }
189 enumerator->destroy(enumerator);
190 }
191
192 METHOD(imc_manager_t, begin_handshake, void,
193 private_tnc_imc_manager_t *this, TNC_ConnectionID id)
194 {
195 enumerator_t *enumerator;
196 imc_t *imc;
197
198 enumerator = this->imcs->create_enumerator(this->imcs);
199 while (enumerator->enumerate(enumerator, &imc))
200 {
201 imc->begin_handshake(imc->get_id(imc), id);
202 }
203 enumerator->destroy(enumerator);
204 }
205
206 METHOD(imc_manager_t, set_message_types, TNC_Result,
207 private_tnc_imc_manager_t *this, TNC_IMCID id,
208 TNC_MessageTypeList supported_types,
209 TNC_UInt32 type_count)
210 {
211 enumerator_t *enumerator;
212 imc_t *imc;
213 TNC_Result result = TNC_RESULT_FATAL;
214
215 enumerator = this->imcs->create_enumerator(this->imcs);
216 while (enumerator->enumerate(enumerator, &imc))
217 {
218 if (id == imc->get_id(imc))
219 {
220 imc->set_message_types(imc, supported_types, type_count);
221 result = TNC_RESULT_SUCCESS;
222 break;
223 }
224 }
225 enumerator->destroy(enumerator);
226 return result;
227 }
228
229 METHOD(imc_manager_t, set_message_types_long, TNC_Result,
230 private_tnc_imc_manager_t *this, TNC_IMCID id,
231 TNC_VendorIDList supported_vids,
232 TNC_MessageSubtypeList supported_subtypes,
233 TNC_UInt32 type_count)
234 {
235 enumerator_t *enumerator;
236 imc_t *imc;
237 TNC_Result result = TNC_RESULT_FATAL;
238
239 enumerator = this->imcs->create_enumerator(this->imcs);
240 while (enumerator->enumerate(enumerator, &imc))
241 {
242 if (id == imc->get_id(imc))
243 {
244 imc->set_message_types_long(imc, supported_vids, supported_subtypes,
245 type_count);
246 result = TNC_RESULT_SUCCESS;
247 break;
248 }
249 }
250 enumerator->destroy(enumerator);
251 return result;
252 }
253
254 METHOD(imc_manager_t, receive_message, void,
255 private_tnc_imc_manager_t *this, TNC_ConnectionID connection_id,
256 TNC_BufferReference message,
257 TNC_UInt32 message_len,
258 TNC_MessageType message_type)
259 {
260 bool type_supported = FALSE;
261 enumerator_t *enumerator;
262 imc_t *imc;
263
264 enumerator = this->imcs->create_enumerator(this->imcs);
265 while (enumerator->enumerate(enumerator, &imc))
266 {
267 if (imc->receive_message && imc->type_supported(imc, message_type))
268 {
269 type_supported = TRUE;
270 imc->receive_message(imc->get_id(imc), connection_id,
271 message, message_len, message_type);
272 }
273 }
274 enumerator->destroy(enumerator);
275 if (!type_supported)
276 {
277 DBG2(DBG_TNC, "message type 0x%08x not supported by any IMC", message_type);
278 }
279 }
280
281 METHOD(imc_manager_t, batch_ending, void,
282 private_tnc_imc_manager_t *this, TNC_ConnectionID id)
283 {
284 enumerator_t *enumerator;
285 imc_t *imc;
286
287 enumerator = this->imcs->create_enumerator(this->imcs);
288 while (enumerator->enumerate(enumerator, &imc))
289 {
290 if (imc->batch_ending)
291 {
292 imc->batch_ending(imc->get_id(imc), id);
293 }
294 }
295 enumerator->destroy(enumerator);
296 }
297
298 METHOD(imc_manager_t, destroy, void,
299 private_tnc_imc_manager_t *this)
300 {
301 imc_t *imc;
302
303 while (this->imcs->remove_last(this->imcs, (void**)&imc) == SUCCESS)
304 {
305 if (imc->terminate &&
306 imc->terminate(imc->get_id(imc)) != TNC_RESULT_SUCCESS)
307 {
308 DBG1(DBG_TNC, "IMC \"%s\" not terminated successfully",
309 imc->get_name(imc));
310 }
311 imc->destroy(imc);
312 }
313 this->imcs->destroy(this->imcs);
314 free(this);
315 }
316
317 /**
318 * Described in header.
319 */
320 imc_manager_t* tnc_imc_manager_create(void)
321 {
322 private_tnc_imc_manager_t *this;
323
324 INIT(this,
325 .public = {
326 .add = _add,
327 .remove = _remove_, /* avoid name conflict with stdio.h */
328 .load = _load,
329 .is_registered = _is_registered,
330 .reserve_id = _reserve_id,
331 .get_preferred_language = _get_preferred_language,
332 .notify_connection_change = _notify_connection_change,
333 .begin_handshake = _begin_handshake,
334 .set_message_types = _set_message_types,
335 .set_message_types_long = _set_message_types_long,
336 .receive_message = _receive_message,
337 .batch_ending = _batch_ending,
338 .destroy = _destroy,
339 },
340 .imcs = linked_list_create(),
341 .next_imc_id = 1,
342 );
343
344 return &this->public;
345 }