Moved data structures to new collections subfolder
[strongswan.git] / src / libcharon / plugins / tnc_imc / tnc_imc.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.h"
18
19 #include <dlfcn.h>
20
21 #include <tncif_pa_subtypes.h>
22
23 #include <debug.h>
24 #include <library.h>
25 #include <collections/linked_list.h>
26 #include <threading/mutex.h>
27
28 typedef struct private_tnc_imc_t private_tnc_imc_t;
29
30 /**
31 * Private data of an imc_t object.
32 */
33 struct private_tnc_imc_t {
34
35 /**
36 * Public members of imc_t.
37 */
38 imc_t public;
39
40 /**
41 * Path of loaded IMC
42 */
43 char *path;
44
45 /**
46 * Name of loaded IMC
47 */
48 char *name;
49
50 /**
51 * Handle of loaded IMC
52 */
53 void *handle;
54
55 /**
56 * ID of loaded IMC
57 */
58 TNC_IMCID id;
59
60 /**
61 * list of additional IMC IDs
62 */
63 linked_list_t *additional_ids;
64
65 /**
66 * List of message types supported by IMC - Vendor ID part
67 */
68 TNC_VendorIDList supported_vids;
69
70 /**
71 * List of message types supported by IMC - Subtype part
72 */
73 TNC_MessageSubtypeList supported_subtypes;
74
75 /**
76 * Number of supported message types
77 */
78 TNC_UInt32 type_count;
79
80 /**
81 * mutex to lock the imc_t object
82 */
83 mutex_t *mutex;
84 };
85
86 METHOD(imc_t, set_id, void,
87 private_tnc_imc_t *this, TNC_IMCID id)
88 {
89 this->id = id;
90 }
91
92 METHOD(imc_t, get_id, TNC_IMCID,
93 private_tnc_imc_t *this)
94 {
95 return this->id;
96 }
97
98 METHOD(imc_t, add_id, void,
99 private_tnc_imc_t *this, TNC_IMCID id)
100 {
101 void *pointer;
102
103 /* store the scalar value in the pointer */
104 pointer = (void*)id;
105 this->additional_ids->insert_last(this->additional_ids, pointer);
106 }
107
108 METHOD(imc_t, has_id, bool,
109 private_tnc_imc_t *this, TNC_IMCID id)
110 {
111 enumerator_t *enumerator;
112 TNC_IMCID additional_id;
113 void *pointer;
114 bool found = FALSE;
115
116 /* check primary IMC ID */
117 if (id == this->id)
118 {
119 return TRUE;
120 }
121
122 /* return if there are no additional IMC IDs */
123 if (this->additional_ids->get_count(this->additional_ids) == 0)
124 {
125 return FALSE;
126 }
127
128 /* check additional IMC IDs */
129 enumerator = this->additional_ids->create_enumerator(this->additional_ids);
130 while (enumerator->enumerate(enumerator, &pointer))
131 {
132 /* interpret pointer as scalar value */
133 additional_id = (TNC_UInt32)pointer;
134
135 if (id == additional_id)
136 {
137 found = TRUE;
138 break;
139 }
140 }
141 enumerator->destroy(enumerator);
142
143 return found;
144 }
145
146 METHOD(imc_t, get_name, char*,
147 private_tnc_imc_t *this)
148 {
149 return this->name;
150 }
151
152 METHOD(imc_t, set_message_types, void,
153 private_tnc_imc_t *this, TNC_MessageTypeList supported_types,
154 TNC_UInt32 type_count)
155 {
156 char buf[BUF_LEN];
157 char *pos = buf;
158 int len = sizeof(buf);
159 int i, written;
160 size_t size;
161 TNC_VendorID vid;
162 TNC_MessageSubtype subtype;
163 enum_name_t *pa_subtype_names;
164
165 /* lock the imc_t instance */
166 this->mutex->lock(this->mutex);
167
168 /* Free existing VendorID and MessageSubtype lists */
169 free(this->supported_vids);
170 this->supported_vids = NULL;
171 free(this->supported_subtypes);
172 this->supported_subtypes = NULL;
173
174 /* Store the new MessageType list */
175 this->type_count = type_count;
176 if (type_count && supported_types)
177 {
178 size = type_count * sizeof(TNC_VendorID);
179 this->supported_vids = malloc(size);
180 size = type_count * sizeof(TNC_MessageSubtype);
181 this->supported_subtypes = malloc(size);
182
183 for (i = 0; i < type_count; i++)
184 {
185 vid = (supported_types[i] >> 8) & TNC_VENDORID_ANY;
186 subtype = supported_types[i] & TNC_SUBTYPE_ANY;
187
188 pa_subtype_names = get_pa_subtype_names(vid);
189 if (pa_subtype_names)
190 {
191 written = snprintf(pos, len," '%N/%N' 0x%06x/0x%02x",
192 pen_names, vid, pa_subtype_names, subtype,
193 vid, subtype);
194 }
195 else
196 {
197 written = snprintf(pos, len," '%N' 0x%06x/0x%02x",
198 pen_names, vid, vid, subtype);
199 }
200 if (written >= len)
201 {
202 break;
203 }
204 pos += written;
205 len -= written;
206
207 this->supported_vids[i] = vid;
208 this->supported_subtypes[i] = subtype;
209 }
210 }
211 *pos = '\0';
212 DBG2(DBG_TNC, "IMC %u supports %u message type%s:%s",
213 this->id, type_count, (type_count == 1) ? "":"s", buf);
214
215 /* unlock the imc_t instance */
216 this->mutex->unlock(this->mutex);
217 }
218
219 METHOD(imc_t, set_message_types_long, void,
220 private_tnc_imc_t *this, TNC_VendorIDList supported_vids,
221 TNC_MessageSubtypeList supported_subtypes, TNC_UInt32 type_count)
222 {
223 char buf[BUF_LEN];
224 char *pos = buf;
225 int len = sizeof(buf);
226 int i, written;
227 size_t size;
228 TNC_VendorID vid;
229 TNC_MessageSubtype subtype;
230 enum_name_t *pa_subtype_names;
231
232 /* lock the imc_t instance */
233 this->mutex->lock(this->mutex);
234
235 /* Free existing VendorID and MessageSubtype lists */
236 free(this->supported_vids);
237 this->supported_vids = NULL;
238 free(this->supported_subtypes);
239 this->supported_subtypes = NULL;
240
241 /* Store the new MessageType list */
242 this->type_count = type_count;
243 if (type_count && supported_vids && supported_subtypes)
244 {
245 size = type_count * sizeof(TNC_VendorID);
246 this->supported_vids = malloc(size);
247 memcpy(this->supported_vids, supported_vids, size);
248 size = type_count * sizeof(TNC_MessageSubtype);
249 this->supported_subtypes = malloc(size);
250 memcpy(this->supported_subtypes, supported_subtypes, size);
251
252 for (i = 0; i < type_count; i++)
253 {
254 vid = supported_vids[i];
255 subtype = supported_subtypes[i];
256
257 pa_subtype_names = get_pa_subtype_names(vid);
258 if (pa_subtype_names)
259 {
260 written = snprintf(pos, len," '%N/%N' 0x%06x/0x%08x",
261 pen_names, vid, pa_subtype_names, subtype,
262 vid, subtype);
263 }
264 else
265 {
266 written = snprintf(pos, len," '%N' 0x%06x/0x%08x",
267 pen_names, vid, vid, subtype);
268 }
269 if (written >= len)
270 {
271 break;
272 }
273 pos += written;
274 len -= written;
275 }
276 }
277 *pos = '\0';
278 DBG2(DBG_TNC, "IMC %u supports %u message type%s:%s",
279 this->id, type_count, (type_count == 1) ? "":"s", buf);
280
281 /* unlock the imc_t instance */
282 this->mutex->unlock(this->mutex);
283 }
284
285 METHOD(imc_t, type_supported, bool,
286 private_tnc_imc_t *this, TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype)
287 {
288 TNC_VendorID vid;
289 TNC_MessageSubtype subtype;
290 int i;
291
292 for (i = 0; i < this->type_count; i++)
293 {
294 vid = this->supported_vids[i];
295 subtype = this->supported_subtypes[i];
296
297 if ((vid == TNC_VENDORID_ANY && subtype == TNC_SUBTYPE_ANY) ||
298 (vid == msg_vid && (subtype == TNC_SUBTYPE_ANY ||
299 subtype == msg_subtype)))
300 {
301 return TRUE;
302 }
303 }
304 return FALSE;
305 }
306
307 METHOD(imc_t, destroy, void,
308 private_tnc_imc_t *this)
309 {
310 dlclose(this->handle);
311 this->mutex->destroy(this->mutex);
312 this->additional_ids->destroy(this->additional_ids);
313 free(this->supported_vids);
314 free(this->supported_subtypes);
315 free(this->name);
316 free(this->path);
317 free(this);
318 }
319
320 /**
321 * Described in header.
322 */
323 imc_t* tnc_imc_create(char *name, char *path)
324 {
325 private_tnc_imc_t *this;
326
327 INIT(this,
328 .public = {
329 .set_id = _set_id,
330 .get_id = _get_id,
331 .add_id = _add_id,
332 .has_id = _has_id,
333 .get_name = _get_name,
334 .set_message_types = _set_message_types,
335 .set_message_types_long = _set_message_types_long,
336 .type_supported = _type_supported,
337 .destroy = _destroy,
338 },
339 .name = name,
340 .path = path,
341 .additional_ids = linked_list_create(),
342 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
343 );
344
345 this->handle = dlopen(path, RTLD_LAZY);
346 if (!this->handle)
347 {
348 DBG1(DBG_TNC, "IMC \"%s\" failed to load: %s", name, dlerror());
349 free(this);
350 return NULL;
351 }
352
353 this->public.initialize = dlsym(this->handle, "TNC_IMC_Initialize");
354 if (!this->public.initialize)
355 {
356 DBG1(DBG_TNC, "could not resolve TNC_IMC_Initialize in %s: %s\n",
357 path, dlerror());
358 dlclose(this->handle);
359 free(this);
360 return NULL;
361 }
362 this->public.notify_connection_change =
363 dlsym(this->handle, "TNC_IMC_NotifyConnectionChange");
364 this->public.begin_handshake = dlsym(this->handle, "TNC_IMC_BeginHandshake");
365 if (!this->public.begin_handshake)
366 {
367 DBG1(DBG_TNC, "could not resolve TNC_IMC_BeginHandshake in %s: %s\n",
368 path, dlerror());
369 dlclose(this->handle);
370 free(this);
371 return NULL;
372 }
373 this->public.receive_message =
374 dlsym(this->handle, "TNC_IMC_ReceiveMessage");
375 this->public.receive_message_long =
376 dlsym(this->handle, "TNC_IMC_ReceiveMessageLong");
377 this->public.batch_ending =
378 dlsym(this->handle, "TNC_IMC_BatchEnding");
379 this->public.terminate =
380 dlsym(this->handle, "TNC_IMC_Terminate");
381 this->public.provide_bind_function =
382 dlsym(this->handle, "TNC_IMC_ProvideBindFunction");
383 if (!this->public.provide_bind_function)
384 {
385 DBG1(DBG_TNC, "could not resolve TNC_IMC_ProvideBindFunction in %s: %s\n",
386 path, dlerror());
387 dlclose(this->handle);
388 free(this);
389 return NULL;
390 }
391
392 return &this->public;
393 }