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