- transform_substructure fully implemented
authorJan Hutter <jhutter@hsr.ch>
Mon, 14 Nov 2005 15:29:35 +0000 (15:29 -0000)
committerJan Hutter <jhutter@hsr.ch>
Mon, 14 Nov 2005 15:29:35 +0000 (15:29 -0000)
- generator now generates ransform_substructure and containing attributes
- test for transform substructure written

Source/charon/generator.c
Source/charon/payloads/transform_substructure.c
Source/charon/payloads/transform_substructure.h
Source/charon/testcases/generator_test.c
Source/charon/testcases/generator_test.h
Source/charon/testcases/testcases.c

index f4d3ad8..8737157 100644 (file)
 
 #include "types.h"
 #include "utils/allocator.h"
+#include "utils/linked_list.h"
 #include "utils/logger_manager.h"
 #include "payloads/payload.h"
+#include "payloads/transform_substructure.h"
 
 
 extern logger_manager_t *global_logger_manager;
@@ -139,6 +141,21 @@ struct private_generator_s {
        
        
        /**
+        * Writes a specific amount of byte into the buffer at a specific offset.
+        * 
+        * @warning buffer size is not check to hold the data if offset is to large.
+        *
+        * @param this                          calling private_generator_t object
+        * @param bytes                                 pointer to bytes to write
+        * @param number_of_bytes       number of bytes to write into buffer
+        * @param offset                                offset to write the data into
+        * @return 
+        *                                                      - SUCCESSFUL if succeeded
+        *                                                      - OUT_OF_RES otherwise
+        */
+       status_t (*write_bytes_to_buffer_at_offset) (private_generator_t *this,void * bytes,size_t number_of_bytes,u_int32_t offset);
+       
+       /**
         * Buffer used to generate the data into.
         */
        u_int8_t *buffer;
@@ -164,6 +181,11 @@ struct private_generator_s {
        void * data_struct;
        
        /*
+        * Last payload length position offset in the buffer
+        */
+       u_int32_t last_payload_length_position_offset;
+       
+       /*
         * Attribute format of the last generated transform attribute
         * 
         * Used to check if a variable value field is used or not for 
@@ -462,6 +484,26 @@ static status_t write_bytes_to_buffer (private_generator_t *this,void * bytes,si
 }
 
 /**
+ * Implements private_generator_t's write_bytes_to_buffer_at_offset function.
+ * See #private_generator_s.write_bytes_to_buffer_at_offset.
+ * TODO automatic buffer increasing!
+ */
+static status_t write_bytes_to_buffer_at_offset (private_generator_t *this,void * bytes,size_t number_of_bytes,u_int32_t offset)
+{
+       u_int8_t *read_position = (u_int8_t *) bytes;
+       int i;
+       u_int8_t *write_position = this->buffer + offset;
+       
+       for (i = 0; i < number_of_bytes; i++)
+       {
+               *(write_position) = *(read_position);
+               read_position++;
+               write_position++;
+       }
+       return SUCCESS;
+}
+
+/**
  * Implements generator_t's write_chunk function.
  * See #generator_s.write_chunk.
  */
@@ -534,6 +576,7 @@ static status_t generate_payload (private_generator_t *this,payload_t *payload)
                        }
                        case PAYLOAD_LENGTH:
                                /* payload length is generated like an U_INT_16 */
+                               this->last_payload_length_position_offset = (this->out_position - this->buffer);
                                status = this->generate_u_int_type(this,U_INT_16,rules[i].offset);
                                break;
 
@@ -543,7 +586,53 @@ static status_t generate_payload (private_generator_t *this,payload_t *payload)
                                break;
                        case SPI_SIZE:
                                /* currently not implemented */
+                               break;
+                       case TRANSFORM_ATTRIBUTES:
+                       {
+                               this->logger->log(this->logger,CONTROL_MORE,"Generate Transform attributes");
+                               /* before iterative generate the transforms, store the current length position */
+                               u_int32_t transform_length_position_offset = this->last_payload_length_position_offset;
+
+                               u_int16_t length_of_transform = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
+                               u_int16_t int16_val;
+                               linked_list_t *transform_attributes =*((linked_list_t **)(this->data_struct + rules[i].offset));
+
+                               linked_list_iterator_t *iterator;
+                               /* create forward iterator */
+                               status = transform_attributes->create_iterator(transform_attributes,&iterator,TRUE);
+                               if (status != SUCCESS)
+                               {
+                                       return status;
+                               }
+                               while (iterator->has_next(iterator))
+                               {
+                                       payload_t *current_attribute;
+                                       u_int32_t before_generate_position_offset;
+                                       u_int32_t after_generate_position_offset;
+                                       status = iterator->current(iterator,(void **)&current_attribute);
+                                       if (status != SUCCESS)
+                                       {
+                                               iterator->destroy(iterator);    
+                                               return status;
+                                       }
+                                       
+                                       before_generate_position_offset = (this->out_position - this->buffer);
+                                       this->public.generate_payload(&(this->public),current_attribute);
+                                       after_generate_position_offset = (this->out_position - this->buffer);
+                                       
+                                       /* increase size of transform */
+                                       length_of_transform += (after_generate_position_offset - before_generate_position_offset);
+                               }
+                               
+                               iterator->destroy(iterator);
                                
+                               this->logger->log(this->logger,CONTROL_MORE,"Length of Transform is %d, offset is %d",length_of_transform,transform_length_position_offset);
+                               
+                               int16_val = htons(length_of_transform);
+                               this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),transform_length_position_offset);
+                               
+                               break;
+                       }       
                        case ATTRIBUTE_FORMAT:
                        {
                                this->logger->log(this->logger,CONTROL_MORE,"Generate Attribute Format flag");
@@ -632,6 +721,7 @@ generator_t * generator_create()
        this->generate_from_chunk = generate_from_chunk;
        this->make_space_available = make_space_available;
        this->write_bytes_to_buffer = write_bytes_to_buffer;
+       this->write_bytes_to_buffer_at_offset = write_bytes_to_buffer_at_offset;
 
 
        /* allocate memory for buffer */
@@ -647,6 +737,7 @@ generator_t * generator_create()
        this->roof_position = this->buffer + GENERATOR_DATA_BUFFER_SIZE;
        this->data_struct = NULL;
        this->current_bit = 0;
+       this->last_payload_length_position_offset = 0;
        this->logger = global_logger_manager->create_logger(global_logger_manager,GENERATOR,NULL);
        return &(this->public);
 }
