Annotation of embedaddon/strongswan/src/libimcv/imc/imc_agent.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2011-2014 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 "imcv.h"
        !            17: #include "imc_agent.h"
        !            18: 
        !            19: #include <tncif_names.h>
        !            20: 
        !            21: #include <utils/debug.h>
        !            22: #include <threading/rwlock.h>
        !            23: 
        !            24: typedef struct private_imc_agent_t private_imc_agent_t;
        !            25: 
        !            26: /**
        !            27:  * Private data of an imc_agent_t object.
        !            28:  */
        !            29: struct private_imc_agent_t {
        !            30: 
        !            31:        /**
        !            32:         * Public members of imc_agent_t
        !            33:         */
        !            34:        imc_agent_t public;
        !            35: 
        !            36:        /**
        !            37:         * name of IMC
        !            38:         */
        !            39:        const char *name;
        !            40: 
        !            41:        /**
        !            42:         * message types registered by IMC
        !            43:         */
        !            44:        pen_type_t *supported_types;
        !            45: 
        !            46:        /**
        !            47:         * number of message types registered by IMC
        !            48:         */
        !            49:        uint32_t type_count;
        !            50: 
        !            51:        /**
        !            52:         * ID of IMC as assigned by TNCC
        !            53:         */
        !            54:        TNC_IMCID id;
        !            55: 
        !            56:        /**
        !            57:         * List of additional IMC IDs assigned by TNCC
        !            58:         */
        !            59:        linked_list_t *additional_ids;
        !            60: 
        !            61:        /**
        !            62:         * list of non-fatal unsupported PA-TNC attribute types
        !            63:         */
        !            64:        linked_list_t *non_fatal_attr_types;
        !            65: 
        !            66:        /**
        !            67:         * list of TNCC connection entries
        !            68:         */
        !            69:        linked_list_t *connections;
        !            70: 
        !            71:        /**
        !            72:         * rwlock to lock TNCC connection entries
        !            73:         */
        !            74:        rwlock_t *connection_lock;
        !            75: 
        !            76:        /**
        !            77:         * Is the transport protocol PT-TLS?
        !            78:         */
        !            79:        bool has_pt_tls;
        !            80: 
        !            81:        /**
        !            82:         * Inform a TNCC about the set of message types the IMC is able to receive
        !            83:         *
        !            84:         * @param imc_id                        IMC ID assigned by TNCC
        !            85:         * @param supported_types       list of supported message types
        !            86:         * @param type_count            number of list elements
        !            87:         * @return                                      TNC result code
        !            88:         */
        !            89:        TNC_Result (*report_message_types)(TNC_IMCID imc_id,
        !            90:                                                                           TNC_MessageTypeList supported_types,
        !            91:                                                                           TNC_UInt32 type_count);
        !            92: 
        !            93:        /**
        !            94:         * Inform a TNCC about the set of message types the IMC is able to receive
        !            95:         *
        !            96:         * @param imc_id                                IMC ID assigned by TNCC
        !            97:         * @param supported_vids                list of supported message vendor IDs
        !            98:         * @param supported_subtypes    list of supported message subtypes
        !            99:         * @param type_count                    number of list elements
        !           100:         * @return                                              TNC result code
        !           101:         */
        !           102:        TNC_Result (*report_message_types_long)(TNC_IMCID imc_id,
        !           103:                                                                        TNC_VendorIDList supported_vids,
        !           104:                                                                        TNC_MessageSubtypeList supported_subtypes,
        !           105:                                                                        TNC_UInt32 type_count);
        !           106: 
        !           107:        /**
        !           108:         * Get the value of an attribute associated with a connection
        !           109:         * or with the TNCC as a whole.
        !           110:         *
        !           111:         * @param imc_id                        IMC ID assigned by TNCC
        !           112:         * @param connection_id         network connection ID assigned by TNCC
        !           113:         * @param attribute_id          attribute ID
        !           114:         * @param buffer_len            length of buffer in bytes
        !           115:         * @param buffer                        buffer
        !           116:         * @param out_value_len         size in bytes of attribute stored in buffer
        !           117:         * @return                                      TNC result code
        !           118:         */
        !           119:        TNC_Result (*get_attribute)(TNC_IMCID imc_id,
        !           120:                                                                TNC_ConnectionID connection_id,
        !           121:                                                                TNC_AttributeID attribute_id,
        !           122:                                                                TNC_UInt32 buffer_len,
        !           123:                                                                TNC_BufferReference buffer,
        !           124:                                                                TNC_UInt32 *out_value_len);
        !           125: 
        !           126:        /**
        !           127:         * Set the value of an attribute associated with a connection
        !           128:         * or with the TNCC as a whole.
        !           129:         *
        !           130:         * @param imc_id                        IMV ID assigned by TNCC
        !           131:         * @param connection_id         network connection ID assigned by TNCC
        !           132:         * @param attribute_id          attribute ID
        !           133:         * @param buffer_len            length of buffer in bytes
        !           134:         * @param buffer                        buffer
        !           135:         * @return                                      TNC result code
        !           136:         */
        !           137:        TNC_Result (*set_attribute)(TNC_IMCID imc_id,
        !           138:                                                                TNC_ConnectionID connection_id,
        !           139:                                                                TNC_AttributeID attribute_id,
        !           140:                                                                TNC_UInt32 buffer_len,
        !           141:                                                                TNC_BufferReference buffer);
        !           142: 
        !           143:        /**
        !           144:         * Reserve an additional IMC ID
        !           145:         *
        !           146:         * @param imc_id                        primary IMC ID assigned by TNCC
        !           147:         * @param out_imc_id            additional IMC ID assigned by TNCC
        !           148:         * @return                                      TNC result code
        !           149:         */
        !           150:        TNC_Result (*reserve_additional_id)(TNC_IMCID imc_id,
        !           151:                                                                                TNC_UInt32 *out_imc_id);
        !           152: 
        !           153: };
        !           154: 
        !           155: METHOD(imc_agent_t, bind_functions, TNC_Result,
        !           156:        private_imc_agent_t *this, TNC_TNCC_BindFunctionPointer bind_function)
        !           157: {
        !           158:        if (!bind_function)
        !           159:        {
        !           160:                DBG1(DBG_IMC, "TNC client failed to provide bind function");
        !           161:                return TNC_RESULT_INVALID_PARAMETER;
        !           162:        }
        !           163:        if (bind_function(this->id, "TNC_TNCC_ReportMessageTypes",
        !           164:                        (void**)&this->report_message_types) != TNC_RESULT_SUCCESS)
        !           165:        {
        !           166:                this->report_message_types = NULL;
        !           167:        }
        !           168:        if (bind_function(this->id, "TNC_TNCC_ReportMessageTypesLong",
        !           169:                        (void**)&this->report_message_types_long) != TNC_RESULT_SUCCESS)
        !           170:        {
        !           171:                this->report_message_types_long = NULL;
        !           172:        }
        !           173:        if (bind_function(this->id, "TNC_TNCC_RequestHandshakeRetry",
        !           174:                        (void**)&this->public.request_handshake_retry) != TNC_RESULT_SUCCESS)
        !           175:        {
        !           176:                this->public.request_handshake_retry = NULL;
        !           177:        }
        !           178:        if (bind_function(this->id, "TNC_TNCC_SendMessage",
        !           179:                        (void**)&this->public.send_message) != TNC_RESULT_SUCCESS)
        !           180:        {
        !           181:                this->public.send_message = NULL;
        !           182:        }
        !           183:        if (bind_function(this->id, "TNC_TNCC_SendMessageLong",
        !           184:                        (void**)&this->public.send_message_long) != TNC_RESULT_SUCCESS)
        !           185:        {
        !           186:                this->public.send_message_long = NULL;
        !           187:        }
        !           188:        if (bind_function(this->id, "TNC_TNCC_GetAttribute",
        !           189:                        (void**)&this->get_attribute) != TNC_RESULT_SUCCESS)
        !           190:        {
        !           191:                this->get_attribute = NULL;
        !           192:        }
        !           193:        if (bind_function(this->id, "TNC_TNCC_SetAttribute",
        !           194:                        (void**)&this->set_attribute) != TNC_RESULT_SUCCESS)
        !           195:        {
        !           196:                this->set_attribute = NULL;
        !           197:        }
        !           198:        if (bind_function(this->id, "TNC_TNCC_ReserveAdditionalIMCID",
        !           199:                        (void**)&this->reserve_additional_id) != TNC_RESULT_SUCCESS)
        !           200:        {
        !           201:                this->reserve_additional_id = NULL;
        !           202:        }
        !           203: 
        !           204:        if (this->report_message_types_long)
        !           205:        {
        !           206:                TNC_VendorIDList vendor_id_list;
        !           207:                TNC_MessageSubtypeList subtype_list;
        !           208:                int i;
        !           209: 
        !           210:                vendor_id_list = malloc(this->type_count * sizeof(TNC_UInt32));
        !           211:                subtype_list   = malloc(this->type_count * sizeof(TNC_UInt32));
        !           212: 
        !           213:                for (i = 0; i < this->type_count; i++)
        !           214:                {
        !           215:                        vendor_id_list[i] = this->supported_types[i].vendor_id;
        !           216:                        subtype_list[i]   = this->supported_types[i].type;
        !           217:                }
        !           218:                this->report_message_types_long(this->id, vendor_id_list, subtype_list,
        !           219:                                                                                this->type_count);
        !           220:                free(vendor_id_list);
        !           221:                free(subtype_list);
        !           222:        }
        !           223:        else if (this->report_message_types)
        !           224:        {
        !           225:                TNC_MessageTypeList type_list;
        !           226:                int i;
        !           227: 
        !           228:                type_list = malloc(this->type_count * sizeof(TNC_UInt32));
        !           229: 
        !           230:                for (i = 0; i < this->type_count; i++)
        !           231:                {
        !           232:                        type_list[i] = (this->supported_types[i].vendor_id << 8) |
        !           233:                                                   (this->supported_types[i].type & 0xff);
        !           234:                }
        !           235:                this->report_message_types(this->id, type_list, this->type_count);
        !           236:                free(type_list);
        !           237:        }
        !           238:        return TNC_RESULT_SUCCESS;
        !           239: }
        !           240: 
        !           241: /**
        !           242:  * finds a connection state based on its Connection ID
        !           243:  */
        !           244: static imc_state_t* find_connection(private_imc_agent_t *this,
        !           245:                                                                         TNC_ConnectionID id)
        !           246: {
        !           247:        enumerator_t *enumerator;
        !           248:        imc_state_t *state, *found = NULL;
        !           249: 
        !           250:        this->connection_lock->read_lock(this->connection_lock);
        !           251:        enumerator = this->connections->create_enumerator(this->connections);
        !           252:        while (enumerator->enumerate(enumerator, &state))
        !           253:        {
        !           254:                if (id == state->get_connection_id(state))
        !           255:                {
        !           256:                        found = state;
        !           257:                        break;
        !           258:                }
        !           259:        }
        !           260:        enumerator->destroy(enumerator);
        !           261:        this->connection_lock->unlock(this->connection_lock);
        !           262: 
        !           263:        return found;
        !           264: }
        !           265: 
        !           266: /**
        !           267:  * delete a connection state with a given Connection ID
        !           268:  */
        !           269: static bool delete_connection(private_imc_agent_t *this, TNC_ConnectionID id)
        !           270: {
        !           271:        enumerator_t *enumerator;
        !           272:        imc_state_t *state;
        !           273:        bool found = FALSE;
        !           274: 
        !           275:        this->connection_lock->write_lock(this->connection_lock);
        !           276:        enumerator = this->connections->create_enumerator(this->connections);
        !           277:        while (enumerator->enumerate(enumerator, &state))
        !           278:        {
        !           279:                if (id == state->get_connection_id(state))
        !           280:                {
        !           281:                        found = TRUE;
        !           282:                        state->destroy(state);
        !           283:                        this->connections->remove_at(this->connections, enumerator);
        !           284:                        break;
        !           285:                }
        !           286:        }
        !           287:        enumerator->destroy(enumerator);
        !           288:        this->connection_lock->unlock(this->connection_lock);
        !           289: 
        !           290:        return found;
        !           291: }
        !           292: 
        !           293: /**
        !           294:  * Read a boolean attribute
        !           295:  */
        !           296: static bool get_bool_attribute(private_imc_agent_t *this, TNC_ConnectionID id,
        !           297:                                                           TNC_AttributeID attribute_id)
        !           298: {
        !           299:        TNC_UInt32 len;
        !           300:        char buf[4];
        !           301: 
        !           302:        return this->get_attribute  &&
        !           303:                   this->get_attribute(this->id, id, attribute_id, 4, buf, &len) ==
        !           304:                                                           TNC_RESULT_SUCCESS && len == 1 && *buf == 0x01;
        !           305: }
        !           306: 
        !           307: /**
        !           308:  * Read a string attribute
        !           309:  */
        !           310: static char* get_str_attribute(private_imc_agent_t *this, TNC_ConnectionID id,
        !           311:                                                                TNC_AttributeID attribute_id)
        !           312: {
        !           313:        TNC_UInt32 len;
        !           314:        char buf[BUF_LEN];
        !           315: 
        !           316:        if (this->get_attribute  &&
        !           317:                this->get_attribute(this->id, id, attribute_id, BUF_LEN, buf, &len) ==
        !           318:                                                        TNC_RESULT_SUCCESS && len <= BUF_LEN)
        !           319:        {
        !           320:                return strdup(buf);
        !           321:        }
        !           322:        return NULL;
        !           323:  }
        !           324: 
        !           325: /**
        !           326:  * Read an UInt32 attribute
        !           327:  */
        !           328: static uint32_t get_uint_attribute(private_imc_agent_t *this, TNC_ConnectionID id,
        !           329:                                                                        TNC_AttributeID attribute_id)
        !           330: {
        !           331:        TNC_UInt32 len;
        !           332:        char buf[4];
        !           333: 
        !           334:        if (this->get_attribute  &&
        !           335:                this->get_attribute(this->id, id, attribute_id, 4, buf, &len) ==
        !           336:                                                        TNC_RESULT_SUCCESS && len == 4)
        !           337:        {
        !           338:                return untoh32(buf);
        !           339:        }
        !           340:        return 0;
        !           341:  }
        !           342: 
        !           343: METHOD(imc_agent_t, create_state, TNC_Result,
        !           344:        private_imc_agent_t *this, imc_state_t *state)
        !           345: {
        !           346:        TNC_ConnectionID conn_id;
        !           347:        char *tnccs_p = NULL, *tnccs_v = NULL, *t_p = NULL, *t_v = NULL;
        !           348:        bool has_long = FALSE, has_excl = FALSE, has_soh = FALSE;
        !           349:        uint32_t max_msg_len;
        !           350: 
        !           351:        conn_id = state->get_connection_id(state);
        !           352:        if (find_connection(this, conn_id))
        !           353:        {
        !           354:                DBG1(DBG_IMC, "IMC %u \"%s\" already created a state for Connection ID %u",
        !           355:                                           this->id, this->name, conn_id);
        !           356:                state->destroy(state);
        !           357:                return TNC_RESULT_OTHER;
        !           358:        }
        !           359: 
        !           360:        /* Get and display attributes from TNCC via IF-IMC */
        !           361:        has_long = get_bool_attribute(this, conn_id, TNC_ATTRIBUTEID_HAS_LONG_TYPES);
        !           362:        has_excl = get_bool_attribute(this, conn_id, TNC_ATTRIBUTEID_HAS_EXCLUSIVE);
        !           363:        has_soh  = get_bool_attribute(this, conn_id, TNC_ATTRIBUTEID_HAS_SOH);
        !           364:        tnccs_p = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFTNCCS_PROTOCOL);
        !           365:        tnccs_v = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFTNCCS_VERSION);
        !           366:        t_p = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFT_PROTOCOL);
        !           367:        t_v = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFT_VERSION);
        !           368:        max_msg_len = get_uint_attribute(this, conn_id, TNC_ATTRIBUTEID_MAX_MESSAGE_SIZE);
        !           369: 
        !           370:        state->set_flags(state, has_long, has_excl);
        !           371:        state->set_max_msg_len(state, max_msg_len);
        !           372: 
        !           373:        DBG2(DBG_IMC, "IMC %u \"%s\" created a state for %s %s Connection ID %u: "
        !           374:                                  "%slong %sexcl %ssoh", this->id, this->name,
        !           375:                                  tnccs_p ? tnccs_p:"?", tnccs_v ? tnccs_v:"?", conn_id,
        !           376:                              has_long ? "+":"-", has_excl ? "+":"-", has_soh ? "+":"-");
        !           377:        DBG2(DBG_IMC, "  over %s %s with maximum PA-TNC message size of %u bytes",
        !           378:                                  t_p ? t_p:"?", t_v ? t_v :"?", max_msg_len);
        !           379: 
        !           380:        this->has_pt_tls = streq(t_p, "IF-T for TLS");
        !           381: 
        !           382:        free(tnccs_p);
        !           383:        free(tnccs_v);
        !           384:        free(t_p);
        !           385:        free(t_v);
        !           386: 
        !           387:        this->connection_lock->write_lock(this->connection_lock);
        !           388:        this->connections->insert_last(this->connections, state);
        !           389:        this->connection_lock->unlock(this->connection_lock);
        !           390:        return TNC_RESULT_SUCCESS;
        !           391: }
        !           392: 
        !           393: METHOD(imc_agent_t, delete_state, TNC_Result,
        !           394:        private_imc_agent_t *this, TNC_ConnectionID connection_id)
        !           395: {
        !           396:        if (!delete_connection(this, connection_id))
        !           397:        {
        !           398:                DBG1(DBG_IMC, "IMC %u \"%s\" has no state for Connection ID %u",
        !           399:                                          this->id, this->name, connection_id);
        !           400:                return TNC_RESULT_FATAL;
        !           401:        }
        !           402:        DBG2(DBG_IMC, "IMC %u \"%s\" deleted the state of Connection ID %u",
        !           403:                                  this->id, this->name, connection_id);
        !           404:        return TNC_RESULT_SUCCESS;
        !           405: }
        !           406: 
        !           407: METHOD(imc_agent_t, change_state, TNC_Result,
        !           408:        private_imc_agent_t *this, TNC_ConnectionID connection_id,
        !           409:                                                           TNC_ConnectionState new_state,
        !           410:                                                           imc_state_t **state_p)
        !           411: {
        !           412:        imc_state_t *state;
        !           413:        TNC_ConnectionState old_state;
        !           414: 
        !           415:        switch (new_state)
        !           416:        {
        !           417:                case TNC_CONNECTION_STATE_HANDSHAKE:
        !           418:                case TNC_CONNECTION_STATE_ACCESS_ALLOWED:
        !           419:                case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
        !           420:                case TNC_CONNECTION_STATE_ACCESS_NONE:
        !           421:                        state = find_connection(this, connection_id);
        !           422: 
        !           423:                        if (!state)
        !           424:                        {
        !           425:                                DBG1(DBG_IMC, "IMC %u \"%s\" has no state for Connection ID %u",
        !           426:                                                          this->id, this->name, connection_id);
        !           427:                                return TNC_RESULT_FATAL;
        !           428:                        }
        !           429:                        old_state = state->change_state(state, new_state);
        !           430:                        DBG2(DBG_IMC, "IMC %u \"%s\" changed state of Connection ID %u to '%N'",
        !           431:                                                  this->id, this->name, connection_id,
        !           432:                                                  TNC_Connection_State_names, new_state);
        !           433:                        if (state_p)
        !           434:                        {
        !           435:                                *state_p = state;
        !           436:                        }
        !           437:                        if (new_state == TNC_CONNECTION_STATE_HANDSHAKE &&
        !           438:                                old_state != TNC_CONNECTION_STATE_CREATE)
        !           439:                        {
        !           440:                                state->reset(state);
        !           441:                                DBG2(DBG_IMC, "IMC %u \"%s\" reset state of Connection ID %u",
        !           442:                                                           this->id, this->name, connection_id);
        !           443:                        }
        !           444:                        break;
        !           445:                case TNC_CONNECTION_STATE_CREATE:
        !           446:                        DBG1(DBG_IMC, "state '%N' should be handled by create_state()",
        !           447:                                                  TNC_Connection_State_names, new_state);
        !           448:                                return TNC_RESULT_FATAL;
        !           449:                case TNC_CONNECTION_STATE_DELETE:
        !           450:                        DBG1(DBG_IMC, "state '%N' should be handled by delete_state()",
        !           451:                                                  TNC_Connection_State_names, new_state);
        !           452:                                return TNC_RESULT_FATAL;
        !           453:                default:
        !           454:                        DBG1(DBG_IMC, "IMC %u \"%s\" was notified of unknown state %u "
        !           455:                                                  "for Connection ID %u",
        !           456:                                                  this->id, this->name, new_state, connection_id);
        !           457:                        return TNC_RESULT_INVALID_PARAMETER;
        !           458:        }
        !           459:        return TNC_RESULT_SUCCESS;
        !           460: }
        !           461: 
        !           462: METHOD(imc_agent_t, get_state, bool,
        !           463:        private_imc_agent_t *this, TNC_ConnectionID connection_id,
        !           464:                                                           imc_state_t **state)
        !           465: {
        !           466:        *state = find_connection(this, connection_id);
        !           467:        if (!*state)
        !           468:        {
        !           469:                DBG1(DBG_IMC, "IMC %u \"%s\" has no state for Connection ID %u",
        !           470:                                          this->id, this->name, connection_id);
        !           471:                return FALSE;
        !           472:        }
        !           473:        return TRUE;
        !           474: }
        !           475: 
        !           476: METHOD(imc_agent_t, get_name, const char*,
        !           477:        private_imc_agent_t *this)
        !           478: {
        !           479:        return  this->name;
        !           480: }
        !           481: 
        !           482: METHOD(imc_agent_t, get_id, TNC_IMCID,
        !           483:        private_imc_agent_t *this)
        !           484: {
        !           485:        return  this->id;
        !           486: }
        !           487: 
        !           488: METHOD(imc_agent_t, reserve_additional_ids, TNC_Result,
        !           489:        private_imc_agent_t *this, int count)
        !           490: {
        !           491:        TNC_Result result;
        !           492:        TNC_UInt32 id;
        !           493:        void *pointer;
        !           494: 
        !           495:        if (!this->reserve_additional_id)
        !           496:        {
        !           497:                DBG1(DBG_IMC, "IMC %u \"%s\" did not detect the capability to reserve "
        !           498:                                          "additional IMC IDs from the TNCC", this->id, this->name);
        !           499:                return TNC_RESULT_ILLEGAL_OPERATION;
        !           500:        }
        !           501:        while (count > 0)
        !           502:        {
        !           503:                result = this->reserve_additional_id(this->id, &id);
        !           504:                if (result != TNC_RESULT_SUCCESS)
        !           505:                {
        !           506:                        DBG1(DBG_IMC, "IMC %u \"%s\" failed to reserve %d additional IMC IDs",
        !           507:                                                  this->id, this->name, count);
        !           508:                        return result;
        !           509:                }
        !           510:                count--;
        !           511: 
        !           512:                /* store the scalar value in the pointer */
        !           513:                pointer = (void*)(uintptr_t)id;
        !           514:                this->additional_ids->insert_last(this->additional_ids, pointer);
        !           515:                DBG2(DBG_IMC, "IMC %u \"%s\" reserved additional ID %u",
        !           516:                                          this->id, this->name, id);
        !           517:        }
        !           518:        return TNC_RESULT_SUCCESS;
        !           519: }
        !           520: 
        !           521: METHOD(imc_agent_t, count_additional_ids, int,
        !           522:        private_imc_agent_t *this)
        !           523: {
        !           524:        return  this->additional_ids->get_count(this->additional_ids);
        !           525: }
        !           526: 
        !           527: METHOD(imc_agent_t, create_id_enumerator, enumerator_t*,
        !           528:        private_imc_agent_t *this)
        !           529: {
        !           530:        return this->additional_ids->create_enumerator(this->additional_ids);
        !           531: }
        !           532: 
        !           533: METHOD(imc_agent_t, add_non_fatal_attr_type, void,
        !           534:        private_imc_agent_t *this, pen_type_t type)
        !           535: {
        !           536:        pen_type_t *type_p;
        !           537: 
        !           538:        type_p = malloc_thing(pen_type_t);
        !           539:        *type_p = type;
        !           540:        this->non_fatal_attr_types->insert_last(this->non_fatal_attr_types, type_p);
        !           541: }
        !           542: 
        !           543: METHOD(imc_agent_t, get_non_fatal_attr_types, linked_list_t*,
        !           544:        private_imc_agent_t *this)
        !           545: {
        !           546:        return this->non_fatal_attr_types;
        !           547: }
        !           548: 
        !           549: METHOD(imc_agent_t, has_pt_tls, bool,
        !           550:        private_imc_agent_t *this)
        !           551: {
        !           552:        return  this->has_pt_tls;
        !           553: }
        !           554: 
        !           555: METHOD(imc_agent_t, destroy, void,
        !           556:        private_imc_agent_t *this)
        !           557: {
        !           558:        DBG1(DBG_IMC, "IMC %u \"%s\" terminated", this->id, this->name);
        !           559:        this->additional_ids->destroy(this->additional_ids);
        !           560:        this->non_fatal_attr_types->destroy_function(this->non_fatal_attr_types,
        !           561:                                                                                                 free);
        !           562:        this->connections->destroy_function(this->connections, free);
        !           563:        this->connection_lock->destroy(this->connection_lock);
        !           564:        free(this);
        !           565: 
        !           566:        /* decrease the reference count or terminate */
        !           567:        libimcv_deinit();
        !           568: }
        !           569: 
        !           570: /**
        !           571:  * Described in header.
        !           572:  */
        !           573: imc_agent_t *imc_agent_create(const char *name,
        !           574:                                                          pen_type_t *supported_types, uint32_t type_count,
        !           575:                                                          TNC_IMCID id, TNC_Version *actual_version)
        !           576: {
        !           577:        private_imc_agent_t *this;
        !           578: 
        !           579:        /* initialize  or increase the reference count */
        !           580:        if (!libimcv_init(FALSE))
        !           581:        {
        !           582:                return NULL;
        !           583:        }
        !           584: 
        !           585:        INIT(this,
        !           586:                .public = {
        !           587:                        .bind_functions = _bind_functions,
        !           588:                        .create_state = _create_state,
        !           589:                        .delete_state = _delete_state,
        !           590:                        .change_state = _change_state,
        !           591:                        .get_state = _get_state,
        !           592:                        .get_name = _get_name,
        !           593:                        .get_id = _get_id,
        !           594:                        .reserve_additional_ids = _reserve_additional_ids,
        !           595:                        .count_additional_ids = _count_additional_ids,
        !           596:                        .create_id_enumerator = _create_id_enumerator,
        !           597:                        .add_non_fatal_attr_type = _add_non_fatal_attr_type,
        !           598:                        .get_non_fatal_attr_types = _get_non_fatal_attr_types,
        !           599:                        .has_pt_tls = _has_pt_tls,
        !           600:                        .destroy = _destroy,
        !           601:                },
        !           602:                .name = name,
        !           603:                .supported_types = supported_types,
        !           604:                .type_count = type_count,
        !           605:                .id = id,
        !           606:                .additional_ids = linked_list_create(),
        !           607:                .non_fatal_attr_types = linked_list_create(),
        !           608:                .connections = linked_list_create(),
        !           609:                .connection_lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
        !           610:        );
        !           611: 
        !           612:        *actual_version = TNC_IFIMC_VERSION_1;
        !           613:        DBG1(DBG_IMC, "IMC %u \"%s\" initialized", this->id, this->name);
        !           614: 
        !           615:        return &this->public;
        !           616: }

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