Annotation of embedaddon/strongswan/src/libimcv/imv/imv_msg.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2012-2015 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 "imv_msg.h"
        !            17: 
        !            18: #include "ietf/ietf_attr.h"
        !            19: #include "ietf/ietf_attr_assess_result.h"
        !            20: #include "ietf/ietf_attr_remediation_instr.h"
        !            21: #include "tcg/seg/tcg_seg_attr_max_size.h"
        !            22: #include "tcg/seg/tcg_seg_attr_seg_env.h"
        !            23: #include "tcg/seg/tcg_seg_attr_next_seg.h"
        !            24: 
        !            25: #include <tncif_names.h>
        !            26: #include <tncif_pa_subtypes.h>
        !            27: 
        !            28: #include <pen/pen.h>
        !            29: #include <collections/linked_list.h>
        !            30: #include <utils/debug.h>
        !            31: 
        !            32: typedef struct private_imv_msg_t private_imv_msg_t;
        !            33: 
        !            34: /**
        !            35:  * Private data of a imv_msg_t object.
        !            36:  *
        !            37:  */
        !            38: struct private_imv_msg_t {
        !            39: 
        !            40:        /**
        !            41:         * Public imv_msg_t interface.
        !            42:         */
        !            43:        imv_msg_t public;
        !            44: 
        !            45:        /**
        !            46:         * Connection ID
        !            47:         */
        !            48:        TNC_ConnectionID connection_id;
        !            49: 
        !            50:        /**
        !            51:         * source ID
        !            52:         */
        !            53:        TNC_UInt32 src_id;
        !            54: 
        !            55:        /**
        !            56:         * destination ID
        !            57:         */
        !            58:        TNC_UInt32 dst_id;
        !            59: 
        !            60:        /**
        !            61:         * PA-TNC message type
        !            62:         */
        !            63:        pen_type_t msg_type;
        !            64: 
        !            65:        /**
        !            66:         * List of PA-TNC attributes to be sent
        !            67:         */
        !            68:        linked_list_t *attr_list;
        !            69: 
        !            70:        /**
        !            71:         * PA-TNC message
        !            72:         */
        !            73:        pa_tnc_msg_t *pa_msg;
        !            74: 
        !            75:        /**
        !            76:         * Assigned IMV agent
        !            77:         */
        !            78:        imv_agent_t *agent;
        !            79: 
        !            80:        /**
        !            81:         * Assigned IMV state
        !            82:         */
        !            83:        imv_state_t *state;
        !            84: };
        !            85: 
        !            86: METHOD(imv_msg_t, get_src_id, TNC_UInt32,
        !            87:        private_imv_msg_t *this)
        !            88: {
        !            89:        return this->src_id;
        !            90: }
        !            91: 
        !            92: METHOD(imv_msg_t, get_dst_id, TNC_UInt32,
        !            93:        private_imv_msg_t *this)
        !            94: {
        !            95:        return this->dst_id;
        !            96: }
        !            97: 
        !            98: METHOD(imv_msg_t, set_msg_type, void,
        !            99:        private_imv_msg_t *this, pen_type_t msg_type)
        !           100: {
        !           101:        if (msg_type.vendor_id != this->msg_type.vendor_id ||
        !           102:                msg_type.type != this->msg_type.type)
        !           103:        {
        !           104:                this->msg_type = msg_type;
        !           105:                this->dst_id = TNC_IMCID_ANY;
        !           106:        }
        !           107: }
        !           108: 
        !           109: METHOD(imv_msg_t, get_msg_type, pen_type_t,
        !           110:        private_imv_msg_t *this)
        !           111: {
        !           112:        return this->msg_type;
        !           113: }
        !           114: 
        !           115: METHOD(imv_msg_t, add_attribute, void,
        !           116:        private_imv_msg_t *this, pa_tnc_attr_t *attr)
        !           117: {
        !           118:        this->attr_list->insert_last(this->attr_list, attr);
        !           119: }
        !           120: 
        !           121: METHOD(imv_msg_t, send_, TNC_Result,
        !           122:        private_imv_msg_t *this, bool excl)
        !           123: {
        !           124:        pa_tnc_msg_t *pa_tnc_msg;
        !           125:        pa_tnc_attr_t *attr;
        !           126:        TNC_UInt32 msg_flags;
        !           127:        TNC_MessageType msg_type;
        !           128:        size_t max_msg_len, min_seg_attr_len, space_left;
        !           129:        bool attr_added, oversize;
        !           130:        chunk_t msg;
        !           131:        seg_contract_t *contract;
        !           132:        seg_contract_manager_t *contracts;
        !           133:        enumerator_t *enumerator;
        !           134:        TNC_Result result = TNC_RESULT_SUCCESS;
        !           135: 
        !           136:        /* Get IF-M segmentation contract for this subtype if any */
        !           137:        contracts = this->state->get_contracts(this->state);
        !           138:        contract = contracts->get_contract(contracts, this->msg_type,
        !           139:                                                                           FALSE, this->dst_id);
        !           140: 
        !           141:        /* Retrieve maximum allowed PA-TNC message size if set */
        !           142:        max_msg_len = this->state->get_max_msg_len(this->state);
        !           143: 
        !           144:        /* Minimum size needed for Segmentation Envelope Attribute */
        !           145:        min_seg_attr_len = PA_TNC_ATTR_HEADER_SIZE + TCG_SEG_ATTR_SEG_ENV_HEADER +
        !           146:                                           PA_TNC_ATTR_HEADER_SIZE;
        !           147: 
        !           148:        while (this->attr_list->get_count(this->attr_list))
        !           149:        {
        !           150:                pa_tnc_msg = pa_tnc_msg_create(max_msg_len);
        !           151:                attr_added = FALSE;
        !           152: 
        !           153:                enumerator = this->attr_list->create_enumerator(this->attr_list);
        !           154:                while (enumerator->enumerate(enumerator, &attr))
        !           155:                {
        !           156:                        space_left = pa_tnc_msg->get_space(pa_tnc_msg);
        !           157: 
        !           158:                        if (contract && contract->check_size(contract, attr, &oversize))
        !           159:                        {
        !           160:                                if (oversize)
        !           161:                                {
        !           162:                                        /* TODO handle oversized attributes */
        !           163:                                }
        !           164:                                else if (max_msg_len == 0 || space_left >= min_seg_attr_len)
        !           165:                                {
        !           166:                                        attr = contract->first_segment(contract, attr, space_left);
        !           167:                                }
        !           168:                                else
        !           169:                                {
        !           170:                                        /* segment attribute in next iteration */
        !           171:                                        break;
        !           172:                                }
        !           173:                        }
        !           174:                        if (pa_tnc_msg->add_attribute(pa_tnc_msg, attr))
        !           175:                        {
        !           176:                                attr_added = TRUE;
        !           177:                        }
        !           178:                        else
        !           179:                        {
        !           180:                                if (attr_added)
        !           181:                                {
        !           182:                                        /* there might be space for attribute in next iteration */
        !           183:                                        break;
        !           184:                                }
        !           185:                                else
        !           186:                                {
        !           187:                                        DBG1(DBG_IMV, "PA-TNC attribute too large to send, deleted");
        !           188:                                        attr->destroy(attr);
        !           189:                                }
        !           190:                        }
        !           191:                        this->attr_list->remove_at(this->attr_list, enumerator);
        !           192:                }
        !           193:                enumerator->destroy(enumerator);
        !           194: 
        !           195:                /* build and send the PA-TNC message via the IF-IMV interface */
        !           196:                if (!pa_tnc_msg->build(pa_tnc_msg))
        !           197:                {
        !           198:                        pa_tnc_msg->destroy(pa_tnc_msg);
        !           199:                        return TNC_RESULT_FATAL;
        !           200:                }
        !           201:                msg = pa_tnc_msg->get_encoding(pa_tnc_msg);
        !           202:                DBG3(DBG_IMV, "created PA-TNC message: %B", &msg);
        !           203: 
        !           204:                if (this->state->has_long(this->state) && this->agent->send_message_long)
        !           205:                {
        !           206:                        excl = excl && this->state->has_excl(this->state) &&
        !           207:                                                   this->dst_id != TNC_IMCID_ANY;
        !           208:                        msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0;
        !           209:                        result = this->agent->send_message_long(this->src_id,
        !           210:                                                        this->connection_id, msg_flags, msg.ptr, msg.len,
        !           211:                                                        this->msg_type.vendor_id, this->msg_type.type,
        !           212:                                                        this->dst_id);
        !           213:                }
        !           214:                else if (this->agent->send_message)
        !           215:                {
        !           216:                        msg_type = (this->msg_type.vendor_id << 8) |
        !           217:                                           (this->msg_type.type & 0x000000ff);
        !           218:                        result = this->agent->send_message(this->src_id, this->connection_id,
        !           219:                                                                                           msg.ptr, msg.len, msg_type);
        !           220:                }
        !           221: 
        !           222:                pa_tnc_msg->destroy(pa_tnc_msg);
        !           223: 
        !           224:                if (result != TNC_RESULT_SUCCESS)
        !           225:                {
        !           226:                        break;
        !           227:                }
        !           228:        }
        !           229:        return result;
        !           230: }
        !           231: 
        !           232: METHOD(imv_msg_t, send_assessment, TNC_Result,
        !           233:        private_imv_msg_t *this)
        !           234: {
        !           235:        TNC_IMV_Action_Recommendation rec;
        !           236:        TNC_IMV_Evaluation_Result eval;
        !           237:        pa_tnc_attr_t *attr;
        !           238:        chunk_t string = chunk_empty;
        !           239:        char *lang_code = NULL, *uri = NULL;
        !           240:        enumerator_t *e;
        !           241: 
        !           242:        /* Remove any attributes that have already been constructed */
        !           243:        while (this->attr_list->remove_last(this->attr_list, (void**)&attr) == SUCCESS)
        !           244:        {
        !           245:                attr->destroy(attr);
        !           246:        }
        !           247: 
        !           248:        /* Send an IETF Assessment Result attribute if enabled */
        !           249:        if (lib->settings->get_bool(lib->settings, "%s.imcv.assessment_result",
        !           250:                                                                TRUE, lib->ns))
        !           251:        {
        !           252:                this->state->get_recommendation(this->state, &rec, &eval);
        !           253:                attr = ietf_attr_assess_result_create(eval);
        !           254:                add_attribute(this, attr);
        !           255: 
        !           256:                /* Send IETF Remediation Instructions if available */
        !           257:                if (eval != TNC_IMV_EVALUATION_RESULT_COMPLIANT)
        !           258:                {
        !           259:                        e = this->agent->create_language_enumerator(this->agent,
        !           260:                                                                        this->state);
        !           261:                        if (this->state->get_remediation_instructions(this->state,
        !           262:                                                                        e, &string, &lang_code, &uri))
        !           263:                        {
        !           264:                                if (string.len && lang_code)
        !           265:                                {
        !           266:                                        attr = ietf_attr_remediation_instr_create_from_string(string,
        !           267:                                                                        chunk_create(lang_code, strlen(lang_code)));
        !           268:                                        add_attribute(this, attr);
        !           269:                                }
        !           270:                                if (uri)
        !           271:                                {
        !           272:                                        attr = ietf_attr_remediation_instr_create_from_uri(
        !           273:                                                                        chunk_create(uri, strlen(uri)));
        !           274:                                        add_attribute(this, attr);
        !           275:                                }
        !           276:                        }
        !           277:                        e->destroy(e);
        !           278:                }
        !           279: 
        !           280:                /* send PA-TNC message with the excl flag set */
        !           281:                return send_(this, TRUE);
        !           282:        }
        !           283:        return TNC_RESULT_SUCCESS;
        !           284: }
        !           285: 
        !           286: METHOD(imv_msg_t, receive, TNC_Result,
        !           287:        private_imv_msg_t *this, imv_msg_t *out_msg, bool *fatal_error)
        !           288: {
        !           289:        TNC_Result result = TNC_RESULT_SUCCESS;
        !           290:        TNC_UInt32 target_imv_id;
        !           291:        linked_list_t *non_fatal_types;
        !           292:        enumerator_t *enumerator;
        !           293:        pa_tnc_attr_t *attr;
        !           294:        chunk_t msg;
        !           295: 
        !           296:        if (this->state->has_long(this->state))
        !           297:        {
        !           298:                if (this->dst_id != TNC_IMVID_ANY)
        !           299:                {
        !           300:                        DBG2(DBG_IMV, "IMV %u \"%s\" received message for Connection ID %u "
        !           301:                                                  "from IMC %u to IMV %u",
        !           302:                                                   this->agent->get_id(this->agent),
        !           303:                                                   this->agent->get_name(this->agent),
        !           304:                                                   this->connection_id, this->src_id, this->dst_id);
        !           305:                }
        !           306:                else
        !           307:                {
        !           308:                        DBG2(DBG_IMV, "IMV %u \"%s\" received message for Connection ID %u "
        !           309:                                                  "from IMC %u", this->agent->get_id(this->agent),
        !           310:                                                   this->agent->get_name(this->agent),
        !           311:                                                   this->connection_id, this->src_id);
        !           312:                }
        !           313:        }
        !           314:        else
        !           315:        {
        !           316:                DBG2(DBG_IMV, "IMV %u \"%s\" received message for Connection ID %u",
        !           317:                                           this->agent->get_id(this->agent),
        !           318:                                           this->agent->get_name(this->agent),
        !           319:                                           this->connection_id);
        !           320:        }
        !           321:        msg = this->pa_msg->get_encoding(this->pa_msg);
        !           322:        DBG3(DBG_IMV, "%B", &msg);
        !           323: 
        !           324:        switch (this->pa_msg->process(this->pa_msg))
        !           325:        {
        !           326:                case SUCCESS:
        !           327:                        break;
        !           328:                case VERIFY_ERROR:
        !           329:                {
        !           330:                        /* extract and copy by reference all error attributes */
        !           331:                        enumerator = this->pa_msg->create_error_enumerator(this->pa_msg);
        !           332:                        while (enumerator->enumerate(enumerator, &attr))
        !           333:                        {
        !           334:                                out_msg->add_attribute(out_msg, attr->get_ref(attr));
        !           335:                        }
        !           336:                        enumerator->destroy(enumerator);
        !           337:                }
        !           338:                case FAILED:
        !           339:                default:
        !           340:                        return TNC_RESULT_FATAL;
        !           341:        }
        !           342: 
        !           343:        /* determine target IMV ID */
        !           344:        target_imv_id = (this->dst_id != TNC_IMVID_ANY) ?
        !           345:                                         this->dst_id : this->agent->get_id(this->agent);
        !           346: 
        !           347:        /* process IF-M segmentation attributes */
        !           348:        enumerator = this->pa_msg->create_attribute_enumerator(this->pa_msg);
        !           349:        while (enumerator->enumerate(enumerator, &attr))
        !           350:        {
        !           351:                uint32_t max_attr_size, max_seg_size, my_max_attr_size, my_max_seg_size;
        !           352:                seg_contract_manager_t *contracts;
        !           353:                seg_contract_t *contract;
        !           354:                char buf[BUF_LEN];
        !           355:                pen_type_t type;
        !           356: 
        !           357:                type = attr->get_type(attr);
        !           358: 
        !           359:                if (type.vendor_id != PEN_TCG)
        !           360:                {
        !           361:                        continue;
        !           362:                }
        !           363: 
        !           364:                contracts = this->state->get_contracts(this->state);
        !           365: 
        !           366:                switch (type.type)
        !           367:                {
        !           368:                        case TCG_SEG_MAX_ATTR_SIZE_REQ:
        !           369:                        {
        !           370:                                tcg_seg_attr_max_size_t *attr_cast;
        !           371: 
        !           372:                                attr_cast = (tcg_seg_attr_max_size_t*)attr;
        !           373:                                attr_cast->get_attr_size(attr_cast, &max_attr_size,
        !           374:                                                                                                        &max_seg_size);
        !           375:                                contract = contracts->get_contract(contracts, this->msg_type,
        !           376:                                                                                                   FALSE, this->src_id);
        !           377:                                if (contract)
        !           378:                                {
        !           379:                                        contract->set_max_size(contract, max_attr_size,
        !           380:                                                                                                         max_seg_size);
        !           381:                                }
        !           382:                                else
        !           383:                                {
        !           384:                                        contract = seg_contract_create(this->msg_type, max_attr_size,
        !           385:                                                                        max_seg_size, FALSE, this->src_id, FALSE);
        !           386:                                        contract->set_responder(contract, target_imv_id);
        !           387:                                        contracts->add_contract(contracts, contract);
        !           388:                                }
        !           389:                                contract->get_info_string(contract, buf, BUF_LEN, TRUE);
        !           390:                                DBG2(DBG_IMV, "%s", buf);
        !           391: 
        !           392:                                /* Determine maximum PA-TNC attribute segment size */
        !           393:                                my_max_seg_size = this->state->get_max_msg_len(this->state)
        !           394:                                                                        - PA_TNC_HEADER_SIZE
        !           395:                                                                        - PA_TNC_ATTR_HEADER_SIZE
        !           396:                                                                        - TCG_SEG_ATTR_SEG_ENV_HEADER;
        !           397: 
        !           398:                                /* If segmentation is possible select lower segment size */
        !           399:                                if (max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION &&
        !           400:                                        max_seg_size > my_max_seg_size)
        !           401:                                {
        !           402:                                        max_seg_size = my_max_seg_size;
        !           403:                                        contract->set_max_size(contract, max_attr_size,
        !           404:                                                                                                         max_seg_size);
        !           405:                                        DBG2(DBG_IMV, "  lowered maximum segment size to %u bytes",
        !           406:                                                 max_seg_size);
        !           407:                                }
        !           408: 
        !           409:                                /* Add Maximum Attribute Size Response attribute */
        !           410:                                attr = tcg_seg_attr_max_size_create(max_attr_size,
        !           411:                                                                                                        max_seg_size, FALSE);
        !           412:                                out_msg->add_attribute(out_msg, attr);
        !           413:                                break;
        !           414:                        }
        !           415:                        case TCG_SEG_MAX_ATTR_SIZE_RESP:
        !           416:                        {
        !           417:                                tcg_seg_attr_max_size_t *attr_cast;
        !           418: 
        !           419:                                attr_cast = (tcg_seg_attr_max_size_t*)attr;
        !           420:                                attr_cast->get_attr_size(attr_cast, &max_attr_size,
        !           421:                                                                                                        &max_seg_size);
        !           422:                                contract = contracts->get_contract(contracts, this->msg_type,
        !           423:                                                                                                   TRUE, this->src_id);
        !           424:                                if (!contract)
        !           425:                                {
        !           426:                                        contract = contracts->get_contract(contracts, this->msg_type,
        !           427:                                                                                                   TRUE, TNC_IMCID_ANY);
        !           428:                                        if (contract)
        !           429:                                        {
        !           430:                                                contract = contract->clone(contract);
        !           431:                                                contract->set_responder(contract, this->src_id);
        !           432:                                                contracts->add_contract(contracts, contract);
        !           433:                                        }
        !           434:                                }
        !           435:                                if (contract)
        !           436:                                {
        !           437:                                        contract->get_max_size(contract, &my_max_attr_size,
        !           438:                                                                                                         &my_max_seg_size);
        !           439:                                        if (my_max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION &&
        !           440:                                                my_max_seg_size > max_seg_size)
        !           441:                                        {
        !           442:                                                my_max_seg_size = max_seg_size;
        !           443:                                                contract->set_max_size(contract, my_max_attr_size,
        !           444:                                                                                                                 my_max_seg_size);
        !           445:                                        }
        !           446:                                        contract->get_info_string(contract, buf, BUF_LEN, FALSE);
        !           447:                                        DBG2(DBG_IMV, "%s", buf);
        !           448:                                }
        !           449:                                else
        !           450:                                {
        !           451:                                        /* TODO no request pending */
        !           452:                                        DBG1(DBG_IMV, "no contract for this PA message type found");
        !           453:                                }
        !           454:                                break;
        !           455:                        }
        !           456:                        case TCG_SEG_ATTR_SEG_ENV:
        !           457:                        {
        !           458:                                tcg_seg_attr_seg_env_t *seg_env_attr;
        !           459:                                pa_tnc_attr_t *error;
        !           460:                                uint32_t base_attr_id;
        !           461:                                bool more;
        !           462: 
        !           463:                                seg_env_attr = (tcg_seg_attr_seg_env_t*)attr;
        !           464:                                base_attr_id = seg_env_attr->get_base_attr_id(seg_env_attr);
        !           465: 
        !           466:                                contract = contracts->get_contract(contracts, this->msg_type,
        !           467:                                                                                                   TRUE, this->src_id);
        !           468:                                if (!contract)
        !           469:                                {
        !           470:                                        DBG2(DBG_IMV, "no contract for received attribute segment "
        !           471:                                                 "with base attribute ID %u", base_attr_id);
        !           472:                                        continue;
        !           473:                                }
        !           474:                                attr = contract->add_segment(contract, attr, &error, &more);
        !           475:                                if (error)
        !           476:                                {
        !           477:                                        out_msg->add_attribute(out_msg, error);
        !           478:                                }
        !           479:                                if (attr)
        !           480:                                {
        !           481:                                        this->pa_msg->add_attribute(this->pa_msg, attr);
        !           482:                                }
        !           483:                                if (more)
        !           484:                                {
        !           485:                                        /* Send Next Segment Request */
        !           486:                                        attr = tcg_seg_attr_next_seg_create(base_attr_id, FALSE);
        !           487:                                        out_msg->add_attribute(out_msg, attr);
        !           488:                                }
        !           489:                                break;
        !           490:                        }
        !           491:                        case TCG_SEG_NEXT_SEG_REQ:
        !           492:                        {
        !           493:                                tcg_seg_attr_next_seg_t *attr_cast;
        !           494:                                uint32_t base_attr_id;
        !           495: 
        !           496:                                attr_cast = (tcg_seg_attr_next_seg_t*)attr;
        !           497:                                base_attr_id = attr_cast->get_base_attr_id(attr_cast);
        !           498: 
        !           499:                                contract = contracts->get_contract(contracts, this->msg_type,
        !           500:                                                                                                   FALSE, this->src_id);
        !           501:                                if (!contract)
        !           502:                                {
        !           503:                                        /* TODO no contract - generate error message */
        !           504:                                        DBG1(DBG_IMV, "no contract for received next segment "
        !           505:                                                 "request with base attribute ID %u", base_attr_id);
        !           506:                                        continue;
        !           507:                                }
        !           508:                                attr = contract->next_segment(contract, base_attr_id);
        !           509:                                if (attr)
        !           510:                                {
        !           511:                                        out_msg->add_attribute(out_msg, attr);
        !           512:                                }
        !           513:                                else
        !           514:                                {
        !           515:                                        /* TODO no more segments - generate error message */
        !           516:                                        DBG1(DBG_IMV, "no more segments found for "
        !           517:                                                 "base attribute ID %u", base_attr_id);
        !           518:                                }
        !           519:                                break;
        !           520:                        }
        !           521:                        default:
        !           522:                                break;
        !           523:                }
        !           524:        }
        !           525:        enumerator->destroy(enumerator);
        !           526: 
        !           527:        /* preprocess any received IETF standard error attributes */
        !           528:        non_fatal_types = this->agent->get_non_fatal_attr_types(this->agent);
        !           529:        *fatal_error = this->pa_msg->process_ietf_std_errors(this->pa_msg,
        !           530:                                                                                                                 non_fatal_types);
        !           531: 
        !           532:        return result;
        !           533: }
        !           534: 
        !           535: METHOD(imv_msg_t, get_attribute_count, int,
        !           536:        private_imv_msg_t *this)
        !           537: {
        !           538:        return this->attr_list->get_count(this->attr_list);
        !           539: }
        !           540: 
        !           541: METHOD(imv_msg_t, create_attribute_enumerator, enumerator_t*,
        !           542:        private_imv_msg_t *this)
        !           543: {
        !           544:        return this->pa_msg->create_attribute_enumerator(this->pa_msg);
        !           545: }
        !           546: 
        !           547: METHOD(imv_msg_t, get_encoding, chunk_t,
        !           548:        private_imv_msg_t *this)
        !           549: {
        !           550:        if (this->pa_msg)
        !           551:        {
        !           552:                return this->pa_msg->get_encoding(this->pa_msg);
        !           553:        }
        !           554:        return chunk_empty;
        !           555: }
        !           556: 
        !           557: METHOD(imv_msg_t, destroy, void,
        !           558:        private_imv_msg_t *this)
        !           559: {
        !           560:        this->attr_list->destroy_offset(this->attr_list,
        !           561:                                                                        offsetof(pa_tnc_attr_t, destroy));
        !           562:        DESTROY_IF(this->pa_msg);
        !           563:        free(this);
        !           564: }
        !           565: 
        !           566: /**
        !           567:  * See header
        !           568:  */
        !           569: imv_msg_t *imv_msg_create(imv_agent_t *agent, imv_state_t *state,
        !           570:                                                  TNC_ConnectionID connection_id,
        !           571:                                                  TNC_UInt32 src_id, TNC_UInt32 dst_id,
        !           572:                                                  pen_type_t msg_type)
        !           573: {
        !           574:        private_imv_msg_t *this;
        !           575: 
        !           576:        INIT(this,
        !           577:                .public = {
        !           578:                        .get_src_id = _get_src_id,
        !           579:                        .get_dst_id = _get_dst_id,
        !           580:                        .set_msg_type = _set_msg_type,
        !           581:                        .get_msg_type = _get_msg_type,
        !           582:                        .send = _send_,
        !           583:                        .send_assessment = _send_assessment,
        !           584:                        .receive = _receive,
        !           585:                        .add_attribute = _add_attribute,
        !           586:                        .get_attribute_count = _get_attribute_count,
        !           587:                        .create_attribute_enumerator = _create_attribute_enumerator,
        !           588:                        .get_encoding = _get_encoding,
        !           589:                        .destroy = _destroy,
        !           590:                },
        !           591:                .connection_id = connection_id,
        !           592:                .src_id = src_id,
        !           593:                .dst_id = dst_id,
        !           594:                .msg_type = msg_type,
        !           595:                .attr_list = linked_list_create(),
        !           596:                .agent = agent,
        !           597:                .state = state,
        !           598:        );
        !           599: 
        !           600:        return &this->public;
        !           601: }
        !           602: 
        !           603: /**
        !           604:  * See header
        !           605:  */
        !           606: imv_msg_t* imv_msg_create_as_reply(imv_msg_t *msg)
        !           607: {
        !           608:        private_imv_msg_t *in;
        !           609:        TNC_UInt32 src_id;
        !           610: 
        !           611:        in = (private_imv_msg_t*)msg;
        !           612:        src_id = (in->dst_id != TNC_IMVID_ANY) ?
        !           613:                          in->dst_id : in->agent->get_id(in->agent);
        !           614: 
        !           615:        return imv_msg_create(in->agent, in->state, in->connection_id, src_id,
        !           616:                                                  in->src_id, in->msg_type);
        !           617: }
        !           618: 
        !           619: /**
        !           620:  * See header
        !           621:  */
        !           622: imv_msg_t *imv_msg_create_from_data(imv_agent_t *agent, imv_state_t *state,
        !           623:                                                                        TNC_ConnectionID connection_id,
        !           624:                                                                        TNC_MessageType msg_type,
        !           625:                                                                        chunk_t msg)
        !           626: {
        !           627:        TNC_VendorID msg_vid;
        !           628:        TNC_MessageSubtype msg_subtype;
        !           629: 
        !           630:        msg_vid = msg_type >> 8;
        !           631:        msg_subtype = msg_type & TNC_SUBTYPE_ANY;
        !           632: 
        !           633:        return imv_msg_create_from_long_data(agent, state, connection_id,
        !           634:                                                                TNC_IMCID_ANY, agent->get_id(agent),
        !           635:                                                                msg_vid, msg_subtype, msg);
        !           636: }
        !           637: 
        !           638: /**
        !           639:  * See header
        !           640:  */
        !           641: imv_msg_t *imv_msg_create_from_long_data(imv_agent_t *agent, imv_state_t *state,
        !           642:                                                                                 TNC_ConnectionID connection_id,
        !           643:                                                                                 TNC_UInt32 src_id,
        !           644:                                                                                 TNC_UInt32 dst_id,
        !           645:                                                                                 TNC_VendorID msg_vid,
        !           646:                                                                                 TNC_MessageSubtype msg_subtype,
        !           647:                                                                                 chunk_t msg)
        !           648: {
        !           649:        private_imv_msg_t *this;
        !           650: 
        !           651:        this = (private_imv_msg_t*)imv_msg_create(agent, state,
        !           652:                                                                                connection_id, src_id, dst_id,
        !           653:                                                                                pen_type_create(msg_vid, msg_subtype));
        !           654:        this->pa_msg = pa_tnc_msg_create_from_data(msg);
        !           655: 
        !           656:        return &this->public;
        !           657: }

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