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