Return to tnc_imv_manager.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_manager.h" 17: #include "tnc_imv.h" 18: #include "tnc_imv_recommendations.h" 19: 20: #include <tncifimv.h> 21: 22: #include <sys/types.h> 23: #include <sys/stat.h> 24: #include <unistd.h> 25: #include <errno.h> 26: #include <fcntl.h> 27: 28: #include <utils/debug.h> 29: #include <threading/rwlock.h> 30: #include <threading/mutex.h> 31: #include <collections/linked_list.h> 32: 33: typedef struct private_tnc_imv_manager_t private_tnc_imv_manager_t; 34: 35: /** 36: * Private data of an imv_manager_t object. 37: */ 38: struct private_tnc_imv_manager_t { 39: 40: /** 41: * Public members of imv_manager_t. 42: */ 43: imv_manager_t public; 44: 45: /** 46: * Linked list of IMVs 47: */ 48: linked_list_t *imvs; 49: 50: /** 51: * Lock for IMV list 52: */ 53: rwlock_t *lock; 54: 55: /** 56: * Next IMV ID to be assigned 57: */ 58: TNC_IMVID next_imv_id; 59: 60: /** 61: * Mutex to access next IMV ID 62: */ 63: mutex_t *id_mutex; 64: 65: /** 66: * Policy defining how to derive final recommendation from individual ones 67: */ 68: recommendation_policy_t policy; 69: }; 70: 71: METHOD(imv_manager_t, add, bool, 72: private_tnc_imv_manager_t *this, imv_t *imv) 73: { 74: TNC_Version version; 75: TNC_IMVID imv_id; 76: 77: this->id_mutex->lock(this->id_mutex); 78: imv_id = this->next_imv_id++; 79: this->id_mutex->unlock(this->id_mutex); 80: 81: imv->set_id(imv, imv_id); 82: if (imv->initialize(imv_id, TNC_IFIMV_VERSION_1, 83: TNC_IFIMV_VERSION_1, &version) != TNC_RESULT_SUCCESS) 84: { 85: DBG1(DBG_TNC, "IMV \"%s\" failed to initialize", imv->get_name(imv)); 86: return FALSE; 87: } 88: this->lock->write_lock(this->lock); 89: this->imvs->insert_last(this->imvs, imv); 90: this->lock->unlock(this->lock); 91: 92: if (imv->provide_bind_function(imv->get_id(imv), 93: TNC_TNCS_BindFunction) != TNC_RESULT_SUCCESS) 94: { 95: if (imv->terminate) 96: { 97: imv->terminate(imv->get_id(imv)); 98: } 99: DBG1(DBG_TNC, "IMV \"%s\" failed to obtain bind function", 100: imv->get_name(imv)); 101: this->lock->write_lock(this->lock); 102: this->imvs->remove_last(this->imvs, (void**)&imv); 103: this->lock->unlock(this->lock); 104: return FALSE; 105: } 106: return TRUE; 107: } 108: 109: METHOD(imv_manager_t, remove_, imv_t*, 110: private_tnc_imv_manager_t *this, TNC_IMVID id) 111: { 112: enumerator_t *enumerator; 113: imv_t *imv, *removed_imv = NULL; 114: 115: this->lock->write_lock(this->lock); 116: enumerator = this->imvs->create_enumerator(this->imvs); 117: while (enumerator->enumerate(enumerator, &imv)) 118: { 119: if (id == imv->get_id(imv)) 120: { 121: this->imvs->remove_at(this->imvs, enumerator); 122: removed_imv = imv; 123: break; 124: } 125: } 126: enumerator->destroy(enumerator); 127: this->lock->unlock(this->lock); 128: 129: return removed_imv; 130: } 131: 132: METHOD(imv_manager_t, load, bool, 133: private_tnc_imv_manager_t *this, char *name, char *path) 134: { 135: imv_t *imv; 136: 137: imv = tnc_imv_create(name, path); 138: if (!imv) 139: { 140: return FALSE; 141: } 142: if (!add(this, imv)) 143: { 144: imv->destroy(imv); 145: return FALSE; 146: } 147: DBG1(DBG_TNC, "IMV %u \"%s\" loaded from '%s'", imv->get_id(imv), name, path); 148: return TRUE; 149: } 150: 151: METHOD(imv_manager_t, load_from_functions, bool, 152: private_tnc_imv_manager_t *this, char *name, 153: TNC_IMV_InitializePointer initialize, 154: TNC_IMV_NotifyConnectionChangePointer notify_connection_change, 155: TNC_IMV_ReceiveMessagePointer receive_message, 156: TNC_IMV_ReceiveMessageLongPointer receive_message_long, 157: TNC_IMV_SolicitRecommendationPointer solicit_recommendation, 158: TNC_IMV_BatchEndingPointer batch_ending, 159: TNC_IMV_TerminatePointer terminate, 160: TNC_IMV_ProvideBindFunctionPointer provide_bind_function) 161: { 162: imv_t *imv; 163: 164: imv = tnc_imv_create_from_functions(name, 165: initialize,notify_connection_change, 166: receive_message, receive_message_long, 167: solicit_recommendation, batch_ending, 168: terminate, provide_bind_function); 169: if (!imv) 170: { 171: return FALSE; 172: } 173: if (!add(this, imv)) 174: { 175: imv->destroy(imv); 176: return FALSE; 177: } 178: DBG1(DBG_TNC, "IMV %u \"%s\" loaded", imv->get_id(imv), name); 179: return TRUE; 180: } 181: 182: METHOD(imv_manager_t, is_registered, bool, 183: private_tnc_imv_manager_t *this, TNC_IMVID id) 184: { 185: enumerator_t *enumerator; 186: imv_t *imv; 187: bool found = FALSE; 188: 189: this->lock->read_lock(this->lock); 190: enumerator = this->imvs->create_enumerator(this->imvs); 191: while (enumerator->enumerate(enumerator, &imv)) 192: { 193: if (imv->has_id(imv, id)) 194: { 195: found = TRUE; 196: break; 197: } 198: } 199: enumerator->destroy(enumerator); 200: this->lock->unlock(this->lock); 201: 202: return found; 203: } 204: 205: METHOD(imv_manager_t, reserve_id, bool, 206: private_tnc_imv_manager_t *this, TNC_IMVID id, TNC_UInt32 *new_id) 207: { 208: enumerator_t *enumerator; 209: imv_t *imv; 210: bool found = FALSE; 211: 212: this->lock->read_lock(this->lock); 213: enumerator = this->imvs->create_enumerator(this->imvs); 214: while (enumerator->enumerate(enumerator, &imv)) 215: { 216: if (id == imv->get_id(imv)) 217: { 218: found = TRUE; 219: this->id_mutex->lock(this->id_mutex); 220: *new_id = this->next_imv_id++; 221: this->id_mutex->unlock(this->id_mutex); 222: imv->add_id(imv, *new_id); 223: DBG2(DBG_TNC, "additional ID %u reserved for IMV with primary ID %u", 224: *new_id, id); 225: break; 226: } 227: } 228: enumerator->destroy(enumerator); 229: this->lock->unlock(this->lock); 230: 231: return found; 232: } 233: 234: METHOD(imv_manager_t, get_recommendation_policy, recommendation_policy_t, 235: private_tnc_imv_manager_t *this) 236: { 237: return this->policy; 238: } 239: 240: METHOD(imv_manager_t, create_recommendations, recommendations_t*, 241: private_tnc_imv_manager_t *this) 242: { 243: return tnc_imv_recommendations_create(this->imvs); 244: } 245: 246: 247: METHOD(imv_manager_t, notify_connection_change, void, 248: private_tnc_imv_manager_t *this, TNC_ConnectionID id, 249: TNC_ConnectionState state) 250: { 251: enumerator_t *enumerator; 252: imv_t *imv; 253: 254: this->lock->read_lock(this->lock); 255: enumerator = this->imvs->create_enumerator(this->imvs); 256: while (enumerator->enumerate(enumerator, &imv)) 257: { 258: if (imv->notify_connection_change) 259: { 260: imv->notify_connection_change(imv->get_id(imv), id, state); 261: } 262: } 263: enumerator->destroy(enumerator); 264: this->lock->unlock(this->lock); 265: } 266: 267: METHOD(imv_manager_t, set_message_types, TNC_Result, 268: private_tnc_imv_manager_t *this, TNC_IMVID id, 269: TNC_MessageTypeList supported_types, 270: TNC_UInt32 type_count) 271: { 272: enumerator_t *enumerator; 273: imv_t *imv; 274: TNC_Result result = TNC_RESULT_FATAL; 275: 276: this->lock->read_lock(this->lock); 277: enumerator = this->imvs->create_enumerator(this->imvs); 278: while (enumerator->enumerate(enumerator, &imv)) 279: { 280: if (id == imv->get_id(imv)) 281: { 282: imv->set_message_types(imv, supported_types, type_count); 283: result = TNC_RESULT_SUCCESS; 284: break; 285: } 286: } 287: enumerator->destroy(enumerator); 288: this->lock->unlock(this->lock); 289: return result; 290: } 291: 292: METHOD(imv_manager_t, set_message_types_long, TNC_Result, 293: private_tnc_imv_manager_t *this, TNC_IMVID id, 294: TNC_VendorIDList supported_vids, 295: TNC_MessageSubtypeList supported_subtypes, 296: TNC_UInt32 type_count) 297: { 298: enumerator_t *enumerator; 299: imv_t *imv; 300: TNC_Result result = TNC_RESULT_FATAL; 301: 302: this->lock->read_lock(this->lock); 303: enumerator = this->imvs->create_enumerator(this->imvs); 304: while (enumerator->enumerate(enumerator, &imv)) 305: { 306: if (id == imv->get_id(imv)) 307: { 308: imv->set_message_types_long(imv, supported_vids, supported_subtypes, 309: type_count); 310: result = TNC_RESULT_SUCCESS; 311: break; 312: } 313: } 314: enumerator->destroy(enumerator); 315: this->lock->unlock(this->lock); 316: return result; 317: } 318: 319: METHOD(imv_manager_t, solicit_recommendation, void, 320: private_tnc_imv_manager_t *this, TNC_ConnectionID id) 321: { 322: enumerator_t *enumerator; 323: imv_t *imv; 324: 325: this->lock->read_lock(this->lock); 326: enumerator = this->imvs->create_enumerator(this->imvs); 327: while (enumerator->enumerate(enumerator, &imv)) 328: { 329: imv->solicit_recommendation(imv->get_id(imv), id); 330: } 331: enumerator->destroy(enumerator); 332: this->lock->unlock(this->lock); 333: } 334: 335: METHOD(imv_manager_t, receive_message, void, 336: private_tnc_imv_manager_t *this, TNC_ConnectionID connection_id, 337: bool excl, 338: TNC_BufferReference msg, 339: TNC_UInt32 msg_len, 340: TNC_VendorID msg_vid, 341: TNC_MessageSubtype msg_subtype, 342: TNC_UInt32 src_imc_id, 343: TNC_UInt32 dst_imv_id) 344: { 345: bool type_supported = FALSE; 346: TNC_MessageType msg_type; 347: TNC_UInt32 msg_flags; 348: enumerator_t *enumerator; 349: imv_t *imv; 350: 351: msg_type = (msg_vid << 8) | msg_subtype; 352: 353: this->lock->read_lock(this->lock); 354: enumerator = this->imvs->create_enumerator(this->imvs); 355: while (enumerator->enumerate(enumerator, &imv)) 356: { 357: if (imv->type_supported(imv, msg_vid, msg_subtype) && 358: (!excl || (excl && imv->has_id(imv, dst_imv_id)))) 359: { 360: if (imv->receive_message_long && src_imc_id) 361: { 362: type_supported = TRUE; 363: msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0; 364: imv->receive_message_long(imv->get_id(imv), connection_id, 365: msg_flags, msg, msg_len, msg_vid, msg_subtype, 366: src_imc_id, dst_imv_id); 367: 368: } 369: else if (imv->receive_message && msg_vid <= TNC_VENDORID_ANY && 370: msg_subtype <= TNC_SUBTYPE_ANY) 371: { 372: type_supported = TRUE; 373: msg_type = (msg_vid << 8) | msg_subtype; 374: imv->receive_message(imv->get_id(imv), connection_id, 375: msg, msg_len, msg_type); 376: } 377: } 378: } 379: enumerator->destroy(enumerator); 380: this->lock->unlock(this->lock); 381: 382: if (!type_supported) 383: { 384: DBG2(DBG_TNC, "message type 0x%06x/0x%08x not supported by any IMV", 385: msg_vid, msg_subtype); 386: } 387: } 388: 389: METHOD(imv_manager_t, batch_ending, void, 390: private_tnc_imv_manager_t *this, TNC_ConnectionID id) 391: { 392: enumerator_t *enumerator; 393: imv_t *imv; 394: 395: this->lock->read_lock(this->lock); 396: enumerator = this->imvs->create_enumerator(this->imvs); 397: while (enumerator->enumerate(enumerator, &imv)) 398: { 399: if (imv->batch_ending) 400: { 401: imv->batch_ending(imv->get_id(imv), id); 402: } 403: } 404: enumerator->destroy(enumerator); 405: this->lock->unlock(this->lock); 406: } 407: 408: METHOD(imv_manager_t, destroy, void, 409: private_tnc_imv_manager_t *this) 410: { 411: imv_t *imv; 412: 413: while (this->imvs->remove_last(this->imvs, (void**)&imv) == SUCCESS) 414: { 415: if (imv->terminate && 416: imv->terminate(imv->get_id(imv)) != TNC_RESULT_SUCCESS) 417: { 418: DBG1(DBG_TNC, "IMV \"%s\" not terminated successfully", 419: imv->get_name(imv)); 420: } 421: imv->destroy(imv); 422: } 423: this->imvs->destroy(this->imvs); 424: this->lock->destroy(this->lock); 425: this->id_mutex->destroy(this->id_mutex); 426: free(this); 427: } 428: 429: /** 430: * Described in header. 431: */ 432: imv_manager_t* tnc_imv_manager_create(void) 433: { 434: private_tnc_imv_manager_t *this; 435: char *polname; 436: 437: INIT(this, 438: .public = { 439: .add = _add, 440: .remove = _remove_, /* avoid name conflict with stdio.h */ 441: .load = _load, 442: .load_from_functions = _load_from_functions, 443: .is_registered = _is_registered, 444: .reserve_id = _reserve_id, 445: .get_recommendation_policy = _get_recommendation_policy, 446: .create_recommendations = _create_recommendations, 447: .notify_connection_change = _notify_connection_change, 448: .set_message_types = _set_message_types, 449: .set_message_types_long = _set_message_types_long, 450: .solicit_recommendation = _solicit_recommendation, 451: .receive_message = _receive_message, 452: .batch_ending = _batch_ending, 453: .destroy = _destroy, 454: }, 455: .imvs = linked_list_create(), 456: .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), 457: .id_mutex = mutex_create(MUTEX_TYPE_DEFAULT), 458: .next_imv_id = 1, 459: ); 460: 461: polname = lib->settings->get_str(lib->settings, 462: "%s.plugins.tnc-imv.recommendation_policy", "default", lib->ns); 463: if (!enum_from_name(recommendation_policy_names, polname, &this->policy)) 464: { 465: this->policy = RECOMMENDATION_POLICY_DEFAULT; 466: } 467: DBG1(DBG_TNC, "TNC recommendation policy is '%N'", 468: recommendation_policy_names, this->policy); 469: 470: return &this->public; 471: }