summaryrefslogtreecommitdiff
path: root/src/libimcv/imc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libimcv/imc')
-rw-r--r--src/libimcv/imc/imc_agent.c170
-rw-r--r--src/libimcv/imc/imc_agent.h8
-rw-r--r--src/libimcv/imc/imc_state.h41
3 files changed, 151 insertions, 68 deletions
diff --git a/src/libimcv/imc/imc_agent.c b/src/libimcv/imc/imc_agent.c
index de2f959a4..8d1e70716 100644
--- a/src/libimcv/imc/imc_agent.c
+++ b/src/libimcv/imc/imc_agent.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -18,7 +19,6 @@
#include <tncif_names.h>
#include <debug.h>
-#include <utils/linked_list.h>
#include <threading/rwlock.h>
typedef struct private_imc_agent_t private_imc_agent_t;
@@ -333,12 +333,31 @@ static char* get_str_attribute(private_imc_agent_t *this, TNC_ConnectionID id,
return NULL;
}
+/**
+ * Read an UInt32 attribute
+ */
+static u_int32_t get_uint_attribute(private_imc_agent_t *this, TNC_ConnectionID id,
+ TNC_AttributeID attribute_id)
+{
+ TNC_UInt32 len;
+ char buf[4];
+
+ if (this->get_attribute &&
+ this->get_attribute(this->id, id, attribute_id, 4, buf, &len) ==
+ TNC_RESULT_SUCCESS && len == 4)
+ {
+ return untoh32(buf);
+ }
+ return 0;
+ }
+
METHOD(imc_agent_t, create_state, TNC_Result,
private_imc_agent_t *this, imc_state_t *state)
{
TNC_ConnectionID conn_id;
char *tnccs_p = NULL, *tnccs_v = NULL, *t_p = NULL, *t_v = NULL;
bool has_long = FALSE, has_excl = FALSE, has_soh = FALSE;
+ u_int32_t max_msg_len;
conn_id = state->get_connection_id(state);
if (find_connection(this, conn_id))
@@ -357,14 +376,18 @@ METHOD(imc_agent_t, create_state, TNC_Result,
tnccs_v = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFTNCCS_VERSION);
t_p = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFT_PROTOCOL);
t_v = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFT_VERSION);
+ max_msg_len = get_uint_attribute(this, conn_id, TNC_ATTRIBUTEID_MAX_MESSAGE_SIZE);
state->set_flags(state, has_long, has_excl);
+ state->set_max_msg_len(state, max_msg_len);
+
+ DBG2(DBG_IMC, "IMC %u \"%s\" created a state for %s %s Connection ID %u: "
+ "%slong %sexcl %ssoh", this->id, this->name,
+ tnccs_p ? tnccs_p:"?", tnccs_v ? tnccs_v:"?", conn_id,
+ has_long ? "+":"-", has_excl ? "+":"-", has_soh ? "+":"-");
+ DBG2(DBG_IMC, " over %s %s with maximum PA-TNC message size of %u bytes",
+ t_p ? t_p:"?", t_v ? t_v :"?", max_msg_len);
- DBG2(DBG_IMC, "IMC %u \"%s\" created a state for Connection ID %u: "
- "%s %s with %slong %sexcl %ssoh over %s %s",
- this->id, this->name, conn_id, tnccs_p ? tnccs_p:"?",
- tnccs_v ? tnccs_v:"?", has_long ? "+":"-", has_excl ? "+":"-",
- has_soh ? "+":"-", t_p ? t_p:"?", t_v ? t_v :"?");
free(tnccs_p);
free(tnccs_v);
free(t_p);
@@ -453,11 +476,17 @@ METHOD(imc_agent_t, get_state, bool,
METHOD(imc_agent_t, send_message, TNC_Result,
private_imc_agent_t *this, TNC_ConnectionID connection_id, bool excl,
- TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id, chunk_t msg)
+ TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id, linked_list_t *attr_list)
{
TNC_MessageType type;
TNC_UInt32 msg_flags;
+ TNC_Result result = TNC_RESULT_FATAL;
imc_state_t *state;
+ pa_tnc_attr_t *attr;
+ pa_tnc_msg_t *pa_tnc_msg;
+ chunk_t msg;
+ enumerator_t *enumerator;
+ bool attr_added;
state = find_connection(this, connection_id);
if (!state)
@@ -467,26 +496,70 @@ METHOD(imc_agent_t, send_message, TNC_Result,
return TNC_RESULT_FATAL;
}
- if (state->has_long(state) && this->send_message_long)
+ while (attr_list->get_count(attr_list))
{
- if (!src_imc_id)
+ pa_tnc_msg = pa_tnc_msg_create(state->get_max_msg_len(state));
+ attr_added = FALSE;
+
+ enumerator = attr_list->create_enumerator(attr_list);
+ while (enumerator->enumerate(enumerator, &attr))
{
- src_imc_id = this->id;
+ if (pa_tnc_msg->add_attribute(pa_tnc_msg, attr))
+ {
+ attr_added = TRUE;
+ }
+ else
+ {
+ if (attr_added)
+ {
+ break;
+ }
+ else
+ {
+ DBG1(DBG_IMC, "PA-TNC attribute too large to send, deleted");
+ attr->destroy(attr);
+ }
+ }
+ attr_list->remove_at(attr_list, enumerator);
}
- msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0;
+ enumerator->destroy(enumerator);
- return this->send_message_long(src_imc_id, connection_id, msg_flags,
- msg.ptr, msg.len, this->vendor_id,
- this->subtype, dst_imv_id);
- }
- if (this->send_message)
- {
- type = (this->vendor_id << 8) | this->subtype;
+ /* build and send the PA-TNC message via the IF-IMC interface */
+ if (!pa_tnc_msg->build(pa_tnc_msg))
+ {
+ pa_tnc_msg->destroy(pa_tnc_msg);
+ return TNC_RESULT_FATAL;
+ }
+ msg = pa_tnc_msg->get_encoding(pa_tnc_msg);
+
+ if (state->has_long(state) && this->send_message_long)
+ {
+ if (!src_imc_id)
+ {
+ src_imc_id = this->id;
+ }
+ msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0;
+
+ result = this->send_message_long(src_imc_id, connection_id,
+ msg_flags, msg.ptr, msg.len, this->vendor_id,
+ this->subtype, dst_imv_id);
+ }
+ else if (this->send_message)
+ {
+ type = (this->vendor_id << 8) | this->subtype;
- return this->send_message(this->id, connection_id, msg.ptr, msg.len,
- type);
+ result = this->send_message(this->id, connection_id, msg.ptr,
+ msg.len, type);
+ }
+
+ pa_tnc_msg->destroy(pa_tnc_msg);
+
+ if (result != TNC_RESULT_SUCCESS)
+ {
+ break;
+ }
}
- return TNC_RESULT_FATAL;
+ return result;
}
METHOD(imc_agent_t, receive_message, TNC_Result,
@@ -494,11 +567,11 @@ METHOD(imc_agent_t, receive_message, TNC_Result,
TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype,
TNC_UInt32 src_imv_id, TNC_UInt32 dst_imc_id, pa_tnc_msg_t **pa_tnc_msg)
{
- pa_tnc_msg_t *pa_msg, *error_msg;
+ pa_tnc_msg_t *pa_msg;
pa_tnc_attr_t *error_attr;
+ linked_list_t *error_attr_list;
enumerator_t *enumerator;
- TNC_MessageType msg_type;
- TNC_UInt32 msg_flags, src_imc_id, dst_imv_id;
+ TNC_UInt32 src_imc_id, dst_imv_id;
TNC_ConnectionID connection_id;
TNC_Result result;
@@ -534,51 +607,24 @@ METHOD(imc_agent_t, receive_message, TNC_Result,
*pa_tnc_msg = pa_msg;
break;
case VERIFY_ERROR:
- /* build error message */
- error_msg = pa_tnc_msg_create();
+ /* extract and copy by refence all error attributes */
+ error_attr_list = linked_list_create();
+
enumerator = pa_msg->create_error_enumerator(pa_msg);
while (enumerator->enumerate(enumerator, &error_attr))
{
- error_msg->add_attribute(error_msg,
- error_attr->get_ref(error_attr));
+ error_attr_list->insert_last(error_attr_list,
+ error_attr->get_ref(error_attr));
}
enumerator->destroy(enumerator);
- error_msg->build(error_msg);
-
- /* send error message */
- if (state->has_long(state) && this->send_message_long)
- {
- if (state->has_excl(state))
- {
- msg_flags = TNC_MESSAGE_FLAGS_EXCLUSIVE;
- dst_imv_id = src_imv_id;
- }
- else
- {
- msg_flags = 0;
- dst_imv_id = TNC_IMVID_ANY;
- }
- src_imc_id = (dst_imc_id == TNC_IMCID_ANY) ? this->id
- : dst_imc_id;
- result = this->send_message_long(src_imc_id, connection_id,
- msg_flags, msg.ptr, msg.len, msg_vid,
- msg_subtype, dst_imv_id);
- }
- else if (this->send_message)
- {
- msg_type = (msg_vid << 8) | msg_subtype;
+ src_imc_id = (dst_imc_id == TNC_IMCID_ANY) ? this->id : dst_imc_id;
+ dst_imv_id = state->has_excl(state) ? src_imv_id : TNC_IMVID_ANY;
- result = this->send_message(this->id, connection_id,
- msg.ptr, msg.len, msg_type);
- }
- else
- {
- result = TNC_RESULT_FATAL;
- }
+ result = send_message(this, connection_id, state->has_excl(state),
+ src_imc_id, dst_imv_id, error_attr_list);
- /* clean up */
- error_msg->destroy(error_msg);
+ error_attr_list->destroy(error_attr_list);
pa_msg->destroy(pa_msg);
return result;
case FAILED:
diff --git a/src/libimcv/imc/imc_agent.h b/src/libimcv/imc/imc_agent.h
index d1fef4d8d..e87450aa6 100644
--- a/src/libimcv/imc/imc_agent.h
+++ b/src/libimcv/imc/imc_agent.h
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -26,6 +27,7 @@
#include <tncifimc.h>
#include <pen/pen.h>
+#include <utils/linked_list.h>
#include <library.h>
@@ -104,13 +106,13 @@ struct imc_agent_t {
* @param excl exclusive flag
* @param src_imc_id IMC ID to be set as source
* @param dst_imv_id IMV ID to be set as destination
- * @param msg message to send
+ * @param attr_list list of PA-TNC attributes to send
* @return TNC result code
*/
TNC_Result (*send_message)(imc_agent_t *this,
TNC_ConnectionID connection_id, bool excl,
TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id,
- chunk_t msg);
+ linked_list_t *attr_list);
/**
* Call when a PA-TNC message was received
diff --git a/src/libimcv/imc/imc_state.h b/src/libimcv/imc/imc_state.h
index f1b0358c9..c34441f0f 100644
--- a/src/libimcv/imc/imc_state.h
+++ b/src/libimcv/imc/imc_state.h
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -22,6 +23,8 @@
#define IMC_STATE_H_
#include <tncif.h>
+#include <tncifimv.h>
+#include <tncifimc.h>
#include <library.h>
@@ -33,8 +36,7 @@ typedef struct imc_state_t imc_state_t;
struct imc_state_t {
/**
- * Get the TNCS connection I
-D attached to the state
+ * Get the TNCS connection ID attached to the state
*
* @return TNCS connection ID of the state
*/
@@ -64,6 +66,20 @@ D attached to the state
void (*set_flags)(imc_state_t *this, bool has_long, bool has_excl);
/**
+ * Set the maximum size of a PA-TNC message for this TNCCS connection
+ *
+ * @max_msg_len maximum size of a PA-TNC message
+ */
+ void (*set_max_msg_len)(imc_state_t *this, u_int32_t max_msg_len);
+
+ /**
+ * Get the maximum size of a PA-TNC message for this TNCCS connection
+ *
+ * @return maximum size of a PA-TNC message
+ */
+ u_int32_t (*get_max_msg_len)(imc_state_t *this);
+
+ /**
* Change the connection state
*
* @param new_state new connection state
@@ -71,6 +87,25 @@ D attached to the state
void (*change_state)(imc_state_t *this, TNC_ConnectionState new_state);
/**
+ * Set the Assessment/Evaluation Result
+ *
+ * @param id IMC ID
+ * @param result Assessment/Evaluation Result
+ */
+ void (*set_result)(imc_state_t *this, TNC_IMCID id,
+ TNC_IMV_Evaluation_Result result);
+
+ /**
+ * Get the Assessment/Evaluation Result
+ *
+ * @param id IMC ID
+ * @param result Assessment/Evaluation Result
+ * @return TRUE if result is known
+ */
+ bool (*get_result)(imc_state_t *this, TNC_IMCID id,
+ TNC_IMV_Evaluation_Result *result);
+
+ /**
* Destroys an imc_state_t object
*/
void (*destroy)(imc_state_t *this);