Return to tnc_imv.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libtnccs / plugins / tnc_imv |
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: }