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

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