File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libimcv / imc / imc_msg.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 09:46:43 2020 UTC (4 years, 3 months ago) by misho
Branches: strongswan, MAIN
CVS tags: v5_9_2p0, v5_8_4p7, HEAD
Strongswan

    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>