Annotation of embedaddon/strongswan/src/libtnccs/plugins/tnc_imv/tnc_imv_manager.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_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: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>