index 6a302fb..9313ff5 100644 (file)
@@ -65,12 +65,12 @@ struct private_transform_substructure_s {
        /**
         * Transform ID
         */
-       u_int8_t transform_id;
+       u_int16_t transform_id;
        
        /**
         * Transforms Attributes are stored in a linked_list_t
         */
-       linked_list_t * attributes;
+       linked_list_t *attributes;
 };
 
 
@@ -93,7 +93,7 @@ encoding_rule_t transform_substructure_encodings[] = {
        /* Reserved Byte is skipped */
        { RESERVED_BYTE,                0                                                                                                                               },      
        /* tranform ID is a number of 8 bit */
-       { U_INT_8,                              offsetof(private_transform_substructure_t, transform_id)                },      
+       { U_INT_16,                             offsetof(private_transform_substructure_t, transform_id)                },      
        /* Attributes are stored in a transform attribute, 
           offset points to a linked_list_t pointer */
        { TRANSFORM_ATTRIBUTES, offsetof(private_transform_substructure_t, attributes)          }
@@ -158,6 +158,21 @@ static payload_type_t get_next_type(private_transform_substructure_t *this)
  */
 static size_t get_length(private_transform_substructure_t *this)
 {
+       linked_list_iterator_t *iterator;
+       status_t status;
+       size_t length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
+       status = this->attributes->create_iterator(this->attributes,&iterator,TRUE);
+       if (status != SUCCESS)
+       return length;
+       while (iterator->has_next(iterator))
+       {
+               payload_t * current_attribute;
+               iterator->current(iterator,(void **) &current_attribute);
+               length += current_attribute->get_length(current_attribute);
+       }
+       
+       this->transform_length = length;
+               
        return this->transform_length;
 }
 
@@ -177,8 +192,66 @@ static status_t create_transform_attribute_iterator (private_transform_substruct
 static status_t add_transform_attribute (private_transform_substructure_t *this,transform_attribute_t *attribute)
 {
        return (this->attributes->insert_last(this->attributes,(void *) attribute));
+       this->transform_length += ((payload_t *)this->attributes)->get_length(((payload_t *)this->attributes));
+       return SUCCESS;
+}
+
+/**
+ * Implements transform_substructure_t's set_is_last_transform function.
+ * See #transform_substructure_s.set_is_last_transform for description.
+ */
+static status_t set_is_last_transform (private_transform_substructure_t *this, bool is_last)
+{
+       this->next_payload = (is_last) ? 0 : TRANSFORM_TYPE_VALUE;
+       return SUCCESS;
+}
+
+/**
+ * Implements transform_substructure_t's get_is_last_transform function.
+ * See #transform_substructure_s.get_is_last_transform for description.
+ */
+static bool get_is_last_transform (private_transform_substructure_t *this)
+{
+       return ((this->next_payload == TRANSFORM_TYPE_VALUE) ? FALSE : TRUE);
+}
+
+/**
+ * Implements transform_substructure_t's set_transform_type function.
+ * See #transform_substructure_s.set_transform_type for description.
+ */
+static status_t set_transform_type (private_transform_substructure_t *this,u_int8_t type)
+{
+       this->transform_type = type;
+       return SUCCESS;
+}
+       
+/**
+ * Implements transform_substructure_t's get_transform_type function.
+ * See #transform_substructure_s.get_transform_type for description.
+ */
+static u_int8_t get_transform_type (private_transform_substructure_t *this)
+{
+       return this->transform_type;
 }
 
+/**
+ * Implements transform_substructure_t's set_transform_id function.
+ * See #transform_substructure_s.set_transform_id for description.
+ */
+static status_t set_transform_id (private_transform_substructure_t *this,u_int16_t id)
+{
+       this->transform_id = id;
+       return SUCCESS;
+}
+       
+/**
+ * Implements transform_substructure_t's get_transform_id function.
+ * See #transform_substructure_s.get_transform_id for description.
+ */
+static u_int16_t get_transform_id (private_transform_substructure_t *this)
+{
+       return this->transform_id;
+}
 
 /*
  * Described in header
@@ -198,11 +271,17 @@ transform_substructure_t *transform_substructure_create()
        this->public.payload_interface.destroy = (status_t (*) (payload_t *))destroy;
        this->public.create_transform_attribute_iterator = (status_t (*) (transform_substructure_t *,linked_list_iterator_t **,bool)) create_transform_attribute_iterator;
        this->public.add_transform_attribute = (status_t (*) (transform_substructure_t *,transform_attribute_t *)) add_transform_attribute;
+       this->public.set_is_last_transform = (status_t (*) (transform_substructure_t *,bool)) set_is_last_transform;
+       this->public.get_is_last_transform = (bool (*) (transform_substructure_t *)) get_is_last_transform;
+       this->public.set_transform_type = (status_t (*) (transform_substructure_t *,u_int8_t)) set_transform_type;
+       this->public.get_transform_type = (u_int8_t (*) (transform_substructure_t *)) get_transform_type;
+       this->public.set_transform_id = (status_t (*) (transform_substructure_t *,u_int16_t)) set_transform_id;
+       this->public.get_transform_id = (u_int16_t (*) (transform_substructure_t *)) get_transform_id;
        this->public.destroy = (status_t (*) (transform_substructure_t *)) destroy;
        
        /* set default values of the fields */
        this->next_payload = NO_PAYLOAD;
-       this->transform_length = 0;
+       this->transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
        this->transform_id = 0;
        this->transform_type = 0;
 
index 0454ad6..ba49880 100644 (file)
 #include "transform_attribute.h"
 
 /**
+ * IKEv1 Value for a transform payload
+ */
+#define TRANSFORM_TYPE_VALUE 3
+
+/**
+ * Length of the transform substructure header in bytes
+ */
+#define TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH 8
+
+/**
  * Object representing an IKEv2- TRANSFORM SUBSTRUCTURE
  * 
  * The TRANSFORM SUBSTRUCTURE format is described in RFC section 3.3.2.
@@ -48,6 +58,9 @@ struct transform_substructure_s {
         * @brief Creates an iterator of stored transform_attribute_t objects.
         * 
         * @warning The created iterator has to get destroyed by the caller!
+        * 
+        * @warning When deleting an transform attribute, the length of this transform substructure
+        *                      has to be refreshed with get_length!
         *
         * @param this                  calling transform_substructure_t object
         * @param iterator              the created iterator is stored at the pointed pointer
@@ -72,6 +85,60 @@ struct transform_substructure_s {
        status_t (*add_transform_attribute) (transform_substructure_t *this,transform_attribute_t *attribute);
        
        /**
+        * @brief Sets the next_payload field of this substructure
+        * 
+        * If this is the last transform, next payload field is set to 0,
+        * otherwise to 3 (payload type of transform in IKEv1)
+        *
+        * @param this          calling transform_substructure_t object
+        * @param is_last       When TRUE, next payload field is set to 0, otherwise to 3
+        * @return                      - SUCCESS
+        */
+       status_t (*set_is_last_transform) (transform_substructure_t *this, bool is_last);
+       
+       /**
+        * @brief Checks if this is the last transform.
+        * 
+        * @param this          calling transform_substructure_t object
+        * @return                      TRUE if this is the last Transform, FALSE otherwise
+        */
+       bool (*get_is_last_transform) (transform_substructure_t *this);
+       
+       /**
+        * @brief Sets transform type of the current transform substructure.
+        *
+        * @param this          calling transform_substructure_t object
+        * @param type          type value to set
+        * @return                      - SUCCESS
+        */
+       status_t (*set_transform_type) (transform_substructure_t *this,u_int8_t type);
+       
+       /**
+        * @brief get transform type of the current transform.
+        * 
+        * @param this          calling transform_substructure_t object
+        * @return                      Transform type of current transform substructure.
+        */
+       u_int8_t (*get_transform_type) (transform_substructure_t *this);
+       
+       /**
+        * @brief Sets transform id of the current transform substructure.
+        *
+        * @param this          calling transform_substructure_t object
+        * @param id                    transform id to set
+        * @return                      - SUCCESS
+        */
+       status_t (*set_transform_id) (transform_substructure_t *this,u_int16_t id);
+       
+       /**
+        * @brief get transform id of the current transform.
+        * 
+        * @param this          calling transform_substructure_t object
+        * @return                      Transform id of current transform substructure.
+        */
+       u_int16_t (*get_transform_id) (transform_substructure_t *this);
+
+       /**
         * @brief Destroys an transform_substructure_t object.
         *
         * @param this  transform_substructure_t object to destroy
index 038dc26..5ec4bca 100644 (file)
@@ -32,6 +32,7 @@
 #include "../payloads/encodings.h"
 #include "../payloads/ike_header.h"
 #include "../payloads/transform_attribute.h"
+#include "../payloads/transform_substructure.h"
 
 /*
  * Described in Header 
@@ -138,7 +139,7 @@ void test_generator_with_transform_attribute(tester_t *tester)
        chunk_t generated_data;
        logger_t *logger;
        
-       logger = global_logger_manager->create_logger(global_logger_manager,TESTER,"header payload");
+       logger = global_logger_manager->create_logger(global_logger_manager,TESTER,"transform_attribute payload");
        
        
        /* test empty attribute */
@@ -226,3 +227,84 @@ void test_generator_with_transform_attribute(tester_t *tester)
 
        global_logger_manager->destroy_logger(global_logger_manager,logger);    
 }
+
+
+
+/*
+ * Described in header
+ */ 
+void test_generator_with_transform_substructure(tester_t *tester)
+{
+       generator_t *generator;
+       transform_attribute_t *attribute1, *attribute2;
+       transform_substructure_t *transform;
+       chunk_t data;
+       status_t status;
+       chunk_t generated_data;
+       logger_t *logger;
+       
+       logger = global_logger_manager->create_logger(global_logger_manager,TESTER,"transform substr.");
+       
+       /* create generator */
+       generator = generator_create();
+       tester->assert_true(tester,(generator != NULL), "generator create check");
+
+       /* create attribute 1 */        
+       attribute1 = transform_attribute_create();
+       char *stringval = "abcd";
+       data.ptr = (void *) stringval;
+       data.len = 4;
+       status = attribute1->set_value(attribute1,data);
+       tester->assert_true(tester,(status == SUCCESS),"set_value call check");
+       status = attribute1->set_attribute_type(attribute1,0);
+       tester->assert_true(tester,(status == SUCCESS),"set_attribute_type call check");
+       logger->log(logger,CONTROL,"attribute1 created");
+
+       /* create attribute 2 */
+       attribute2 = transform_attribute_create();
+       stringval = "efgh";
+       data.ptr = (void *) stringval;
+       data.len = 4;
+       status = attribute2->set_value(attribute2,data);
+       tester->assert_true(tester,(status == SUCCESS),"set_value call check");
+       status = attribute2->set_attribute_type(attribute2,0);
+       tester->assert_true(tester,(status == SUCCESS),"set_attribute_type call check");
+       logger->log(logger,CONTROL,"attribute2 created");
+
+       /* create transform */
+       transform = transform_substructure_create();
+       tester->assert_true(tester,(transform != NULL), "transform create check");
+       status = transform->add_transform_attribute(transform,attribute1);
+       tester->assert_true(tester,(status == SUCCESS),"add_transform_attribute call check");
+       status = transform->add_transform_attribute(transform,attribute2);
+       tester->assert_true(tester,(status == SUCCESS),"add_transform_attribute call check");
+       status = transform->set_transform_type(transform,5); /* hex 5 */
+       tester->assert_true(tester,(status == SUCCESS),"set_transform_type call check");
+       status = transform->set_transform_id(transform,65000); /* hex FDE8 */
+       tester->assert_true(tester,(status == SUCCESS),"set_transform_id call check");
+       
+       
+       logger->log(logger,CONTROL,"transform created");
+
+       status = generator->generate_payload(generator,(payload_t *)transform);
+       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 transform",&generated_data);    
+
+       u_int8_t expected_generation3[] = {
+               0x00,0x00,0x00,0x18,
+               0x05,0x00,0xFD,0xE8,
+               0x00,0x00,0x00,0x04,
+               0x61,0x62,0x63,0x64,
+               0x00,0x00,0x00,0x04,
+               0x65,0x66,0x67,0x68,
+       };
+       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,(transform->destroy(transform) == SUCCESS), "transform destroy call check");
+       tester->assert_true(tester,(generator->destroy(generator) == SUCCESS), "generator destroy call check");
+       
+       
+       global_logger_manager->destroy_logger(global_logger_manager,logger);    
+}
index ac574f4..7031dae 100644 (file)
@@ -41,4 +41,14 @@ void test_generator_with_header_payload(tester_t *tester);
  */
 void test_generator_with_transform_attribute(tester_t *tester);
 
