diff options
-rw-r--r-- | src/libimcv/imc/imc_msg.c | 31 | ||||
-rw-r--r-- | src/libimcv/imv/imv_msg.c | 28 | ||||
-rw-r--r-- | src/libimcv/seg/seg_contract.c | 57 | ||||
-rw-r--r-- | src/libimcv/seg/seg_contract.h | 28 | ||||
-rw-r--r-- | src/libimcv/seg/seg_contract_manager.c | 7 | ||||
-rw-r--r-- | src/libimcv/seg/seg_contract_manager.h | 4 |
6 files changed, 133 insertions, 22 deletions
diff --git a/src/libimcv/imc/imc_msg.c b/src/libimcv/imc/imc_msg.c index 810a92a93..83337cf7b 100644 --- a/src/libimcv/imc/imc_msg.c +++ b/src/libimcv/imc/imc_msg.c @@ -117,7 +117,8 @@ METHOD(imc_msg_t, send_, TNC_Result, /* 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); + contract = contracts->get_contract(contracts, this->msg_type, + FALSE, this->dst_id); while (this->attr_list->get_count(this->attr_list)) { @@ -287,6 +288,10 @@ METHOD(imc_msg_t, receive, TNC_Result, return TNC_RESULT_FATAL; } + /* determine target IMC ID */ + target_imc_id = (this->dst_id != TNC_IMCID_ANY) ? + this->dst_id : this->agent->get_id(this->agent); + /* process any IF-M segmentation contracts */ enumerator = this->pa_msg->create_attribute_enumerator(this->pa_msg); while (enumerator->enumerate(enumerator, &attr)) @@ -316,7 +321,7 @@ METHOD(imc_msg_t, receive, TNC_Result, attr_cast->get_attr_size(attr_cast, &max_attr_size, &max_seg_size); contract = contracts->get_contract(contracts, this->msg_type, - FALSE); + FALSE, this->src_id); if (contract) { contract->set_max_size(contract, max_attr_size, @@ -326,6 +331,7 @@ METHOD(imc_msg_t, receive, TNC_Result, { contract = seg_contract_create(this->msg_type, max_attr_size, max_seg_size, FALSE, this->src_id, TRUE); + contract->set_responder(contract, target_imc_id); contracts->add_contract(contracts, contract); } contract->get_info_string(contract, buf, BUF_LEN, TRUE); @@ -364,7 +370,18 @@ METHOD(imc_msg_t, receive, TNC_Result, attr_cast->get_attr_size(attr_cast, &max_attr_size, &max_seg_size); contract = contracts->get_contract(contracts, this->msg_type, - TRUE); + TRUE, this->src_id); + if (!contract) + { + contract = contracts->get_contract(contracts, this->msg_type, + TRUE, TNC_IMCID_ANY); + if (contract) + { + contract = contract->clone(contract); + contract->set_responder(contract, this->src_id); + contracts->add_contract(contracts, contract); + } + } if (contract) { contract->get_max_size(contract, &my_max_attr_size, @@ -397,7 +414,7 @@ METHOD(imc_msg_t, receive, TNC_Result, base_attr_id = seg_env_attr->get_base_attr_id(seg_env_attr); contract = contracts->get_contract(contracts, this->msg_type, - TRUE); + TRUE, this->src_id); if (!contract) { DBG2(DBG_IMC, "no contract for received attribute segment " @@ -430,7 +447,7 @@ METHOD(imc_msg_t, receive, TNC_Result, base_attr_id = attr_cast->get_base_attr_id(attr_cast); contract = contracts->get_contract(contracts, this->msg_type, - FALSE); + FALSE, this->src_id); if (!contract) { /* TODO no contract - generate error message */ @@ -457,10 +474,6 @@ METHOD(imc_msg_t, receive, TNC_Result, } enumerator->destroy(enumerator); - /* determine target IMC ID */ - target_imc_id = (this->dst_id != TNC_IMCID_ANY) ? - this->dst_id : this->agent->get_id(this->agent); - /* preprocess any received IETF standard error attributes */ non_fatal_types = this->agent->get_non_fatal_attr_types(this->agent); *fatal_error = this->pa_msg->process_ietf_std_errors(this->pa_msg, diff --git a/src/libimcv/imv/imv_msg.c b/src/libimcv/imv/imv_msg.c index 6c4b998a2..fdf63325d 100644 --- a/src/libimcv/imv/imv_msg.c +++ b/src/libimcv/imv/imv_msg.c @@ -134,7 +134,8 @@ METHOD(imv_msg_t, send_, TNC_Result, /* 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); + contract = contracts->get_contract(contracts, this->msg_type, + FALSE, this->dst_id); while (this->attr_list->get_count(this->attr_list)) { @@ -270,6 +271,7 @@ METHOD(imv_msg_t, receive, TNC_Result, private_imv_msg_t *this, imv_msg_t *out_msg, bool *fatal_error) { TNC_Result result = TNC_RESULT_SUCCESS; + TNC_UInt32 target_imv_id; linked_list_t *non_fatal_types; enumerator_t *enumerator; pa_tnc_attr_t *attr; @@ -322,6 +324,10 @@ METHOD(imv_msg_t, receive, TNC_Result, return TNC_RESULT_FATAL; } + /* determine target IMV ID */ + target_imv_id = (this->dst_id != TNC_IMVID_ANY) ? + this->dst_id : this->agent->get_id(this->agent); + /* process IF-M segmentation attributes */ enumerator = this->pa_msg->create_attribute_enumerator(this->pa_msg); while (enumerator->enumerate(enumerator, &attr)) @@ -351,7 +357,7 @@ METHOD(imv_msg_t, receive, TNC_Result, attr_cast->get_attr_size(attr_cast, &max_attr_size, &max_seg_size); contract = contracts->get_contract(contracts, this->msg_type, - FALSE); + FALSE, this->src_id); if (contract) { contract->set_max_size(contract, max_attr_size, @@ -361,6 +367,7 @@ METHOD(imv_msg_t, receive, TNC_Result, { contract = seg_contract_create(this->msg_type, max_attr_size, max_seg_size, FALSE, this->src_id, FALSE); + contract->set_responder(contract, target_imv_id); contracts->add_contract(contracts, contract); } contract->get_info_string(contract, buf, BUF_LEN, TRUE); @@ -399,7 +406,18 @@ METHOD(imv_msg_t, receive, TNC_Result, attr_cast->get_attr_size(attr_cast, &max_attr_size, &max_seg_size); contract = contracts->get_contract(contracts, this->msg_type, - TRUE); + TRUE, this->src_id); + if (!contract) + { + contract = contracts->get_contract(contracts, this->msg_type, + TRUE, TNC_IMCID_ANY); + if (contract) + { + contract = contract->clone(contract); + contract->set_responder(contract, this->src_id); + contracts->add_contract(contracts, contract); + } + } if (contract) { contract->get_max_size(contract, &my_max_attr_size, @@ -432,7 +450,7 @@ METHOD(imv_msg_t, receive, TNC_Result, base_attr_id = seg_env_attr->get_base_attr_id(seg_env_attr); contract = contracts->get_contract(contracts, this->msg_type, - TRUE); + TRUE, this->src_id); if (!contract) { DBG2(DBG_IMV, "no contract for received attribute segment " @@ -465,7 +483,7 @@ METHOD(imv_msg_t, receive, TNC_Result, base_attr_id = attr_cast->get_base_attr_id(attr_cast); contract = contracts->get_contract(contracts, this->msg_type, - FALSE); + FALSE, this->src_id); if (!contract) { /* TODO no contract - generate error message */ diff --git a/src/libimcv/seg/seg_contract.c b/src/libimcv/seg/seg_contract.c index df25e64e9..7db702a08 100644 --- a/src/libimcv/seg/seg_contract.c +++ b/src/libimcv/seg/seg_contract.c @@ -72,11 +72,16 @@ struct private_seg_contract_t { bool is_issuer; /** - * Issuer ID (either IMV ID or IMC ID) + * Issuer ID (either IMV or IMC ID) */ TNC_UInt32 issuer_id; /** + * Responder ID (either IMC or IMV ID) + */ + TNC_UInt32 responder_id; + + /** * IMC/IMV role */ bool is_imc; @@ -290,6 +295,36 @@ METHOD(seg_contract_t, is_null, bool, return this->is_null; } +METHOD(seg_contract_t, set_responder, void, + private_seg_contract_t *this, TNC_UInt32 responder_id) +{ + this->responder_id = responder_id; +} + +METHOD(seg_contract_t, get_responder, TNC_UInt32, + private_seg_contract_t *this) +{ + return this->responder_id; +} + +METHOD(seg_contract_t, get_issuer, TNC_UInt32, + private_seg_contract_t *this) +{ + return this->issuer_id; +} + +METHOD(seg_contract_t, clone_, seg_contract_t*, + private_seg_contract_t *this) +{ + private_seg_contract_t *clone; + + clone = malloc_thing(private_seg_contract_t); + memcpy(clone, this, sizeof(private_seg_contract_t)); + clone->seg_envs = linked_list_create(); + + return &clone->public; +} + METHOD(seg_contract_t, get_info_string, void, private_seg_contract_t *this, char *buf, size_t len, bool request) { @@ -308,7 +343,10 @@ METHOD(seg_contract_t, get_info_string, void, } else { - written = snprintf(pos, len, "received"); + written = snprintf(pos, len, "%s %d received", + this->is_imc ? "IMC" : "IMV", + this->is_issuer ? this->issuer_id : + this->responder_id); } if (written < 0 || written > len) { @@ -318,7 +356,8 @@ METHOD(seg_contract_t, get_info_string, void, len -= written; written = snprintf(pos, len, " a %ssegmentation contract%s ", - this->is_null ? "null" : "", request ? "" : " response"); + this->is_null ? "null" : "", request ? + (this->is_issuer ? "" : " request") : " response"); if (written < 0 || written > len) { return; @@ -326,10 +365,13 @@ METHOD(seg_contract_t, get_info_string, void, pos += written; len -= written; - if (!this->is_issuer && this->issuer_id != TNC_IMVID_ANY) + if ((!this->is_issuer && this->issuer_id != TNC_IMVID_ANY) || + ( this->is_issuer && this->responder_id != TNC_IMVID_ANY)) { written = snprintf(pos, len, "from %s %d ", - this->is_imc ? "IMV" : "IMC", this->issuer_id); + this->is_imc ? "IMV" : "IMC", + this->is_issuer ? this->responder_id : + this->issuer_id); if (written < 0 || written > len) { return; @@ -413,6 +455,10 @@ seg_contract_t *seg_contract_create(pen_type_t msg_type, .add_segment = _add_segment, .is_issuer = _is_issuer, .is_null = _is_null, + .set_responder = _set_responder, + .get_responder = _get_responder, + .get_issuer = _get_issuer, + .clone = _clone_, .get_info_string = _get_info_string, .destroy = _destroy, }, @@ -422,6 +468,7 @@ seg_contract_t *seg_contract_create(pen_type_t msg_type, .seg_envs = linked_list_create(), .is_issuer = is_issuer, .issuer_id = issuer_id, + .responder_id = is_imc ? TNC_IMVID_ANY : TNC_IMCID_ANY, .is_imc = is_imc, .is_null = max_attr_size == SEG_CONTRACT_MAX_SIZE_VALUE && max_seg_size == SEG_CONTRACT_MAX_SIZE_VALUE, diff --git a/src/libimcv/seg/seg_contract.h b/src/libimcv/seg/seg_contract.h index 48828c472..2a2666f42 100644 --- a/src/libimcv/seg/seg_contract.h +++ b/src/libimcv/seg/seg_contract.h @@ -118,6 +118,34 @@ struct seg_contract_t { bool (*is_null)(seg_contract_t *this); /** + * Set the responder ID + * + * @param responder IMC or IMV ID of responder + */ + void (*set_responder)(seg_contract_t *this, TNC_UInt32 responder); + + /** + * Get the responder ID + * + * @return IMC or IMV ID of responder + */ + TNC_UInt32 (*get_responder)(seg_contract_t *this); + + /** + * Get the issuer ID + * + * @return IMC or IMV ID of issuer + */ + TNC_UInt32 (*get_issuer)(seg_contract_t *this); + + /** + * Clone a contract + * + * @return Cloned contract + */ + seg_contract_t* (*clone)(seg_contract_t *this); + + /** * Get an info string about the contract * * @param buf String buffer of at least size len diff --git a/src/libimcv/seg/seg_contract_manager.c b/src/libimcv/seg/seg_contract_manager.c index d099436fc..604c51134 100644 --- a/src/libimcv/seg/seg_contract_manager.c +++ b/src/libimcv/seg/seg_contract_manager.c @@ -42,7 +42,8 @@ METHOD(seg_contract_manager_t, add_contract, void, } METHOD(seg_contract_manager_t, get_contract, seg_contract_t*, - private_seg_contract_manager_t *this, pen_type_t msg_type, bool is_issuer) + private_seg_contract_manager_t *this, pen_type_t msg_type, bool is_issuer, + TNC_UInt32 id) { enumerator_t *enumerator; seg_contract_t *contract, *found = NULL; @@ -51,7 +52,9 @@ METHOD(seg_contract_manager_t, get_contract, seg_contract_t*, while (enumerator->enumerate(enumerator, &contract)) { if (contract->is_issuer(contract) == is_issuer && - pen_type_equals(contract->get_msg_type(contract), msg_type)) + pen_type_equals(contract->get_msg_type(contract), msg_type) && + id == (is_issuer ? contract->get_responder(contract) : + contract->get_issuer(contract))) { found = contract; break; diff --git a/src/libimcv/seg/seg_contract_manager.h b/src/libimcv/seg/seg_contract_manager.h index 355822d99..2757eca9e 100644 --- a/src/libimcv/seg/seg_contract_manager.h +++ b/src/libimcv/seg/seg_contract_manager.h @@ -43,9 +43,11 @@ struct seg_contract_manager_t { * * @param msg_type PA-TNC message type governed by contract * @param is_issuer If TRUE get only issuer contracts + * @param id Match either issuer or responder ID */ seg_contract_t* (*get_contract)(seg_contract_manager_t *this, - pen_type_t msg_type, bool is_issuer); + pen_type_t msg_type, bool is_issuer, + TNC_UInt32 id); /** * Destroys a seg_contract_manager_t object. |