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