aboutsummaryrefslogtreecommitdiffstats
path: root/src/libimcv/imv
diff options
context:
space:
mode:
authorAndreas Steffen <andreas.steffen@strongswan.org>2014-08-28 21:14:13 +0200
committerAndreas Steffen <andreas.steffen@strongswan.org>2014-10-05 12:55:37 +0200
commite911ac9a5f9f605785613df04b0eeabb47121aa4 (patch)
tree1c0310a1d2a6db8af75b5ebc6dba09d602085b7b /src/libimcv/imv
parent89d12654b343e92fc7a4f511b32475402a5120ed (diff)
downloadstrongswan-e911ac9a5f9f605785613df04b0eeabb47121aa4.tar.bz2
strongswan-e911ac9a5f9f605785613df04b0eeabb47121aa4.tar.xz
Implemented IF-M segmentation
Diffstat (limited to 'src/libimcv/imv')
-rw-r--r--src/libimcv/imv/imv_msg.c235
-rw-r--r--src/libimcv/imv/imv_state.h2
2 files changed, 171 insertions, 66 deletions
diff --git a/src/libimcv/imv/imv_msg.c b/src/libimcv/imv/imv_msg.c
index 35209dc18..b32b01c06 100644
--- a/src/libimcv/imv/imv_msg.c
+++ b/src/libimcv/imv/imv_msg.c
@@ -24,6 +24,7 @@
#include <tcg/seg/tcg_seg_attr_max_size.h>
#include <tcg/seg/tcg_seg_attr_seg_env.h>
+#include <tcg/seg/tcg_seg_attr_next_seg.h>
#include <pen/pen.h>
#include <collections/linked_list.h>
@@ -125,11 +126,17 @@ METHOD(imv_msg_t, send_, TNC_Result,
pa_tnc_attr_t *attr;
TNC_UInt32 msg_flags;
TNC_MessageType msg_type;
- bool attr_added;
+ bool attr_added, oversize;
chunk_t msg;
+ seg_contract_t *contract;
+ seg_contract_manager_t *contracts;
enumerator_t *enumerator;
TNC_Result result = TNC_RESULT_SUCCESS;
+ /* Get IF-M segmentation contract for this subtype if any */
+ contracts = this->state->get_contracts(this->state);
+ contract = contracts->get_contract(contracts, this->msg_type, FALSE);
+
while (this->attr_list->get_count(this->attr_list))
{
pa_tnc_msg = pa_tnc_msg_create(this->state->get_max_msg_len(this->state));
@@ -138,6 +145,17 @@ METHOD(imv_msg_t, send_, TNC_Result,
enumerator = this->attr_list->create_enumerator(this->attr_list);
while (enumerator->enumerate(enumerator, &attr))
{
+ if (contract && contract->check_size(contract, attr, &oversize))
+ {
+ if (oversize)
+ {
+ /* TODO generate SWID error msg */
+ }
+ else
+ {
+ attr = contract->first_segment(contract, attr);
+ }
+ }
if (pa_tnc_msg->add_attribute(pa_tnc_msg, attr))
{
attr_added = TRUE;
@@ -317,15 +335,14 @@ METHOD(imv_msg_t, receive, TNC_Result,
return TNC_RESULT_FATAL;
}
- /* process any IF-M segmentation contracts */
+ /* process IF-M segmentation attributes */
enumerator = this->pa_msg->create_attribute_enumerator(this->pa_msg);
while (enumerator->enumerate(enumerator, &attr))
{
uint32_t max_attr_size, max_seg_size, my_max_attr_size, my_max_seg_size;
- tcg_seg_attr_max_size_t *attr_cast;
imv_msg_t *out_msg;
- seg_contract_t *contract;
seg_contract_manager_t *contracts;
+ seg_contract_t *contract;
char buf[BUF_LEN];
pen_type_t type;
@@ -336,81 +353,169 @@ METHOD(imv_msg_t, receive, TNC_Result,
continue;
}
- if (type.type == TCG_SEG_MAX_ATTR_SIZE_REQ)
- {
- attr_cast = (tcg_seg_attr_max_size_t*)attr;
- attr_cast->get_attr_size(attr_cast, &max_attr_size, &max_seg_size);
+ contracts = this->state->get_contracts(this->state);
- contracts = this->state->get_contracts(this->state);
- contract = contracts->get_contract(contracts, this->msg_type, FALSE);
- if (contract)
- {
- contract->set_max_size(contract, max_attr_size, max_seg_size);
- }
- else
+ switch (type.type)
+ {
+ case TCG_SEG_MAX_ATTR_SIZE_REQ:
{
- contract = seg_contract_create(this->msg_type, max_attr_size,
+ tcg_seg_attr_max_size_t *attr_cast;
+
+ attr_cast = (tcg_seg_attr_max_size_t*)attr;
+ attr_cast->get_attr_size(attr_cast, &max_attr_size,
+ &max_seg_size);
+ contract = contracts->get_contract(contracts, this->msg_type,
+ FALSE);
+ if (contract)
+ {
+ contract->set_max_size(contract, max_attr_size,
+ max_seg_size);
+ }
+ else
+ {
+ contract = seg_contract_create(this->msg_type, max_attr_size,
max_seg_size, FALSE, this->src_id, FALSE);
- contracts->add_contract(contracts, contract);
- }
- contract->get_info_string(contract, buf, BUF_LEN, TRUE);
- DBG2(DBG_IMV, "%s", buf);
-
- /* Determine maximum PA-TNC attribute segment size */
- my_max_seg_size = this->state->get_max_msg_len(this->state)
- - PA_TNC_HEADER_SIZE
- - PA_TNC_ATTR_HEADER_SIZE
- - TCG_SEG_ATTR_SEG_ENV_HEADER
- - PA_TNC_ATTR_HEADER_SIZE
- - TCG_SEG_ATTR_MAX_SIZE_SIZE;
-
- /* If segmentation is not prohibited select lower segment size */
- if (max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION &&
- max_seg_size > my_max_seg_size)
- {
- max_seg_size = my_max_seg_size;
- contract->set_max_size(contract, max_attr_size, max_seg_size);
- DBG2(DBG_IMV, " lowered maximum segment size to %u bytes",
- max_seg_size);
- }
+ contracts->add_contract(contracts, contract);
+ }
+ contract->get_info_string(contract, buf, BUF_LEN, TRUE);
+ DBG2(DBG_IMV, "%s", buf);
+
+ /* Determine maximum PA-TNC attribute segment size */
+ my_max_seg_size = this->state->get_max_msg_len(this->state)
+ - PA_TNC_HEADER_SIZE
+ - PA_TNC_ATTR_HEADER_SIZE
+ - TCG_SEG_ATTR_SEG_ENV_HEADER
+ - PA_TNC_ATTR_HEADER_SIZE
+ - TCG_SEG_ATTR_MAX_SIZE_SIZE;
+
+ /* If segmentation is possible select lower segment size */
+ if (max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION &&
+ max_seg_size > my_max_seg_size)
+ {
+ max_seg_size = my_max_seg_size;
+ contract->set_max_size(contract, max_attr_size,
+ max_seg_size);
+ DBG2(DBG_IMV, " lowered maximum segment size to %u bytes",
+ max_seg_size);
+ }
- /* Send Maximum Attribute Size Response */
- out_msg = imv_msg_create_as_reply(&this->public);
- attr = tcg_seg_attr_max_size_create(max_attr_size,
- max_seg_size, FALSE);
- out_msg->add_attribute(out_msg, attr);
- result = out_msg->send(out_msg, TRUE);
- out_msg->destroy(out_msg);
- if (result != TNC_RESULT_SUCCESS)
- {
+ /* Send Maximum Attribute Size Response */
+ out_msg = imv_msg_create_as_reply(&this->public);
+ attr = tcg_seg_attr_max_size_create(max_attr_size,
+ max_seg_size, FALSE);
+ out_msg->add_attribute(out_msg, attr);
+ result = out_msg->send(out_msg, TRUE);
+ out_msg->destroy(out_msg);
+ if (result != TNC_RESULT_SUCCESS)
+ {
+ break;
+ }
break;
}
- }
- else if (type.type == TCG_SEG_MAX_ATTR_SIZE_RESP)
- {
- attr_cast = (tcg_seg_attr_max_size_t*)attr;
- attr_cast->get_attr_size(attr_cast, &max_attr_size, &max_seg_size);
-
- contracts = this->state->get_contracts(this->state);
- contract = contracts->get_contract(contracts, this->msg_type, TRUE);
- if (contract)
+ case TCG_SEG_MAX_ATTR_SIZE_RESP:
{
- contract->get_max_size(contract, &my_max_attr_size,
- &my_max_seg_size);
- if (my_max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION &&
- my_max_seg_size > max_seg_size)
+ tcg_seg_attr_max_size_t *attr_cast;
+
+ attr_cast = (tcg_seg_attr_max_size_t*)attr;
+ attr_cast->get_attr_size(attr_cast, &max_attr_size,
+ &max_seg_size);
+ contract = contracts->get_contract(contracts, this->msg_type,
+ TRUE);
+ if (contract)
{
- my_max_seg_size = max_seg_size;
- contract->set_max_size(contract, my_max_attr_size,
- my_max_seg_size);
+ contract->get_max_size(contract, &my_max_attr_size,
+ &my_max_seg_size);
+ if (my_max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION &&
+ my_max_seg_size > max_seg_size)
+ {
+ my_max_seg_size = max_seg_size;
+ contract->set_max_size(contract, my_max_attr_size,
+ my_max_seg_size);
+ }
contract->get_info_string(contract, buf, BUF_LEN, FALSE);
DBG2(DBG_IMV, "%s", buf);
}
+ else
+ {
+ /* TODO no request pending */
+ DBG1(DBG_IMV, "no contract for this PA message type found");
+ }
+ break;
}
- else
+ case TCG_SEG_ATTR_SEG_ENV:
+ {
+ tcg_seg_attr_seg_env_t *seg_env_attr;
+ pa_tnc_attr_t *error;
+ uint32_t base_attr_id;
+ bool more;
+
+ seg_env_attr = (tcg_seg_attr_seg_env_t*)attr;
+ base_attr_id = seg_env_attr->get_base_attr_id(seg_env_attr);
+
+ contract = contracts->get_contract(contracts, this->msg_type,
+ TRUE);
+ if (!contract)
+ {
+ DBG2(DBG_IMV, "no contract for received attribute segment "
+ "with base attribute ID %u", base_attr_id);
+ continue;
+ }
+ attr = contract->add_segment(contract, attr, &error, &more);
+ if (error)
+ {
+ out_msg = imv_msg_create_as_reply(&this->public);
+ out_msg->add_attribute(out_msg, error);
+ result = out_msg->send(out_msg, TRUE);
+ out_msg->destroy(out_msg);
+ }
+ if (attr)
+ {
+ this->pa_msg->add_attribute(this->pa_msg, attr);
+ }
+ if (more)
+ {
+ /* Send Next Segment Request */
+ out_msg = imv_msg_create_as_reply(&this->public);
+ attr = tcg_seg_attr_next_seg_create(base_attr_id, FALSE);
+ out_msg->add_attribute(out_msg, attr);
+ result = out_msg->send(out_msg, TRUE);
+ out_msg->destroy(out_msg);
+ }
+ break;
+ }
+ case TCG_SEG_NEXT_SEG_REQ:
{
- /* TODO no request pending */
+ tcg_seg_attr_next_seg_t *attr_cast;
+ uint32_t base_attr_id;
+
+ attr_cast = (tcg_seg_attr_next_seg_t*)attr;
+ base_attr_id = attr_cast->get_base_attr_id(attr_cast);
+
+ contract = contracts->get_contract(contracts, this->msg_type,
+ FALSE);
+ if (!contract)
+ {
+ /* TODO no contract - generate error message */
+ DBG2(DBG_IMV, "no contract for received next segment "
+ "request with base attribute ID %u", base_attr_id);
+ continue;
+ }
+ attr = contract->next_segment(contract, base_attr_id);
+ if (attr)
+ {
+ out_msg = imv_msg_create_as_reply(&this->public);
+ out_msg->add_attribute(out_msg, attr);
+ result = out_msg->send(out_msg, TRUE);
+ out_msg->destroy(out_msg);
+ }
+ else
+ {
+ /* TODO no more segments - generate error message */
+ }
+ break;
}
+ default:
+ break;
}
}
enumerator->destroy(enumerator);
diff --git a/src/libimcv/imv/imv_state.h b/src/libimcv/imv/imv_state.h
index 3a93a5f95..30ed612b3 100644
--- a/src/libimcv/imv/imv_state.h
+++ b/src/libimcv/imv/imv_state.h
@@ -23,7 +23,7 @@
#define IMV_STATE_H_
#include "imv_session.h"
-#include "seg_contract/seg_contract_manager.h"
+#include "seg/seg_contract_manager.h"
#include <tncifimv.h>