diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2014-08-28 21:14:13 +0200 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2014-10-05 12:55:37 +0200 |
commit | e911ac9a5f9f605785613df04b0eeabb47121aa4 (patch) | |
tree | 1c0310a1d2a6db8af75b5ebc6dba09d602085b7b /src/libimcv/imv | |
parent | 89d12654b343e92fc7a4f511b32475402a5120ed (diff) | |
download | strongswan-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.c | 235 | ||||
-rw-r--r-- | src/libimcv/imv/imv_state.h | 2 |
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> |