Annotation of embedaddon/strongswan/src/libtnccs/plugins/tnc_imc/tnc_imc.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_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>