diff options
author | Jan Hutter <jhutter@hsr.ch> | 2005-11-14 13:51:49 +0000 |
---|---|---|
committer | Jan Hutter <jhutter@hsr.ch> | 2005-11-14 13:51:49 +0000 |
commit | f561c205e8d631d165a602ff644a7fe02b8f3e1e (patch) | |
tree | bd33c387e302950fc768b97bd80a0ebed7626b05 /Source | |
parent | 353c317a1507ed24cf23f7ba8b6ab8e310c4ce95 (diff) | |
download | strongswan-f561c205e8d631d165a602ff644a7fe02b8f3e1e.tar.bz2 strongswan-f561c205e8d631d165a602ff644a7fe02b8f3e1e.tar.xz |
- class transform_attribute fully tested and written
- generating of this type works!
Diffstat (limited to 'Source')
-rw-r--r-- | Source/charon/generator.c | 112 | ||||
-rw-r--r-- | Source/charon/payloads/payload.c | 1 | ||||
-rw-r--r-- | Source/charon/payloads/transform_attribute.c | 71 | ||||
-rw-r--r-- | Source/charon/payloads/transform_attribute.h | 40 | ||||
-rw-r--r-- | Source/charon/testcases/generator_test.c | 101 | ||||
-rw-r--r-- | Source/charon/testcases/generator_test.h | 8 |
6 files changed, 328 insertions, 5 deletions
diff --git a/Source/charon/generator.c b/Source/charon/generator.c index 30ca74c2e..f4d3ad8e6 100644 --- a/Source/charon/generator.c +++ b/Source/charon/generator.c @@ -98,6 +98,15 @@ struct private_generator_s { */ status_t (*write_chunk) (private_generator_t *this,chunk_t *data); + /** + * Generates a bytestream from a chunk_t + * + * @param this private_generator_t object + * @param offset offset of chunk_t value in data struct + * @return - SUCCESS if succeeded + * - OUT_OF_RES if out of ressources + */ + status_t (*generate_from_chunk) (private_generator_t *this,u_int32_t offset); /** * Makes sure enough space is available in buffer to store amount of bits. @@ -154,6 +163,21 @@ struct private_generator_s { */ void * data_struct; + /* + * Attribute format of the last generated transform attribute + * + * Used to check if a variable value field is used or not for + * the transform attribute value. + */ + bool attribute_format; + + /* + * Depending on the value of attribute_format this field is used + * to hold the length of the transform attribute in bytes + */ + + u_int16_t attribute_length; + /** * Associated Logger */ @@ -187,12 +211,15 @@ static status_t generate_u_int_type (private_generator_t *this,encoding_type_t i case U_INT_64: number_of_bits = 64; break; + case ATTRIBUTE_TYPE: + number_of_bits = 15; + break; default: return FAILED; } if (((number_of_bits % 8) == 0) && (this->current_bit != 0)) { - /* current bit has to be zero for values greater then 4 bits */ + /* current bit has to be zero for values multiple of 8 bits */ return FAILED; } @@ -240,6 +267,26 @@ static status_t generate_u_int_type (private_generator_t *this,encoding_type_t i break; } + case ATTRIBUTE_TYPE: + { + if (this->current_bit != 1) + { + return FAILED; + } + u_int8_t attribute_format_flag = *(this->out_position) & 0x80; + + u_int16_t int16_val = htons(*((u_int16_t*)(this->data_struct + offset))); + + int16_val = int16_val & 0xFF7F; + + int16_val = int16_val | attribute_format_flag; + + this->write_bytes_to_buffer(this,&int16_val,sizeof(u_int16_t)); + this->current_bit = 0; + break; + + } + case U_INT_16: { u_int16_t int16_val = htons(*((u_int16_t*)(this->data_struct + offset))); @@ -344,6 +391,22 @@ static status_t generate_flag (private_generator_t *this,u_int32_t offset) } /** + * Implements private_generator_t's generate_from_chunk function. + * See #private_generator_s.generate_from_chunk. + */ +static status_t generate_from_chunk (private_generator_t *this,u_int32_t offset) +{ + if (this->current_bit != 0) + { + return FAILED; + } + chunk_t *attribute_value = (chunk_t *)(this->data_struct + offset); + + return this->write_bytes_to_buffer (this,attribute_value->ptr,attribute_value->len); + +} + +/** * Implements private_generator_t's generator_context_make_space_available function. * See #private_generator_s.generator_context_make_space_available. */ @@ -480,14 +543,54 @@ static status_t generate_payload (private_generator_t *this,payload_t *payload) break; case SPI_SIZE: /* currently not implemented */ - default: + + case ATTRIBUTE_FORMAT: + { + this->logger->log(this->logger,CONTROL_MORE,"Generate Attribute Format flag"); + /* Attribute format is a flag which is stored in context*/ + + status = this->generate_flag(this,rules[i].offset); + this->attribute_format = *((bool *) (this->data_struct + rules[i].offset)); + break; + } + case ATTRIBUTE_TYPE: + { + this->logger->log(this->logger,CONTROL_MORE,"Generate Attribute Type field"); + // the attribute type is a 15 bit integer so it has to be generated special + status = this->generate_u_int_type(this,ATTRIBUTE_TYPE,rules[i].offset); + break; + } + case ATTRIBUTE_LENGTH_OR_VALUE: + { + this->logger->log(this->logger,CONTROL_MORE,"Generate Attribute Length or Value field"); + if (this->attribute_format == FALSE) + { + status = this->generate_u_int_type(this,U_INT_16,rules[i].offset); + /* this field hold the length of the attribute */ + this->attribute_length = *((u_int16_t *)(this->data_struct + rules[i].offset)); + } + else + { + status = this->write_bytes_to_buffer(this,(this->data_struct + rules[i].offset),2); + } break; + } + case ATTRIBUTE_VALUE: + { + if (this->attribute_format == FALSE) + { + this->logger->log(this->logger,CONTROL_MORE,"Attribute value has not fixed size"); + /* the attribute value is generated */ + status = this->generate_from_chunk(this,rules[i].offset); + } + break; + } + default: + return NOT_SUPPORTED; } } return status; - - return NOT_SUPPORTED; } /** @@ -526,6 +629,7 @@ generator_t * generator_create() this->generate_u_int_type = generate_u_int_type; this->generate_reserved_field = generate_reserved_field; this->generate_flag = generate_flag; + this->generate_from_chunk = generate_from_chunk; this->make_space_available = make_space_available; this->write_bytes_to_buffer = write_bytes_to_buffer; diff --git a/Source/charon/payloads/payload.c b/Source/charon/payloads/payload.c index af0eb7839..bbb1a5d06 100644 --- a/Source/charon/payloads/payload.c +++ b/Source/charon/payloads/payload.c @@ -54,6 +54,7 @@ mapping_t payload_type_t_mappings[] = { {HEADER, "HEADER"}, {PROPOSAL_SUBSTRUCTURE, "PROPOSAL_SUBSTRUCTURE"}, {TRANSFORM_SUBSTRUCTURE, "TRANSFORM_SUBSTRUCTURE"}, + {TRANSFORM_ATTRIBUTE, "TRANSFORM_ATTRIBUTE"}, {MAPPING_END, NULL} }; diff --git a/Source/charon/payloads/transform_attribute.c b/Source/charon/payloads/transform_attribute.c index 1681eb564..dfdd4072b 100644 --- a/Source/charon/payloads/transform_attribute.c +++ b/Source/charon/payloads/transform_attribute.c @@ -59,7 +59,7 @@ struct private_transform_attribute_s { /** * Attribute Length if attribute_format is 0, attribute Value otherwise */ - u_int8_t attribute_length_or_value; + u_int16_t attribute_length_or_value; /** * Attribute value as chunk if attribute_format is 0 (FALSE) @@ -144,6 +144,71 @@ static size_t get_length(private_transform_attribute_t *this) } return (this->attribute_length_or_value + 4); } +/** + * Implements transform_attribute_t's set_value function. + * See #transform_attribute_s.set_value for description. + */ +static status_t set_value (private_transform_attribute_t *this, chunk_t value) +{ + if (value.len > 2) + { + this->attribute_value.ptr = allocator_clone_bytes(value.ptr,value.len); + if (this->attribute_value.ptr == NULL) + { + return OUT_OF_RES; + } + this->attribute_value.len = value.len; + this->attribute_length_or_value = value.len; + /* attribute has not a fixed length */ + this->attribute_format = FALSE; + } + else + { + memcpy(&(this->attribute_length_or_value),value.ptr,value.len); + } + return SUCCESS; +} + +/** + * Implements transform_attribute_t's get_value function. + * See #transform_attribute_s.get_value for description. + */ +static chunk_t get_value (private_transform_attribute_t *this) +{ + chunk_t value; + + if (this->attribute_format == FALSE) + { + value.ptr = this->attribute_value.ptr; + value.len = this->attribute_value.len; + } + else + { + value.ptr = (void *) &(this->attribute_length_or_value); + value.len = 2; + } + + return value; +} + +/** + * Implements transform_attribute_t's set_attribute_type function. + * See #transform_attribute_s.set_attribute_type for description. + */ +static status_t set_attribute_type (private_transform_attribute_t *this, u_int16_t type) +{ + this->attribute_type = type & 0x7FFF; + return SUCCESS; +} + +/** + * Implements transform_attribute_t's get_attribute_type function. + * See #transform_attribute_s.get_attribute_type for description. + */ +static u_int16_t get_attribute_type (private_transform_attribute_t *this) +{ + return this->attribute_type; +} /* * Described in header @@ -161,6 +226,10 @@ transform_attribute_t *transform_attribute_create() this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type; this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type; this->public.payload_interface.destroy = (status_t (*) (payload_t *))destroy; + this->public.set_value = (status_t (*) (transform_attribute_t *,chunk_t value)) set_value; + this->public.get_value = (chunk_t (*) (transform_attribute_t *)) get_value; + this->public.set_attribute_type = (status_t (*) (transform_attribute_t *,u_int16_t type)) set_attribute_type; + this->public.get_attribute_type = (u_int16_t (*) (transform_attribute_t *)) get_attribute_type; this->public.destroy = (status_t (*) (transform_attribute_t *)) destroy; /* set default values of the fields */ diff --git a/Source/charon/payloads/transform_attribute.h b/Source/charon/payloads/transform_attribute.h index 8bfb4fd13..c0355a424 100644 --- a/Source/charon/payloads/transform_attribute.h +++ b/Source/charon/payloads/transform_attribute.h @@ -41,6 +41,46 @@ struct transform_attribute_s { * implements payload_t interface */ payload_t payload_interface; + + /** + * @brief Returns the currently set value of the attribute + * + * @warning Returned data are not copied + * + * @param this calling transform_attribute_t object + * @return chunk_t pointing to the value + */ + chunk_t (*get_value) (transform_attribute_t *this); + + /** + * @brief Sets the value of the attribute. + * + * @warning Value is getting copied + * + * @param this calling transform_attribute_t object + * @param value chunk_t pointing to the value to set + * @return + * - SUCCESS or + * - OUT_OF_RES + */ + status_t (*set_value) (transform_attribute_t *this, chunk_t value); + + /** + * @brief Sets the type of the attribute. + * + * @param this calling transform_attribute_t object + * @param type type to set (most significant bit is set to zero) + * @return SUCCESS + */ + status_t (*set_attribute_type) (transform_attribute_t *this, u_int16_t type); + + /** + * @brief get the type of the attribute. + * + * @param this calling transform_attribute_t object + * @return type of the value + */ + u_int16_t (*get_attribute_type) (transform_attribute_t *this); /** * @brief Destroys an transform_attribute_t object. diff --git a/Source/charon/testcases/generator_test.c b/Source/charon/testcases/generator_test.c index 49c90182d..038dc26d5 100644 --- a/Source/charon/testcases/generator_test.c +++ b/Source/charon/testcases/generator_test.c @@ -31,6 +31,7 @@ #include "../utils/logger.h" #include "../payloads/encodings.h" #include "../payloads/ike_header.h" +#include "../payloads/transform_attribute.h" /* * Described in Header @@ -125,3 +126,103 @@ void test_generator_with_header_payload(tester_t *tester) global_logger_manager->destroy_logger(global_logger_manager,logger); tester->assert_true(tester,(generator->destroy(generator) == SUCCESS), "generator destroy call check"); } + +/* + * Described in header + */ +void test_generator_with_transform_attribute(tester_t *tester) +{ + generator_t *generator; + transform_attribute_t *attribute; + status_t status; + chunk_t generated_data; + logger_t *logger; + + logger = global_logger_manager->create_logger(global_logger_manager,TESTER,"header payload"); + + + /* test empty attribute */ + generator = generator_create(); + tester->assert_true(tester,(generator != NULL), "generator create check"); + attribute = transform_attribute_create(); + status = generator->generate_payload(generator,(payload_t *)attribute); + tester->assert_true(tester,(status == SUCCESS),"generate_payload call check"); + tester->assert_true(tester,(generator->write_to_chunk(generator,&generated_data) == SUCCESS),"write_to_chunk call check"); + logger->log_chunk(logger,RAW,"generated attribute",&generated_data); + + u_int8_t expected_generation[] = { + 0x80,0x00,0x00,0x00, + }; + tester->assert_true(tester,(memcmp(expected_generation,generated_data.ptr,sizeof(expected_generation)) == 0), "compare generated data"); + allocator_free_chunk(generated_data); + tester->assert_true(tester,(attribute->destroy(attribute) == SUCCESS), "attribute destroy call check"); + tester->assert_true(tester,(generator->destroy(generator) == SUCCESS), "generator destroy call check"); + + /* test attribute with 2 byte data */ + generator = generator_create(); + tester->assert_true(tester,(generator != NULL), "generator create check"); + + attribute = transform_attribute_create(); + u_int16_t dataval = 5768; + chunk_t data; + data.ptr = (void *) &dataval; + data.len = 2; + + attribute->set_value(attribute,data); + + status = generator->generate_payload(generator,(payload_t *)attribute); + tester->assert_true(tester,(status == SUCCESS),"generate_payload call check"); + tester->assert_true(tester,(generator->write_to_chunk(generator,&generated_data) == SUCCESS),"write_to_chunk call check"); + logger->log_chunk(logger,RAW,"generated attribute",&generated_data); + + u_int8_t expected_generation2[] = { + 0x80,0x00,0x88,0x16, + }; + tester->assert_true(tester,(memcmp(expected_generation2,generated_data.ptr,sizeof(expected_generation2)) == 0), "compare generated data"); + + allocator_free_chunk(generated_data); + tester->assert_true(tester,(attribute->destroy(attribute) == SUCCESS), "attribute destroy call check"); + tester->assert_true(tester,(generator->destroy(generator) == SUCCESS), "generator destroy call check"); + + + + /* test attribute with 25 byte data */ + generator = generator_create(); + tester->assert_true(tester,(generator != NULL), "generator create check"); + + attribute = transform_attribute_create(); + char *stringval = "ddddddddddeeeeeeeeeefffff"; + data.ptr = (void *) stringval; + data.len = 25; + + status = attribute->set_value(attribute,data); + tester->assert_true(tester,(status == SUCCESS),"set_value call check"); + + status = attribute->set_attribute_type(attribute,456); + tester->assert_true(tester,(status == SUCCESS),"set_attribute_type call check"); + + + status = generator->generate_payload(generator,(payload_t *)attribute); + tester->assert_true(tester,(status == SUCCESS),"generate_payload call check"); + tester->assert_true(tester,(generator->write_to_chunk(generator,&generated_data) == SUCCESS),"write_to_chunk call check"); + logger->log_chunk(logger,RAW,"generated attribute",&generated_data); + + u_int8_t expected_generation3[] = { + 0x01,0xC8,0x00,0x19, + 0x64,0x64,0x64,0x64, + 0x64,0x64,0x64,0x64, + 0x64,0x64,0x65,0x65, + 0x65,0x65,0x65,0x65, + 0x65,0x65,0x65,0x65, + 0x66,0x66,0x66,0x66, + 0x66 + }; + tester->assert_true(tester,(memcmp(expected_generation3,generated_data.ptr,sizeof(expected_generation3)) == 0), "compare generated data"); + + allocator_free_chunk(generated_data); + tester->assert_true(tester,(attribute->destroy(attribute) == SUCCESS), "attribute destroy call check"); + tester->assert_true(tester,(generator->destroy(generator) == SUCCESS), "generator destroy call check"); + + + global_logger_manager->destroy_logger(global_logger_manager,logger); +} diff --git a/Source/charon/testcases/generator_test.h b/Source/charon/testcases/generator_test.h index 6727cf9b9..ac574f450 100644 --- a/Source/charon/testcases/generator_test.h +++ b/Source/charon/testcases/generator_test.h @@ -33,4 +33,12 @@ */ void test_generator_with_header_payload(tester_t *tester); +/** + * @brief Test function used to test the generator with transform attribute payload + * + * + * @param tester associated tester object + */ +void test_generator_with_transform_attribute(tester_t *tester); + #endif /*GENERATOR_TEST_H_*/ |