Annotation of embedaddon/strongswan/src/libimcv/imv/imv_msg.c, revision 1.1.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>