Annotation of embedaddon/strongswan/src/libtnccs/plugins/tnc_imv/tnc_imv.c, revision 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>