+
+/**
+ * @brief Test function used to test the generator with transform substructure payload
+ * 
+ *
+ * @param tester associated tester object
+ */
+void test_generator_with_transform_substructure(tester_t *tester);
+
+
 #endif /*GENERATOR_TEST_H_*/
index ac5ca5e..10f036d 100644 (file)
@@ -43,7 +43,7 @@
 #include "ike_sa_test.h"
 #include "ike_sa_manager_test.h"
 #include "generator_test.h"
-#include "parser_test.h"
+//#include "parser_test.h"
 #include "packet_test.h"
 
 
@@ -122,14 +122,24 @@ test_t ike_sa_test = {test_ike_sa,"IKE_SA"};
 test_t ike_sa_manager_test = {test_ike_sa_manager, "IKE_SA-Manager"};
 
 /**
+ * Test 1 for generator_t
+ */
+test_t generator_test1 = {test_generator_with_header_payload,"Generator: header payload"};
+/**
  * Test 2 for generator_t
  */
-test_t generator_test2 = {test_generator_with_header_payload,"Generator: header payload"};
+test_t generator_test2 = {test_generator_with_transform_attribute,"Generator: transform attribute"};
+
+/**
+ * Test 3 for generator_t
+ */
+test_t generator_test3 = {test_generator_with_transform_substructure,"Generator: transform substructure"};
+
 
 /**
  * Test 2 for generator_t
  */
-test_t parser_test = {test_parser_with_header_payload, "Parser: header payload"};
+//test_t parser_test = {test_parser_with_header_payload, "Parser: header payload"};
 
 
 /**
@@ -182,13 +192,15 @@ logger_manager_t *global_logger_manager;
        &receiver_test,
        &ike_sa_id_test,
        &ike_sa_test,
+       &generator_test1,
        &generator_test2,
-       &parser_test,
+       &generator_test3,
+//     &parser_test,
        &ike_sa_manager_test,
        &packet_test,
        NULL
        };
-       global_logger_manager = logger_manager_create(CONTROL);
+       global_logger_manager = logger_manager_create(ALL);
        
        global_socket = socket_create(4600);
        
@@ -200,8 +212,8 @@ logger_manager_t *global_logger_manager;
                
        tester_t *tester = tester_create(test_output, FALSE);
 
-       tester->perform_tests(tester,all_tests);
-       //tester->perform_test(tester,&parser_test);   
+       //tester->perform_tests(tester,all_tests);
+       tester->perform_test(tester,&generator_test3);   
        
        tester->destroy(tester);