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