aboutsummaryrefslogtreecommitdiffstats
path: root/Source/charon/encoding
diff options
context:
space:
mode:
Diffstat (limited to 'Source/charon/encoding')
-rw-r--r--Source/charon/encoding/generator.c1125
-rw-r--r--Source/charon/encoding/generator.h89
-rw-r--r--Source/charon/encoding/message.c877
-rw-r--r--Source/charon/encoding/message.h280
-rw-r--r--Source/charon/encoding/parser.c923
-rw-r--r--Source/charon/encoding/parser.h88
-rw-r--r--Source/charon/encoding/payloads/encodings.c54
-rw-r--r--Source/charon/encoding/payloads/encodings.h359
-rw-r--r--Source/charon/encoding/payloads/ike_header.c446
-rw-r--r--Source/charon/encoding/payloads/ike_header.h242
-rw-r--r--Source/charon/encoding/payloads/ke_payload.c319
-rw-r--r--Source/charon/encoding/payloads/ke_payload.h120
-rw-r--r--Source/charon/encoding/payloads/nonce_payload.c271
-rw-r--r--Source/charon/encoding/payloads/nonce_payload.h93
-rw-r--r--Source/charon/encoding/payloads/notify_payload.c419
-rw-r--r--Source/charon/encoding/payloads/notify_payload.h159
-rw-r--r--Source/charon/encoding/payloads/payload.c92
-rw-r--r--Source/charon/encoding/payloads/payload.h240
-rw-r--r--Source/charon/encoding/payloads/proposal_substructure.c512
-rw-r--r--Source/charon/encoding/payloads/proposal_substructure.h186
-rw-r--r--Source/charon/encoding/payloads/sa_payload.c343
-rw-r--r--Source/charon/encoding/payloads/sa_payload.h110
-rw-r--r--Source/charon/encoding/payloads/transform_attribute.c363
-rw-r--r--Source/charon/encoding/payloads/transform_attribute.h153
-rw-r--r--Source/charon/encoding/payloads/transform_substructure.c577
-rw-r--r--Source/charon/encoding/payloads/transform_substructure.h298
26 files changed, 8738 insertions, 0 deletions
diff --git a/Source/charon/encoding/generator.c b/Source/charon/encoding/generator.c
new file mode 100644
index 000000000..734c089a0
--- /dev/null
+++ b/Source/charon/encoding/generator.c
@@ -0,0 +1,1125 @@
+/**
+ * @file generator.c
+ *
+ * @brief Generic generator class used to generate IKEv2-header and payloads.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+
+
+#include "generator.h"
+
+#include <types.h>
+#include <globals.h>
+#include <utils/allocator.h>
+#include <utils/linked_list.h>
+#include <utils/logger_manager.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/proposal_substructure.h>
+#include <encoding/payloads/transform_substructure.h>
+#include <encoding/payloads/sa_payload.h>
+#include <encoding/payloads/ke_payload.h>
+#include <encoding/payloads/notify_payload.h>
+#include <encoding/payloads/nonce_payload.h>
+
+/**
+ * Private part of a generator_t object
+ */
+typedef struct private_generator_s private_generator_t;
+
+struct private_generator_s {
+ /**
+ * Public part of a generator_t object
+ */
+ generator_t public;
+
+ /* private functions and fields */
+
+
+ /**
+ * Generates a U_INT-Field type and writes it to buffer.
+ *
+ * @param this private_generator_t object
+ * @param int_type type of U_INT field (U_INT_4, U_INT_8, etc.)
+ * ATTRIBUTE_TYPE is also generated in this function
+ * @param offset offset of value in data struct
+ * @param generator_contexts generator_contexts_t object where the context is written or read from
+ * @return - SUCCESS if succeeded
+ * - OUT_OF_RES if out of ressources
+ */
+ status_t (*generate_u_int_type) (private_generator_t *this,encoding_type_t int_type,u_int32_t offset);
+
+ /**
+ * Get size of current buffer in bytes.
+ *
+ * @param this private_generator_t object
+ * @return Size of buffer in bytes
+ */
+ size_t (*get_current_buffer_size) (private_generator_t *this);
+
+ /**
+ * Get free space of current buffer in bytes.
+ *
+ * @param this private_generator_t object
+ * @return space in buffer in bytes
+ */
+ size_t (*get_current_buffer_space) (private_generator_t *this);
+
+ /**
+ * Get length of data in buffer (in bytes).
+ *
+ * @param this private_generator_t object
+ * @return length of data in bytes
+ */
+ size_t (*get_current_data_length) (private_generator_t *this);
+
+ /**
+ * Get current offset in buffer (in bytes).
+ *
+ * @param this private_generator_t object
+ * @return offset in bytes
+ */
+ u_int32_t (*get_current_buffer_offset) (private_generator_t *this);
+
+ /**
+ * Generates a RESERVED BIT field or a RESERVED BYTE field and writes
+ * it to the buffer.
+ *
+ * @param this private_generator_t object
+ * @param generator_contexts generator_contexts_t object where the context is written or read from
+ * @param bits number of bits to generate
+ * @return - SUCCESS if succeeded
+ * - OUT_OF_RES if out of ressources
+ * - FAILED if bit count not supported
+ */
+ status_t (*generate_reserved_field) (private_generator_t *this,int bits);
+
+ /**
+ * Generates a FLAG field
+ *
+ * @param this private_generator_t object
+ * @param generator_contexts generator_contexts_t object where the context is written or read from
+ * @param offset offset of flag value in data struct
+ * @return - SUCCESS if succeeded
+ * - OUT_OF_RES if out of ressources
+ */
+ status_t (*generate_flag) (private_generator_t *this,u_int32_t offset);
+
+ /**
+ * Writes the current buffer content into a chunk_t
+ *
+ * Memory of specific chunk_t gets allocated.
+ *
+ * @param this calling private_generator_t object
+ * @param data pointer of chunk_t to write to
+ * @return
+ * - SUCCESSFUL if succeeded
+ * - OUT_OF_RES otherwise
+ */
+ 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.
+ *
+ * If buffer is to small to hold the specific amount of bits it
+ * is increased using reallocation function of allocator.
+ *
+ * @param this calling private_generator_t object
+ * @param bits number of bits to make available in buffer
+ * @return
+ * - SUCCESSFUL if succeeded
+ * - OUT_OF_RES otherwise
+ */
+ status_t (*make_space_available) (private_generator_t *this,size_t bits);
+
+ /**
+ * Writes a specific amount of byte into the buffer.
+ *
+ * If buffer is to small to hold the specific amount of bytes it
+ * is increased.
+ *
+ * @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
+ * @return
+ * - SUCCESSFUL if succeeded
+ * - OUT_OF_RES otherwise
+ */
+ status_t (*write_bytes_to_buffer) (private_generator_t *this,void * bytes,size_t number_of_bytes);
+
+
+ /**
+ * 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;
+
+ /**
+ * Current write position in buffer (one byte aligned).
+ */
+ u_int8_t *out_position;
+
+ /**
+ * Position of last byte in buffer.
+ */
+ u_int8_t *roof_position;
+
+ /**
+ * Current bit writing to in current byte (between 0 and 7).
+ */
+ size_t current_bit;
+
+ /**
+ * Associated data struct to read informations from.
+ */
+ void * data_struct;
+
+ /*
+ * Last payload length position offset in the buffer
+ */
+ u_int32_t last_payload_length_position_offset;
+
+ /**
+ * Offset of the header length field in the buffer
+ */
+ u_int32_t header_length_position_offset;
+
+ /**
+ * Last SPI size
+ */
+ u_int8_t last_spi_size;
+
+ /*
+ * 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
+ */
+ logger_t *logger;
+};
+
+/**
+ * Implements private_generator_t's get_current_buffer_size function.
+ * See #private_generator_s.get_current_buffer_size.
+ */
+static size_t get_current_buffer_size (private_generator_t *this)
+{
+ return ((this->roof_position) - (this->buffer));
+}
+
+/**
+ * Implements private_generator_t's get_current_buffer_space function.
+ * See #private_generator_s.get_current_buffer_space.
+ */
+static size_t get_current_buffer_space (private_generator_t *this)
+{
+ /* we know, one byte more */
+ size_t space = (this->roof_position) - (this->out_position);
+ return (space);
+}
+
+/**
+ * Implements private_generator_t's get_current_buffer_space function.
+ * See #private_generator_s.get_current_buffer_space.
+ */
+static size_t get_current_data_length (private_generator_t *this)
+{
+ return (this->out_position - this->buffer);
+}
+
+/**
+ * Implements private_generator_t's get_current_buffer_offset function.
+ * See #private_generator_s.get_current_buffer_offset.
+ */
+static u_int32_t get_current_buffer_offset (private_generator_t *this)
+{
+ return (this->out_position - this->buffer);
+}
+
+
+/**
+ * Implements private_generator_t's generate_u_int_type function.
+ * See #private_generator_s.generate_u_int_type.
+ */
+static status_t generate_u_int_type (private_generator_t *this,encoding_type_t int_type,u_int32_t offset)
+{
+ size_t number_of_bits = 0;
+ status_t status;
+
+ /* find out number of bits of each U_INT type to check for enough space
+ in buffer */
+ switch (int_type)
+ {
+ case U_INT_4:
+ number_of_bits = 4;
+ break;
+ case U_INT_8:
+ number_of_bits = 8;
+ break;
+ case U_INT_16:
+ number_of_bits = 16;
+ break;
+ case U_INT_32:
+ number_of_bits = 32;
+ break;
+ case U_INT_64:
+ number_of_bits = 64;
+ break;
+ case ATTRIBUTE_TYPE:
+ number_of_bits = 15;
+ break;
+ case IKE_SPI:
+ number_of_bits = 64;
+ break;
+
+ default:
+ return FAILED;
+ }
+ /* U_INT Types of multiple then 8 bits must be aligned */
+ if (((number_of_bits % 8) == 0) && (this->current_bit != 0))
+ {
+ this->logger->log(this->logger, ERROR, "U_INT Type %s is not 8 Bit aligned",
+ mapping_find(encoding_type_m,int_type));
+ /* current bit has to be zero for values multiple of 8 bits */
+ return FAILED;
+ }
+
+ /* make sure enough space is available in buffer */
+ status = this->make_space_available(this,number_of_bits);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ /* now handle each u int type differently */
+ switch (int_type)
+ {
+ case U_INT_4:
+ {
+ if (this->current_bit == 0)
+ {
+ /* highval of current byte in buffer has to be set to the new value*/
+ u_int8_t high_val = *((u_int8_t *)(this->data_struct + offset)) << 4;
+ /* lowval in buffer is not changed */
+ u_int8_t low_val = *(this->out_position) & 0x0F;
+ /* highval is set, low_val is not changed */
+ *(this->out_position) = high_val | low_val;
+ this->logger->log(this->logger, RAW|MOST, " => 0x%x", *(this->out_position));
+ /* write position is not changed, just bit position is moved */
+ this->current_bit = 4;
+ }
+ else if (this->current_bit == 4)
+ {
+ /* highval in buffer is not changed */
+ u_int high_val = *(this->out_position) & 0xF0;
+ /* lowval of current byte in buffer has to be set to the new value*/
+ u_int low_val = *((u_int8_t *)(this->data_struct + offset)) & 0x0F;
+ *(this->out_position) = high_val | low_val;
+ this->logger->log(this->logger, RAW|MOST, " => 0x%x", *(this->out_position));
+ this->out_position++;
+ this->current_bit = 0;
+
+ }
+ else
+ {
+ this->logger->log(this->logger, ERROR, "U_INT_4 Type is not 4 Bit aligned");
+ /* 4 Bit integers must have a 4 bit alignment */
+ return FAILED;
+ };
+ break;
+ }
+ case U_INT_8:
+ {
+ /* 8 bit values are written as they are */
+ *this->out_position = *((u_int8_t *)(this->data_struct + offset));
+ this->logger->log(this->logger, RAW|MOST, " => 0x%x", *(this->out_position));
+ this->out_position++;
+ break;
+
+ }
+ case ATTRIBUTE_TYPE:
+ {
+ /* attribute type must not change first bit uf current byte ! */
+ if (this->current_bit != 1)
+ {
+ this->logger->log(this->logger, ERROR, "ATTRIBUTE FORMAT flag is not set");
+ /* first bit has to be set! */
+ return FAILED;
+ }
+ /* get value of attribute format flag */
+ u_int8_t attribute_format_flag = *(this->out_position) & 0x80;
+ /* get attribute type value as 16 bit integer*/
+ u_int16_t int16_val = htons(*((u_int16_t*)(this->data_struct + offset)));
+ /* last bit must be unset */
+ int16_val = int16_val & 0xFF7F;
+
+ int16_val = int16_val | attribute_format_flag;
+ this->logger->log(this->logger, RAW|MOST, " => 0x%x", int16_val);
+ /* write bytes to buffer (set bit is overwritten)*/
+ 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)));
+ this->logger->log_bytes(this->logger, RAW|MOST, " =>", (void*)&int16_val, sizeof(int16_val));
+ this->write_bytes_to_buffer(this,&int16_val,sizeof(u_int16_t));
+ break;
+ }
+ case U_INT_32:
+ {
+ u_int32_t int32_val = htonl(*((u_int32_t*)(this->data_struct + offset)));
+ this->logger->log_bytes(this->logger, RAW|MOST, " =>", (void*)&int32_val, sizeof(int32_val));
+ this->write_bytes_to_buffer(this,&int32_val,sizeof(u_int32_t));
+ break;
+ }
+ case U_INT_64:
+ {
+ /* 64 bit integers are written as two 32 bit integers */
+ u_int32_t int32_val_low = htonl(*((u_int32_t*)(this->data_struct + offset)));
+ u_int32_t int32_val_high = htonl(*((u_int32_t*)(this->data_struct + offset) + 1));
+ this->logger->log_bytes(this->logger, RAW|MOST, " => (low)", (void*)&int32_val_low, sizeof(int32_val_low));
+ this->logger->log_bytes(this->logger, RAW|MOST, " => (high)", (void*)&int32_val_high, sizeof(int32_val_high));
+ /* TODO add support for big endian machines */
+ this->write_bytes_to_buffer(this,&int32_val_high,sizeof(u_int32_t));
+ this->write_bytes_to_buffer(this,&int32_val_low,sizeof(u_int32_t));
+ break;
+ }
+
+ case IKE_SPI:
+ {
+ /* 64 bit are written as they come :-) */
+ this->write_bytes_to_buffer(this,(this->data_struct + offset),sizeof(u_int64_t));
+ this->logger->log_bytes(this->logger, RAW|MOST, " =>", (void*)(this->data_struct + offset), sizeof(u_int64_t));
+ break;
+ }
+
+ default:
+ this->logger->log(this->logger, ERROR, "U_INT Type %s is not supported", mapping_find(encoding_type_m,int_type));
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implements private_generator_t's generate_reserved_field function.
+ * See #private_generator_s.generate_reserved_field.
+ */
+static status_t generate_reserved_field(private_generator_t *this,int bits)
+{
+ status_t status;
+
+ /* only one bit or 8 bit fields are supported */
+ if ((bits != 1) && (bits != 8))
+ {
+ this->logger->log(this->logger, ERROR, "Reserved field of %d bits cannot be generated", bits);
+ return FAILED;
+ }
+ /* make sure enough space is available in buffer */
+ status = this->make_space_available(this,bits);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+
+ if (bits == 1)
+ {
+ /* one bit processing */
+ u_int8_t reserved_bit = ~(1 << (7 - this->current_bit));
+ *(this->out_position) = *(this->out_position) & reserved_bit;
+ if (this->current_bit == 0)
+ {
+ /* memory must be zero */
+ *(this->out_position) = 0x00;
+ }
+
+
+ this->current_bit++;
+ if (this->current_bit >= 8)
+ {
+ this->current_bit = this->current_bit % 8;
+ this->out_position++;
+ }
+ }
+ else
+ {
+ /* one byte processing*/
+ if (this->current_bit > 0)
+ {
+ this->logger->log(this->logger, ERROR,
+ "Reserved field cannot be written cause allignement of current bit is %d",
+ this->current_bit);
+ return FAILED;
+ }
+ *(this->out_position) = 0x00;
+ this->out_position++;
+ }
+
+ return SUCCESS;
+
+
+}
+
+/**
+ * Implements private_generator_t's generate_flag function.
+ * See #private_generator_s.generate_flag.
+ */
+static status_t generate_flag (private_generator_t *this,u_int32_t offset)
+{
+ status_t status;
+ /* value of current flag */
+ u_int8_t flag_value;
+ /* position of flag in current byte */
+ u_int8_t flag;
+
+ /* if the value in the data_struct is TRUE, flag_value is set to 1, 0 otherwise */
+ flag_value = (*((bool *) (this->data_struct + offset))) ? 1 : 0;
+ /* get flag position */
+ flag = (flag_value << (7 - this->current_bit));
+
+ /* make sure one bit is available in buffer */
+ status = this->make_space_available(this,1);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ if (this->current_bit == 0)
+ {
+ /* memory must be zero */
+ *(this->out_position) = 0x00;
+ }
+
+ *(this->out_position) = *(this->out_position) | flag;
+
+
+ this->logger->log(this->logger, RAW|MOST, " => 0x0%x", *(this->out_position));
+
+ this->current_bit++;
+ if (this->current_bit >= 8)
+ {
+ this->current_bit = this->current_bit % 8;
+ this->out_position++;
+ }
+ return SUCCESS;
+}
+
+/**
+ * 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)
+ {
+ this->logger->log(this->logger, ERROR, "can not generate a chunk at Bitpos %d", this->current_bit);
+ return FAILED;
+ }
+
+ /* position in buffer */
+ chunk_t *attribute_value = (chunk_t *)(this->data_struct + offset);
+
+ this->logger->log_chunk(this->logger, RAW|MOST, " =>", attribute_value);
+
+ /* use write_bytes_to_buffer function to do the job */
+ 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.
+ */
+static status_t make_space_available (private_generator_t *this, size_t bits)
+{
+ while (((this->get_current_buffer_space(this) * 8) - this->current_bit) < bits)
+ {
+ /* must increase buffer */
+ u_int8_t *new_buffer;
+ size_t old_buffer_size = this->get_current_buffer_size(this);
+ size_t new_buffer_size = old_buffer_size + GENERATOR_DATA_BUFFER_INCREASE_VALUE;
+ size_t out_position_offset = ((this->out_position) - (this->buffer));
+
+ this->logger->log(this->logger, CONTROL|MOST, "increased gen buffer from %d to %d byte",
+ old_buffer_size, new_buffer_size);
+
+ /* Reallocate space for new buffer */
+ new_buffer = allocator_realloc(this->buffer,new_buffer_size);
+ if (new_buffer == NULL)
+ {
+ this->logger->log(this->logger, ERROR, "reallocation of gen buffer failed!!!");
+ return OUT_OF_RES;
+ }
+
+ this->buffer = new_buffer;
+
+ this->out_position = (this->buffer + out_position_offset);
+ this->roof_position = (this->buffer + new_buffer_size);
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implements private_generator_t's write_bytes_to_buffer function.
+ * See #private_generator_s.write_bytes_to_buffer.
+ */
+static status_t write_bytes_to_buffer (private_generator_t *this,void * bytes, size_t number_of_bytes)
+{
+ int i;
+ status_t status;
+ u_int8_t *read_position = (u_int8_t *) bytes;
+
+ status = this->make_space_available(this,number_of_bytes * 8);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+
+ for (i = 0; i < number_of_bytes; i++)
+ {
+ *(this->out_position) = *(read_position);
+ read_position++;
+ this->out_position++;
+ }
+ return status;
+}
+
+/**
+ * Implements private_generator_t's write_bytes_to_buffer_at_offset function.
+ * See #private_generator_s.write_bytes_to_buffer_at_offset.
+ */
+static status_t write_bytes_to_buffer_at_offset (private_generator_t *this,void * bytes,size_t number_of_bytes,u_int32_t offset)
+{
+ int i;
+ status_t status;
+ u_int8_t *read_position = (u_int8_t *) bytes;
+ u_int8_t *write_position;
+ u_int32_t free_space_after_offset = (this->get_current_buffer_size(this) - offset);
+
+ /* check first if enough space for new data is available */
+ if (number_of_bytes > free_space_after_offset)
+ {
+ status = this->make_space_available(this,(number_of_bytes - free_space_after_offset) * 8);
+ }
+
+ 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.
+ */
+static status_t write_to_chunk (private_generator_t *this,chunk_t *data)
+{
+ size_t data_length = this->get_current_data_length(this);
+ u_int32_t header_length_field = data_length;
+
+ /* write length into header length field */
+ if (this->header_length_position_offset > 0)
+ {
+ u_int32_t int32_val = htonl(header_length_field);
+ this->write_bytes_to_buffer_at_offset(this,&int32_val,sizeof(u_int32_t),this->header_length_position_offset);
+ }
+
+ if (this->current_bit > 0)
+ data_length++;
+ data->ptr = allocator_alloc(data_length);
+ if (data->ptr == NULL)
+ {
+ data->len = 0;
+ this->logger->log(this->logger, ERROR, "not enougth ressources to allocate chunk");
+ return OUT_OF_RES;
+ }
+ memcpy(data->ptr,this->buffer,data_length);
+ data->len = data_length;
+
+ this->logger->log_chunk(this->logger, RAW, "generated data of this parser", data);
+
+ return SUCCESS;
+}
+
+/**
+ * Implements generator_t's generate_payload function.
+ * See #generator_s.generate_payload.
+ */
+static status_t generate_payload (private_generator_t *this,payload_t *payload)
+{
+ int i;
+ status_t status;
+ this->data_struct = payload;
+ size_t rule_count;
+ encoding_rule_t *rules;
+ payload_type_t payload_type;
+ u_int8_t *payload_start;
+
+ /* get payload type */
+ payload_type = payload->get_type(payload);
+ /* spi size has to get reseted */
+ this->last_spi_size = 0;
+
+ payload_start = this->out_position;
+
+ this->logger->log(this->logger, CONTROL, "generating payload of type %s",
+ mapping_find(payload_type_m,payload_type));
+
+ /* each payload has its own encoding rules */
+ payload->get_encoding_rules(payload,&rules,&rule_count);
+
+ for (i = 0; i < rule_count;i++)
+ {
+ status = SUCCESS;
+ this->logger->log(this->logger, CONTROL|MORE, " generating rule %d %s",
+ i, mapping_find(encoding_type_m,rules[i].type));
+ switch (rules[i].type)
+ {
+ /* all u int values, IKE_SPI and ATTRIBUTE_TYPE are generated in generate_u_int_type */
+ case U_INT_4:
+ case U_INT_8:
+ case U_INT_16:
+ case U_INT_32:
+ case U_INT_64:
+ case IKE_SPI:
+ case ATTRIBUTE_TYPE:
+ {
+ status = this->generate_u_int_type(this,rules[i].type,rules[i].offset);
+ break;
+ }
+ case RESERVED_BIT:
+ {
+ status = this->generate_reserved_field(this,1);
+ break;
+ }
+ case RESERVED_BYTE:
+ {
+ status = this->generate_reserved_field(this,8);
+ break;
+ }
+ case FLAG:
+ {
+ status = this->generate_flag(this,rules[i].offset);
+ break;
+ }
+ case PAYLOAD_LENGTH:
+ {
+ /* position of payload lenght field is temporary stored */
+ this->last_payload_length_position_offset = this->get_current_buffer_offset(this);
+ /* payload length is generated like an U_INT_16 */
+ status = this->generate_u_int_type(this,U_INT_16,rules[i].offset);
+ break;
+ }
+ case HEADER_LENGTH:
+ {
+ /* position of header length field is temporary stored */
+ this->header_length_position_offset = this->get_current_buffer_offset(this);
+ /* header length is generated like an U_INT_32 */
+ status = this->generate_u_int_type(this,U_INT_32,rules[i].offset);
+ break;
+ }
+ case SPI_SIZE:
+ /* spi size is handled as 8 bit unsigned integer */
+ status = this->generate_u_int_type(this,U_INT_8,rules[i].offset);
+ /* last spi size is temporary stored */
+ this->last_spi_size = *((u_int8_t *)(this->data_struct + rules[i].offset));
+ break;
+ case SPI:
+ {
+ /* the SPI value is generated from chunk */
+ status = this->generate_from_chunk(this,rules[i].offset);
+ break;
+ }
+ case KEY_EXCHANGE_DATA:
+ {
+ /* the Key Exchange Data value is generated from chunk */
+ status = this->generate_from_chunk(this,rules[i].offset);
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, ERROR, "could no write key exchange data from chunk");
+ return status;
+ }
+
+ u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
+ /* Length of KE_PAYLOAD is calculated */
+ u_int16_t length_of_ke_payload = KE_PAYLOAD_HEADER_LENGTH + ((chunk_t *)(this->data_struct + rules[i].offset))->len;
+
+ u_int16_t int16_val = htons(length_of_ke_payload);
+ status = this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, ERROR, "could not write payload length into buffer");
+ return status;
+ }
+ break;
+ }
+ case NOTIFICATION_DATA:
+ {
+ /* the Notification Data value is generated from chunk */
+ status = this->generate_from_chunk(this,rules[i].offset);
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, ERROR, "Could not generate notification data from chunk");
+ return status;
+ }
+
+ u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
+ /* Length of Notification PAYLOAD is calculated */
+ u_int16_t length_of_notify_payload = NOTIFY_PAYLOAD_HEADER_LENGTH + ((chunk_t *)(this->data_struct + rules[i].offset))->len;
+ length_of_notify_payload += this->last_spi_size;
+ u_int16_t int16_val = htons(length_of_notify_payload);
+
+ status = this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, ERROR, "could not write payload length into buffer");
+ return status;
+ }
+ break;
+ }
+ case NONCE_DATA:
+ {
+ /* the Nonce Data value is generated from chunk */
+ status = this->generate_from_chunk(this, rules[i].offset);
+
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, ERROR, "could not write nonce data from chunk");
+ return status;
+ }
+
+ u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
+ /* Length of nonce PAYLOAD is calculated */
+ u_int16_t length_of_nonce_payload = NONCE_PAYLOAD_HEADER_LENGTH + ((chunk_t *)(this->data_struct + rules[i].offset))->len;
+ u_int16_t int16_val = htons(length_of_nonce_payload);
+
+ status = this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, ERROR, "could not write payload length into buffer");
+ return status;
+ }
+ break;
+ }
+ case PROPOSALS:
+ {
+ /* before iterative generate the transforms, store the current payload length position */
+ u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
+ /* Length of SA_PAYLOAD is calculated */
+ u_int16_t length_of_sa_payload = SA_PAYLOAD_HEADER_LENGTH;
+ u_int16_t int16_val;
+ /* proposals are stored in a linked list and so accessed */
+ linked_list_t *proposals = *((linked_list_t **)(this->data_struct + rules[i].offset));
+
+ linked_list_iterator_t *iterator;
+ /* create forward iterator */
+ status = proposals->create_iterator(proposals,&iterator,TRUE);
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, ERROR, "could not create iterator for proposals");
+ return status;
+ }
+ /* every proposal is processed (iterative call )*/
+ while (iterator->has_next(iterator))
+ {
+ payload_t *current_proposal;
+ u_int32_t before_generate_position_offset;
+ u_int32_t after_generate_position_offset;
+
+ status = iterator->current(iterator,(void **)&current_proposal);
+ if (status != SUCCESS)
+ {
+ iterator->destroy(iterator);
+ return status;
+ }
+ before_generate_position_offset = this->get_current_buffer_offset(this);
+ status = this->public.generate_payload(&(this->public),current_proposal);
+ after_generate_position_offset = this->get_current_buffer_offset(this);
+ if (status != SUCCESS)
+ {
+ iterator->destroy(iterator);
+ return status;
+ }
+
+ /* increase size of transform */
+ length_of_sa_payload += (after_generate_position_offset - before_generate_position_offset);
+ }
+ iterator->destroy(iterator);
+
+ int16_val = htons(length_of_sa_payload);
+ status = this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, ERROR, "could not write payload length into buffer");
+ return status;
+ }
+ break;
+ }
+
+ case TRANSFORMS:
+ {
+ /* before iterative generate the transforms, store the current length position */
+ u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
+ u_int16_t length_of_proposal = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH + this->last_spi_size;
+ u_int16_t int16_val;
+ linked_list_t *transforms = *((linked_list_t **)(this->data_struct + rules[i].offset));
+ linked_list_iterator_t *iterator;
+
+ /* create forward iterator */
+ status = transforms->create_iterator(transforms,&iterator,TRUE);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ while (iterator->has_next(iterator))
+ {
+ payload_t *current_transform;
+ u_int32_t before_generate_position_offset;
+ u_int32_t after_generate_position_offset;
+
+ status = iterator->current(iterator,(void **)&current_transform);
+ if (status != SUCCESS)
+ {
+ iterator->destroy(iterator);
+ return status;
+ }
+
+ before_generate_position_offset = this->get_current_buffer_offset(this);
+ status = this->public.generate_payload(&(this->public),current_transform);
+ after_generate_position_offset = this->get_current_buffer_offset(this);
+ if (status != SUCCESS)
+ {
+ iterator->destroy(iterator);
+ return status;
+ }
+
+ /* increase size of transform */
+ length_of_proposal += (after_generate_position_offset - before_generate_position_offset);
+ }
+
+ iterator->destroy(iterator);
+
+ int16_val = htons(length_of_proposal);
+ this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
+
+ break;
+ }
+ case TRANSFORM_ATTRIBUTES:
+ {
+ /* before iterative generate the transform attributes, 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->get_current_buffer_offset(this);
+ this->public.generate_payload(&(this->public),current_attribute);
+ after_generate_position_offset = this->get_current_buffer_offset(this);
+
+ /* increase size of transform */
+ length_of_transform += (after_generate_position_offset - before_generate_position_offset);
+ }
+
+ iterator->destroy(iterator);
+
+ 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:
+ {
+ status = this->generate_flag(this,rules[i].offset);
+ /* Attribute format is a flag which is stored in context*/
+ this->attribute_format = *((bool *) (this->data_struct + rules[i].offset));
+ break;
+ }
+
+ case ATTRIBUTE_LENGTH_OR_VALUE:
+ {
+ 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->generate_u_int_type(this,U_INT_16,rules[i].offset);
+// 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|MOST, "attribute value has not fixed size");
+ /* the attribute value is generated */
+ status = this->generate_from_chunk(this,rules[i].offset);
+ }
+ break;
+ }
+ default:
+ this->logger->log(this->logger, ERROR, "field type %s is not supported",
+ mapping_find(encoding_type_m,rules[i].type));
+ return NOT_SUPPORTED;
+ }
+ }
+ this->logger->log_bytes(this->logger, RAW|MORE, "generated data for this payload",
+ payload_start, this->out_position-payload_start);
+
+ return status;
+}
+
+/**
+ * Implements generator_t's destroy function.
+ * See #generator_s.destroy.
+ */
+static status_t destroy(private_generator_t *this)
+{
+ allocator_free(this->buffer);
+ global_logger_manager->destroy_logger(global_logger_manager,this->logger);
+ allocator_free(this);
+ return SUCCESS;
+}
+
+/*
+ * Described in header
+ */
+generator_t * generator_create()
+{
+ private_generator_t *this;
+
+ this = allocator_alloc_thing(private_generator_t);
+ if (this == NULL)
+ {
+ return NULL;
+ }
+
+ /* initiate public functions */
+ this->public.generate_payload = (status_t(*)(generator_t*, payload_t *)) generate_payload;
+ this->public.destroy = (status_t(*)(generator_t*)) destroy;
+ this->public.write_to_chunk = (status_t (*) (generator_t *,chunk_t *)) write_to_chunk;
+
+
+ /* initiate private functions */
+ this->get_current_buffer_size = get_current_buffer_size;
+ this->get_current_buffer_space = get_current_buffer_space;
+ this->get_current_data_length = get_current_data_length;
+ this->get_current_buffer_offset = get_current_buffer_offset;
+ 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;
+ this->write_bytes_to_buffer_at_offset = write_bytes_to_buffer_at_offset;
+
+
+ /* allocate memory for buffer */
+ this->buffer = allocator_alloc(GENERATOR_DATA_BUFFER_SIZE);
+ if (this->buffer == NULL)
+ {
+ allocator_free(this);
+ return NULL;
+ }
+
+ /* initiate private variables */
+ this->out_position = this->buffer;
+ 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->header_length_position_offset = 0;
+ this->logger = global_logger_manager->create_logger(global_logger_manager,GENERATOR,NULL);
+ this->logger->disable_level(this->logger, FULL);
+ this->logger->enable_level(this->logger, CONTROL);
+
+ if (this->logger == NULL)
+ {
+ allocator_free(this->buffer);
+ allocator_free(this);
+ return NULL;
+ }
+ return &(this->public);
+}
diff --git a/Source/charon/encoding/generator.h b/Source/charon/encoding/generator.h
new file mode 100644
index 000000000..312ac0054
--- /dev/null
+++ b/Source/charon/encoding/generator.h
@@ -0,0 +1,89 @@
+/**
+ * @file generator.h
+ *
+ * @brief Generic generator class used to generate IKEv2-header and payloads.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef GENERATOR_H_
+#define GENERATOR_H_
+
+#include <types.h>
+#include <encoding/payloads/encodings.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * Generating is done in a data buffer.
+ * This is thehe start size of this buffer in Bytes.
+ */
+#define GENERATOR_DATA_BUFFER_SIZE 500
+
+/**
+ * Number of bytes to increase the buffer, if it is to small.
+ */
+#define GENERATOR_DATA_BUFFER_INCREASE_VALUE 500
+
+/**
+ *A generator_t object which generates payloads of specific type.
+ */
+typedef struct generator_s generator_t;
+
+struct generator_s {
+
+ /**
+ * @brief Generates a specific payload from given payload object.
+ *
+ * Remember: Header and substructures are also handled as payloads.
+ *
+ * @param this generator_t object
+ * @param[in] payload interface payload_t implementing object
+ * @return
+ * - SUCCESSFUL if succeeded
+ * - OUT_OF_RES if out of ressources
+ */
+ status_t (*generate_payload) (generator_t *this,payload_t *payload);
+
+ /**
+ * Writes all generated data of current generator context to a chunk
+ *
+ * @param this generator_t object
+ * * @param[out] data chunk to write the data to
+ * @return
+ * @return
+ * - SUCCESSFUL if succeeded
+ * - OUT_OF_RES otherwise
+ */
+ status_t (*write_to_chunk) (generator_t *this,chunk_t *data);
+
+ /**
+ * @brief Destroys a generator_t object.
+ *
+ * @param this generator_t object
+ *
+ * @return always success
+ */
+ status_t (*destroy) (generator_t *this);
+};
+
+/**
+ * Constructor to create a generator
+ *
+ */
+generator_t * generator_create();
+
+#endif /*GENERATOR_H_*/
diff --git a/Source/charon/encoding/message.c b/Source/charon/encoding/message.c
new file mode 100644
index 000000000..d32126ec0
--- /dev/null
+++ b/Source/charon/encoding/message.c
@@ -0,0 +1,877 @@
+/**
+ * @file message.c
+ *
+ * @brief Class message_t. Object of this type represents an IKEv2-Message.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stdlib.h>
+
+#include "message.h"
+
+#include <types.h>
+#include <globals.h>
+#include <ike_sa_id.h>
+#include <encoding/generator.h>
+#include <encoding/parser.h>
+#include <utils/linked_list.h>
+#include <utils/allocator.h>
+#include <utils/logger_manager.h>
+#include <encoding/payloads/encodings.h>
+#include <encoding/payloads/payload.h>
+
+
+/**
+ * Supported payload entry used in message_rule_t
+ *
+ */
+typedef struct supported_payload_entry_s supported_payload_entry_t;
+
+struct supported_payload_entry_s {
+ /**
+ * Payload type
+ */
+ payload_type_t payload_type;
+
+ /**
+ * Minimal occurence of this payload
+ */
+ size_t min_occurence;
+
+ /**
+ * Max occurence of this payload
+ */
+ size_t max_occurence;
+};
+
+/**
+ * Message Rule used to find out which payloads are supported by each message type
+ *
+ */
+typedef struct message_rule_s message_rule_t;
+
+struct message_rule_s {
+ /**
+ * Type of message
+ */
+ exchange_type_t exchange_type;
+
+ /**
+ * Is message a request or response
+ */
+ bool is_request;
+ /**
+ * Number of supported payloads
+ */
+ size_t supported_payloads_count;
+ /**
+ * Pointer to first supported payload entry
+ */
+ supported_payload_entry_t *supported_payloads;
+};
+
+/**
+ * message rule for ike_sa_init from initiator
+ */
+static supported_payload_entry_t supported_ike_sa_init_i_payloads[] =
+{
+ {SECURITY_ASSOCIATION,1,1},
+ {KEY_EXCHANGE,1,1},
+ {NONCE,1,1},
+};
+
+/**
+ * message rule for ike_sa_init from responder
+ */
+static supported_payload_entry_t supported_ike_sa_init_r_payloads[] =
+{
+ {SECURITY_ASSOCIATION,1,1},
+ {KEY_EXCHANGE,1,1},
+ {NONCE,1,1},
+};
+
+
+/**
+ * message rules, defines allowed payloads
+ */
+static message_rule_t message_rules[] = {
+ {IKE_SA_INIT,TRUE,(sizeof(supported_ike_sa_init_i_payloads)/sizeof(supported_payload_entry_t)),supported_ike_sa_init_i_payloads},
+ {IKE_SA_INIT,FALSE,(sizeof(supported_ike_sa_init_r_payloads)/sizeof(supported_payload_entry_t)),supported_ike_sa_init_r_payloads}
+};
+
+/**
+ * Entry for a payload in the internal used linked list
+ *
+ */
+typedef struct payload_entry_s payload_entry_t;
+
+struct payload_entry_s {
+ /**
+ * Type of payload
+ */
+ payload_type_t payload_type;
+ /**
+ * Data struct holding the data of given payload
+ */
+ void *data_struct;
+};
+
+
+/**
+ * Private data of an message_t object
+ */
+typedef struct private_message_s private_message_t;
+
+struct private_message_s {
+
+ /**
+ * Public part of a message_t object
+ */
+ message_t public;
+
+
+ /**
+ * Minor version of message
+ */
+ u_int8_t major_version;
+
+ /**
+ * Major version of message
+ */
+ u_int8_t minor_version;
+
+ /**
+ * First Payload in message
+ */
+ payload_type_t first_payload;
+
+ /**
+ * Assigned exchange type
+ */
+ exchange_type_t exchange_type;
+
+
+ /**
+ * TRUE if message is request.
+ * FALSE if message is reply.
+ */
+ bool is_request;
+
+ /**
+ * Message ID of this message
+ */
+ u_int32_t message_id;
+
+ /**
+ * ID of assigned IKE_SA
+ */
+ ike_sa_id_t *ike_sa_id;
+
+ /**
+ * Assigned UDP packet.
+ *
+ * Stores incoming packet or last generated one.
+ */
+ packet_t *packet;
+
+ /**
+ * Linked List where payload data are stored in
+ */
+ linked_list_t *payloads;
+
+ /**
+ * Assigned parser to parse Header and Body of this message
+ */
+ parser_t *parser;
+
+ /**
+ * logger for this message
+ */
+ logger_t *logger;
+
+ /**
+ * Gets a list of supported payloads of this message type
+ *
+ * @param this calling object
+ * @param[out] supported_payloads first entry of supported payloads
+ * @param[out] supported_payloads_count number of supported payload entries
+ *
+ * @return SUCCESS
+ * NOT_FOUND if no supported payload definition could be found
+ */
+ status_t (*get_supported_payloads) (private_message_t *this, supported_payload_entry_t **supported_payloads,size_t *supported_payloads_count);
+
+};
+
+/**
+ * Implements private_message_t's get_supported_payloads function.
+ * See #private_message_t.get_supported_payloads.
+ */
+status_t get_supported_payloads (private_message_t *this, supported_payload_entry_t **supported_payloads,size_t *supported_payloads_count)
+{
+ int i;
+ exchange_type_t exchange_type = this->public.get_exchange_type(&(this->public));
+ bool is_request = this->public.get_request(&(this->public));
+
+
+ for (i = 0; i < (sizeof(message_rules) / sizeof(message_rule_t)); i++)
+ {
+ if ((exchange_type == message_rules[i].exchange_type) &&
+ (is_request == message_rules[i].is_request))
+ {
+ /* found rule for given exchange_type*/
+ *supported_payloads = message_rules[i].supported_payloads;
+ *supported_payloads_count = message_rules[i].supported_payloads_count;
+
+ return SUCCESS;
+ }
+
+
+ }
+ *supported_payloads = NULL;
+ *supported_payloads_count = 0;
+ return NOT_FOUND;
+}
+
+/**
+ * Implements message_t's set_ike_sa_id function.
+ * See #message_s.set_ike_sa_id.
+ */
+static status_t set_ike_sa_id (private_message_t *this,ike_sa_id_t *ike_sa_id)
+{
+ status_t status;
+ status = ike_sa_id->clone(ike_sa_id,&(this->ike_sa_id));
+ return status;
+}
+
+/**
+ * Implements message_t's get_ike_sa_id function.
+ * See #message_s.get_ike_sa_id.
+ */
+static status_t get_ike_sa_id (private_message_t *this,ike_sa_id_t **ike_sa_id)
+{
+ status_t status;
+ if (this->ike_sa_id == NULL)
+ {
+ return FAILED;
+ }
+ status = this->ike_sa_id->clone(this->ike_sa_id,ike_sa_id);
+ return status;
+}
+
+
+/**
+ * Implements message_t's set_message_id function.
+ * See #message_s.set_message_id.
+ */
+static status_t set_message_id (private_message_t *this,u_int32_t message_id)
+{
+ this->message_id = message_id;
+ return SUCCESS;
+}
+
+
+/**
+ * Implements message_t's set_message_id function.
+ * See #message_s.set_message_id.
+ */
+static u_int32_t get_message_id (private_message_t *this)
+{
+ return this->message_id;
+}
+
+/**
+ * Implements message_t's get_responder_spi function.
+ * See #message_s.get_responder_spi.
+ */
+static u_int64_t get_responder_spi (private_message_t *this)
+{
+ return (this->ike_sa_id->get_responder_spi(this->ike_sa_id));
+}
+
+/**
+ * Implements message_t's set_major_version function.
+ * See #message_s.set_major_version.
+ */
+static status_t set_major_version (private_message_t *this,u_int8_t major_version)
+{
+ this->major_version = major_version;
+ return SUCCESS;
+}
+
+
+/**
+ * Implements message_t's get_major_version function.
+ * See #message_s.get_major_version.
+ */
+static u_int8_t get_major_version (private_message_t *this)
+{
+ return this->major_version;
+}
+
+/**
+ * Implements message_t's set_minor_version function.
+ * See #message_s.set_minor_version.
+ */
+static status_t set_minor_version (private_message_t *this,u_int8_t minor_version)
+{
+ this->minor_version = minor_version;
+ return SUCCESS;
+}
+
+
+/**
+ * Implements message_t's get_minor_version function.
+ * See #message_s.get_minor_version.
+ */
+static u_int8_t get_minor_version (private_message_t *this)
+{
+ return this->minor_version;
+}
+
+/**
+ * Implements message_t's set_exchange_type function.
+ * See #message_s.set_exchange_type.
+ */
+static status_t set_exchange_type (private_message_t *this,exchange_type_t exchange_type)
+{
+ this->exchange_type = exchange_type;
+ return SUCCESS;
+}
+
+
+/**
+ * Implements message_t's get_exchange_type function.
+ * See #message_s.get_exchange_type.
+ */
+static exchange_type_t get_exchange_type (private_message_t *this)
+{
+ return this->exchange_type;
+}
+
+
+/**
+ * Implements message_t's set_request function.
+ * See #message_s.set_request.
+ */
+static status_t set_request (private_message_t *this,bool request)
+{
+ this->is_request = request;
+ return SUCCESS;
+}
+
+/**
+ * Implements message_t's get_request function.
+ * See #message_s.get_request.
+ */
+static exchange_type_t get_request (private_message_t *this)
+{
+ return this->is_request;
+}
+
+static status_t add_payload(private_message_t *this, payload_t *payload)
+{
+ payload_t *last_payload;
+ if ((this->payloads->get_count(this->payloads) > 0) &&
+ (this->payloads->get_last(this->payloads,(void **) &last_payload) != SUCCESS))
+ {
+ return OUT_OF_RES;
+ }
+
+ if (this->payloads->insert_last(this->payloads, payload) != SUCCESS)
+ {
+ return OUT_OF_RES;
+ }
+ if (this->payloads->get_count(this->payloads) == 1)
+ {
+ this->first_payload = payload->get_type(payload);
+ }
+ else
+ {
+ last_payload->set_next_type(last_payload,payload->get_type(payload));
+ }
+
+ this->logger->log(this->logger, CONTROL|MORE, "added payload of type %s to message",
+ mapping_find(payload_type_m, payload->get_type(payload)));
+
+ return SUCCESS;
+}
+
+static status_t set_source(private_message_t *this, host_t *host)
+{
+ if (this->packet->source != NULL)
+ {
+ this->packet->source->destroy(this->packet->source);
+ }
+ this->packet->source = host;
+ return SUCCESS;
+}
+
+static status_t set_destination(private_message_t *this, host_t *host)
+{
+ if (this->packet->destination != NULL)
+ {
+ this->packet->destination->destroy(this->packet->destination);
+ }
+ this->packet->destination = host;
+ return SUCCESS;
+}
+
+static status_t get_source(private_message_t *this, host_t **host)
+{
+ *host = this->packet->source;
+ return SUCCESS;
+}
+
+static status_t get_destination(private_message_t *this, host_t **host)
+{
+ *host = this->packet->destination;
+ return SUCCESS;
+}
+
+
+static status_t get_payload_iterator(private_message_t *this, linked_list_iterator_t **iterator)
+{
+ return this->payloads->create_iterator(this->payloads, iterator, TRUE);
+}
+
+
+/**
+ * Implements message_t's generate function.
+ * See #message_s.generate.
+ */
+static status_t generate(private_message_t *this, packet_t **packet)
+{
+ generator_t *generator;
+ ike_header_t *ike_header;
+ payload_t *payload, *next_payload;
+ linked_list_iterator_t *iterator;
+ status_t status;
+
+
+ this->logger->log(this->logger, CONTROL, "generating message, contains %d payloads",
+ this->payloads->get_count(this->payloads));
+
+ if (this->exchange_type == EXCHANGE_TYPE_UNDEFINED)
+ {
+ this->logger->log(this->logger, ERROR, "exchange type is not defined");
+ return INVALID_STATE;
+ }
+
+ if (this->packet->source == NULL ||
+ this->packet->destination == NULL)
+ {
+ this->logger->log(this->logger, ERROR, "source/destination not defined");
+ return INVALID_STATE;
+ }
+
+
+ ike_header = ike_header_create();
+ if (ike_header == NULL)
+ {
+ return OUT_OF_RES;
+ }
+
+
+ ike_header->set_exchange_type(ike_header, this->exchange_type);
+ ike_header->set_message_id(ike_header, this->message_id);
+ ike_header->set_response_flag(ike_header, !this->is_request);
+ ike_header->set_initiator_flag(ike_header, this->ike_sa_id->is_initiator(this->ike_sa_id));
+ ike_header->set_initiator_spi(ike_header, this->ike_sa_id->get_initiator_spi(this->ike_sa_id));
+ ike_header->set_responder_spi(ike_header, this->ike_sa_id->get_responder_spi(this->ike_sa_id));
+
+ generator = generator_create();
+ if (generator == NULL)
+ {
+ return OUT_OF_RES;
+ }
+
+ payload = (payload_t*)ike_header;
+
+ if (this->payloads->create_iterator(this->payloads, &iterator, TRUE) != SUCCESS)
+ {
+ generator->destroy(generator);
+ ike_header->destroy(ike_header);
+ return OUT_OF_RES;
+ }
+ while(iterator->has_next(iterator))
+ {
+ iterator->current(iterator, (void**)&next_payload);
+ payload->set_next_type(payload, next_payload->get_type(next_payload));
+ status = generator->generate_payload(generator, payload);
+ if (status != SUCCESS)
+ {
+ generator->destroy(generator);
+ ike_header->destroy(ike_header);
+ return status;
+ }
+ payload = next_payload;
+ }
+ iterator->destroy(iterator);
+
+ payload->set_next_type(payload, NO_PAYLOAD);
+ status = generator->generate_payload(generator, payload);
+ if (status != SUCCESS)
+ {
+ generator->destroy(generator);
+ ike_header->destroy(ike_header);
+ return status;
+ }
+
+ ike_header->destroy(ike_header);
+
+
+
+ if (this->packet->data.ptr != NULL)
+ {
+ allocator_free(this->packet->data.ptr);
+ }
+
+ status = generator->write_to_chunk(generator, &(this->packet->data));
+ if (status != SUCCESS)
+ {
+ generator->destroy(generator);
+ return status;
+ }
+
+ this->packet->clone(this->packet, packet);
+
+ generator->destroy(generator);
+
+
+ this->logger->log(this->logger, CONTROL, "message generated successfully");
+ return SUCCESS;
+}
+
+/**
+ * Implements message_t's parse_header function.
+ * See #message_s.parse_header.
+ */
+static status_t parse_header(private_message_t *this)
+{
+ ike_header_t *ike_header;
+ status_t status;
+
+
+ this->logger->log(this->logger, CONTROL, "parsing header of message");
+
+ this->parser->reset_context(this->parser);
+ status = this->parser->parse_payload(this->parser,HEADER,(payload_t **) &ike_header);
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, ERROR, "Header could not be parsed");
+ return status;
+
+ }
+
+ /* verify payload */
+ status = ike_header->payload_interface.verify(&(ike_header->payload_interface));
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, ERROR, "Header verification failed");
+ ike_header->destroy(ike_header);
+ return status;
+ }
+
+ if (this->ike_sa_id != NULL)
+ {
+ this->ike_sa_id->destroy(this->ike_sa_id);
+ }
+
+ this->ike_sa_id = ike_sa_id_create(ike_header->get_initiator_spi(ike_header),
+ ike_header->get_responder_spi(ike_header),
+ ike_header->get_initiator_flag(ike_header));
+ if (this->ike_sa_id == NULL)
+ {
+ this->logger->log(this->logger, ERROR, "could not create ike_sa_id object");
+ ike_header->destroy(ike_header);
+ return OUT_OF_RES;
+ }
+ this->exchange_type = ike_header->get_exchange_type(ike_header);
+ this->message_id = ike_header->get_message_id(ike_header);
+ this->is_request = (!(ike_header->get_response_flag(ike_header)));
+ this->major_version = ike_header->get_maj_version(ike_header);
+ this->minor_version = ike_header->get_min_version(ike_header);
+ this->first_payload = ike_header->payload_interface.get_next_type(&(ike_header->payload_interface));
+
+
+ this->logger->log(this->logger, CONTROL, "parsing header successfully");
+
+ ike_header->destroy(ike_header);
+ return SUCCESS;
+}
+
+/**
+ * Implements message_t's parse_body function.
+ * See #message_s.parse_body.
+ */
+static status_t parse_body (private_message_t *this)
+{
+ status_t status = SUCCESS;
+ int i;
+ payload_type_t current_payload_type = this->first_payload;
+ supported_payload_entry_t *supported_payloads;
+ size_t supported_payloads_count;
+
+
+ this->logger->log(this->logger, CONTROL, "parsing body of message");
+
+ if (this->get_supported_payloads (this, &supported_payloads, &supported_payloads_count) != SUCCESS)
+ {
+ this->logger->log(this->logger, ERROR, "could not get supported payloads");
+ return FAILED;
+ }
+
+ while (current_payload_type != NO_PAYLOAD)
+ {
+ payload_t *current_payload;
+ bool supported = FALSE;
+
+ this->logger->log(this->logger, CONTROL|MORE, "start parsing payload of type %s",
+ mapping_find(payload_type_m, current_payload_type));
+ for (i = 0; i < supported_payloads_count;i++)
+ {
+ if (supported_payloads[i].payload_type == current_payload_type)
+ {
+ supported = TRUE;
+ break;
+ }
+ }
+ if (!supported && (current_payload_type != NO_PAYLOAD))
+ {
+ /* type not supported */
+ status = NOT_SUPPORTED;
+ this->logger->log(this->logger, ERROR, "payload type %s not supported",mapping_find(payload_type_m,current_payload_type));
+ break;
+ }
+
+ status = this->parser->parse_payload(this->parser,current_payload_type,(payload_t **) &current_payload);
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, ERROR, "payload type %s could not be parsed",mapping_find(payload_type_m,current_payload_type));
+ break;
+ }
+
+ status = current_payload->verify(current_payload);
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, ERROR, "payload type %s could not be verified",mapping_find(payload_type_m,current_payload_type));
+ status = VERIFY_ERROR;
+ break;
+ }
+
+ /* get next payload type */
+ current_payload_type = current_payload->get_next_type(current_payload);
+
+ status = this->payloads->insert_last(this->payloads,current_payload);
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, ERROR, "Could not insert current payload to internal list cause of ressource exhausting");
+ break;
+ }
+
+ }
+ if (status != SUCCESS)
+ {
+ /* already parsed payload is destroyed later in destroy call from outside this object */
+ }
+ else
+ {
+ linked_list_iterator_t *iterator;
+
+ status = this->payloads->create_iterator(this->payloads,&iterator,TRUE);
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, ERROR, "Could not create iterator to check supported payloads");
+ return status;
+ }
+
+ /* check for payloads with wrong count*/
+ for (i = 0; i < supported_payloads_count;i++)
+ {
+ size_t min_occurence = supported_payloads[i].min_occurence;
+ size_t max_occurence = supported_payloads[i].max_occurence;
+ payload_type_t payload_type = supported_payloads[i].payload_type;
+ size_t found_payloads = 0;
+
+ iterator->reset(iterator);
+
+ while(iterator->has_next(iterator))
+ {
+ payload_t *current_payload;
+ status = iterator->current(iterator,(void **)&current_payload);
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, ERROR, "Could not get payload from internal list");
+ iterator->destroy(iterator);
+ return status;
+ }
+ if (current_payload->get_type(current_payload) == payload_type)
+ {
+ found_payloads++;
+ if (found_payloads > max_occurence)
+ {
+ this->logger->log(this->logger, ERROR, "Payload of type %s more than %d times (%d) occured in current message",
+ mapping_find(payload_type_m,current_payload->get_type(current_payload)),max_occurence,found_payloads);
+ iterator->destroy(iterator);
+ return NOT_SUPPORTED;
+ }
+ }
+
+ }
+ if (found_payloads < min_occurence)
+ {
+ this->logger->log(this->logger, ERROR, "Payload of type %s not occured %d times",
+ mapping_find(payload_type_m,payload_type),min_occurence);
+ iterator->destroy(iterator);
+ return NOT_SUPPORTED;
+ }
+
+ }
+ iterator->destroy(iterator);
+ }
+ return status;
+}
+
+
+
+/**
+ * Implements message_t's destroy function.
+ * See #message_s.destroy.
+ */
+static status_t destroy (private_message_t *this)
+{
+ linked_list_iterator_t *iterator;
+
+ this->packet->destroy(this->packet);
+
+ if (this->ike_sa_id != NULL)
+ {
+ this->ike_sa_id->destroy(this->ike_sa_id);
+ }
+
+ this->payloads->create_iterator(this->payloads, &iterator, TRUE);
+ while (iterator->has_next(iterator))
+ {
+ payload_t *payload;
+ iterator->current(iterator, (void**)&payload);
+ this->logger->log(this->logger, CONTROL|MOST, "Destroying payload of type %s",
+ mapping_find(payload_type_m, payload->get_type(payload)));
+ payload->destroy(payload);
+ }
+ iterator->destroy(iterator);
+ this->payloads->destroy(this->payloads);
+ this->parser->destroy(this->parser);
+ global_logger_manager->destroy_logger(global_logger_manager, this->logger);
+
+ allocator_free(this);
+ return SUCCESS;
+}
+
+/*
+ * Described in Header-File
+ */
+message_t *message_create_from_packet(packet_t *packet)
+{
+ private_message_t *this = allocator_alloc_thing(private_message_t);
+ if (this == NULL)
+ {
+ return NULL;
+ }
+
+ /* public functions */
+ this->public.set_major_version = (status_t(*)(message_t*, u_int8_t))set_major_version;
+ this->public.get_major_version = (u_int8_t(*)(message_t*))get_major_version;
+ this->public.set_minor_version = (status_t(*)(message_t*, u_int8_t))set_minor_version;
+ this->public.get_minor_version = (u_int8_t(*)(message_t*))get_minor_version;
+ this->public.set_message_id = (status_t(*)(message_t*, u_int32_t))set_message_id;
+ this->public.get_message_id = (u_int32_t(*)(message_t*))get_message_id;
+ this->public.get_responder_spi = (u_int64_t(*)(message_t*))get_responder_spi;
+ this->public.set_ike_sa_id = (status_t(*)(message_t*, ike_sa_id_t *))set_ike_sa_id;
+ this->public.get_ike_sa_id = (status_t(*)(message_t*, ike_sa_id_t **))get_ike_sa_id;
+ this->public.set_exchange_type = (status_t(*)(message_t*, exchange_type_t))set_exchange_type;
+ this->public.get_exchange_type = (exchange_type_t(*)(message_t*))get_exchange_type;
+ this->public.set_request = (status_t(*)(message_t*, bool))set_request;
+ this->public.get_request = (bool(*)(message_t*))get_request;
+ this->public.add_payload = (status_t(*)(message_t*,payload_t*))add_payload;
+ this->public.generate = (status_t (*) (message_t *, packet_t**)) generate;
+ this->public.set_source = (status_t (*) (message_t*,host_t*)) set_source;
+ this->public.get_source = (status_t (*) (message_t*,host_t**)) get_source;
+ this->public.set_destination = (status_t (*) (message_t*,host_t*)) set_destination;
+ this->public.get_destination = (status_t (*) (message_t*,host_t**)) get_destination;
+ this->public.get_payload_iterator = (status_t (*) (message_t *, linked_list_iterator_t **)) get_payload_iterator;
+ this->public.parse_header = (status_t (*) (message_t *)) parse_header;
+ this->public.parse_body = (status_t (*) (message_t *)) parse_body;
+ this->public.destroy = (status_t(*)(message_t*))destroy;
+
+ /* public values */
+ this->exchange_type = EXCHANGE_TYPE_UNDEFINED;
+ this->is_request = TRUE;
+ this->ike_sa_id = NULL;
+ this->first_payload = NO_PAYLOAD;
+ this->message_id = 0;
+
+ /* private functions */
+ this->get_supported_payloads = get_supported_payloads;
+
+ /* private values */
+ if (packet == NULL)
+ {
+ packet = packet_create();
+ }
+ if (packet == NULL)
+ {
+ allocator_free(this);
+ return NULL;
+ }
+ this->packet = packet;
+ this->payloads = linked_list_create();
+ if (this->payloads == NULL)
+ {
+ allocator_free(this);
+ return NULL;
+ }
+
+ /* parser is created from data of packet */
+ this->parser = parser_create(this->packet->data);
+ if (this->parser == NULL)
+ {
+ this->payloads->destroy(this->payloads);
+ allocator_free(this);
+ return NULL;
+ }
+
+ this->logger = global_logger_manager->create_logger(global_logger_manager, MESSAGE, NULL);
+ if (this->logger == NULL)
+ {
+ this->parser->destroy(this->parser);
+ this->payloads->destroy(this->payloads);
+ allocator_free(this);
+ return NULL;
+ }
+
+ return (&this->public);
+}
+
+/*
+ * Described in Header-File
+ */
+message_t *message_create()
+{
+ return message_create_from_packet(NULL);
+}
diff --git a/Source/charon/encoding/message.h b/Source/charon/encoding/message.h
new file mode 100644
index 000000000..960be94af
--- /dev/null
+++ b/Source/charon/encoding/message.h
@@ -0,0 +1,280 @@
+/**
+ * @file message.h
+ *
+ * @brief Class message_t. Object of this type represents an IKEv2-Message.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef MESSAGE_H_
+#define MESSAGE_H_
+
+#include <types.h>
+#include <ike_sa_id.h>
+#include <network/packet.h>
+#include <encoding/payloads/ike_header.h>
+#include <utils/linked_list.h>
+
+
+
+
+/**
+ * @brief This class is used to represent an IKEv2-Message.
+ *
+ * An IKEv2-Message is either a request or response.
+ */
+typedef struct message_s message_t;
+
+struct message_s {
+
+ /**
+ * @brief Sets the IKE major version of the message.
+ *
+ * @param this message_t object
+ * @param major_version major version to set
+ * @return SUCCESS
+ */
+ status_t (*set_major_version) (message_t *this,u_int8_t major_version);
+
+ /**
+ * @brief Gets the IKE major version of the message.
+ *
+ * @param this message_t object
+ * @return major version of the message
+ */
+ u_int8_t (*get_major_version) (message_t *this);
+
+ /**
+ * @brief Sets the IKE minor version of the message.
+ *
+ * @param this message_t object
+ * @param minor_version minor version to set
+ * @return SUCCESS
+ */
+ status_t (*set_minor_version) (message_t *this,u_int8_t minor_version);
+
+ /**
+ * @brief Gets the IKE minor version of the message.
+ *
+ * @param this message_t object
+ * @return minor version of the message
+ */
+ u_int8_t (*get_minor_version) (message_t *this);
+
+ /**
+ * @brief Sets the Message ID of the message.
+ *
+ * @param this message_t object
+ * @param message_id message_id to set
+ * @return SUCCESS
+ */
+ status_t (*set_message_id) (message_t *this,u_int32_t message_id);
+
+ /**
+ * @brief Gets the Message ID of the message.
+ *
+ * @param this message_t object
+ * @return message_id type of the message
+ */
+ u_int32_t (*get_message_id) (message_t *this);
+
+ /**
+ * @brief Gets the responder SPI of the message.
+ *
+ * @param this message_t object
+ * @return responder spi of the message
+ */
+ u_int64_t (*get_responder_spi) (message_t *this);
+
+ /**
+ * @brief Sets the IKE_SA ID of the message.
+ *
+ * @warning ike_sa_id gets cloned internaly and
+ * so can be destroyed afterwards.
+ *
+ * @param this message_t object
+ * @param ike_sa_id ike_sa_id to set
+ * @return
+ * - SUCCESS
+ * - OUT_OF_RES
+ * @return SUCCESS
+ */
+ status_t (*set_ike_sa_id) (message_t *this,ike_sa_id_t * ike_sa_id);
+
+ /**
+ * @brief Gets the IKE_SA ID of the message.
+ *
+ * @warning The returned ike_sa_id is a clone of the internal one.
+ * So it has to be destroyed by the caller.
+ *
+ * @param this message_t object
+ * @param ike_sa_id pointer to ike_sa_id pointer which will be set
+ * @return
+ * - SUCCESS
+ * - OUT_OF_RES
+ * - FAILED if no ike_sa_id is set
+ */
+ status_t (*get_ike_sa_id) (message_t *this,ike_sa_id_t **ike_sa_id);
+
+ /**
+ * @brief Sets the exchange type of the message.
+ *
+ * @param this message_t object
+ * @param exchange_type exchange_type to set
+ * @return SUCCESS
+ */
+ status_t (*set_exchange_type) (message_t *this,exchange_type_t exchange_type);
+
+ /**
+ * @brief Gets the exchange type of the message.
+ *
+ * @param this message_t object
+ * @return exchange type of the message
+ */
+ exchange_type_t (*get_exchange_type) (message_t *this);
+
+ /**
+ * @brief Sets the original initiator flag.
+ *
+ * @param this message_t object
+ * @param original_initiator TRUE if message is from original initiator
+ * @return SUCCESS
+ */
+ status_t (*set_original_initiator) (message_t *this,bool original_initiator);
+
+ /**
+ * @brief Gets original initiator flag.
+ *
+ * @param this message_t object
+ * @return TRUE if message is from original initiator, FALSE otherwise
+ */
+ bool (*get_original_initiator) (message_t *this);
+
+ /**
+ * @brief Sets the request flag.
+ *
+ * @param this message_t object
+ * @param original_initiator TRUE if message is a request, FALSE if it is a reply
+ * @return SUCCESS
+ */
+ status_t (*set_request) (message_t *this,bool request);
+
+ /**
+ * @brief Gets request flag.
+ *
+ * @param this message_t object
+ * @return TRUE if message is a request, FALSE if it is a reply
+ */
+ bool (*get_request) (message_t *this);
+
+ /**
+ * @brief Append a payload to the message.
+ *
+ * @param this message_t object
+ * @param payload payload to append
+ * @return
+ * - SUCCESS or
+ * - OUT_OF_RES
+ */
+ status_t (*add_payload) (message_t *this, payload_t *payload);
+
+ /**
+ * @brief Parses header of message
+ *
+ * @param this message_t object
+ * @return
+ * - SUCCESS if header could be parsed
+ * - OUT_OF_RES if out of ressources
+ * - PARSE_ERROR if corrupted/invalid data found
+ * - FAILED if consistence check of header failed
+ */
+ status_t (*parse_header) (message_t *this);
+
+ /**
+ * @brief Parses body of message
+ *
+ * @param this message_t object
+ * @return
+ * - SUCCESS if header could be parsed
+ * - NOT_SUPPORTED if unsupported payload are contained in body
+ * - OUT_OF_RES if out of ressources
+ * - FAILED if message type is not suppported!
+ * - PARSE_ERROR if corrupted/invalid data found
+ * - VERIFY_ERROR if verification of some payload failed
+ */
+ status_t (*parse_body) (message_t *this);
+
+ /**
+ * @brief Generates the UDP packet of specific message
+ *
+ * @param this message_t object
+ * @return
+ * - SUCCESS if packet could be generated
+ * - EXCHANGE_TYPE_NOT_SET if exchange type is currently not set
+ * ....
+ */
+ status_t (*generate) (message_t *this, packet_t **packet);
+ status_t (*get_source) (message_t *this, host_t **host);
+ status_t (*set_source) (message_t *this, host_t *host);
+ status_t (*get_destination) (message_t *this, host_t **host);
+ status_t (*set_destination) (message_t *this, host_t *host);
+ status_t (*get_payload_iterator) (message_t *this, linked_list_iterator_t **iterator);
+
+ /**
+ * @brief Destroys a message and all including objects
+ *
+ * @param this message_t object
+ * @return SUCCESS
+ */
+ status_t (*destroy) (message_t *this);
+};
+
+/**
+ * Creates an message_t object from a incoming UDP Packet.
+ *
+ * @warning the given packet_t object is not copied and gets
+ * destroyed in message_t's destroy call.
+ *
+ * @warning Packet is not parsed in here!
+ *
+ * - exchange_type is set to NOT_SET
+ * - original_initiator is set to TRUE
+ * - is_request is set to TRUE
+ *
+ * @param packet packet_t object which is assigned to message
+ *
+ * @return
+ * - created message_t object
+ * - NULL if out of ressources
+ */
+message_t * message_create_from_packet(packet_t *packet);
+
+
+/**
+ * Creates an empty message_t object.
+ *
+ * - exchange_type is set to NOT_SET
+ * - original_initiator is set to TRUE
+ * - is_request is set to TRUE
+ *
+ * @return
+ * - created message_t object
+ * - NULL if out of ressources
+ */
+message_t * message_create();
+
+#endif /*MESSAGE_H_*/
diff --git a/Source/charon/encoding/parser.c b/Source/charon/encoding/parser.c
new file mode 100644
index 000000000..cf7d0b8ee
--- /dev/null
+++ b/Source/charon/encoding/parser.c
@@ -0,0 +1,923 @@
+/**
+ * @file parser.c
+ *
+ * @brief Generic parser class used to parse IKEv2-Header and Payload
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stdlib.h>
+#include <arpa/inet.h>
+
+#include "parser.h"
+
+#include <types.h>
+#include <definitions.h>
+#include <globals.h>
+#include <utils/allocator.h>
+#include <utils/logger.h>
+#include <utils/linked_list.h>
+#include <encoding/payloads/encodings.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/sa_payload.h>
+#include <encoding/payloads/proposal_substructure.h>
+#include <encoding/payloads/transform_substructure.h>
+#include <encoding/payloads/transform_attribute.h>
+#include <encoding/payloads/ke_payload.h>
+#include <encoding/payloads/nonce_payload.h>
+#include <encoding/payloads/notify_payload.h>
+
+
+
+/**
+ * @private data stored in a context
+ *
+ * contains pointers and counters to store current state
+ */
+typedef struct private_parser_s private_parser_t;
+
+struct private_parser_s {
+ /**
+ * Public members, see parser_t
+ */
+ parser_t public;
+
+ /**
+ * @brief parse a 4-Bit unsigned integer from the current parsing position.
+ *
+ * @param this parser object
+ * @param rule_number number of current rule
+ * @param[out] output_pos pointer where to write the parsed result
+ * @return
+ * - SUCCESS or
+ * - PARSE_ERROR when not successful
+ */
+ status_t (*parse_uint4) (private_parser_t *this, int rule_number, u_int8_t *output_pos);
+
+ /**
+ * @brief parse a 8-Bit unsigned integer from the current parsing position.
+ *
+ * @param this parser object
+ * @param rule_number number of current rule
+ * @param[out] output_pos pointer where to write the parsed result
+ * @return
+ * - SUCCESS or
+ * - PARSE_ERROR when not successful
+ */
+ status_t (*parse_uint8) (private_parser_t *this, int rule_number, u_int8_t *output_pos);
+
+ /**
+ * @brief parse a 15-Bit unsigned integer from the current parsing position.
+ *
+ * This is a special case used for ATTRIBUTE_TYPE.
+ * Big-/Little-endian conversion is done here.
+ *
+ * @param this parser object
+ * @param rule_number number of current rule
+ * @param[out] output_pos pointer where to write the parsed result
+ * @return
+ * - SUCCESS or
+ * - PARSE_ERROR when not successful
+ */
+ status_t (*parse_uint15) (private_parser_t *this, int rule_number, u_int16_t *output_pos);
+
+ /**
+ * @brief parse a 16-Bit unsigned integer from the current parsing position.
+ *
+ * Big-/Little-endian conversion is done here.
+ *
+ * @param this parser object
+ * @param rule_number number of current rule
+ * @param[out] output_pos pointer where to write the parsed result
+ * @return
+ * - SUCCESS or
+ * - PARSE_ERROR when not successful
+ */
+ status_t (*parse_uint16) (private_parser_t *this, int rule_number, u_int16_t *output_pos);
+
+ /**
+ * @brief parse a 32-Bit unsigned integer from the current parsing position.
+ *
+ * Big-/Little-endian conversion is done here.
+ *
+ * @param this parser object
+ * @param rule_number number of current rule
+ * @param[out] output_pos pointer where to write the parsed result
+ * @return
+ * - SUCCESS or
+ * - PARSE_ERROR when not successful
+ */
+ status_t (*parse_uint32) (private_parser_t *this, int rule_number, u_int32_t *output_pos);
+
+ /**
+ * @brief parse a 64-Bit unsigned integer from the current parsing position.
+ *
+ * @todo add support for big-endian machines.
+ *
+ * @param this parser object
+ * @param rule_number number of current rule
+ * @param[out] output_pos pointer where to write the parsed result
+ * @return
+ * - SUCCESS or
+ * - PARSE_ERROR when not successful
+ */
+ status_t (*parse_uint64) (private_parser_t *this, int rule_number, u_int64_t *output_pos);
+
+ /**
+ * @brief parse a given amount of bytes and writes them to a specific location
+ *
+ * @param this parser object
+ * @param rule_number number of current rule
+ * @param[out] output_pos pointer where to write the parsed result
+ * @param bytes number of bytes to parse
+ * @return
+ * - SUCCESS or
+ * - PARSE_ERROR when not successful
+ */
+ status_t (*parse_bytes) (private_parser_t *this, int rule_number, u_int8_t *output_pos,size_t bytes);
+
+ /**
+ * @brief parse a single Bit from the current parsing position
+ *
+ * @param this parser object
+ * @param rule_number number of current rule
+ * @param[out] output_pos pointer where to write the parsed result
+ * @return
+ * - SUCCESS or
+ * - PARSE_ERROR when not successful
+ */
+ status_t (*parse_bit) (private_parser_t *this, int rule_number, bool *output_pos);
+
+ /**
+ * @brief parse substructures in a list
+ *
+ * This function calls the parser recursivly to parse contained substructures
+ * in a linked_list_t. The list must already be created. Payload defines
+ * the type of the substructures. parsing is continued until the specified length
+ * is completely parsed.
+ *
+ * @param this parser object
+ * @param rule_number number of current rule
+ * @param[out] output_pos pointer of a linked_list where substructures are added
+ * @param payload_type type of the contained substructures to parse
+ * @param length number of bytes to parse in this list
+ * @return
+ * - SUCCESS or
+ * - PARSE_ERROR when not successful
+ */
+ status_t (*parse_list) (private_parser_t *this, int rule_number, linked_list_t **output_pos, payload_type_t payload_ype, size_t length);
+
+ /**
+ * @brief parse data from current parsing position in a chunk.
+ *
+ * This function clones length number of bytes to output_pos, without
+ * modifiyng them. Space will be allocated and must be freed by caller.
+ *
+ * @param this parser object
+ * @param rule_number number of current rule
+ * @param[out] output_pos pointer of a chunk which will point to the allocated data
+ * @param length number of bytes to clone
+ * @return
+ * - SUCCESS or
+ * - PARSE_ERROR when not successful
+ */
+ status_t (*parse_chunk) (private_parser_t *this, int rule_number, chunk_t *output_pos, size_t length);
+
+ /**
+ * Current bit for reading in input data
+ */
+ u_int8_t bit_pos;
+
+ /**
+ * Current byte for reading in input data
+ */
+ u_int8_t *byte_pos;
+
+ /**
+ * input data to parse
+ */
+ u_int8_t *input;
+
+ /**
+ * roof of input, used for length-checking
+ */
+ u_int8_t *input_roof;
+
+ /**
+ * set of encoding rules for this parsing session
+ */
+ encoding_rule_t *rules;
+
+ /**
+ * logger object
+ */
+ logger_t *logger;
+};
+
+/**
+ * implementation of private_parser_t.parse_uint4
+ */
+static status_t parse_uint4(private_parser_t *this, int rule_number, u_int8_t *output_pos)
+{
+ if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
+ {
+ this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
+ rule_number, mapping_find(encoding_type_m,
+ this->rules[rule_number].type));
+ return PARSE_ERROR;
+ }
+ switch (this->bit_pos)
+ {
+ case 0:
+ /* caller interested in result ? */
+ if (output_pos != NULL)
+ {
+ *output_pos = *(this->byte_pos) >> 4;
+ }
+ this->bit_pos = 4;
+ break;
+ case 4:
+ /* caller interested in result ? */
+ if (output_pos != NULL)
+ {
+ *output_pos = *(this->byte_pos) & 0x0F;
+ }
+ this->bit_pos = 0;
+ this->byte_pos++;
+ break;
+ default:
+ this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
+ rule_number, mapping_find(encoding_type_m,
+ this->rules[rule_number].type), this->bit_pos);
+ return PARSE_ERROR;
+ }
+
+ if (output_pos != NULL)
+ {
+ this->logger->log(this->logger, RAW|MOST, " => %d", *output_pos);
+ }
+
+
+ return SUCCESS;
+}
+
+/**
+ * implementation of private_parser_t.parse_uint8
+ */
+static status_t parse_uint8(private_parser_t *this, int rule_number, u_int8_t *output_pos)
+{
+ if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
+ {
+ this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
+ rule_number, mapping_find(encoding_type_m,
+ this->rules[rule_number].type));
+ return PARSE_ERROR;
+ }
+ if (this->bit_pos)
+ {
+ this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
+ rule_number, mapping_find(encoding_type_m,
+ this->rules[rule_number].type), this->bit_pos);
+ return PARSE_ERROR;
+ }
+
+ /* caller interested in result ? */
+ if (output_pos != NULL)
+ {
+ *output_pos = *(this->byte_pos);
+ this->logger->log(this->logger, RAW|MOST, " => %d", *output_pos);
+ }
+ this->byte_pos++;
+
+
+
+ return SUCCESS;
+}
+
+/**
+ * implementation of private_parser_t.parse_uint15
+ */
+static status_t parse_uint15(private_parser_t *this, int rule_number, u_int16_t *output_pos)
+{
+ if (this->byte_pos + sizeof(u_int16_t) > this->input_roof)
+ {
+ this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
+ rule_number, mapping_find(encoding_type_m,
+ this->rules[rule_number].type));
+ return PARSE_ERROR;
+ }
+ if (this->bit_pos != 1)
+ {
+ this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
+ rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
+ this->bit_pos);
+ return PARSE_ERROR;
+ }
+ /* caller interested in result ? */
+ if (output_pos != NULL)
+ {
+ *output_pos = ntohs(*((u_int16_t*)this->byte_pos)) & ~0x8000;
+ this->logger->log(this->logger, RAW|MOST, " => %d", *output_pos);
+ }
+ this->byte_pos += 2;
+ this->bit_pos = 0;
+
+
+
+ return SUCCESS;
+}
+
+/**
+ * implementation of private_parser_t.parse_uint16
+ */
+static status_t parse_uint16(private_parser_t *this, int rule_number, u_int16_t *output_pos)
+{
+ if (this->byte_pos + sizeof(u_int16_t) > this->input_roof)
+ {
+ this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
+ rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
+ return PARSE_ERROR;
+ }
+ if (this->bit_pos)
+ {
+ this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
+ rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
+ this->bit_pos);
+ return PARSE_ERROR;
+ }
+ /* caller interested in result ? */
+ if (output_pos != NULL)
+ {
+ *output_pos = ntohs(*((u_int16_t*)this->byte_pos));
+
+ this->logger->log(this->logger, RAW|MOST, " => %d", *output_pos);
+ }
+ this->byte_pos += 2;
+
+
+ return SUCCESS;
+}
+/**
+ * implementation of private_parser_t.parse_uint32
+ */
+static status_t parse_uint32(private_parser_t *this, int rule_number, u_int32_t *output_pos)
+{
+ if (this->byte_pos + sizeof(u_int32_t) > this->input_roof)
+ {
+ this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
+ rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
+ return PARSE_ERROR;
+ }
+ if (this->bit_pos)
+ {
+ this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
+ rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
+ this->bit_pos);
+ return PARSE_ERROR;
+ }
+ /* caller interested in result ? */
+ if (output_pos != NULL)
+ {
+ *output_pos = ntohl(*((u_int32_t*)this->byte_pos));
+
+ this->logger->log(this->logger, RAW|MOST, " => %d", *output_pos);
+ }
+ this->byte_pos += 4;
+
+
+ return SUCCESS;
+}
+
+/**
+ * implementation of private_parser_t.parse_uint64
+ */
+static status_t parse_uint64(private_parser_t *this, int rule_number, u_int64_t *output_pos)
+{
+ if (this->byte_pos + sizeof(u_int64_t) > this->input_roof)
+ {
+ this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
+ rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
+ return PARSE_ERROR;
+ }
+ if (this->bit_pos)
+ {
+ this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
+ rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
+ this->bit_pos);
+ return PARSE_ERROR;
+ }
+ /* caller interested in result ? */
+ if (output_pos != NULL)
+ {
+ /* assuming little endian host order */
+ *(output_pos + 1) = ntohl(*((u_int32_t*)this->byte_pos));
+ *output_pos = ntohl(*(((u_int32_t*)this->byte_pos) + 1));
+
+ this->logger->log_bytes(this->logger, RAW|MOST, " =>", (void*)output_pos, 8);
+ }
+ this->byte_pos += 8;
+
+
+
+ return SUCCESS;
+}
+
+static status_t parse_bytes (private_parser_t *this, int rule_number, u_int8_t *output_pos,size_t bytes)
+{
+ if (this->byte_pos + bytes > this->input_roof)
+ {
+ this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
+ rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
+ return PARSE_ERROR;
+ }
+ if (this->bit_pos)
+ {
+ this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
+ rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
+ this->bit_pos);
+ return PARSE_ERROR;
+ }
+
+ /* caller interested in result ? */
+ if (output_pos != NULL)
+ {
+ memcpy(output_pos,this->byte_pos,bytes);
+
+ this->logger->log_bytes(this->logger, RAW|MOST, " =>", (void*)output_pos, bytes);
+ }
+ this->byte_pos += bytes;
+
+ return SUCCESS;
+}
+
+/**
+ * implementation of private_parser_t.parse_bit
+ */
+static status_t parse_bit(private_parser_t *this, int rule_number, bool *output_pos)
+{
+ if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
+ {
+ this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
+ rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
+ return PARSE_ERROR;
+ }
+ /* caller interested in result ? */
+ if (output_pos != NULL)
+ {
+ u_int8_t mask;
+ mask = 0x01 << (7 - this->bit_pos);
+ *output_pos = *this->byte_pos & mask;
+
+ if (*output_pos)
+ {
+ /* set to a "clean", comparable true */
+ *output_pos = TRUE;
+ }
+
+ this->logger->log(this->logger, RAW|MOST, " => %d", *output_pos);
+ }
+ this->bit_pos = (this->bit_pos + 1) % 8;
+ if (this->bit_pos == 0)
+ {
+ this->byte_pos++;
+ }
+
+
+ return SUCCESS;
+}
+
+/**
+ * implementation of private_parser_t.parse_list
+ */
+static status_t parse_list(private_parser_t *this, int rule_number, linked_list_t **output_pos, payload_type_t payload_type, size_t length)
+{
+ linked_list_t * list = *output_pos;
+
+ if (length < 0)
+ {
+ this->logger->log(this->logger, ERROR, " invalid length for rule %d %s",
+ rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
+ return PARSE_ERROR;
+ }
+
+ if (this->bit_pos)
+ {
+ this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
+ rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), this->bit_pos);
+ return PARSE_ERROR;
+ }
+
+ while (length > 0)
+ {
+ u_int8_t *pos_before = this->byte_pos;
+ payload_t *payload;
+ status_t status;
+ this->logger->log(this->logger, CONTROL|MORE, " %d bytes left, parsing recursivly %s",
+ length, mapping_find(payload_type_m, payload_type));
+ status = this->public.parse_payload((parser_t*)this, payload_type, &payload);
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, ERROR, " parsing of a %s substructure failed",
+ mapping_find(payload_type_m, payload_type));
+ return status;
+ }
+ list->insert_last(list, payload);
+ length -= this->byte_pos - pos_before;
+ }
+ *output_pos = list;
+ return SUCCESS;
+}
+
+/**
+ * implementation of private_parser_t.parse_chunk
+ */
+static status_t parse_chunk(private_parser_t *this, int rule_number, chunk_t *output_pos, size_t length)
+{
+ if (this->byte_pos + length > this->input_roof)
+ {
+ this->logger->log(this->logger, ERROR, " not enough input (%d bytes) to parse rule %d %s",
+ length, rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
+ return PARSE_ERROR;
+ }
+ if (this->bit_pos)
+ {
+ this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
+ rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), this->bit_pos);
+ return PARSE_ERROR;
+ }
+ if (output_pos != NULL)
+ {
+ output_pos->len = length;
+ output_pos->ptr = allocator_alloc(length);
+ if (output_pos->ptr == NULL)
+ {
+ this->logger->log(this->logger, ERROR, " allocation of chunk (%d bytes) failed", length);
+ return OUT_OF_RES;
+ }
+ memcpy(output_pos->ptr, this->byte_pos, length);
+ }
+ this->byte_pos += length;
+ this->logger->log_bytes(this->logger, RAW|MOST, " =>", (void*)output_pos->ptr, length);
+
+ return SUCCESS;
+}
+
+/**
+ * implementation of parser_context_t.parse_payload
+ */
+static status_t parse_payload(private_parser_t *this, payload_type_t payload_type, payload_t **payload)
+{
+ payload_t *pld;
+ void *output;
+ size_t rule_count, payload_length, spi_size, attribute_length;
+ bool attribute_format;
+ int rule_number;
+ encoding_rule_t *rule;
+
+ this->logger->log(this->logger, CONTROL, "parsing %s payload, %d bytes left",
+ mapping_find(payload_type_m, payload_type),
+ this->input_roof-this->byte_pos);
+
+ this->logger->log_bytes(this->logger, RAW, "parsing payload from", this->byte_pos,
+ this->input_roof-this->byte_pos);
+
+ /* ok, do the parsing */
+ pld = payload_create(payload_type);
+ if (pld == NULL)
+ {
+ this->logger->log(this->logger, ERROR, " payload %s not supported", mapping_find(payload_type_m, payload_type));
+ return NOT_SUPPORTED;
+ }
+ /* base pointer for output, avoids casting in every rule */
+ output = pld;
+
+ pld->get_encoding_rules(pld, &(this->rules), &rule_count);
+
+ for (rule_number = 0; rule_number < rule_count; rule_number++)
+ {
+ rule = &(this->rules[rule_number]);
+ this->logger->log(this->logger, CONTROL|MORE, " parsing rule %d %s",
+ rule_number, mapping_find(encoding_type_m, rule->type));
+ switch (rule->type)
+ {
+ case U_INT_4:
+ {
+ if (this->parse_uint4(this, rule_number, output + rule->offset) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case U_INT_8:
+ {
+ if (this->parse_uint8(this, rule_number, output + rule->offset) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case U_INT_16:
+ {
+ if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case U_INT_32:
+ {
+ if (this->parse_uint32(this, rule_number, output + rule->offset) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case U_INT_64:
+ {
+ if (this->parse_uint64(this, rule_number, output + rule->offset) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case IKE_SPI:
+ {
+ if (this->parse_bytes(this, rule_number, output + rule->offset,8) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case RESERVED_BIT:
+ {
+ if (this->parse_bit(this, rule_number, NULL) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case RESERVED_BYTE:
+ {
+ if (this->parse_uint8(this, rule_number, NULL) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case FLAG:
+ {
+ if (this->parse_bit(this, rule_number, output + rule->offset) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case PAYLOAD_LENGTH:
+ {
+ if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ payload_length = *(u_int16_t*)(output + rule->offset);
+ break;
+ }
+ case HEADER_LENGTH:
+ {
+ if (this->parse_uint32(this, rule_number, output + rule->offset) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case SPI_SIZE:
+ {
+ if (this->parse_uint8(this, rule_number, output + rule->offset) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ spi_size = *(u_int8_t*)(output + rule->offset);
+ break;
+ }
+ case SPI:
+ {
+ if (this->parse_chunk(this, rule_number, output + rule->offset, spi_size) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case PROPOSALS:
+ {
+ size_t proposals_length = payload_length - SA_PAYLOAD_HEADER_LENGTH;
+ if (this->parse_list(this, rule_number, output + rule->offset, PROPOSAL_SUBSTRUCTURE, proposals_length) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case TRANSFORMS:
+ {
+ size_t transforms_length = payload_length - spi_size - PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH;
+ if (this->parse_list(this, rule_number, output + rule->offset, TRANSFORM_SUBSTRUCTURE, transforms_length) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case TRANSFORM_ATTRIBUTES:
+ {
+ size_t transform_a_length = payload_length - TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
+ if (this->parse_list(this, rule_number, output + rule->offset, TRANSFORM_ATTRIBUTE, transform_a_length) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case ATTRIBUTE_FORMAT:
+ {
+ if (this->parse_bit(this, rule_number, output + rule->offset) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ attribute_format = *(bool*)(output + rule->offset);
+ break;
+ }
+ case ATTRIBUTE_TYPE:
+ {
+ if (this->parse_uint15(this, rule_number, output + rule->offset) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ attribute_format = *(bool*)(output + rule->offset);
+ break;
+ }
+ case ATTRIBUTE_LENGTH_OR_VALUE:
+ {
+ if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ attribute_length = *(u_int16_t*)(output + rule->offset);
+ break;
+ }
+ case ATTRIBUTE_VALUE:
+ {
+ if (attribute_format == FALSE)
+ {
+ if (this->parse_chunk(this, rule_number, output + rule->offset, attribute_length) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ }
+ break;
+ }
+ case NONCE_DATA:
+ {
+ size_t nonce_length = payload_length - NONCE_PAYLOAD_HEADER_LENGTH;
+ if (this->parse_chunk(this, rule_number, output + rule->offset, nonce_length) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case KEY_EXCHANGE_DATA:
+ {
+ size_t keydata_length = payload_length - KE_PAYLOAD_HEADER_LENGTH;
+ if (this->parse_chunk(this, rule_number, output + rule->offset, keydata_length) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case NOTIFICATION_DATA:
+ {
+ size_t notify_length = payload_length - NOTIFY_PAYLOAD_HEADER_LENGTH - spi_size;
+ if (this->parse_chunk(this, rule_number, output + rule->offset, notify_length) != SUCCESS)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ default:
+ {
+ this->logger->log(this->logger, ERROR, " no rule to parse rule %d %s (%d)", rule_number, mapping_find(encoding_type_m, rule->type), rule->type);
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ }
+ /* process next rulue */
+ rule++;
+ }
+
+ *payload = pld;
+
+ this->logger->log(this->logger, CONTROL, "parsing %s successful", mapping_find(payload_type_m, payload_type));
+ return SUCCESS;
+}
+
+/**
+ * implementation of parser_t.reset_context
+ */
+static status_t reset_context (private_parser_t *this)
+{
+ this->byte_pos = this->input;
+ this->bit_pos = 0;
+ return SUCCESS;
+}
+
+/**
+ * implementation of parser_t.destroy
+ */
+static status_t destroy(private_parser_t *this)
+{
+ global_logger_manager->destroy_logger(global_logger_manager,this->logger);
+ allocator_free(this);
+
+ return SUCCESS;
+}
+
+/*
+ * see header file
+ */
+parser_t *parser_create(chunk_t data)
+{
+ private_parser_t *this = allocator_alloc_thing(private_parser_t);
+
+ if (this == NULL)
+ {
+ return NULL;
+ }
+
+ this->logger = global_logger_manager->create_logger(global_logger_manager, PARSER, NULL);
+ this->logger->disable_level(this->logger, FULL);
+ this->logger->enable_level(this->logger, CONTROL);
+
+
+ if (this->logger == NULL)
+ {
+ global_logger_manager->destroy_logger(global_logger_manager, this->logger);
+ allocator_free(this);
+ return NULL;
+ }
+
+ this->public.parse_payload = (status_t(*)(parser_t*,payload_type_t,payload_t**)) parse_payload;
+ this->public.reset_context = (status_t(*)(parser_t*)) reset_context;
+ this->public.destroy = (status_t(*)(parser_t*)) destroy;
+
+
+ this->parse_uint4 = parse_uint4;
+ this->parse_uint8 = parse_uint8;
+ this->parse_uint15 = parse_uint15;
+ this->parse_uint16 = parse_uint16;
+ this->parse_uint32 = parse_uint32;
+ this->parse_uint64 = parse_uint64;
+ this->parse_bytes = parse_bytes;
+ this->parse_bit = parse_bit;
+ this->parse_list = parse_list;
+ this->parse_chunk = parse_chunk;
+
+ this->input = data.ptr;
+ this->byte_pos = data.ptr;
+ this->bit_pos = 0;
+ this->input_roof = data.ptr + data.len;
+
+ return (parser_t*)this;
+}
+
diff --git a/Source/charon/encoding/parser.h b/Source/charon/encoding/parser.h
new file mode 100644
index 000000000..9a99fabb4
--- /dev/null
+++ b/Source/charon/encoding/parser.h
@@ -0,0 +1,88 @@
+/**
+ * @file parser.h
+ *
+ * @brief Generic parser class used to parse IKEv2-Header and Payload
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef PARSER_H_
+#define PARSER_H_
+
+#include <types.h>
+#include <encoding/payloads/encodings.h>
+#include <encoding/payloads/payload.h>
+
+
+/**
+ * @brief A parser_t object which parses payloads
+ *
+ * A parser is used for parsing one chunk of data. Multiple
+ * payloads can be parsed out of the chunk using parse_payload.
+ * The parser remains the state until destroyed.
+ */
+typedef struct parser_s parser_t;
+
+struct parser_s {
+
+ /**
+ * @brief parses the next payload
+ *
+ * @warning caller is responsible for freeing allocated payload
+ *
+ * Rules for parsing are described in the payload definition.
+ *
+ * @param this parser Object
+ * @param payload_type payload type to parse
+ * @param[out] payload pointer where parsed payload was allocated
+ * @return
+ * - SUCCESSFUL if succeeded,
+ * - NOT_SUPPORTED if payload_type is not supported
+ * - OUT_OF_RES if out of ressources
+ * - PARSE_ERROR if corrupted/invalid data found
+ */
+ status_t (*parse_payload) (parser_t *this, payload_type_t payload_type, payload_t **payload);
+
+ /**
+ * @brief Resets the current parser context
+ *
+ * @param parser parser object
+ * @return
+ * - SUCCESSFUL in any case
+ */
+ status_t (*reset_context) (parser_t *this);
+
+ /**
+ * @brief Destroys a parser object
+ *
+ * @param parser parser object
+ * @return
+ * - SUCCESSFUL in any case
+ */
+ status_t (*destroy) (parser_t *this);
+};
+
+/**
+ * @brief Constructor to create a parser
+ *
+ * @param data chunk of data to parse with this parser object
+ * @return the parser, or NULL if failed
+ *
+ */
+parser_t *parser_create(chunk_t data);
+
+#endif /*PARSER_H_*/
diff --git a/Source/charon/encoding/payloads/encodings.c b/Source/charon/encoding/payloads/encodings.c
new file mode 100644
index 000000000..4747ddc22
--- /dev/null
+++ b/Source/charon/encoding/payloads/encodings.c
@@ -0,0 +1,54 @@
+/**
+ * @file encodings.c
+ *
+ * @brief Type definitions for parser and generator,
+ * also payload types are defined here.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+
+#include "encodings.h"
+
+
+mapping_t encoding_type_m[] = {
+ {U_INT_4, "U_INT_4"},
+ {U_INT_8, "U_INT_8"},
+ {U_INT_16, "U_INT_16"},
+ {U_INT_32, "U_INT_32"},
+ {U_INT_64, "U_INT_64"},
+ {IKE_SPI, "IKE_SPI"},
+ {RESERVED_BIT, "RESERVED_BIT"},
+ {RESERVED_BYTE, "RESERVED_BYTE"},
+ {FLAG, "FLAG"},
+ {PAYLOAD_LENGTH, "PAYLOAD_LENGTH"},
+ {HEADER_LENGTH, "HEADER_LENGTH"},
+ {SPI_SIZE, "SPI_SIZE"},
+ {SPI, "SPI"},
+ {KEY_EXCHANGE_DATA, "KEY_EXCHANGE_DATA"},
+ {NOTIFICATION_DATA, "NOTIFICATION_DATA"},
+ {PROPOSALS, "PROPOSALS"},
+ {TRANSFORMS, "TRANSFORMS"},
+ {TRANSFORM_ATTRIBUTES, "TRANSFORM_ATTRIBUTES"},
+ {ATTRIBUTE_FORMAT, "ATTRIBUTE_FORMAT"},
+ {ATTRIBUTE_TYPE, "ATTRIBUTE_TYPE"},
+ {ATTRIBUTE_LENGTH_OR_VALUE, "ATTRIBUTE_LENGTH_OR_VALUE"},
+ {ATTRIBUTE_VALUE, "ATTRIBUTE_VALUE"},
+ {NONCE_DATA, "NONCE_DATA"},
+ {MAPPING_END, NULL}
+};
+
diff --git a/Source/charon/encoding/payloads/encodings.h b/Source/charon/encoding/payloads/encodings.h
new file mode 100644
index 000000000..1401ea798
--- /dev/null
+++ b/Source/charon/encoding/payloads/encodings.h
@@ -0,0 +1,359 @@
+/**
+ * @file encodings.h
+ *
+ * @brief Type definitions for parser and generator,
+ * also payload types are defined here.
+ *
+ * Header is parsed like a payload and gets its one payload_id
+ * from PRIVATE USE space. Also the substructures
+ * of specific payload types get their own payload_id
+ * from PRIVATE_USE space. See RFC for mor informations.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef ENCODINGS_H_
+#define ENCODINGS_H_
+
+#include <types.h>
+#include <definitions.h>
+
+
+/**
+ * @brief All different kinds of encoding types.
+ *
+ * Each field of an IKEv2-Message (in header or payload)
+ * which has to be parsed or generated differently has its own
+ * type defined here.
+ */
+typedef enum encoding_type_e encoding_type_t;
+
+enum encoding_type_e{
+ /**
+ * Representing a 4 Bit unsigned int value
+ *
+ *
+ * When generating it must be changed from host to network order.
+ * The value is read from the associated data struct.
+ * The current write position is moved 4 bit forward afterwards.
+ *
+ * When parsing it must be changed from network to host order.
+ * The value is written to the associated data struct.
+ * The current read pointer is moved 4 bit forward afterwards.
+ */
+ U_INT_4,
+ /**
+ * Representing a 8 Bit unsigned int value
+ *
+ *
+ * When generating it must be changed from host to network order.
+ * The value is read from the associated data struct.
+ * The current write position is moved 8 bit forward afterwards.
+ *
+ * When parsing it must be changed from network to host order.
+ * The value is written to the associated data struct.
+ * The current read pointer is moved 8 bit forward afterwards.
+ */
+ U_INT_8,
+ /**
+ * Representing a 16 Bit unsigned int value
+ *
+ *
+ * When generating it must be changed from host to network order.
+ * The value is read from the associated data struct.
+ * The current write position is moved 16 bit forward afterwards.
+ *
+ * When parsing it must be changed from network to host order.
+ * The value is written to the associated data struct.
+ * The current read pointer is moved 16 bit forward afterwards.
+ */
+ U_INT_16,
+ /**
+ * Representing a 32 Bit unsigned int value
+ *
+ * When generating it must be changed from host to network order.
+ * The value is read from the associated data struct.
+ * The current write position is moved 32 bit forward afterwards.
+ *
+ * When parsing it must be changed from network to host order.
+ * The value is written to the associated data struct.
+ * The current read pointer is moved 32 bit forward afterwards.
+ */
+
+ U_INT_32,
+ /**
+ * Representing a 64 Bit unsigned int value
+ *
+ * When generating it must be changed from host to network order.
+ * The value is read from the associated data struct.
+ * The current write position is moved 64 bit forward afterwards.
+ *
+ * When parsing it must be changed from network to host order.
+ * The value is written to the associated data struct.
+ * The current read pointer is moved 64 bit forward afterwards.
+ */
+ U_INT_64,
+ /**
+ * @brief represents a RESERVED_BIT used in FLAG-Bytes
+ *
+ * When generating, the next bit is set to zero and the current write
+ * position is moved one bit forward.
+ * No value is read from the associated data struct.
+ * The current write position is moved 1 bit forward afterwards.
+ *
+ * When parsing, the current read pointer is moved one bit forward.
+ * No value is written to the associated data struct.
+ * The current read pointer is moved 1 bit forward afterwards.
+ */
+ RESERVED_BIT,
+ /**
+ * @brief represents a RESERVED_BYTE
+ *
+ * When generating, the next byte is set to zero and the current write
+ * position is moved one byte forward.
+ * No value is read from the associated data struct.
+ * The current write position is moved 1 byte forward afterwards.
+ *
+ * When parsing, the current read pointer is moved one byte forward.
+ * No value is written to the associated data struct.
+ * The current read pointer is moved 1 byte forward afterwards.
+ */
+ RESERVED_BYTE,
+ /**
+ * Representing a 1 Bit flag.
+ *
+ * When generation, the next bit is set to 1 if the associated value
+ * in the data struct is TRUE, 0 otherwise. The current write position
+ * is moved 1 bit forward afterwards.
+ *
+ * When parsing, the next bit is read and stored in the associated data
+ * struct. 0 means FALSE, 1 means TRUE, The current read pointer
+ * is moved 1 bit forward afterwards
+ */
+ FLAG,
+ /**
+ * Representating a length field of a payload
+ *
+ * When generating it must be changed from host to network order.
+ * The value is read from the associated data struct.
+ * The current write position is moved 16 bit forward afterwards.
+ *
+ * When parsing it must be changed from network to host order.
+ * The value is written to the associated data struct.
+ * The current read pointer is moved 16 bit forward afterwards.
+ */
+ PAYLOAD_LENGTH,
+ /**
+ * Representating a length field of a header
+ *
+ * When generating it must be changed from host to network order.
+ * The value is read from the associated data struct.
+ * The current write position is moved 32 bit forward afterwards.
+ *
+ * When parsing it must be changed from network to host order.
+ * The value is written to the associated data struct.
+ * The current read pointer is moved 32 bit forward afterwards.
+ */
+ HEADER_LENGTH,
+ /**
+ * Representating a spi size field
+ *
+ * When generating it must be changed from host to network order.
+ * The value is read from the associated data struct.
+ * The current write position is moved 8 bit forward afterwards.
+ *
+ * When parsing it must be changed from network to host order.
+ * The value is written to the associated data struct.
+ * The current read pointer is moved 8 bit forward afterwards.
+ */
+ SPI_SIZE,
+ /**
+ * Representating a spi field
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing SPI_SIZE bytes are read and written into the chunk pointing to.
+ */
+ SPI,
+ /**
+ * Representating a Key Exchange Data field
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to.
+ */
+ KEY_EXCHANGE_DATA,
+ /**
+ * Representating a Notification field
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing (Payload Length - spi size - 8) bytes are read and written into the chunk pointing to.
+ */
+ NOTIFICATION_DATA,
+ /**
+ * Representating one or more proposal substructures
+ *
+ * The offset points to a linked_list_t pointer.
+ *
+ * When generating the proposal_substructure_t objects are stored
+ * in the pointed linked_list.
+ *
+ * When parsing the parsed proposal_substructure_t objects have
+ * to be stored in the pointed linked_list.
+ */
+ PROPOSALS,
+ /**
+ * Representating one or more transform substructures
+ *
+ * The offset points to a linked_list_t pointer.
+ *
+ * When generating the transform_substructure_t objects are stored
+ * in the pointed linked_list.
+ *
+ * When parsing the parsed transform_substructure_t objects have
+ * to be stored in the pointed linked_list.
+ */
+ TRANSFORMS,
+ /**
+ * Representating one or more Attributes of a transform substructure
+ *
+ * The offset points to a linked_list_t pointer.
+ *
+ * When generating the transform_attribute_t objects are stored
+ * in the pointed linked_list.
+ *
+ * When parsing the parsed transform_attribute_t objects have
+ * to be stored in the pointed linked_list.
+ */
+ TRANSFORM_ATTRIBUTES,
+ /**
+ * Representing a 1 Bit flag specifying the format of a transform attribute.
+ *
+ * When generation, the next bit is set to 1 if the associated value
+ * in the data struct is TRUE, 0 otherwise. The current write position
+ * is moved 1 bit forward afterwards.
+ *
+ * When parsing, the next bit is read and stored in the associated data
+ * struct. 0 means FALSE, 1 means TRUE, The current read pointer
+ * is moved 1 bit forward afterwards.
+ */
+ ATTRIBUTE_FORMAT,
+ /**
+ * Representing a 15 Bit unsigned int value used as attribute type
+ * in an attribute transform
+ *
+ *
+ * When generating it must be changed from host to network order.
+ * The value is read from the associated data struct.
+ * The current write position is moved 15 bit forward afterwards.
+ *
+ * When parsing it must be changed from network to host order.
+ * The value is written to the associated data struct.
+ * The current read pointer is moved 15 bit forward afterwards.
+ */
+ ATTRIBUTE_TYPE,
+
+ /**
+ * Depending on the field of type ATTRIBUTE_FORMAT
+ * this field contains the length or the value of an transform attribute.
+ * Its stored in a 16 unsigned integer field
+ *
+ * When generating it must be changed from host to network order.
+ * The value is read from the associated data struct.
+ * The current write position is moved 16 bit forward afterwards.
+ *
+ * When parsing it must be changed from network to host order.
+ * The value is written to the associated data struct.
+ * The current read pointer is moved 16 bit forward afterwards.
+ */
+ ATTRIBUTE_LENGTH_OR_VALUE,
+
+ /*
+ * Depending on the field of type ATTRIBUTE_FORMAT
+ * this field is available or missing and so parsed/generated
+ * or not parsed/not generated
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing SPI_SIZE bytes are read and written into the chunk pointing to.
+ */
+ ATTRIBUTE_VALUE,
+
+ /**
+ * Representating a Nonce Data field
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
+ */
+ NONCE_DATA,
+
+ /**
+ * Representating an IKE_SPI field in an IKEv2 Header
+ *
+ * When generating the value of the u_int64_t pointing to
+ * is written (host and networ order is not changed).
+ *
+ * When parsing 8 bytes are read and written into the u_int64_t pointing to.
+ */
+ IKE_SPI
+};
+
+/**
+ * mappings to map encoding_type_t's to strings
+ */
+extern mapping_t encoding_type_m[];
+
+/**
+ * An encoding rule is a mapping of a specific encoding type to
+ * a location in the data struct where the current field is stored to
+ * or read from.
+ *
+ * For examples see directory encodings/.
+ *
+ * This rules are used by parser and generator.
+ */
+typedef struct encoding_rule_s encoding_rule_t;
+
+struct encoding_rule_s{
+ /**
+ * Encoding type
+ */
+ encoding_type_t type;
+ /**
+ * Offset in the data struct
+ *
+ * When parsing, data are written to this offset of the
+ * data struct.
+ *
+ * When generating, data are read from this offset in the
+ * data struct.
+ */
+ u_int32_t offset;
+};
+
+
+
+
+
+#endif /*ENCODINGS_H_*/
diff --git a/Source/charon/encoding/payloads/ike_header.c b/Source/charon/encoding/payloads/ike_header.c
new file mode 100644
index 000000000..1f1c34253
--- /dev/null
+++ b/Source/charon/encoding/payloads/ike_header.c
@@ -0,0 +1,446 @@
+/**
+ * @file ike_header.c
+ *
+ * @brief Declaration of the class ike_header_t.
+ *
+ * An object of this type represents an ike header and is used to
+ * generate and parse ike headers.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/* offsetof macro */
+#include <stddef.h>
+
+#include "ike_header.h"
+
+#include <encoding/payloads/encodings.h>
+#include <utils/allocator.h>
+
+typedef struct private_ike_header_s private_ike_header_t;
+
+struct private_ike_header_s {
+ /**
+ * public interface
+ */
+ ike_header_t public;
+
+ /**
+ * SPI of the initiator
+ */
+ u_int64_t initiator_spi;
+ /**
+ * SPI of the responder
+ */
+ u_int64_t responder_spi;
+ /**
+ * next payload type
+ */
+ u_int8_t next_payload;
+ /**
+ * IKE major version
+ */
+ u_int8_t maj_version;
+
+ /**
+ * IKE minor version
+ */
+ u_int8_t min_version;
+
+ /**
+ * Exchange type
+ */
+ u_int8_t exchange_type;
+
+ /**
+ * Flags of the Message
+ *
+ */
+ struct {
+ /**
+ * Sender is initiator of the associated IKE_SA_INIT-Exchange
+ */
+ bool initiator;
+ /**
+ * is protocol supporting higher version?
+ */
+ bool version;
+ /**
+ * TRUE, if this is a response, FALSE if its a Request
+ */
+ bool response;
+ } flags;
+ /**
+ * Associated Message-ID
+ */
+ u_int32_t message_id;
+ /**
+ * Length of the whole IKEv2-Message (header and all payloads)
+ */
+ u_int32_t length;
+};
+
+/**
+ * mappings used to get strings for exchange_type_t
+ */
+mapping_t exchange_type_m[] = {
+ {EXCHANGE_TYPE_UNDEFINED, "EXCHANGE_TYPE_UNDEFINED"},
+ {IKE_SA_INIT, "IKE_SA_INIT"},
+ {IKE_AUTH, "IKE_AUTH"},
+ {CREATE_CHILD_SA, "CREATE_CHILD_SA"},
+ {INFORMATIONAL, "INFORMATIONAL"}
+};
+
+
+/**
+ * Encoding rules to parse or generate a IKEv2-Header
+ *
+ * The defined offsets are the positions in a object of type
+ * ike_header_t.
+ *
+ */
+encoding_rule_t ike_header_encodings[] = {
+ /* 8 Byte SPI, stored in the field initiator_spi */
+ { IKE_SPI, offsetof(private_ike_header_t, initiator_spi) },
+ /* 8 Byte SPI, stored in the field responder_spi */
+ { IKE_SPI, offsetof(private_ike_header_t, responder_spi) },
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_ike_header_t, next_payload) },
+ /* 4 Bit major version, stored in the field maj_version */
+ { U_INT_4, offsetof(private_ike_header_t, maj_version) },
+ /* 4 Bit minor version, stored in the field min_version */
+ { U_INT_4, offsetof(private_ike_header_t, min_version) },
+ /* 8 Bit for the exchange type */
+ { U_INT_8, offsetof(private_ike_header_t, exchange_type) },
+ /* 2 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* 3 Bit flags, stored in the fields response, version and initiator */
+ { FLAG, offsetof(private_ike_header_t, flags.response) },
+ { FLAG, offsetof(private_ike_header_t, flags.version) },
+ { FLAG, offsetof(private_ike_header_t, flags.initiator) },
+ /* 3 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* 4 Byte message id, stored in the field message_id */
+ { U_INT_32, offsetof(private_ike_header_t, message_id) },
+ /* 4 Byte length fied, stored in the field length */
+ { HEADER_LENGTH, offsetof(private_ike_header_t, length) }
+};
+
+
+/* 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! IKE_SA Initiator's SPI !
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! IKE_SA Responder's SPI !
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload ! MjVer ! MnVer ! Exchange Type ! Flags !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Message ID !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+
+/**
+ * Implements payload_t's verify function.
+ * See #payload_s.verify for description.
+ */
+static status_t verify(private_ike_header_t *this)
+{
+ if ((this->exchange_type < IKE_SA_INIT) || (this->exchange_type > INFORMATIONAL))
+ {
+ /* unsupported exchange type */
+ return FAILED;
+ }
+ if (this->initiator_spi == 0)
+ {
+ /* initiator spi not set */
+ return FAILED;
+ }
+
+ if ((this->responder_spi == 0) && (!this->flags.initiator))
+ {
+ /* must be original initiator*/
+ return FAILED;
+ }
+
+ if ((this->responder_spi == 0) && (this->flags.response))
+ {
+ /* must be request*/
+ return FAILED;
+ }
+
+ /* verification of version is not done in here */
+
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's set_next_type function.
+ * See #payload_s.set_next_type for description.
+ */
+static status_t set_next_type(payload_t *this,payload_type_t type)
+{
+ ((private_ike_header_t *)this)->next_payload = type;
+ return SUCCESS;
+}
+/**
+ * Implements ike_header_t's get_initiator_spi fuction.
+ * See #ike_header_t.get_initiator_spi for description.
+ */
+static u_int64_t get_initiator_spi(private_ike_header_t *this)
+{
+ return this->initiator_spi;
+}
+
+/**
+ * Implements ike_header_t's set_initiator_spi fuction.
+ * See #ike_header_t.set_initiator_spi for description.
+ */
+static void set_initiator_spi(private_ike_header_t *this, u_int64_t initiator_spi)
+{
+ this->initiator_spi = initiator_spi;
+}
+
+/**
+ * Implements ike_header_t's get_responder_spi fuction.
+ * See #ike_header_t.get_responder_spi for description.
+ */
+static u_int64_t get_responder_spi(private_ike_header_t *this)
+{
+ return this->responder_spi;
+}
+
+/**
+ * Implements ike_header_t's set_responder_spi fuction.
+ * See #ike_header_t.set_responder_spi for description.
+ */
+static void set_responder_spi(private_ike_header_t *this, u_int64_t responder_spi)
+{
+ this->responder_spi = responder_spi;
+}
+
+/**
+ * Implements ike_header_t's get_maj_version fuction.
+ * See #ike_header_t.get_maj_version for description.
+ */
+static u_int8_t get_maj_version(private_ike_header_t *this)
+{
+ return this->maj_version;
+}
+
+/**
+ * Implements ike_header_t's get_min_version fuction.
+ * See #ike_header_t.get_min_version for description.
+ */
+static u_int8_t get_min_version(private_ike_header_t *this)
+{
+ return this->min_version;
+}
+
+/**
+ * Implements ike_header_t's get_response_flag fuction.
+ * See #ike_header_t.get_response_flag for description.
+ */
+static bool get_response_flag(private_ike_header_t *this)
+{
+ return this->flags.response;
+}
+
+/**
+ * Implements ike_header_t's set_response_flag fuction.
+ * See #ike_header_t.set_response_flag for description.
+ */
+static void set_response_flag(private_ike_header_t *this, bool response)
+{
+ this->flags.response = response;
+}
+
+/**
+ * Implements ike_header_t's get_version_flag fuction.
+ * See #ike_header_t.get_version_flag for description.
+ */
+static bool get_version_flag(private_ike_header_t *this)
+{
+ return this->flags.version;
+}
+
+/**
+ * Implements ike_header_t's get_initiator_flag fuction.
+ * See #ike_header_t.get_initiator_flag for description.
+ */
+static bool get_initiator_flag(private_ike_header_t *this)
+{
+ return this->flags.initiator;
+}
+
+/**
+ * Implements ike_header_t's set_initiator_flag fuction.
+ * See #ike_header_t.set_initiator_flag for description.
+ */
+static void set_initiator_flag(private_ike_header_t *this, bool initiator)
+{
+ this->flags.initiator = initiator;
+}
+
+/**
+ * Implements ike_header_t's get_exchange_type function
+ * See #ike_header_t.get_exchange_type for description.
+ */
+static u_int8_t get_exchange_type(private_ike_header_t *this)
+{
+ return this->exchange_type;
+}
+
+/**
+ * Implements ike_header_t's set_exchange_type function.
+ * See #ike_header_t.set_exchange_type for description.
+ */
+static void set_exchange_type(private_ike_header_t *this, u_int8_t exchange_type)
+{
+ this->exchange_type = exchange_type;
+}
+
+/**
+ * Implements ike_header_t's get_message_id function.
+ * See #ike_header_t.get_message_id for description.
+ */
+static u_int32_t get_message_id(private_ike_header_t *this)
+{
+ return this->message_id;
+}
+
+/**
+ * Implements ike_header_t's set_message_id function.
+ * See #ike_header_t.set_message_id for description.
+ */
+static void set_message_id(private_ike_header_t *this, u_int32_t message_id)
+{
+ this->message_id = message_id;
+}
+
+/**
+ * Implements payload_t's and ike_header_t's destroy function.
+ * See #payload_s.destroy or ike_header_s.destroy for description.
+ */
+static status_t destroy(ike_header_t *this)
+{
+ allocator_free(this);
+
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's get_encoding_rules function.
+ * See #payload_s.get_encoding_rules for description.
+ */
+static status_t get_encoding_rules(payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = ike_header_encodings;
+ *rule_count = sizeof(ike_header_encodings) / sizeof(encoding_rule_t);
+
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's get_type function.
+ * See #payload_s.get_type for description.
+ */
+static payload_type_t get_type(payload_t *this)
+{
+ return HEADER;
+}
+
+/**
+ * Implements payload_t's get_next_type function.
+ * See #payload_s.get_next_type for description.
+ */
+static payload_type_t get_next_type(payload_t *this)
+{
+ return (((private_ike_header_t*)this)->next_payload);
+}
+
+/**
+ * Implements payload_t's get_length function.
+ * See #payload_s.get_length for description.
+ */
+static size_t get_length(payload_t *this)
+{
+ return (((private_ike_header_t*)this)->length);
+}
+
+/*
+ * Described in header
+ */
+ike_header_t *ike_header_create()
+{
+ private_ike_header_t *this = allocator_alloc_thing(private_ike_header_t);
+ if (this == NULL)
+ {
+ return NULL;
+ }
+
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = get_encoding_rules;
+ this->public.payload_interface.get_length = get_length;
+ this->public.payload_interface.get_next_type = get_next_type;
+ this->public.payload_interface.set_next_type = set_next_type;
+ this->public.payload_interface.get_type = get_type;
+ this->public.payload_interface.destroy = (status_t (*) (payload_t *))destroy;
+ this->public.destroy = destroy;
+
+ this->public.get_initiator_spi = (u_int64_t (*) (ike_header_t*))get_initiator_spi;
+ this->public.set_initiator_spi = (void (*) (ike_header_t*,u_int64_t))set_initiator_spi;
+ this->public.get_responder_spi = (u_int64_t (*) (ike_header_t*))get_responder_spi;
+ this->public.set_responder_spi = (void (*) (ike_header_t *,u_int64_t))set_responder_spi;
+ this->public.get_maj_version = (u_int8_t (*) (ike_header_t*))get_maj_version;
+ this->public.get_min_version = (u_int8_t (*) (ike_header_t*))get_min_version;
+ this->public.get_response_flag = (bool (*) (ike_header_t*))get_response_flag;
+ this->public.set_response_flag = (void (*) (ike_header_t*,bool))set_response_flag;
+ this->public.get_version_flag = (bool (*) (ike_header_t*))get_version_flag;
+ this->public.get_initiator_flag = (bool (*) (ike_header_t*))get_initiator_flag;
+ this->public.set_initiator_flag = (void (*) (ike_header_t*,bool))set_initiator_flag;
+ this->public.get_exchange_type = (u_int8_t (*) (ike_header_t*))get_exchange_type;
+ this->public.set_exchange_type = (void (*) (ike_header_t*,u_int8_t))set_exchange_type;
+ this->public.get_message_id = (u_int32_t (*) (ike_header_t*))get_message_id;
+ this->public.set_message_id = (void (*) (ike_header_t*,u_int32_t))set_message_id;
+
+ /* set default values of the fields */
+ this->initiator_spi = 0;
+ this->responder_spi = 0;
+ this->next_payload = 0;
+ this->maj_version = IKE_MAJOR_VERSION;
+ this->min_version = IKE_MINOR_VERSION;
+ this->exchange_type = EXCHANGE_TYPE_UNDEFINED;
+ this->flags.initiator = TRUE;
+ this->flags.version = HIGHER_VERSION_SUPPORTED_FLAG;
+ this->flags.response = FALSE;
+ this->message_id = 0;
+ this->length = IKE_HEADER_LENGTH;
+
+
+ return (ike_header_t*)this;
+}
+
+
diff --git a/Source/charon/encoding/payloads/ike_header.h b/Source/charon/encoding/payloads/ike_header.h
new file mode 100644
index 000000000..ce52b55df
--- /dev/null
+++ b/Source/charon/encoding/payloads/ike_header.h
@@ -0,0 +1,242 @@
+/**
+ * @file ike_header.h
+ *
+ * @brief Declaration of the class ike_header_t.
+ *
+ * An object of this type represents an ike header and is used to
+ * generate and parse ike headers.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef IKE_HEADER_H_
+#define IKE_HEADER_H_
+
+#include <types.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * Major Version of IKEv2
+ */
+#define IKE_MAJOR_VERSION 2
+
+/**
+ * Minor Version of IKEv2
+ */
+#define IKE_MINOR_VERSION 0
+
+/**
+ * Flag in IKEv2-Header. Always 0
+ */
+#define HIGHER_VERSION_SUPPORTED_FLAG 0
+
+/**
+ * Length of IKE Header in Bytes
+ */
+#define IKE_HEADER_LENGTH 28
+
+/**
+ * @brief Different types of IKE-Exchanges.
+ *
+ * See RFC for different types.
+ */
+typedef enum exchange_type_e exchange_type_t;
+
+enum exchange_type_e{
+
+ /**
+ * EXCHANGE_TYPE_UNDEFINED, not a official message type :-)
+ */
+ EXCHANGE_TYPE_UNDEFINED = 240,
+ /**
+ * IKE_SA_INIT
+ */
+ IKE_SA_INIT = 34,
+ /**
+ * IKE_AUTH
+ */
+ IKE_AUTH = 35,
+ /**
+ * CREATE_CHILD_SA
+ */
+ CREATE_CHILD_SA = 36,
+ /**
+ * INFORMATIONAL
+ */
+ INFORMATIONAL = 37
+};
+
+extern mapping_t exchange_type_m[];
+
+/**
+ * Object representing an IKEv2-Header
+ *
+ * The header format of an IKEv2-Message is compatible to the
+ * ISAKMP-Header format to allow implementations supporting
+ * both versions of the IKE-protocol.
+ *
+ */
+typedef struct ike_header_s ike_header_t;
+
+struct ike_header_s {
+ /**
+ * implements payload_t interface
+ */
+ payload_t payload_interface;
+
+ /**
+ * @brief get the initiator spi
+ *
+ * @param this ike_header_t object
+ * @return initiator_spi
+ */
+ u_int64_t (*get_initiator_spi) (ike_header_t *this);
+
+ /**
+ * @brief set the initiator spi
+ *
+ * @param this ike_header_t object
+ * @param initiator_spi initiator_spi
+ */
+ void (*set_initiator_spi) (ike_header_t *this, u_int64_t initiator_spi);
+
+ /**
+ * @brief get the responder spi
+ *
+ * @param this ike_header_t object
+ * @return responder_spi
+ */
+ u_int64_t (*get_responder_spi) (ike_header_t *this);
+
+ /**
+ * @brief set the responder spi
+ *
+ * @param this ike_header_t object
+ * @param responder_spi responder_spi
+ */
+ void (*set_responder_spi) (ike_header_t *this, u_int64_t responder_spi);
+
+ /**
+ * @brief get the major version
+ *
+ * @param this ike_header_t object
+ * @return major version
+ */
+ u_int8_t (*get_maj_version) (ike_header_t *this);
+
+ /**
+ * @brief get the mainor version
+ *
+ * @param this ike_header_t object
+ * @return minor version
+ */
+ u_int8_t (*get_min_version) (ike_header_t *this);
+
+ /**
+ * @brief get the response flag
+ *
+ * @param this ike_header_t object
+ * @return response flag
+ */
+ bool (*get_response_flag) (ike_header_t *this);
+
+ /**
+ * @brief Set the response flag
+ *
+ * @param this ike_header_t object
+ * @param response response flag
+ *
+ */
+ void (*set_response_flag) (ike_header_t *this, bool response);
+ /**
+ * @brief get "higher version supported"-flag
+ *
+ * @param this ike_header_t object
+ * @return version flag
+ */
+ bool (*get_version_flag) (ike_header_t *this);
+
+ /**
+ * @brief get the initiator flag
+ *
+ * @param this ike_header_t object
+ * @return initiator flag
+ */
+ bool (*get_initiator_flag) (ike_header_t *this);
+
+ /**
+ * @brief Set the initiator flag
+ *
+ * @param this ike_header_t object
+ * @param initiator initiator flag
+ *
+ */
+ void (*set_initiator_flag) (ike_header_t *this, bool initiator);
+
+ /**
+ * @brief get the exchange type
+ *
+ * @param this ike_header_t object
+ * @return exchange type
+ */
+ u_int8_t (*get_exchange_type) (ike_header_t *this);
+
+ /**
+ * @brief set the exchange type
+ *
+ * @param this ike_header_t object
+ * @param exchange_type exchange type
+ */
+ void (*set_exchange_type) (ike_header_t *this, u_int8_t exchange_type);
+
+ /**
+ * @brief get the message id
+ *
+ * @param this ike_header_t object
+ * @return message id
+ */
+ u_int32_t (*get_message_id) (ike_header_t *this);
+
+ /**
+ * @brief set the message id
+ *
+ * @param this ike_header_t object
+ * @param initiator_spi message id
+ */
+ void (*set_message_id) (ike_header_t *this, u_int32_t message_id);
+
+ /**
+ * @brief Destroys a ike_header_t object.
+ *
+ * @param this ike_header_t object to destroy
+ * @return
+ * SUCCESS in any case
+ */
+ status_t (*destroy) (ike_header_t *this);
+};
+
+/**
+ * @brief Create an ike_header_t object
+ *
+ * @return
+ * - created ike_header, or
+ * - NULL if failed
+ */
+
+ike_header_t *ike_header_create();
+
+#endif /*IKE_HEADER_H_*/
diff --git a/Source/charon/encoding/payloads/ke_payload.c b/Source/charon/encoding/payloads/ke_payload.c
new file mode 100644
index 000000000..478519634
--- /dev/null
+++ b/Source/charon/encoding/payloads/ke_payload.c
@@ -0,0 +1,319 @@
+/**
+ * @file ke_payload.c
+ *
+ * @brief Declaration of the class ke_payload_t.
+ *
+ * An object of this type represents an IKEv2 KE-Payload.
+ *
+ * See section 3.4 of RFC for details of this payload type.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/* offsetof macro */
+#include <stddef.h>
+
+#include "ke_payload.h"
+
+#include <encoding/payloads/encodings.h>
+#include <utils/allocator.h>
+
+
+/**
+ * Private data of an ke_payload_t Object
+ *
+ */
+typedef struct private_ke_payload_s private_ke_payload_t;
+
+struct private_ke_payload_s {
+ /**
+ * public ke_payload_t interface
+ */
+ ke_payload_t public;
+
+ /**
+ * next payload type
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag
+ */
+ bool critical;
+
+ /**
+ * Length of this payload
+ */
+ u_int16_t payload_length;
+
+
+ /**
+ * DH Group Number
+ */
+ diffie_hellman_group_t dh_group_number;
+
+ /**
+ * Key Exchange Data of this KE payload
+ */
+ chunk_t key_exchange_data;
+
+ /**
+ * @brief Computes the length of this payload.
+ *
+ * @param this calling private_ke_payload_t object
+ * @return
+ * SUCCESS in any case
+ */
+ status_t (*compute_length) (private_ke_payload_t *this);
+};
+
+/**
+ * Encoding rules to parse or generate a IKEv2-KE Payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_ke_payload_t.
+ *
+ */
+encoding_rule_t ke_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_ke_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_ke_payload_t, critical) },
+ /* 7 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* Length of the whole payload*/
+ { PAYLOAD_LENGTH, offsetof(private_ke_payload_t, payload_length) },
+ /* DH Group number as 16 bit field*/
+ { U_INT_16, offsetof(private_ke_payload_t, dh_group_number) },
+ { RESERVED_BYTE, 0 },
+ { RESERVED_BYTE, 0 },
+ /* Key Exchange Data is from variable size */
+ { KEY_EXCHANGE_DATA, offsetof(private_ke_payload_t, key_exchange_data) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! DH Group # ! RESERVED !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Key Exchange Data ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implements payload_t's verify function.
+ * See #payload_s.verify for description.
+ */
+static status_t verify(private_ke_payload_t *this)
+{
+ if (this->critical)
+ {
+ /* critical bit is set! */
+ return FAILED;
+ }
+
+ /* dh group is not verified in here */
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's and ke_payload_t's destroy function.
+ * See #payload_s.destroy or ke_payload_s.destroy for description.
+ */
+static status_t destroy(private_ke_payload_t *this)
+{
+ if (this->key_exchange_data.ptr != NULL)
+ {
+ allocator_free(this->key_exchange_data.ptr);
+ }
+ allocator_free(this);
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's get_encoding_rules function.
+ * See #payload_s.get_encoding_rules for description.
+ */
+static status_t get_encoding_rules(private_ke_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = ke_payload_encodings;
+ *rule_count = sizeof(ke_payload_encodings) / sizeof(encoding_rule_t);
+
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's get_type function.
+ * See #payload_s.get_type for description.
+ */
+static payload_type_t get_type(private_ke_payload_t *this)
+{
+ return KEY_EXCHANGE;
+}
+
+/**
+ * Implements payload_t's get_next_type function.
+ * See #payload_s.get_next_type for description.
+ */
+static payload_type_t get_next_type(private_ke_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implements payload_t's set_next_type function.
+ * See #payload_s.set_next_type for description.
+ */
+static status_t set_next_type(private_ke_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's get_length function.
+ * See #payload_s.get_length for description.
+ */
+static size_t get_length(private_ke_payload_t *this)
+{
+ this->compute_length(this);
+ return this->payload_length;
+}
+
+/**
+ * Implements private_ke_payload_t's compute_length function.
+ * See #private_ke_payload_s.compute_length for description.
+ */
+static status_t compute_length (private_ke_payload_t *this)
+{
+ size_t length = KE_PAYLOAD_HEADER_LENGTH;
+ if (this->key_exchange_data.ptr != NULL)
+ {
+ length += this->key_exchange_data.len;
+ }
+
+ this->payload_length = length;
+
+ return SUCCESS;
+}
+
+
+/**
+ * Implements ke_payload_t's get_key_exchange_data function.
+ * See #ke_payload_t.get_key_exchange_data for description.
+ */
+chunk_t get_key_exchange_data(private_ke_payload_t *this)
+{
+ return (this->key_exchange_data);
+}
+
+/**
+ * Implements ke_payload_t's set_key_exchange_data function.
+ * See #ke_payload_t.set_key_exchange_data for description.
+ */
+status_t set_key_exchange_data(private_ke_payload_t *this, chunk_t key_exchange_data)
+{
+ /* destroy existing data first */
+ if (this->key_exchange_data.ptr != NULL)
+ {
+ /* free existing value */
+ allocator_free(this->key_exchange_data.ptr);
+ this->key_exchange_data.ptr = NULL;
+ this->key_exchange_data.len = 0;
+
+ }
+
+ this->key_exchange_data.ptr = allocator_clone_bytes(key_exchange_data.ptr,key_exchange_data.len);
+ if (this->key_exchange_data.ptr == NULL)
+ {
+ return OUT_OF_RES;
+ }
+ this->key_exchange_data.len = key_exchange_data.len;
+ this->compute_length(this);
+
+ return SUCCESS;
+}
+
+/**
+ * Implements ke_payload_t's get_dh_group_number function.
+ * See #ke_payload_t.get_dh_group_number for description.
+ */
+diffie_hellman_group_t get_dh_group_number(private_ke_payload_t *this)
+{
+ return this->dh_group_number;
+}
+
+/**
+ * Implements ke_payload_t's set_dh_group_number function.
+ * See #ke_payload_t.set_dh_group_number for description.
+ */
+status_t set_dh_group_number(private_ke_payload_t *this, diffie_hellman_group_t dh_group_number)
+{
+ this->dh_group_number = dh_group_number;
+ return SUCCESS;
+}
+
+/*
+ * Described in header
+ */
+ke_payload_t *ke_payload_create()
+{
+ private_ke_payload_t *this = allocator_alloc_thing(private_ke_payload_t);
+ if (this == NULL)
+ {
+ return NULL;
+ }
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (status_t (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (status_t (*) (payload_t *,payload_type_t)) set_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;
+
+ /* public functions */
+ this->public.get_key_exchange_data = (chunk_t (*) (ke_payload_t *)) get_key_exchange_data;
+ this->public.set_key_exchange_data = (status_t (*) (ke_payload_t *,chunk_t)) set_key_exchange_data;
+ this->public.get_dh_group_number = (diffie_hellman_group_t (*) (ke_payload_t *)) get_dh_group_number;
+ this->public.set_dh_group_number =(status_t (*) (ke_payload_t *,diffie_hellman_group_t)) set_dh_group_number;
+ this->public.destroy = (status_t (*) (ke_payload_t *)) destroy;
+
+ /* private functions */
+ this->compute_length = compute_length;
+
+ /* set default values of the fields */
+ this->critical = KE_PAYLOAD_CRITICAL_FLAG;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = KE_PAYLOAD_HEADER_LENGTH;
+ this->key_exchange_data.ptr = NULL;
+ this->key_exchange_data.len = 0;
+ this->dh_group_number = 0;
+
+ return (&(this->public));
+}
diff --git a/Source/charon/encoding/payloads/ke_payload.h b/Source/charon/encoding/payloads/ke_payload.h
new file mode 100644
index 000000000..8855941f1
--- /dev/null
+++ b/Source/charon/encoding/payloads/ke_payload.h
@@ -0,0 +1,120 @@
+/**
+ * @file ke_payload.h
+ *
+ * @brief Declaration of the class ke_payload_t.
+ *
+ * An object of this type represents an IKEv2 KE-Payload.
+ *
+ * See section 3.4 of RFC for details of this payload type.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef KE_PAYLOAD_H_
+#define KE_PAYLOAD_H_
+
+#include <types.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/transform_substructure.h>
+#include <utils/linked_list.h>
+
+/**
+ * Critical flag must not be set
+ */
+#define KE_PAYLOAD_CRITICAL_FLAG FALSE;
+
+/**
+ * KE payload length in bytes without any key exchange data
+ */
+#define KE_PAYLOAD_HEADER_LENGTH 8
+
+/**
+ * Object representing an IKEv2-KE Payload
+ *
+ * The KE Payload format is described in RFC section 3.4.
+ *
+ */
+typedef struct ke_payload_s ke_payload_t;
+
+struct ke_payload_s {
+ /**
+ * implements payload_t interface
+ */
+ payload_t payload_interface;
+
+ /**
+ * @brief Returns the currently set key exchange data of this KE payload.
+ *
+ * @warning Returned data are not copied.
+ *
+ * @param this calling ke_payload_t object
+ * @return chunk_t pointing to the value
+ */
+ chunk_t (*get_key_exchange_data) (ke_payload_t *this);
+
+ /**
+ * @brief Sets the key exchange data of this KE payload.
+ *
+ * @warning Value is getting copied.
+ *
+ * @param this calling ke_payload_t object
+ * @param key_exchange_data chunk_t pointing to the value to set
+ * @return
+ * - SUCCESS or
+ * - OUT_OF_RES
+ */
+ status_t (*set_key_exchange_data) (ke_payload_t *this, chunk_t key_exchange_data);
+
+ /**
+ * @brief Gets the Diffie-Hellman Group Number of this KE payload.
+ *
+ * @param this calling ke_payload_t object
+ * @return DH Group Number of this payload
+ */
+ diffie_hellman_group_t (*get_dh_group_number) (ke_payload_t *this);
+
+ /**
+ * @brief Sets the Diffie-Hellman Group Number of this KE payload.
+ *
+ * @param this calling ke_payload_t object
+ * @param dh_group_number DH Group to set
+ * @return SUCCESS
+ */
+ status_t (*set_dh_group_number) (ke_payload_t *this, diffie_hellman_group_t dh_group_number);
+
+ /**
+ * @brief Destroys an ke_payload_t object.
+ *
+ * @param this ke_payload_t object to destroy
+ * @return
+ * SUCCESS in any case
+ */
+ status_t (*destroy) (ke_payload_t *this);
+};
+
+/**
+ * @brief Creates an empty ke_payload_t object
+ *
+ * @return
+ * - created ke_payload_t object, or
+ * - NULL if failed
+ */
+
+ke_payload_t *ke_payload_create();
+
+
+#endif /*KE_PAYLOAD_H_*/
diff --git a/Source/charon/encoding/payloads/nonce_payload.c b/Source/charon/encoding/payloads/nonce_payload.c
new file mode 100644
index 000000000..fa3730e2f
--- /dev/null
+++ b/Source/charon/encoding/payloads/nonce_payload.c
@@ -0,0 +1,271 @@
+/**
+ * @file nonce_payload.h
+ *
+ * @brief Declaration of the class nonce_payload_t.
+ *
+ * An object of this type represents an IKEv2 Nonce-Payload.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/* offsetof macro */
+#include <stddef.h>
+
+#include "nonce_payload.h"
+
+#include <encoding/payloads/encodings.h>
+#include <utils/allocator.h>
+
+
+
+/**
+ * Private data of an nonce_payload_t' Object
+ *
+ */
+typedef struct private_nonce_payload_s private_nonce_payload_t;
+
+struct private_nonce_payload_s {
+ /**
+ * public nonce_payload_t interface
+ */
+ nonce_payload_t public;
+
+ /**
+ * next payload type
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag
+ */
+ bool critical;
+
+ /**
+ * Length of this payload
+ */
+ u_int16_t payload_length;
+
+ /**
+ * the contained nonce value
+ */
+ chunk_t nonce;
+
+ /**
+ * @brief Computes the length of this payload.
+ *
+ * @param this calling private_nonce_payload_t object
+ * @return
+ * SUCCESS in any case
+ */
+ status_t (*compute_length) (private_nonce_payload_t *this);
+};
+
+/**
+ * Encoding rules to parse or generate a nonce payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_nonce_payload_t.
+ *
+ */
+encoding_rule_t nonce_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_nonce_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_nonce_payload_t, critical) },
+ /* 7 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* Length of the whole nonce payload*/
+ { PAYLOAD_LENGTH, offsetof(private_nonce_payload_t, payload_length) },
+ /* some nonce bytes, lenth is defined in PAYLOAD_LENGTH */
+ { NONCE_DATA, offsetof(private_nonce_payload_t, nonce) }
+};
+
+/* 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Nonce Data ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implements payload_t's verify function.
+ * See #payload_s.verify for description.
+ */
+static status_t verify(private_nonce_payload_t *this)
+{
+ if (this->critical)
+ {
+ /* critical bit is set! */
+ return FAILED;
+ }
+ if ((this->nonce.len < 16) || ((this->nonce.len > 256)))
+ {
+ /* nonce length is wrong */
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Implements nonce_payload_t's set_nonce function.
+ * See #nonce_payload_t.set_nonce for description.
+ */
+static status_t set_nonce(private_nonce_payload_t *this, chunk_t nonce)
+{
+ if (nonce.len >= 16 && nonce.len <= 256)
+ {
+
+ this->nonce.ptr = allocator_clone_bytes(nonce.ptr, nonce.len);
+ if (this->nonce.ptr == NULL)
+ {
+ return OUT_OF_RES;
+ }
+ this->nonce.len = nonce.len;
+ this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH + nonce.len;
+ return SUCCESS;
+ }
+ return INVALID_ARG;
+}
+
+/**
+ * Implements nonce_payload_t's get_nonce function.
+ * See #nonce_payload_t.get_nonce for description.
+ */
+static status_t get_nonce(private_nonce_payload_t *this, chunk_t *nonce)
+{
+ nonce->ptr = allocator_clone_bytes(this->nonce.ptr,this->nonce.len);
+ if (nonce->ptr == NULL)
+ {
+ return OUT_OF_RES;
+ }
+ nonce->len = this->nonce.len;
+ return SUCCESS;
+}
+
+
+/**
+ * Implements payload_t's get_encoding_rules function.
+ * See #payload_s.get_encoding_rules for description.
+ */
+static status_t get_encoding_rules(private_nonce_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = nonce_payload_encodings;
+ *rule_count = sizeof(nonce_payload_encodings) / sizeof(encoding_rule_t);
+
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's get_type function.
+ * See #payload_s.get_type for description.
+ */
+static payload_type_t get_type(private_nonce_payload_t *this)
+{
+ return NONCE;
+}
+
+/**
+ * Implements payload_t's get_next_type function.
+ * See #payload_s.get_next_type for description.
+ */
+static payload_type_t get_next_type(private_nonce_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implements payload_t's set_next_type function.
+ * See #payload_s.set_next_type for description.
+ */
+static status_t set_next_type(private_nonce_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's get_length function.
+ * See #payload_s.get_length for description.
+ */
+static size_t get_length(private_nonce_payload_t *this)
+{
+ this->compute_length(this);
+ return this->payload_length;
+}
+
+/**
+ * Implements payload_t's and nonce_payload_t's destroy function.
+ * See #payload_s.destroy or nonce_payload_s.destroy for description.
+ */
+static status_t destroy(private_nonce_payload_t *this)
+{
+ if (this->nonce.ptr != NULL)
+ {
+ allocator_free(this->nonce.ptr);
+ }
+
+ allocator_free(this);
+ return SUCCESS;
+}
+
+/*
+ * Described in header
+ */
+nonce_payload_t *nonce_payload_create()
+{
+ private_nonce_payload_t *this = allocator_alloc_thing(private_nonce_payload_t);
+ if (this == NULL)
+ {
+ return NULL;
+ }
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (status_t (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (status_t (*) (payload_t *,payload_type_t)) set_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;
+
+ /* public functions */
+ this->public.destroy = (status_t (*) (nonce_payload_t *)) destroy;
+ this->public.set_nonce = (status_t (*) (nonce_payload_t *,chunk_t)) set_nonce;
+ this->public.get_nonce = (status_t (*) (nonce_payload_t *,chunk_t*)) get_nonce;
+
+ /* private variables */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH;
+ this->nonce.ptr = NULL;
+ this->nonce.len = 0;
+
+ return (&(this->public));
+}
+
+
diff --git a/Source/charon/encoding/payloads/nonce_payload.h b/Source/charon/encoding/payloads/nonce_payload.h
new file mode 100644
index 000000000..7768fa990
--- /dev/null
+++ b/Source/charon/encoding/payloads/nonce_payload.h
@@ -0,0 +1,93 @@
+/**
+ * @file nonce_payload.h
+ *
+ * @brief Declaration of the class nonce_payload_t.
+ *
+ * An object of this type represents an IKEv2 Nonce-Payload.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef NONCE_PAYLOAD_H_
+#define NONCE_PAYLOAD_H_
+
+#include <types.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * length of a nonce payload without a nonce in int
+ */
+#define NONCE_PAYLOAD_HEADER_LENGTH 4
+
+/**
+ * Object representing an IKEv2 Nonce payload
+ *
+ * The Nonce payload format is described in draft section 3.3.
+ *
+ */
+typedef struct nonce_payload_s nonce_payload_t;
+
+struct nonce_payload_s {
+ /**
+ * implements payload_t interface
+ */
+ payload_t payload_interface;
+
+ /**
+ * @brief Set the nonce value.
+ *
+ * The nonce must have length between 16 and 256 bytes
+ *
+ * @param this calling nonce_payload_t object
+ * @param nonce chunk containing the nonce, will be cloned
+ * @return
+ * - SUCCESS or
+ * - INVALID_ARG, if nonce has an invalid size
+ */
+ status_t (*set_nonce) (nonce_payload_t *this, chunk_t nonce);
+
+ /**
+ * @brief Get the nonce value.
+ *
+ * @param this calling nonce_payload_t object
+ * @param[out] nonce chunk where nonce data is located (cloned)
+ * @return SUCCESS in any case
+ */
+ status_t (*get_nonce) (nonce_payload_t *this, chunk_t *nonce);
+
+ /**
+ * @brief Destroys an nonce_payload_t object.
+ *
+ * @param this nonce_payload_t object to destroy
+ * @return
+ * SUCCESS in any case
+ */
+ status_t (*destroy) (nonce_payload_t *this);
+};
+
+/**
+ * @brief Creates an empty nonce_payload_t object
+ *
+ * @return
+ * - created nonce_payload_t object, or
+ * - NULL if failed
+ */
+
+nonce_payload_t *nonce_payload_create();
+
+
+#endif /*NONCE_PAYLOAD_H_*/
diff --git a/Source/charon/encoding/payloads/notify_payload.c b/Source/charon/encoding/payloads/notify_payload.c
new file mode 100644
index 000000000..adcde11a2
--- /dev/null
+++ b/Source/charon/encoding/payloads/notify_payload.c
@@ -0,0 +1,419 @@
+/**
+ * @file notify_payload.c
+ *
+ * @brief Declaration of the class notify_payload_t.
+ *
+ * An object of this type represents an IKEv2 Notify-Payload.
+ *
+ * See section 3.10 of Draft for details of this payload type.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/* offsetof macro */
+#include <stddef.h>
+
+#include "notify_payload.h"
+
+#include <encoding/payloads/encodings.h>
+#include <utils/allocator.h>
+
+/**
+ * Private data of an notify_payload_t Object
+ *
+ */
+typedef struct private_notify_payload_s private_notify_payload_t;
+
+struct private_notify_payload_s {
+ /**
+ * public notify_payload_t interface
+ */
+ notify_payload_t public;
+
+ /**
+ * next payload type
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag
+ */
+ bool critical;
+
+ /**
+ * Length of this payload
+ */
+ u_int16_t payload_length;
+
+ /**
+ * protocol id
+ */
+ u_int8_t protocol_id;
+
+ /**
+ * spi size
+ */
+ u_int8_t spi_size;
+
+ /**
+ * notify message type
+ */
+ u_int16_t notify_message_type;
+
+ /**
+ * Security parameter index (spi)
+ */
+ chunk_t spi;
+
+ /**
+ * Notification data
+ */
+ chunk_t notification_data;
+
+ /**
+ * @brief Computes the length of this payload.
+ *
+ * @param this calling private_ke_payload_t object
+ * @return
+ * SUCCESS in any case
+ */
+ status_t (*compute_length) (private_notify_payload_t *this);
+};
+
+/**
+ * Encoding rules to parse or generate a IKEv2-Notify Payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_notify_payload_t.
+ *
+ */
+encoding_rule_t notify_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_notify_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_notify_payload_t, critical) },
+ /* 7 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* Length of the whole payload*/
+ { PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) },
+ /* Protocol ID as 8 bit field*/
+ { U_INT_8, offsetof(private_notify_payload_t, protocol_id) },
+ /* SPI Size as 8 bit field*/
+ { SPI_SIZE, offsetof(private_notify_payload_t, spi_size) },
+ /* Notify message type as 16 bit field*/
+ { U_INT_16, offsetof(private_notify_payload_t, notify_message_type) },
+ /* SPI as variable length field*/
+ { SPI, offsetof(private_notify_payload_t, spi) },
+ /* Key Exchange Data is from variable size */
+ { NOTIFICATION_DATA, offsetof(private_notify_payload_t, notification_data) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Protocol ID ! SPI Size ! Notify Message Type !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Security Parameter Index (SPI) ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Notification Data ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implements payload_t's verify function.
+ * See #payload_s.verify for description.
+ */
+static status_t verify(private_notify_payload_t *this)
+{
+ if (this->critical)
+ {
+ /* critical bit is set! */
+ return FAILED;
+ }
+ if (this->protocol_id > 3)
+ {
+ /* reserved for future use */
+ return FAILED;
+ }
+
+ /* notify message types and data is not getting checked in here */
+
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's get_encoding_rules function.
+ * See #payload_s.get_encoding_rules for description.
+ */
+static status_t get_encoding_rules(private_notify_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = notify_payload_encodings;
+ *rule_count = sizeof(notify_payload_encodings) / sizeof(encoding_rule_t);
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's get_type function.
+ * See #payload_s.get_type for description.
+ */
+static payload_type_t get_type(private_notify_payload_t *this)
+{
+ return KEY_EXCHANGE;
+}
+
+/**
+ * Implements payload_t's get_next_type function.
+ * See #payload_s.get_next_type for description.
+ */
+static payload_type_t get_next_type(private_notify_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implements payload_t's set_next_type function.
+ * See #payload_s.set_next_type for description.
+ */
+static status_t set_next_type(private_notify_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's get_length function.
+ * See #payload_s.get_length for description.
+ */
+static size_t get_length(private_notify_payload_t *this)
+{
+ this->compute_length(this);
+ return this->payload_length;
+}
+
+/**
+ * Implements private_ke_payload_t's compute_length function.
+ * See #private_ke_payload_s.compute_length for description.
+ */
+static status_t compute_length (private_notify_payload_t *this)
+{
+ size_t length = NOTIFY_PAYLOAD_HEADER_LENGTH;
+ if (this->notification_data.ptr != NULL)
+ {
+ length += this->notification_data.len;
+ }
+ if (this->spi.ptr != NULL)
+ {
+ length += this->spi.len;
+ }
+
+ this->payload_length = length;
+
+ return SUCCESS;
+}
+
+
+/**
+ * Implements notify_payload_t's get_protocol_id function.
+ * See #notify_payload_s.get_protocol_id for description.
+ */
+u_int8_t get_protocol_id(private_notify_payload_t *this)
+{
+ return this->protocol_id;
+}
+
+/**
+ * Implements notify_payload_t's set_protocol_id function.
+ * See #notify_payload_s.set_protocol_id for description.
+ */
+status_t set_protocol_id(private_notify_payload_t *this, u_int8_t protocol_id)
+{
+ this->protocol_id = protocol_id;
+ return SUCCESS;
+}
+
+/**
+ * Implements notify_payload_t's get_notification_data function.
+ * See #notify_payload_s.get_notification_data for description.
+ */
+u_int16_t get_notify_message_type(private_notify_payload_t *this)
+{
+ return this->notify_message_type;
+}
+
+/**
+ * Implements notify_payload_t's get_notification_data function.
+ * See #notify_payload_s.get_notification_data for description.
+ */
+status_t set_notify_message_type(private_notify_payload_t *this, u_int16_t notify_message_type)
+{
+ this->notify_message_type = notify_message_type;
+ return SUCCESS;
+}
+
+/**
+ * Implements notify_payload_t's get_spi function.
+ * See #notify_payload_s.get_spi for description.
+ */
+chunk_t get_spi(private_notify_payload_t *this)
+{
+ return (this->spi);
+}
+
+/**
+ * Implements notify_payload_t's set_spi function.
+ * See #notify_payload_s.set_spi for description.
+ */
+status_t set_spi(private_notify_payload_t *this, chunk_t spi)
+{
+ /* destroy existing data first */
+ if (this->spi.ptr != NULL)
+ {
+ /* free existing value */
+ allocator_free(this->spi.ptr);
+ this->spi.ptr = NULL;
+ this->spi.len = 0;
+
+ }
+
+ this->spi.ptr = allocator_clone_bytes(spi.ptr,spi.len);
+ if (this->spi.ptr == NULL)
+ {
+ return OUT_OF_RES;
+ }
+ this->spi.len = spi.len;
+ this->spi_size = spi.len;
+ this->compute_length(this);
+
+ return SUCCESS;
+}
+
+
+/**
+ * Implements notify_payload_t's get_notification_data function.
+ * See #notify_payload_s.get_notification_data for description.
+ */
+chunk_t get_notification_data(private_notify_payload_t *this)
+{
+ return (this->notification_data);
+}
+
+/**
+ * Implements notify_payload_t's get_notification_data function.
+ * See #notify_payload_s.get_notification_data for description.
+ */
+status_t set_notification_data(private_notify_payload_t *this, chunk_t notification_data)
+{
+ /* destroy existing data first */
+ if (this->notification_data.ptr != NULL)
+ {
+ /* free existing value */
+ allocator_free(this->notification_data.ptr);
+ this->notification_data.ptr = NULL;
+ this->notification_data.len = 0;
+
+ }
+
+ this->notification_data.ptr = allocator_clone_bytes(notification_data.ptr,notification_data.len);
+ if (this->notification_data.ptr == NULL)
+ {
+ return OUT_OF_RES;
+ }
+ this->notification_data.len = notification_data.len;
+ this->compute_length(this);
+
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's and notify_payload_t's destroy function.
+ * See #payload_s.destroy or notify_payload_s.destroy for description.
+ */
+static status_t destroy(private_notify_payload_t *this)
+{
+ if (this->notification_data.ptr != NULL)
+ {
+ allocator_free(this->notification_data.ptr);
+ }
+ if (this->spi.ptr != NULL)
+ {
+ allocator_free(this->spi.ptr);
+ }
+
+ allocator_free(this);
+ return SUCCESS;
+}
+
+/*
+ * Described in header
+ */
+notify_payload_t *notify_payload_create()
+{
+ private_notify_payload_t *this = allocator_alloc_thing(private_notify_payload_t);
+ if (this == NULL)
+ {
+ return NULL;
+ }
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (status_t (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (status_t (*) (payload_t *,payload_type_t)) set_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;
+
+ /* public functions */
+ this->public.get_protocol_id = (u_int8_t (*) (notify_payload_t *)) get_protocol_id;
+ this->public.set_protocol_id = (status_t (*) (notify_payload_t *,u_int8_t)) set_protocol_id;
+ this->public.get_notify_message_type = (u_int16_t (*) (notify_payload_t *)) get_notify_message_type;
+ this->public.set_notify_message_type = (status_t (*) (notify_payload_t *,u_int16_t)) set_notify_message_type;
+ this->public.get_spi = (chunk_t (*) (notify_payload_t *)) get_spi;
+ this->public.set_spi = (status_t (*) (notify_payload_t *,chunk_t)) set_spi;
+ this->public.get_notification_data = (chunk_t (*) (notify_payload_t *)) get_notification_data;
+ this->public.set_notification_data = (status_t (*) (notify_payload_t *,chunk_t)) set_notification_data;
+ this->public.destroy = (status_t (*) (notify_payload_t *)) destroy;
+
+ /* private functions */
+ this->compute_length = compute_length;
+
+ /* set default values of the fields */
+ this->critical = NOTIFY_PAYLOAD_CRITICAL_FLAG;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = NOTIFY_PAYLOAD_HEADER_LENGTH;
+ this->protocol_id = 0;
+ this->notify_message_type = 0;
+ this->spi.ptr = NULL;
+ this->spi.len = 0;
+ this->notification_data.ptr = NULL;
+ this->notification_data.len = 0;
+
+ return (&(this->public));
+}
+
diff --git a/Source/charon/encoding/payloads/notify_payload.h b/Source/charon/encoding/payloads/notify_payload.h
new file mode 100644
index 000000000..cf4235fc3
--- /dev/null
+++ b/Source/charon/encoding/payloads/notify_payload.h
@@ -0,0 +1,159 @@
+/**
+ * @file notify_payload.h
+ *
+ * @brief Declaration of the class notify_payload_t.
+ *
+ * An object of this type represents an IKEv2 Notify-Payload.
+ *
+ * See section 3.10 of Draft for details of this payload type.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+
+#ifndef NOTIFY_PAYLOAD_H_
+#define NOTIFY_PAYLOAD_H_
+
+#include <types.h>
+#include <encoding/payloads/payload.h>
+#include <utils/linked_list.h>
+
+/**
+ * Critical flag must not be set
+ */
+#define NOTIFY_PAYLOAD_CRITICAL_FLAG FALSE;
+
+/**
+ * Notify payload length in bytes without any spi and notification data
+ */
+#define NOTIFY_PAYLOAD_HEADER_LENGTH 8
+
+/**
+ * Object representing an IKEv2-Notify Payload
+ *
+ * The Notify Payload format is described in Draft section 3.10.
+ *
+ */
+typedef struct notify_payload_s notify_payload_t;
+
+struct notify_payload_s {
+ /**
+ * implements payload_t interface
+ */
+ payload_t payload_interface;
+
+ /**
+ * @brief Gets the protocol id of this payload.
+ *
+ * @param this calling notify_payload_t object
+ * @return protocol id of this payload
+ */
+ u_int8_t (*get_protocol_id) (notify_payload_t *this);
+
+ /**
+ * @brief Sets the protocol id of this payload.
+ *
+ * @param this calling notify_payload_t object
+ * @param protocol_id protocol id to set
+ * @return SUCCESS
+ */
+ status_t (*set_protocol_id) (notify_payload_t *this, u_int8_t protocol_id);
+
+ /**
+ * @brief Gets the notify message type of this payload.
+ *
+ * @param this calling notify_payload_t object
+ * @return notify message type of this payload
+ */
+ u_int16_t (*get_notify_message_type) (notify_payload_t *this);
+
+ /**
+ * @brief Sets notify message type of this payload.
+ *
+ * @param this calling notify_payload_t object
+ * @param notify_message_type notify message type to set
+ * @return SUCCESS
+ */
+ status_t (*set_notify_message_type) (notify_payload_t *this, u_int16_t notify_message_type);
+
+ /**
+ * @brief Returns the currently set spi of this payload.
+ *
+ * @warning Returned data are not copied.
+ *
+ * @param this calling notify_payload_t object
+ * @return chunk_t pointing to the value
+ */
+ chunk_t (*get_spi) (notify_payload_t *this);
+
+ /**
+ * @brief Sets the spi of this payload.
+ *
+ * @warning Value is getting copied.
+ *
+ * @param this calling notify_payload_t object
+ * @param spi chunk_t pointing to the value to set
+ * @return
+ * - SUCCESS or
+ * - OUT_OF_RES
+ */
+ status_t (*set_spi) (notify_payload_t *this, chunk_t spi);
+
+ /**
+ * @brief Returns the currently set notification data of payload.
+ *
+ * @warning Returned data are not copied.
+ *
+ * @param this calling notify_payload_t object
+ * @return chunk_t pointing to the value
+ */
+ chunk_t (*get_notification_data) (notify_payload_t *this);
+
+ /**
+ * @brief Sets the notification data of this payload.
+ *
+ * @warning Value is getting copied.
+ *
+ * @param this calling notify_payload_t object
+ * @param notification_data chunk_t pointing to the value to set
+ * @return
+ * - SUCCESS or
+ * - OUT_OF_RES
+ */
+ status_t (*set_notification_data) (notify_payload_t *this, chunk_t notification_data);
+
+ /**
+ * @brief Destroys an notify_payload_t object.
+ *
+ * @param this notify_payload_t object to destroy
+ * @return
+ * SUCCESS in any case
+ */
+ status_t (*destroy) (notify_payload_t *this);
+};
+
+/**
+ * @brief Creates an empty notify_payload_t object
+ *
+ * @return
+ * - created notify_payload_t object, or
+ * - NULL if failed
+ */
+notify_payload_t *notify_payload_create();
+
+
+#endif /*NOTIFY_PAYLOAD_H_*/
diff --git a/Source/charon/encoding/payloads/payload.c b/Source/charon/encoding/payloads/payload.c
new file mode 100644
index 000000000..a2333f6af
--- /dev/null
+++ b/Source/charon/encoding/payloads/payload.c
@@ -0,0 +1,92 @@
+/**
+ * @file payload.c
+ *
+ * @brief Generic payload interface
+ *
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+
+#include "payload.h"
+
+#include <encoding/payloads/ike_header.h>
+#include <encoding/payloads/sa_payload.h>
+#include <encoding/payloads/nonce_payload.h>
+#include <encoding/payloads/ke_payload.h>
+#include <encoding/payloads/notify_payload.h>
+
+
+
+
+
+/*
+ * build the mappings for payload_type_t
+ */
+mapping_t payload_type_m[] = {
+ {NO_PAYLOAD, "NO_PAYLOAD"},
+ {SECURITY_ASSOCIATION, "SECURITY_ASSOCIATION"},
+ {KEY_EXCHANGE, "KEY_EXCHANGE"},
+ {ID_INITIATOR, "ID_INITIATOR"},
+ {ID_RESPONDER, "ID_RESPONDER"},
+ {CERTIFICATE, "CERTIFICATE"},
+ {CERTIFICATE_REQUEST, "CERTIFICATE_REQUEST"},
+ {AUTHENTICATION, "AUTHENTICATION"},
+ {NONCE, "NONCE"},
+ {NOTIFY, "NOTIFY"},
+ {DELETE, "DELETE"},
+ {VENDOR_ID, "VENDOR_ID"},
+ {TRAFFIC_SELECTOR_INITIATOR, "TRAFFIC_SELECTOR_INITIATOR"},
+ {TRAFFIC_SELECTOR_RESPONDER, "TRAFFIC_SELECTOR_RESPONDER"},
+ {ENCRYPTED, "ENCRYPTED"},
+ {CONFIGURATION, "CONFIGURATION"},
+ {EXTENSIBLE_AUTHENTICATION, "EXTENSIBLE_AUTHENTICATION"},
+ {HEADER, "HEADER"},
+ {PROPOSAL_SUBSTRUCTURE, "PROPOSAL_SUBSTRUCTURE"},
+ {TRANSFORM_SUBSTRUCTURE, "TRANSFORM_SUBSTRUCTURE"},
+ {TRANSFORM_ATTRIBUTE, "TRANSFORM_ATTRIBUTE"},
+ {MAPPING_END, NULL}
+};
+
+/*
+ * see header
+ */
+payload_t *payload_create(payload_type_t type)
+{
+ switch (type)
+ {
+ case HEADER:
+ return (payload_t*)ike_header_create();
+ case SECURITY_ASSOCIATION:
+ return (payload_t*)sa_payload_create();
+ case PROPOSAL_SUBSTRUCTURE:
+ return (payload_t*)proposal_substructure_create();
+ case TRANSFORM_SUBSTRUCTURE:
+ return (payload_t*)transform_substructure_create();
+ case TRANSFORM_ATTRIBUTE:
+ return (payload_t*)transform_attribute_create();
+ case NONCE:
+ return (payload_t*)nonce_payload_create();
+ case KEY_EXCHANGE:
+ return (payload_t*)ke_payload_create();
+ case NOTIFY:
+ return (payload_t*)notify_payload_create();
+ default:
+ return NULL;
+ }
+}
+
diff --git a/Source/charon/encoding/payloads/payload.h b/Source/charon/encoding/payloads/payload.h
new file mode 100644
index 000000000..9d8b753cb
--- /dev/null
+++ b/Source/charon/encoding/payloads/payload.h
@@ -0,0 +1,240 @@
+/**
+ * @file payload.h
+ *
+ * @brief Generic payload interface
+ *
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef PAYLOAD_H_
+#define PAYLOAD_H_
+
+#include <types.h>
+#include <definitions.h>
+#include <encoding/payloads/encodings.h>
+
+
+/**
+ * Payload-Types of a IKEv2-Message
+ *
+ *
+ * Header and substructures are also defined as
+ * payload types with values from PRIVATE USE space.
+ */
+typedef enum payload_type_e payload_type_t;
+
+enum payload_type_e{
+
+ /**
+ * NO_PAYLOAD
+ */
+ NO_PAYLOAD = 0,
+
+ /**
+ * SA
+ */
+ SECURITY_ASSOCIATION = 33,
+ /**
+ * KE
+ */
+ KEY_EXCHANGE = 34,
+ /**
+ * IDi
+ */
+ ID_INITIATOR = 35,
+ /**
+ * IDr
+ */
+ ID_RESPONDER = 36,
+ /**
+ * CERT
+ */
+ CERTIFICATE = 37,
+ /**
+ * CERTREQ
+ */
+ CERTIFICATE_REQUEST = 38,
+ /**
+ * AUTH
+ */
+ AUTHENTICATION = 39,
+ /**
+ * Ni, Nr
+ */
+ NONCE = 40,
+ /**
+ * N
+ */
+ NOTIFY = 41,
+ /**
+ * D
+ */
+ DELETE = 42,
+ /**
+ * V
+ */
+ VENDOR_ID = 43,
+ /**
+ * TSi
+ */
+ TRAFFIC_SELECTOR_INITIATOR = 44,
+ /**
+ * TSr
+ */
+ TRAFFIC_SELECTOR_RESPONDER = 45,
+ /**
+ * E
+ */
+ ENCRYPTED = 46,
+ /**
+ * CP
+ */
+ CONFIGURATION = 47,
+ /**
+ * EAP
+ */
+ EXTENSIBLE_AUTHENTICATION = 48,
+
+ /**
+ * Header has a value of PRIVATE USE space
+ *
+ * This payload type is not send over wire and just
+ * used internally to handle IKEv2-Header like a payload.
+ */
+ HEADER = 140,
+
+ /**
+ * PROPOSAL_SUBSTRUCTURE has a value of PRIVATE USE space
+ *
+ * This payload type is not send over wire and just
+ * used internally to handle a proposal substructure like a payload.
+ */
+ PROPOSAL_SUBSTRUCTURE = 141,
+
+ /**
+ * TRANSFORM_SUBSTRUCTURE has a value of PRIVATE USE space
+ *
+ * This payload type is not send over wire and just
+ * used internally to handle a transform substructure like a payload.
+ */
+ TRANSFORM_SUBSTRUCTURE = 142,
+
+ /**
+ * TRANSFORM_ATTRIBUTE has a value of PRIVATE USE space
+ *
+ * This payload type is not send over wire and just
+ * used internally to handle a transform attribute like a payload.
+ */
+ TRANSFORM_ATTRIBUTE = 143,
+};
+
+
+/*
+ * build string mapping array for payload_type_t
+ */
+extern mapping_t payload_type_m[];
+
+
+/**
+ * @brief Generic interface for all payload types (inclusive
+ * header and substructures)
+ *
+ *
+ */
+typedef struct payload_s payload_t;
+
+struct payload_s {
+ /**
+ * @brief Destroys a payload and all included substructures.
+ *
+ * @param this payload to destroy
+ * @return
+ * SUCCESS in any case
+ */
+ status_t (*destroy) (payload_t *this);
+
+ /**
+ * @brief Get encoding rules for this payload
+ *
+ * @param this calling object
+ * @param[out] rules location to store pointer of first rule
+ * @param[out] rule_count location to store number of rules
+ * @return
+ * SUCCESS in any case
+ */
+ status_t (*get_encoding_rules) (payload_t *this, encoding_rule_t **rules, size_t *rule_count);
+
+ /**
+ * @brief get type of payload
+ *
+ * @param this calling object
+ * @return type of this payload
+ */
+ payload_type_t (*get_type) (payload_t *this);
+
+ /**
+ * @brief get type of next payload or zero if this is the last one
+ *
+ * @param this calling object
+ * @return type of next payload
+ */
+ payload_type_t (*get_next_type) (payload_t *this);
+
+ /**
+ * @brief set type of next payload
+ *
+ * @param this calling object
+ * @param type type of next payload
+ * @return SUCCESS in any case
+ */
+ status_t (*set_next_type) (payload_t *this,payload_type_t type);
+
+ /**
+ * @brief get length of payload
+ *
+ * @param this calling object
+ * @return length of this payload
+ */
+ size_t (*get_length) (payload_t *this);
+
+ /**
+ * @brief Verifies payload structure and makes consistence check
+ *
+ * @param this calling object
+ * @return
+ * - SUCCESS
+ * - FAILED if consistence not given
+ */
+ status_t (*verify) (payload_t *this);
+};
+
+/**
+ * @brief Create an empty payload.
+ *
+ * Useful for the parser, who wants a generic constructor for all payloads.
+ * It supports all payload_t methods.
+ *
+ * @param type type of the payload to create
+ * @return
+ * - created payload, or
+ * - NULL if failed
+ */
+
+payload_t *payload_create(payload_type_t type);
+
+#endif /*PAYLOAD_H_*/
diff --git a/Source/charon/encoding/payloads/proposal_substructure.c b/Source/charon/encoding/payloads/proposal_substructure.c
new file mode 100644
index 000000000..b53633fb5
--- /dev/null
+++ b/Source/charon/encoding/payloads/proposal_substructure.c
@@ -0,0 +1,512 @@
+/**
+ * @file proposal_substructure.h
+ *
+ * @brief Declaration of the class proposal_substructure_t.
+ *
+ * An object of this type represents an IKEv2 PROPOSAL Substructure and contains transforms.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+ /* offsetof macro */
+#include <stddef.h>
+
+#include "proposal_substructure.h"
+
+#include <encoding/payloads/encodings.h>
+#include <encoding/payloads/transform_substructure.h>
+#include <types.h>
+#include <utils/allocator.h>
+#include <utils/linked_list.h>
+
+/**
+ * Private data of an proposal_substructure_t' Object
+ *
+ */
+typedef struct private_proposal_substructure_s private_proposal_substructure_t;
+
+struct private_proposal_substructure_s {
+ /**
+ * public proposal_substructure_t interface
+ */
+ proposal_substructure_t public;
+
+ /**
+ * next payload type
+ */
+ u_int8_t next_payload;
+
+
+ /**
+ * Length of this payload
+ */
+ u_int16_t proposal_length;
+
+
+ /**
+ * Proposal number
+ */
+ u_int8_t proposal_number;
+
+ /**
+ * Protocol ID
+ */
+ u_int8_t protocol_id;
+
+ /**
+ * SPI size of the following SPI
+ */
+ u_int8_t spi_size;
+
+ /**
+ * Number of transforms
+ */
+ u_int8_t transforms_count;
+
+ /**
+ * SPI is stored as chunk
+ */
+ chunk_t spi;
+
+ /**
+ * Transforms are stored in a linked_list_t
+ */
+ linked_list_t * transforms;
+
+ /**
+ * @brief Computes the length of this substructure.
+ *
+ * @param this calling private_proposal_substructure_t object
+ * @return
+ * SUCCESS in any case
+ */
+ status_t (*compute_length) (private_proposal_substructure_t *this);
+};
+
+/**
+ * Encoding rules to parse or generate a Proposal substructure
+ *
+ * The defined offsets are the positions in a object of type
+ * private_proposal_substructure_t.
+ *
+ */
+encoding_rule_t proposal_substructure_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_proposal_substructure_t, next_payload) },
+ /* Reserved Byte is skipped */
+ { RESERVED_BYTE, 0 },
+ /* Length of the whole proposal substructure payload*/
+ { PAYLOAD_LENGTH, offsetof(private_proposal_substructure_t, proposal_length) },
+ /* proposal number is a number of 8 bit */
+ { U_INT_8, offsetof(private_proposal_substructure_t, proposal_number) },
+ /* protocol ID is a number of 8 bit */
+ { U_INT_8, offsetof(private_proposal_substructure_t, protocol_id) },
+ /* SPI Size has its own type */
+ { SPI_SIZE, offsetof(private_proposal_substructure_t, spi_size) },
+ /* Number of transforms is a number of 8 bit */
+ { U_INT_8, offsetof(private_proposal_substructure_t, transforms_count) },
+ /* SPI is a chunk of variable size*/
+ { SPI, offsetof(private_proposal_substructure_t, spi) },
+ /* Transforms are stored in a transform substructure,
+ offset points to a linked_list_t pointer */
+ { TRANSFORMS, offsetof(private_proposal_substructure_t, transforms) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! 0 (last) or 2 ! RESERVED ! Proposal Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Proposal # ! Protocol ID ! SPI Size !# of Transforms!
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ~ SPI (variable) ~
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ <Transforms> ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implements payload_t's verify function.
+ * See #payload_s.verify for description.
+ */
+static status_t verify(private_proposal_substructure_t *this)
+{
+ if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != PROPOSAL_SUBSTRUCTURE))
+ {
+ /* must be 0 or 2 */
+ return FAILED;
+ }
+ if (this->transforms_count != this->transforms->get_count(this->transforms))
+ {
+ /* must be the same! */
+ return FAILED;
+ }
+
+ if (this->protocol_id > 4)
+ {
+ /* reserved are not supported */
+ return FAILED;
+ }
+
+ /* proposal number is checked in SA payload */
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's get_encoding_rules function.
+ * See #payload_s.get_encoding_rules for description.
+ */
+static status_t get_encoding_rules(private_proposal_substructure_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = proposal_substructure_encodings;
+ *rule_count = sizeof(proposal_substructure_encodings) / sizeof(encoding_rule_t);
+
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's get_type function.
+ * See #payload_s.get_type for description.
+ */
+static payload_type_t get_type(private_proposal_substructure_t *this)
+{
+ return PROPOSAL_SUBSTRUCTURE;
+}
+
+/**
+ * Implements payload_t's get_next_type function.
+ * See #payload_s.get_next_type for description.
+ */
+static payload_type_t get_next_type(private_proposal_substructure_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implements payload_t's set_next_type function.
+ * See #payload_s.set_next_type for description.
+ */
+static status_t set_next_type(private_proposal_substructure_t *this,payload_type_t type)
+{
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's get_length function.
+ * See #payload_s.get_length for description.
+ */
+static size_t get_length(private_proposal_substructure_t *this)
+{
+ return this->proposal_length;
+}
+
+/**
+ * Implements proposal_substructure_t's create_transform_substructure_iterator function.
+ * See #proposal_substructure_s.create_transform_substructure_iterator for description.
+ */
+static status_t create_transform_substructure_iterator (private_proposal_substructure_t *this,linked_list_iterator_t **iterator,bool forward)
+{
+ return (this->transforms->create_iterator(this->transforms,iterator,forward));
+}
+
+/**
+ * Implements proposal_substructure_t's add_transform_substructure function.
+ * See #proposal_substructure_s.add_transform_substructure for description.
+ */
+static status_t add_transform_substructure (private_proposal_substructure_t *this,transform_substructure_t *transform)
+{
+ status_t status;
+ if (this->transforms->get_count(this->transforms) > 0)
+ {
+ transform_substructure_t *last_transform;
+ status = this->transforms->get_last(this->transforms,(void **) &last_transform);
+ /* last transform is now not anymore last one */
+ last_transform->set_is_last_transform(last_transform,FALSE);
+
+ }
+ transform->set_is_last_transform(transform,TRUE);
+
+ status = this->transforms->insert_last(this->transforms,(void *) transform);
+ this->compute_length(this);
+ return status;
+}
+
+/**
+ * Implements proposal_substructure_t's set_proposal_number function.
+ * See #proposal_substructure_s.set_proposal_number for description.
+ */
+static status_t set_proposal_number(private_proposal_substructure_t *this,u_int8_t proposal_number)
+{
+ this->proposal_number = proposal_number;
+ return SUCCESS;
+}
+
+/**
+ * Implements proposal_substructure_t's get_proposal_number function.
+ * See #proposal_substructure_s.get_proposal_number for description.
+ */
+static u_int8_t get_proposal_number (private_proposal_substructure_t *this)
+{
+ return (this->proposal_number);
+}
+
+/**
+ * Implements proposal_substructure_t's set_protocol_id function.
+ * See #proposal_substructure_s.set_protocol_id for description.
+ */
+static status_t set_protocol_id(private_proposal_substructure_t *this,u_int8_t protocol_id)
+{
+ this->protocol_id = protocol_id;
+ return SUCCESS;
+}
+
+/**
+ * Implements proposal_substructure_t's get_protocol_id function.
+ * See #proposal_substructure_s.get_protocol_id for description.
+ */
+static u_int8_t get_protocol_id (private_proposal_substructure_t *this)
+{
+ return (this->protocol_id);
+}
+
+
+/**
+ * Implements proposal_substructure_t's set_spi function.
+ * See #proposal_substructure_s.set_spi for description.
+ */
+static status_t set_spi (private_proposal_substructure_t *this, chunk_t spi)
+{
+ /* first delete already set spi value */
+ if (this->spi.ptr != NULL)
+ {
+ allocator_free(this->spi.ptr);
+ this->spi.ptr = NULL;
+ this->spi.len = 0;
+ this->compute_length(this);
+ }
+
+ this->spi.ptr = allocator_clone_bytes(spi.ptr,spi.len);
+ if (this->spi.ptr == NULL)
+ {
+ return OUT_OF_RES;
+ }
+ this->spi.len = spi.len;
+ this->spi_size = spi.len;
+ this->compute_length(this);
+
+ return SUCCESS;
+}
+
+/**
+ * Implements proposal_substructure_t's get_spi function.
+ * See #proposal_substructure_s.get_spi for description.
+ */
+static chunk_t get_spi (private_proposal_substructure_t *this)
+{
+ chunk_t spi;
+ spi.ptr = this->spi.ptr;
+ spi.len = this->spi.len;
+
+ return spi;
+}
+
+/**
+ * Implements private_proposal_substructure_t's compute_length function.
+ * See #private_proposal_substructure_s.compute_length for description.
+ */
+static status_t compute_length (private_proposal_substructure_t *this)
+{
+ linked_list_iterator_t *iterator;
+ status_t status;
+ size_t transforms_count = 0;
+ size_t length = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH;
+ status = this->transforms->create_iterator(this->transforms,&iterator,TRUE);
+ if (status != SUCCESS)
+ {
+ return length;
+ }
+ while (iterator->has_next(iterator))
+ {
+ payload_t * current_transform;
+ iterator->current(iterator,(void **) &current_transform);
+ length += current_transform->get_length(current_transform);
+ transforms_count++;
+ }
+ iterator->destroy(iterator);
+
+ length += this->spi.len;
+ this->transforms_count= transforms_count;
+ this->proposal_length = length;
+
+ return SUCCESS;
+}
+
+/**
+ * Implements proposal_substructure_t's clone function.
+ * See #proposal_substructure_s.clone for description.
+ */
+static status_t clone(private_proposal_substructure_t *this, private_proposal_substructure_t **clone)
+{
+ private_proposal_substructure_t * new_clone;
+ linked_list_iterator_t *transforms;
+ status_t status;
+
+ new_clone = (private_proposal_substructure_t *) proposal_substructure_create();
+
+ new_clone->next_payload = this->next_payload;
+ new_clone->proposal_number = this->proposal_number;
+ new_clone->protocol_id = this->protocol_id;
+ new_clone->spi_size = this->spi_size;
+ if (this->spi.ptr != NULL)
+ {
+ new_clone->spi.ptr = allocator_clone_bytes(this->spi.ptr,this->spi.len);
+ if (new_clone->spi.ptr == NULL)
+ {
+ new_clone->public.destroy(&(new_clone->public));
+ return OUT_OF_RES;
+ }
+ new_clone->spi.len = this->spi.len;
+ }
+
+ status = this->transforms->create_iterator(this->transforms,&transforms,FALSE);
+ if (status != SUCCESS)
+ {
+ new_clone->public.destroy(&(new_clone->public));
+ return status;
+ }
+
+ while (transforms->has_next(transforms))
+ {
+ transform_substructure_t *current_transform;
+ transform_substructure_t *current_transform_clone;
+ status = transforms->current(transforms,(void **) &current_transform);
+ if (status != SUCCESS)
+ {
+ transforms->destroy(transforms);
+ new_clone->public.destroy(&(new_clone->public));
+ return status;
+ }
+ status = current_transform->clone(current_transform,&current_transform_clone);
+ if (status != SUCCESS)
+ {
+ transforms->destroy(transforms);
+ new_clone->public.destroy(&(new_clone->public));
+ return status;
+ }
+
+ status = new_clone->public.add_transform_substructure(&(new_clone->public),current_transform_clone);
+ if (status != SUCCESS)
+ {
+ transforms->destroy(transforms);
+ current_transform_clone->destroy(current_transform_clone);
+ new_clone->public.destroy(&(new_clone->public));
+ return status;
+ }
+ }
+
+ transforms->destroy(transforms);
+
+ *clone = new_clone;
+
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's and proposal_substructure_t's destroy function.
+ * See #payload_s.destroy or proposal_substructure_s.destroy for description.
+ */
+static status_t destroy(private_proposal_substructure_t *this)
+{
+ /* all proposals are getting destroyed */
+ while (this->transforms->get_count(this->transforms) > 0)
+ {
+ transform_substructure_t *current_transform;
+ if (this->transforms->remove_last(this->transforms,(void **)&current_transform) != SUCCESS)
+ {
+ break;
+ }
+ current_transform->destroy(current_transform);
+ }
+ this->transforms->destroy(this->transforms);
+
+ if (this->spi.ptr != NULL)
+ {
+ allocator_free(this->spi.ptr);
+ }
+
+ allocator_free(this);
+
+ return SUCCESS;
+}
+
+/*
+ * Described in header
+ */
+proposal_substructure_t *proposal_substructure_create()
+{
+ private_proposal_substructure_t *this = allocator_alloc_thing(private_proposal_substructure_t);
+ if (this == NULL)
+ {
+ return NULL;
+ }
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (status_t (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (status_t (*) (payload_t *,payload_type_t)) set_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;
+
+ /* public functions */
+ this->public.create_transform_substructure_iterator = (status_t (*) (proposal_substructure_t *,linked_list_iterator_t **,bool)) create_transform_substructure_iterator;
+ this->public.add_transform_substructure = (status_t (*) (proposal_substructure_t *,transform_substructure_t *)) add_transform_substructure;
+ this->public.set_proposal_number = (status_t (*) (proposal_substructure_t *,u_int8_t))set_proposal_number;
+ this->public.get_proposal_number = (u_int8_t (*) (proposal_substructure_t *)) get_proposal_number;
+ this->public.set_protocol_id = (status_t (*) (proposal_substructure_t *,u_int8_t))set_protocol_id;
+ this->public.get_protocol_id = (u_int8_t (*) (proposal_substructure_t *)) get_protocol_id;
+ this->public.set_spi = (status_t (*) (proposal_substructure_t *,chunk_t))set_spi;
+ this->public.get_spi = (chunk_t (*) (proposal_substructure_t *)) get_spi;
+ this->public.clone = (status_t (*) (proposal_substructure_t *, proposal_substructure_t **)) clone;
+ this->public.destroy = (status_t (*) (proposal_substructure_t *)) destroy;
+
+ /* private functions */
+ this->compute_length = compute_length;
+
+ /* set default values of the fields */
+ this->next_payload = NO_PAYLOAD;
+ this->proposal_length = 0;
+ this->proposal_number = 0;
+ this->protocol_id = 0;
+ this->transforms_count = 0;
+ this->spi_size = 0;
+ this->spi.ptr = NULL;
+ this->spi.len = 0;
+
+ this->transforms = linked_list_create();
+
+ if (this->transforms == NULL)
+ {
+ allocator_free(this);
+ return NULL;
+ }
+ return (&(this->public));
+}
diff --git a/Source/charon/encoding/payloads/proposal_substructure.h b/Source/charon/encoding/payloads/proposal_substructure.h
new file mode 100644
index 000000000..1da42d10d
--- /dev/null
+++ b/Source/charon/encoding/payloads/proposal_substructure.h
@@ -0,0 +1,186 @@
+/**
+ * @file proposal_substructure.h
+ *
+ * @brief Declaration of the class proposal_substructure_t.
+ *
+ * An object of this type represents an IKEv2 PROPOSAL Substructure and contains transforms.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef PROPOSAL_SUBSTRUCTURE_H_
+#define PROPOSAL_SUBSTRUCTURE_H_
+
+#include <types.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/transform_substructure.h>
+#include <utils/linked_list.h>
+
+/**
+ * Length of the proposal substructure header
+ * (without spi)
+ */
+#define PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH 8
+
+
+/**
+ * Protocol ID of a proposal
+ */
+typedef enum protocol_id_e protocol_id_t;
+
+enum protocol_id_e {
+ UNDEFINED_PROTOCOL_ID = 201,
+ IKE = 1,
+ AH = 2,
+ ESP = 3,
+};
+
+/**
+ * Object representing an IKEv2- PROPOSAL SUBSTRUCTURE
+ *
+ * The PROPOSAL SUBSTRUCTURE format is described in RFC section 3.3.1.
+ *
+ */
+typedef struct proposal_substructure_s proposal_substructure_t;
+
+struct proposal_substructure_s {
+ /**
+ * implements payload_t interface
+ */
+ payload_t payload_interface;
+
+ /**
+ * @brief Creates an iterator of stored transform_substructure_t objects.
+ *
+ * @warning The created iterator has to get destroyed by the caller!
+ * When deleting any transform over this iterator, call
+ * get_size to make sure the length and number values are ok.
+ *
+ * @param this calling proposal_substructure_t object
+ * @param iterator the created iterator is stored at the pointed pointer
+ * @param[in] forward iterator direction (TRUE: front to end)
+ * @return
+ * - SUCCESS or
+ * - OUT_OF_RES if iterator could not be created
+ */
+ status_t (*create_transform_substructure_iterator) (proposal_substructure_t *this,linked_list_iterator_t **iterator, bool forward);
+
+ /**
+ * @brief Adds a transform_substructure_t object to this object.
+ *
+ * @warning The added transform_substructure_t object is
+ * getting destroyed in destroy function of proposal_substructure_t.
+ *
+ * @param this calling proposal_substructure_t object
+ * @param transform transform_substructure_t object to add
+ * @return - SUCCESS if succeeded
+ * - FAILED otherwise
+ */
+ status_t (*add_transform_substructure) (proposal_substructure_t *this,transform_substructure_t *transform);
+
+ /**
+ * @brief Sets the proposal number of current proposal.
+ *
+ * @param this calling proposal_substructure_t object
+ * @param id proposal number to set
+ * @return - SUCCESS
+ */
+ status_t (*set_proposal_number) (proposal_substructure_t *this,u_int8_t proposal_number);
+
+ /**
+ * @brief get proposal number of current proposal.
+ *
+ * @param this calling proposal_substructure_t object
+ * @return proposal number of current proposal substructure.
+ */
+ u_int8_t (*get_proposal_number) (proposal_substructure_t *this);
+
+ /**
+ * @brief Sets the protocol id of current proposal.
+ *
+ * @param this calling proposal_substructure_t object
+ * @param id protocol id to set
+ * @return - SUCCESS
+ */
+ status_t (*set_protocol_id) (proposal_substructure_t *this,u_int8_t protocol_id);
+
+ /**
+ * @brief get protocol id of current proposal.
+ *
+ * @param this calling proposal_substructure_t object
+ * @return protocol id of current proposal substructure.
+ */
+ u_int8_t (*get_protocol_id) (proposal_substructure_t *this);
+
+
+ /**
+ * @brief Returns the currently set SPI of this proposal.
+ *
+ * @warning Returned data are not copied
+ *
+ * @param this calling proposal_substructure_t object
+ * @return chunk_t pointing to the value
+ */
+ chunk_t (*get_spi) (proposal_substructure_t *this);
+
+ /**
+ * @brief Sets the SPI of the current proposal.
+ *
+ * @warning SPI is getting copied
+ *
+ * @param this calling proposal_substructure_t object
+ * @param spi chunk_t pointing to the value to set
+ * @return
+ * - SUCCESS or
+ * - OUT_OF_RES
+ */
+ status_t (*set_spi) (proposal_substructure_t *this, chunk_t spi);
+
+ /**
+ * @brief Clones an proposal_substructure_t object.
+ *
+ * @param this proposal_substructure_t object to clone
+ * @param clone cloned object will be written there
+ * @return
+ * - SUCCESS
+ * - OUT_OF_RES
+ */
+ status_t (*clone) (proposal_substructure_t *this,proposal_substructure_t **clone);
+
+ /**
+ * @brief Destroys an proposal_substructure_t object.
+ *
+ * @param this proposal_substructure_t object to destroy
+ * @return
+ * SUCCESS in any case
+ */
+ status_t (*destroy) (proposal_substructure_t *this);
+};
+
+/**
+ * @brief Creates an empty proposal_substructure_t object
+ *
+ * @return
+ * - created proposal_substructure_t object, or
+ * - NULL if failed
+ */
+
+proposal_substructure_t *proposal_substructure_create();
+
+
+
+#endif /*PROPOSAL_SUBSTRUCTURE_H_*/
diff --git a/Source/charon/encoding/payloads/sa_payload.c b/Source/charon/encoding/payloads/sa_payload.c
new file mode 100644
index 000000000..83eb62acd
--- /dev/null
+++ b/Source/charon/encoding/payloads/sa_payload.c
@@ -0,0 +1,343 @@
+/**
+ * @file sa_payload.c
+ *
+ * @brief Declaration of the class sa_payload_t.
+ *
+ * An object of this type represents an IKEv2 SA-Payload and contains proposal
+ * substructures.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/* offsetof macro */
+#include <stddef.h>
+
+#include "sa_payload.h"
+
+#include <encoding/payloads/encodings.h>
+#include <utils/allocator.h>
+#include <utils/linked_list.h>
+
+
+/**
+ * Private data of an sa_payload_t' Object
+ *
+ */
+typedef struct private_sa_payload_s private_sa_payload_t;
+
+struct private_sa_payload_s {
+ /**
+ * public sa_payload_t interface
+ */
+ sa_payload_t public;
+
+ /**
+ * next payload type
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag
+ */
+ bool critical;
+
+ /**
+ * Length of this payload
+ */
+ u_int16_t payload_length;
+
+ /**
+ * Proposals in this payload are stored in a linked_list_t
+ */
+ linked_list_t * proposals;
+
+ /**
+ * @brief Computes the length of this payload.
+ *
+ * @param this calling private_sa_payload_t object
+ * @return
+ * SUCCESS in any case
+ */
+ status_t (*compute_length) (private_sa_payload_t *this);
+};
+
+/**
+ * Encoding rules to parse or generate a IKEv2-SA Payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_sa_payload_t.
+ *
+ */
+encoding_rule_t sa_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_sa_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_sa_payload_t, critical) },
+ /* 7 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* Length of the whole SA payload*/
+ { PAYLOAD_LENGTH, offsetof(private_sa_payload_t, payload_length) },
+ /* Proposals are stored in a proposal substructure,
+ offset points to a linked_list_t pointer */
+ { PROPOSALS, offsetof(private_sa_payload_t, proposals) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ <Proposals> ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implements payload_t's verify function.
+ * See #payload_s.verify for description.
+ */
+static status_t verify(private_sa_payload_t *this)
+{
+ int proposal_number = 1;
+ status_t status;
+ linked_list_iterator_t *iterator;
+ bool first = TRUE;
+
+ if (this->critical)
+ {
+ /* critical bit set! */
+ return FAILED;
+ }
+
+ /* check proposal numbering */
+ status = this->proposals->create_iterator(this->proposals,&iterator,TRUE);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+
+ while(iterator->has_next(iterator))
+ {
+ proposal_substructure_t *current_proposal;
+ status = iterator->current(iterator,(void **)&current_proposal);
+ {
+ break;
+ }
+ if (current_proposal->get_proposal_number(current_proposal) > proposal_number)
+ {
+ if (first)
+ {
+ /* first number must be 1 */
+ status = FAILED;
+ break;
+ }
+
+ if (current_proposal->get_proposal_number(current_proposal) != (proposal_number + 1))
+ {
+ /* must be only one more then previous proposal */
+ status = FAILED;
+ break;
+ }
+ }
+ else if (current_proposal->get_proposal_number(current_proposal) < proposal_number)
+ {
+ iterator->destroy(iterator);
+ /* must not be smaller then proceeding one */
+ status = FAILED;
+ break;
+ }
+ first = FALSE;
+ }
+
+ iterator->destroy(iterator);
+ return status;
+}
+
+
+/**
+ * Implements payload_t's and sa_payload_t's destroy function.
+ * See #payload_s.destroy or sa_payload_s.destroy for description.
+ */
+static status_t destroy(private_sa_payload_t *this)
+{
+ /* all proposals are getting destroyed */
+ while (this->proposals->get_count(this->proposals) > 0)
+ {
+ proposal_substructure_t *current_proposal;
+ if (this->proposals->remove_last(this->proposals,(void **)&current_proposal) != SUCCESS)
+ {
+ break;
+ }
+ current_proposal->destroy(current_proposal);
+ }
+ this->proposals->destroy(this->proposals);
+
+ allocator_free(this);
+
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's get_encoding_rules function.
+ * See #payload_s.get_encoding_rules for description.
+ */
+static status_t get_encoding_rules(private_sa_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = sa_payload_encodings;
+ *rule_count = sizeof(sa_payload_encodings) / sizeof(encoding_rule_t);
+
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's get_type function.
+ * See #payload_s.get_type for description.
+ */
+static payload_type_t get_type(private_sa_payload_t *this)
+{
+ return SECURITY_ASSOCIATION;
+}
+
+/**
+ * Implements payload_t's get_next_type function.
+ * See #payload_s.get_next_type for description.
+ */
+static payload_type_t get_next_type(private_sa_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implements payload_t's set_next_type function.
+ * See #payload_s.set_next_type for description.
+ */
+static status_t set_next_type(private_sa_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's get_length function.
+ * See #payload_s.get_length for description.
+ */
+static size_t get_length(private_sa_payload_t *this)
+{
+ this->compute_length(this);
+ return this->payload_length;
+}
+
+/**
+ * Implements sa_payload_t's create_proposal_substructure_iterator function.
+ * See #sa_payload_s.create_proposal_substructure_iterator for description.
+ */
+static status_t create_proposal_substructure_iterator (private_sa_payload_t *this,linked_list_iterator_t **iterator,bool forward)
+{
+ return (this->proposals->create_iterator(this->proposals,iterator,forward));
+}
+
+/**
+ * Implements sa_payload_t's add_proposal_substructure function.
+ * See #sa_payload_s.add_proposal_substructure for description.
+ */
+static status_t add_proposal_substructure (private_sa_payload_t *this,proposal_substructure_t *proposal)
+{
+ status_t status;
+ status = this->proposals->insert_last(this->proposals,(void *) proposal);
+ this->compute_length(this);
+ return status;
+}
+
+/**
+ * Implements private_sa_payload_t's compute_length function.
+ * See #private_sa_payload_s.compute_length for description.
+ */
+static status_t compute_length (private_sa_payload_t *this)
+{
+ linked_list_iterator_t *iterator;
+ status_t status;
+ size_t length = SA_PAYLOAD_HEADER_LENGTH;
+ status = this->proposals->create_iterator(this->proposals,&iterator,TRUE);
+ if (status != SUCCESS)
+ {
+ return length;
+ }
+ while (iterator->has_next(iterator))
+ {
+ payload_t *current_proposal;
+ iterator->current(iterator,(void **) &current_proposal);
+ length += current_proposal->get_length(current_proposal);
+ }
+ iterator->destroy(iterator);
+
+ this->payload_length = length;
+
+ return SUCCESS;
+}
+
+/*
+ * Described in header
+ */
+sa_payload_t *sa_payload_create()
+{
+ private_sa_payload_t *this = allocator_alloc_thing(private_sa_payload_t);
+ if (this == NULL)
+ {
+ return NULL;
+ }
+
+ /* public interface */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (status_t (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (status_t (*) (payload_t *,payload_type_t)) set_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;
+
+ /* public functions */
+ this->public.create_proposal_substructure_iterator = (status_t (*) (sa_payload_t *,linked_list_iterator_t **,bool)) create_proposal_substructure_iterator;
+ this->public.add_proposal_substructure = (status_t (*) (sa_payload_t *,proposal_substructure_t *)) add_proposal_substructure;
+ this->public.destroy = (status_t (*) (sa_payload_t *)) destroy;
+
+ /* private functions */
+ this->compute_length = compute_length;
+
+ /* set default values of the fields */
+ this->critical = SA_PAYLOAD_CRITICAL_FLAG;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = SA_PAYLOAD_HEADER_LENGTH;
+
+ this->proposals = linked_list_create();
+
+ if (this->proposals == NULL)
+ {
+ allocator_free(this);
+ return NULL;
+ }
+ return (&(this->public));
+}
+
+
diff --git a/Source/charon/encoding/payloads/sa_payload.h b/Source/charon/encoding/payloads/sa_payload.h
new file mode 100644
index 000000000..f13282de9
--- /dev/null
+++ b/Source/charon/encoding/payloads/sa_payload.h
@@ -0,0 +1,110 @@
+/**
+ * @file sa_payload.h
+ *
+ * @brief Declaration of the class sa_payload_t.
+ *
+ * An object of this type represents an IKEv2 SA-Payload and contains proposal
+ * substructures.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef SA_PAYLOAD_H_
+#define SA_PAYLOAD_H_
+
+#include <types.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/proposal_substructure.h>
+#include <utils/linked_list.h>
+
+/**
+ * Critical flag must not be set
+ */
+#define SA_PAYLOAD_CRITICAL_FLAG FALSE;
+
+/**
+ * SA_PAYLOAD length in bytes without any proposal substructure
+ */
+#define SA_PAYLOAD_HEADER_LENGTH 4
+
+/**
+ * Object representing an IKEv2-SA Payload
+ *
+ * The SA Payload format is described in RFC section 3.3.
+ *
+ */
+typedef struct sa_payload_s sa_payload_t;
+
+struct sa_payload_s {
+ /**
+ * implements payload_t interface
+ */
+ payload_t payload_interface;
+
+ /**
+ * @brief Creates an iterator of stored proposal_substructure_t objects.
+ *
+ * @warning The created iterator has to get destroyed by the caller!
+ *
+ * @warning When deleting an proposal using this iterator,
+ * the length of this transform substructure has to be refreshed
+ * by calling get_length()!
+ *
+ * @param this calling sa_payload_t object
+ * @param iterator the created iterator is stored at the pointed pointer
+ * @param[in] forward iterator direction (TRUE: front to end)
+ * @return
+ * - SUCCESS or
+ * - OUT_OF_RES if iterator could not be created
+ */
+ status_t (*create_proposal_substructure_iterator) (sa_payload_t *this,linked_list_iterator_t **iterator, bool forward);
+
+ /**
+ * @brief Adds a proposal_substructure_t object to this object.
+ *
+ * @warning The added proposal_substructure_t object is
+ * getting destroyed in destroy function of sa_payload_t.
+ *
+ * @param this calling sa_payload_t object
+ * @param proposal proposal_substructure_t object to add
+ * @return - SUCCESS if succeeded
+ * - FAILED otherwise
+ */
+ status_t (*add_proposal_substructure) (sa_payload_t *this,proposal_substructure_t *proposal);
+
+ /**
+ * @brief Destroys an sa_payload_t object.
+ *
+ * @param this sa_payload_t object to destroy
+ * @return
+ * SUCCESS in any case
+ */
+ status_t (*destroy) (sa_payload_t *this);
+};
+
+/**
+ * @brief Creates an empty sa_payload_t object
+ *
+ * @return
+ * - created sa_payload_t object, or
+ * - NULL if failed
+ */
+
+sa_payload_t *sa_payload_create();
+
+
+#endif /*SA_PAYLOAD_H_*/
diff --git a/Source/charon/encoding/payloads/transform_attribute.c b/Source/charon/encoding/payloads/transform_attribute.c
new file mode 100644
index 000000000..9aed1e332
--- /dev/null
+++ b/Source/charon/encoding/payloads/transform_attribute.c
@@ -0,0 +1,363 @@
+/**
+ * @file transform_attribute.c
+ *
+ * @brief Declaration of the class transform_attribute_t.
+ *
+ * An object of this type represents an IKEv2 TRANSFORM attribute.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/* offsetof macro */
+#include <stddef.h>
+
+#include "transform_attribute.h"
+
+#include <encoding/payloads/encodings.h>
+#include <types.h>
+#include <utils/allocator.h>
+
+/**
+ * Private data of an transform_attribute_t Object
+ *
+ */
+typedef struct private_transform_attribute_s private_transform_attribute_t;
+
+struct private_transform_attribute_s {
+ /**
+ * public transform_attribute_t interface
+ */
+ transform_attribute_t public;
+
+ /**
+ * Attribute Format Flag
+ *
+ * - TRUE means value is stored in attribute_length_or_value
+ * - FALSE means value is stored in attribute_value
+ */
+ bool attribute_format;
+
+ /**
+ * Type of the attribute
+ */
+ u_int16_t attribute_type;
+
+ /**
+ * Attribute Length if attribute_format is 0, attribute Value otherwise
+ */
+ u_int16_t attribute_length_or_value;
+
+ /**
+ * Attribute value as chunk if attribute_format is 0 (FALSE)
+ */
+ chunk_t attribute_value;
+};
+
+
+
+/**
+ * string mappings for transform_attribute_type_t
+ */
+mapping_t transform_attribute_type_m[] = {
+ {ATTRIBUTE_UNDEFINED, "ATTRIBUTE_UNDEFINED"},
+ {KEY_LENGTH, "KEY_LENGTH"},
+ {MAPPING_END, NULL}
+};
+
+/**
+ * Encoding rules to parse or generate a Transform attribute
+ *
+ * The defined offsets are the positions in a object of type
+ * private_transform_attribute_t.
+ *
+ */
+encoding_rule_t transform_attribute_encodings[] = {
+ /* Flag defining the format of this payload */
+ { ATTRIBUTE_FORMAT, offsetof(private_transform_attribute_t, attribute_format) },
+ /* type of the attribute as 15 bit unsigned integer */
+ { ATTRIBUTE_TYPE, offsetof(private_transform_attribute_t, attribute_type) },
+ /* Length or value, depending on the attribute format flag */
+ { ATTRIBUTE_LENGTH_OR_VALUE, offsetof(private_transform_attribute_t, attribute_length_or_value) },
+ /* Value of attribute if attribute format flag is zero */
+ { ATTRIBUTE_VALUE, offsetof(private_transform_attribute_t, attribute_value) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ !A! Attribute Type ! AF=0 Attribute Length !
+ !F! ! AF=1 Attribute Value !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! AF=0 Attribute Value !
+ ! AF=1 Not Transmitted !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implements payload_t's verify function.
+ * See #payload_s.verify for description.
+ */
+static status_t verify(private_transform_attribute_t *this)
+{
+ if (this->attribute_type != KEY_LENGTH)
+ {
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's get_encoding_rules function.
+ * See #payload_s.get_encoding_rules for description.
+ */
+static status_t get_encoding_rules(private_transform_attribute_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = transform_attribute_encodings;
+ *rule_count = sizeof(transform_attribute_encodings) / sizeof(encoding_rule_t);
+
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's get_type function.
+ * See #payload_s.get_type for description.
+ */
+static payload_type_t get_type(private_transform_attribute_t *this)
+{
+ return TRANSFORM_ATTRIBUTE;
+}
+
+/**
+ * Implements payload_t's get_next_type function.
+ * See #payload_s.get_next_type for description.
+ */
+static payload_type_t get_next_type(private_transform_attribute_t *this)
+{
+ return (NO_PAYLOAD);
+}
+
+/**
+ * Implements payload_t's set_next_type function.
+ * See #payload_s.set_next_type for description.
+ */
+static status_t set_next_type(private_transform_attribute_t *this,payload_type_t type)
+{
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's get_length function.
+ * See #payload_s.get_length for description.
+ */
+static size_t get_length(private_transform_attribute_t *this)
+{
+ if (this->attribute_format == TRUE)
+ {
+ /*Attribute size is only 4 byte */
+ return 4;
+ }
+ 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_chunk(private_transform_attribute_t *this, chunk_t value)
+{
+ if (this->attribute_value.ptr != NULL)
+ {
+ /* free existing value */
+ allocator_free(this->attribute_value.ptr);
+ this->attribute_value.ptr = NULL;
+ this->attribute_value.len = 0;
+
+ }
+
+ 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 set_value function.
+ * See #transform_attribute_s.set_value for description.
+ */
+static status_t set_value(private_transform_attribute_t *this, u_int16_t value)
+{
+ if (this->attribute_value.ptr != NULL)
+ {
+ /* free existing value */
+ allocator_free(this->attribute_value.ptr);
+ this->attribute_value.ptr = NULL;
+ this->attribute_value.len = 0;
+
+ }
+ this->attribute_length_or_value = value;
+ return SUCCESS;
+}
+
+/**
+ * Implements transform_attribute_t's get_value_chunk function.
+ * See #transform_attribute_s.get_value_chunk for description.
+ */
+static chunk_t get_value_chunk (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 get_value function.
+ * See #transform_attribute_s.get_value for description.
+ */
+static u_int16_t get_value (private_transform_attribute_t *this)
+{
+ return this->attribute_length_or_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;
+}
+
+/**
+ * Implements transform_attribute_t's clone function.
+ * See transform_attribute_s.clone for description.
+ */
+static status_t clone(private_transform_attribute_t *this,transform_attribute_t **clone)
+{
+ private_transform_attribute_t *new_clone;
+
+ new_clone = (private_transform_attribute_t *) transform_attribute_create();
+
+ new_clone->attribute_format = this->attribute_format;
+ new_clone->attribute_type = this->attribute_type;
+ new_clone->attribute_length_or_value = this->attribute_length_or_value;
+
+ if (!new_clone->attribute_format)
+ {
+ new_clone->attribute_value.ptr = allocator_clone_bytes(this->attribute_value.ptr,this->attribute_value.len);
+ new_clone->attribute_value.len = this->attribute_value.len;
+ if (new_clone->attribute_value.ptr == NULL)
+ {
+ new_clone->public.destroy(&(new_clone->public));
+ return OUT_OF_RES;
+ }
+ }
+
+ *clone = (transform_attribute_t *) new_clone;
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's and transform_attribute_t's destroy function.
+ * See #payload_s.destroy or transform_attribute_s.destroy for description.
+ */
+static status_t destroy(private_transform_attribute_t *this)
+{
+ if (this->attribute_value.ptr != NULL)
+ {
+ allocator_free(this->attribute_value.ptr);
+ }
+ allocator_free(this);
+
+ return SUCCESS;
+}
+
+/*
+ * Described in header
+ */
+transform_attribute_t *transform_attribute_create()
+{
+ private_transform_attribute_t *this = allocator_alloc_thing(private_transform_attribute_t);
+ if (this == NULL)
+ {
+ return NULL;
+ }
+
+ /* payload interface */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (status_t (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (status_t (*) (payload_t *,payload_type_t)) set_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;
+
+ /* public functions */
+ this->public.set_value_chunk = (status_t (*) (transform_attribute_t *,chunk_t)) set_value_chunk;
+ this->public.set_value = (status_t (*) (transform_attribute_t *,u_int16_t)) set_value;
+ this->public.get_value_chunk = (chunk_t (*) (transform_attribute_t *)) get_value_chunk;
+ this->public.get_value = (u_int16_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.clone = (status_t (*) (transform_attribute_t *,transform_attribute_t **)) clone;
+ this->public.destroy = (status_t (*) (transform_attribute_t *)) destroy;
+
+ /* set default values of the fields */
+ this->attribute_format = TRUE;
+ this->attribute_type = 0;
+ this->attribute_length_or_value = 0;
+ this->attribute_value.ptr = NULL;
+ this->attribute_value.len = 0;
+
+ return (&(this->public));
+}
+
diff --git a/Source/charon/encoding/payloads/transform_attribute.h b/Source/charon/encoding/payloads/transform_attribute.h
new file mode 100644
index 000000000..7cc72f207
--- /dev/null
+++ b/Source/charon/encoding/payloads/transform_attribute.h
@@ -0,0 +1,153 @@
+/**
+ * @file transform_attribute.h
+ *
+ * @brief Declaration of the class transform_attribute_t.
+ *
+ * An object of this type represents an IKEv2 TRANSFORM attribute.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef TRANSFORM_ATTRIBUTE_H_
+#define TRANSFORM_ATTRIBUTE_H_
+
+#include <types.h>
+#include <encoding/payloads/payload.h>
+
+
+/**
+ * Type of the attribute, as in IKEv2 draft 3.3.5
+ */
+typedef enum transform_attribute_type_e transform_attribute_type_t;
+
+enum transform_attribute_type_e {
+ ATTRIBUTE_UNDEFINED = 16384,
+ KEY_LENGTH = 14
+};
+
+/**
+ * string mappings for transform_attribute_type_t
+ */
+extern mapping_t transform_attribute_type_m[];
+
+/**
+ * Object representing an IKEv2- TRANSFORM Attribute
+ *
+ * The TRANSFORM ATTRIBUTE format is described in RFC section 3.3.5.
+ *
+ */
+typedef struct transform_attribute_s transform_attribute_t;
+
+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_chunk) (transform_attribute_t *this);
+
+ /**
+ * @brief Returns the currently set value of the attribute
+ *
+ * @warning Returned data are not copied
+ *
+ * @param this calling transform_attribute_t object
+ * @return value
+ */
+ u_int16_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_chunk) (transform_attribute_t *this, chunk_t value);
+
+ /**
+ * @brief Sets the value of the attribute.
+ *
+ * @param this calling transform_attribute_t object
+ * @param value value to set
+ * @return
+ * - SUCCESS or
+ * - OUT_OF_RES
+ */
+ status_t (*set_value) (transform_attribute_t *this, u_int16_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 Clones an transform_attribute_t object.
+ *
+ * @param this transform_attribute_t object to clone
+ * @param clone the new clone will be written there
+ * @return
+ * - OUT_OF_RES
+ * - SUCCESS
+ */
+ status_t (*clone) (transform_attribute_t *this,transform_attribute_t **clone);
+
+ /**
+ * @brief Destroys an transform_attribute_t object.
+ *
+ * @param this transform_attribute_t object to destroy
+ * @return
+ * SUCCESS in any case
+ */
+ status_t (*destroy) (transform_attribute_t *this);
+};
+
+/**
+ * @brief Creates an empty transform_attribute_t object
+ *
+ * @return
+ * - created transform_attribute_t object, or
+ * - NULL if failed
+ */
+
+transform_attribute_t *transform_attribute_create();
+
+#endif /*TRANSFORM_ATTRIBUTE_H_*/
diff --git a/Source/charon/encoding/payloads/transform_substructure.c b/Source/charon/encoding/payloads/transform_substructure.c
new file mode 100644
index 000000000..d44d4c4f8
--- /dev/null
+++ b/Source/charon/encoding/payloads/transform_substructure.c
@@ -0,0 +1,577 @@
+/**
+ * @file transform_substructure.h
+ *
+ * @brief Declaration of the class transform_substructure_t.
+ *
+ * An object of this type represents an IKEv2 TRANSFORM Substructure and contains Attributes.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+ /* offsetof macro */
+#include <stddef.h>
+
+#include "transform_substructure.h"
+
+#include <encoding/payloads/transform_attribute.h>
+#include <encoding/payloads/encodings.h>
+#include <types.h>
+#include <utils/allocator.h>
+#include <utils/linked_list.h>
+
+/**
+ * Private data of an transform_substructure_t' Object
+ *
+ */
+typedef struct private_transform_substructure_s private_transform_substructure_t;
+
+struct private_transform_substructure_s {
+ /**
+ * public transform_substructure_t interface
+ */
+ transform_substructure_t public;
+
+ /**
+ * next payload type
+ */
+ u_int8_t next_payload;
+
+
+ /**
+ * Length of this payload
+ */
+ u_int16_t transform_length;
+
+
+ /**
+ * Type of the transform
+ */
+ u_int8_t transform_type;
+
+ /**
+ * Transform ID
+ */
+ u_int16_t transform_id;
+
+ /**
+ * Transforms Attributes are stored in a linked_list_t
+ */
+ linked_list_t *attributes;
+
+ /**
+ * @brief Computes the length of this substructure.
+ *
+ * @param this calling private_transform_substructure_t object
+ * @return
+ * SUCCESS in any case
+ */
+ status_t (*compute_length) (private_transform_substructure_t *this);
+};
+
+
+/**
+ * string mappings for transform_type_t
+ */
+mapping_t transform_type_m[] = {
+ {UNDEFINED_TRANSFORM_TYPE, "UNDEFINED_TRANSFORM_TYPE"},
+ {ENCRYPTION_ALGORITHM, "ENCRYPTION_ALGORITHM"},
+ {PSEUDO_RANDOM_FUNCTION, "PSEUDO_RANDOM_FUNCTION"},
+ {INTEGRITIY_ALGORITHM, "INTEGRITIY_ALGORITHM"},
+ {DIFFIE_HELLMAN_GROUP, "DIFFIE_HELLMAN_GROUP"},
+ {EXTENDED_SEQUENCE_NUNBERS, "EXTENDED_SEQUENCE_NUNBERS"},
+ {MAPPING_END, NULL}
+};
+
+
+/**
+ * string mappings for encryption_algorithm_t
+ */
+mapping_t encryption_algorithm_m[] = {
+ {ENCR_UNDEFINED, "ENCR_UNDEFINED"},
+ {ENCR_DES_IV64, "ENCR_DES_IV64"},
+ {ENCR_DES, "ENCR_DES"},
+ {ENCR_3DES, "ENCR_3DES"},
+ {ENCR_RC5, "ENCR_RC5"},
+ {ENCR_IDEA, "ENCR_IDEA"},
+ {ENCR_CAST, "ENCR_CAST"},
+ {ENCR_BLOWFISH, "ENCR_BLOWFISH"},
+ {ENCR_3IDEA, "ENCR_3IDEA"},
+ {ENCR_DES_IV32, "ENCR_DES_IV32"},
+ {ENCR_NULL, "ENCR_NULL"},
+ {ENCR_AES_CBC, "ENCR_AES_CBC"},
+ {ENCR_AES_CTR, "ENCR_AES_CTR"},
+ {MAPPING_END, NULL}
+};
+
+/**
+ * string mappings for encryption_algorithm_t
+ */
+mapping_t pseudo_random_function_m[] = {
+ {PRF_UNDEFINED, "PRF_UNDEFINED"},
+ {PRF_HMAC_MD5, "PRF_HMAC_MD5"},
+ {PRF_HMAC_SHA1, "PRF_HMAC_SHA1"},
+ {PRF_HMAC_TIGER, "PRF_HMAC_TIGER"},
+ {PRF_AES128_CBC, "PRF_AES128_CBC"},
+ {MAPPING_END, NULL}
+};
+
+/**
+ * string mappings for integrity_algorithm_t
+ */
+mapping_t integrity_algorithm_m[] = {
+ {AUTH_UNDEFINED, "AUTH_UNDEFINED"},
+ {AUTH_HMAC_MD5_96, "AUTH_HMAC_MD5_96"},
+ {AUTH_HMAC_SHA1_96, "AUTH_HMAC_SHA1_96"},
+ {AUTH_DES_MAC, "AUTH_DES_MAC"},
+ {AUTH_KPDK_MD5, "AUTH_KPDK_MD5"},
+ {AUTH_AES_XCBC_96, "AUTH_AES_XCBC_96"},
+ {MAPPING_END, NULL}
+};
+
+/**
+ * string mappings for diffie_hellman_group_t
+ */
+mapping_t diffie_hellman_group_m[] = {
+ {MODP_UNDEFINED, "MODP_UNDEFINED"},
+ {MODP_768_BIT, "MODP_768_BIT"},
+ {MODP_1024_BIT, "MODP_1024_BIT"},
+ {MODP_1536_BIT, "MODP_1536_BIT"},
+ {MODP_2048_BIT, "MODP_2048_BIT"},
+ {MODP_3072_BIT, "MODP_3072_BIT"},
+ {MODP_4096_BIT, "MODP_4096_BIT"},
+ {MODP_6144_BIT, "MODP_6144_BIT"},
+ {MODP_8192_BIT, "MODP_8192_BIT"},
+ {MAPPING_END, NULL}
+};
+
+/**
+ * string mappings for extended_sequence_numbers_t
+ */
+mapping_t extended_sequence_numbers_m[] = {
+ {NO_EXT_SEQ_NUMBERS, "NO_EXT_SEQ_NUMBERS"},
+ {EXT_SEQ_NUMBERS, "EXT_SEQ_NUMBERS"},
+ {MAPPING_END, NULL}
+};
+
+/**
+ * Encoding rules to parse or generate a Transform substructure
+ *
+ * The defined offsets are the positions in a object of type
+ * private_transform_substructure_t.
+ *
+ */
+encoding_rule_t transform_substructure_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_transform_substructure_t, next_payload) },
+ /* Reserved Byte is skipped */
+ { RESERVED_BYTE, 0 },
+ /* Length of the whole transform substructure*/
+ { PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length) },
+ /* transform type is a number of 8 bit */
+ { U_INT_8, offsetof(private_transform_substructure_t, transform_type) },
+ /* Reserved Byte is skipped */
+ { RESERVED_BYTE, 0 },
+ /* tranform ID is a number of 8 bit */
+ { 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) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! 0 (last) or 3 ! RESERVED ! Transform Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ !Transform Type ! RESERVED ! Transform ID !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Transform Attributes ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+
+/**
+ * Implements payload_t's verify function.
+ * See #payload_s.verify for description.
+ */
+static status_t verify(private_transform_substructure_t *this)
+{
+ if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != TRANSFORM_SUBSTRUCTURE))
+ {
+ /* must be 0 or 3 */
+ return FAILED;
+ }
+
+ switch (this->transform_type)
+ {
+ case ENCRYPTION_ALGORITHM:
+ {
+ if ((this->transform_id < ENCR_DES_IV64) || (this->transform_id > ENCR_AES_CTR))
+ {
+ return FAILED;
+ }
+ break;
+ }
+ case PSEUDO_RANDOM_FUNCTION:
+ {
+ if ((this->transform_id < PRF_HMAC_MD5) || (this->transform_id > PRF_AES128_CBC))
+ {
+ return FAILED;
+ }
+ break;
+ }
+ case INTEGRITIY_ALGORITHM:
+ {
+ if ((this->transform_id < AUTH_HMAC_MD5_96) || (this->transform_id > AUTH_AES_XCBC_96))
+ {
+ return FAILED;
+ }
+ break;
+ }
+ case DIFFIE_HELLMAN_GROUP:
+ {
+ switch (this->transform_id)
+ {
+ case MODP_768_BIT:
+ case MODP_1024_BIT:
+ case MODP_1536_BIT:
+ case MODP_2048_BIT:
+ case MODP_3072_BIT:
+ case MODP_4096_BIT:
+ case MODP_6144_BIT:
+ case MODP_8192_BIT:
+ {
+ break;
+ }
+ default:
+ {
+ return FAILED;
+ }
+ }
+
+
+ break;
+ }
+ case EXTENDED_SEQUENCE_NUNBERS:
+ {
+ if ((this->transform_id != NO_EXT_SEQ_NUMBERS) && (this->transform_id != EXT_SEQ_NUMBERS))
+ {
+ return FAILED;
+ }
+ break;
+ }
+ default:
+ {
+ /* not a supported transform type! */
+ return FAILED;
+ }
+ }
+
+ /* proposal number is checked in SA payload */
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's get_encoding_rules function.
+ * See #payload_s.get_encoding_rules for description.
+ */
+static status_t get_encoding_rules(private_transform_substructure_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = transform_substructure_encodings;
+ *rule_count = sizeof(transform_substructure_encodings) / sizeof(encoding_rule_t);
+
+ return SUCCESS;
+}
+
+/**
+ * Implements payload_t's get_type function.
+ * See #payload_s.get_type for description.
+ */
+static payload_type_t get_type(private_transform_substructure_t *this)
+{
+ return TRANSFORM_SUBSTRUCTURE;
+}
+
+/**
+ * Implements payload_t's get_next_type function.
+ * See #payload_s.get_next_type for description.
+ */
+static payload_type_t get_next_type(private_transform_substructure_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implements payload_t's get_length function.
+ * See #payload_s.get_length for description.
+ */
+static size_t get_length(private_transform_substructure_t *this)
+{
+ this->compute_length(this);
+
+ return this->transform_length;
+}
+
+/**
+ * Implements transform_substructure_t's create_transform_attribute_iterator function.
+ * See #transform_substructure_s.create_transform_attribute_iterator for description.
+ */
+static status_t create_transform_attribute_iterator (private_transform_substructure_t *this,linked_list_iterator_t **iterator,bool forward)
+{
+ return (this->attributes->create_iterator(this->attributes,iterator,forward));
+}
+
+/**
+ * Implements transform_substructure_t's add_transform_attribute function.
+ * See #transform_substructure_s.add_transform_attribute for description.
+ */
+static status_t add_transform_attribute (private_transform_substructure_t *this,transform_attribute_t *attribute)
+{
+ status_t status;
+ status = this->attributes->insert_last(this->attributes,(void *) attribute);
+ this->compute_length(this);
+ return status;
+}
+
+/**
+ * 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 payload_t's set_next_type function.
+ * See #payload_s.set_next_type for description.
+ */
+static status_t set_next_type(private_transform_substructure_t *this,payload_type_t type)
+{
+ return SUCCESS;
+}
+
+/**
+ * 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;
+}
+
+/**
+ * Implements private_transform_substructure_t's compute_length function.
+ * See #private_transform_substructure_s.compute_length for description.
+ */
+static status_t compute_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);
+ }
+ iterator->destroy(iterator);
+
+ this->transform_length = length;
+
+ return SUCCESS;
+}
+
+/**
+ * Implements transform_substructure_t's clone function.
+ * See transform_substructure_s.clone for description.
+ */
+static status_t clone(private_transform_substructure_t *this,transform_substructure_t **clone)
+{
+ private_transform_substructure_t *new_clone;
+ linked_list_iterator_t *attributes;
+ status_t status;
+
+ new_clone = (private_transform_substructure_t *) transform_substructure_create();
+
+ new_clone->next_payload = this->next_payload;
+ new_clone->transform_type = this->transform_type;
+ new_clone->transform_id = this->transform_id;
+
+ status = this->attributes->create_iterator(this->attributes,&attributes,FALSE);
+ if (status != SUCCESS)
+ {
+ new_clone->public.destroy(&(new_clone->public));
+ return status;
+ }
+
+ while (attributes->has_next(attributes))
+ {
+ transform_attribute_t *current_attribute;
+ transform_attribute_t *current_attribute_clone;
+ status = attributes->current(attributes,(void **) &current_attribute);
+ if (status != SUCCESS)
+ {
+ attributes->destroy(attributes);
+ new_clone->public.destroy(&(new_clone->public));
+ return status;
+ }
+ status = current_attribute->clone(current_attribute,&current_attribute_clone);
+ if (status != SUCCESS)
+ {
+ attributes->destroy(attributes);
+ new_clone->public.destroy(&(new_clone->public));
+ return status;
+ }
+
+ status = new_clone->public.add_transform_attribute(&(new_clone->public),current_attribute_clone);
+ if (status != SUCCESS)
+ {
+ attributes->destroy(attributes);
+ current_attribute_clone->destroy(current_attribute_clone);
+ new_clone->public.destroy(&(new_clone->public));
+ return status;
+ }
+ }
+
+ attributes->destroy(attributes);
+
+ *clone = &(new_clone->public);
+ return SUCCESS;
+}
+
+
+/**
+ * Implements payload_t's and transform_substructure_t's destroy function.
+ * See #payload_s.destroy or transform_substructure_s.destroy for description.
+ */
+static status_t destroy(private_transform_substructure_t *this)
+{
+ /* all proposals are getting destroyed */
+ while (this->attributes->get_count(this->attributes) > 0)
+ {
+ transform_attribute_t *current_attribute;
+ if (this->attributes->remove_last(this->attributes,(void **)&current_attribute) != SUCCESS)
+ {
+ break;
+ }
+ current_attribute->destroy(current_attribute);
+ }
+ this->attributes->destroy(this->attributes);
+
+ allocator_free(this);
+
+ return SUCCESS;
+}
+
+/*
+ * Described in header
+ */
+transform_substructure_t *transform_substructure_create()
+{
+ private_transform_substructure_t *this = allocator_alloc_thing(private_transform_substructure_t);
+ if (this == NULL)
+ {
+ return NULL;
+ }
+
+ /* payload interface */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (status_t (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (status_t (*) (payload_t *,payload_type_t)) set_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;
+
+ /* public functions */
+ 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.clone = (status_t (*) (transform_substructure_t *,transform_substructure_t **)) clone;
+ this->public.destroy = (status_t (*) (transform_substructure_t *)) destroy;
+
+ /* private functions */
+ this->compute_length = compute_length;
+
+ /* set default values of the fields */
+ this->next_payload = NO_PAYLOAD;
+ this->transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
+ this->transform_id = 0;
+ this->transform_type = 0;
+
+ this->attributes = linked_list_create();
+
+ if (this->attributes == NULL)
+ {
+ allocator_free(this);
+ return NULL;
+ }
+ return (&(this->public));
+}
diff --git a/Source/charon/encoding/payloads/transform_substructure.h b/Source/charon/encoding/payloads/transform_substructure.h
new file mode 100644
index 000000000..1be66597e
--- /dev/null
+++ b/Source/charon/encoding/payloads/transform_substructure.h
@@ -0,0 +1,298 @@
+/**
+ * @file transform_substructure.h
+ *
+ * @brief Declaration of the class transform_substructure_t.
+ *
+ * An object of this type represents an IKEv2 TRANSFORM Substructure and contains Attributes.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef TRANSFORM_SUBSTRUCTURE_H_
+#define TRANSFORM_SUBSTRUCTURE_H_
+
+#include <types.h>
+#include <definitions.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/transform_attribute.h>
+#include <utils/linked_list.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
+
+
+/**
+ * Type of a transform, as in IKEv2 draft 3.3.2
+ */
+typedef enum transform_type_e transform_type_t;
+
+enum transform_type_e {
+ UNDEFINED_TRANSFORM_TYPE = 241,
+ ENCRYPTION_ALGORITHM = 1,
+ PSEUDO_RANDOM_FUNCTION = 2,
+ INTEGRITIY_ALGORITHM = 3,
+ DIFFIE_HELLMAN_GROUP = 4,
+ EXTENDED_SEQUENCE_NUNBERS = 5
+};
+
+/**
+ * string mappings for transform_type_t
+ */
+extern mapping_t transform_type_m[];
+
+/**
+ * Encryption algorithm, as in IKEv2 draft 3.3.2
+ */
+typedef enum encryption_algorithm_e encryption_algorithm_t;
+
+enum encryption_algorithm_e {
+ ENCR_UNDEFINED = 1024,
+ ENCR_DES_IV64 = 1,
+ ENCR_DES = 2,
+ ENCR_3DES = 3,
+ ENCR_RC5 = 4,
+ ENCR_IDEA = 5,
+ ENCR_CAST = 6,
+ ENCR_BLOWFISH = 7,
+ ENCR_3IDEA = 8,
+ ENCR_DES_IV32 = 9,
+ RESERVED = 10,
+ ENCR_NULL = 11,
+ ENCR_AES_CBC = 12,
+ ENCR_AES_CTR = 13
+};
+
+/**
+ * string mappings for encryption_algorithm_t
+ */
+extern mapping_t encryption_algorithm_m[];
+
+/**
+ * Pseudo random function, as in IKEv2 draft 3.3.2
+ */
+typedef enum pseudo_random_function_e pseudo_random_function_t;
+
+enum pseudo_random_function_e {
+ PRF_UNDEFINED = 1024,
+ PRF_HMAC_MD5 = 1,
+ PRF_HMAC_SHA1 = 2,
+ PRF_HMAC_TIGER = 3,
+ PRF_AES128_CBC = 4
+};
+
+/**
+ * string mappings for encryption_algorithm_t
+ */
+extern mapping_t pseudo_random_function_m[];
+
+/**
+ * Integrity algorithm, as in IKEv2 draft 3.3.2
+ */
+typedef enum integrity_algorithm_e integrity_algorithm_t;
+
+enum integrity_algorithm_e {
+ AUTH_UNDEFINED = 1024,
+ AUTH_HMAC_MD5_96 = 1,
+ AUTH_HMAC_SHA1_96 = 2,
+ AUTH_DES_MAC = 3,
+ AUTH_KPDK_MD5 = 4,
+ AUTH_AES_XCBC_96 = 5
+};
+
+/**
+ * string mappings for integrity_algorithm_t
+ */
+extern mapping_t integrity_algorithm_m[];
+
+
+/**
+ * Diffie-Hellman group, as in IKEv2 draft 3.3.2 and RFC 3526
+ */
+typedef enum diffie_hellman_group_e diffie_hellman_group_t;
+
+enum diffie_hellman_group_e {
+ MODP_UNDEFINED = 1024,
+ MODP_768_BIT = 1,
+ MODP_1024_BIT = 2,
+ MODP_1536_BIT = 5,
+ MODP_2048_BIT = 14,
+ MODP_3072_BIT = 15,
+ MODP_4096_BIT = 16,
+ MODP_6144_BIT = 17,
+ MODP_8192_BIT = 18
+};
+
+/**
+ * string mappings for diffie_hellman_group_t
+ */
+extern mapping_t diffie_hellman_group_m[];
+
+/**
+ * Extended sequence numbers, as in IKEv2 draft 3.3.2
+ */
+typedef enum extended_sequence_numbers_e extended_sequence_numbers_t;
+
+enum extended_sequence_numbers_e {
+ NO_EXT_SEQ_NUMBERS = 0,
+ EXT_SEQ_NUMBERS = 1
+};
+
+/**
+ * string mappings for extended_sequence_numbers_t
+ */
+extern mapping_t extended_sequence_numbers_m[];
+
+/**
+ * Object representing an IKEv2- TRANSFORM SUBSTRUCTURE
+ *
+ * The TRANSFORM SUBSTRUCTURE format is described in RFC section 3.3.2.
+ *
+ */
+typedef struct transform_substructure_s transform_substructure_t;
+
+struct transform_substructure_s {
+ /**
+ * implements payload_t interface
+ */
+ payload_t payload_interface;
+
+ /**
+ * @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 using this iterator,
+ * the length of this transform substructure has to be refreshed
+ * by calling get_length()!
+ *
+ * @param this calling transform_substructure_t object
+ * @param iterator the created iterator is stored at the pointed pointer
+ * @param[in] forward iterator direction (TRUE: front to end)
+ * @return
+ * - SUCCESS or
+ * - OUT_OF_RES if iterator could not be created
+ */
+ status_t (*create_transform_attribute_iterator) (transform_substructure_t *this,linked_list_iterator_t **iterator, bool forward);
+
+ /**
+ * @brief Adds a transform_attribute_t object to this object.
+ *
+ * @warning The added proposal_substructure_t object is
+ * getting destroyed in destroy function of transform_substructure_t.
+ *
+ * @param this calling transform_substructure_t object
+ * @param proposal transform_attribute_t object to add
+ * @return - SUCCESS if succeeded
+ * - FAILED otherwise
+ */
+ 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 Clones an transform_substructure_t object.
+ *
+ * @param this transform_substructure_t object to clone
+ * @param clone pointer to a transform_substructure_t object pointer
+ * where the new object is stored to.
+ * @return
+ * - OUT_OF_RES
+ * - SUCCESS in any case
+ */
+ status_t (*clone) (transform_substructure_t *this,transform_substructure_t **clone);
+
+ /**
+ * @brief Destroys an transform_substructure_t object.
+ *
+ * @param this transform_substructure_t object to destroy
+ * @return
+ * SUCCESS in any case
+ */
+ status_t (*destroy) (transform_substructure_t *this);
+};
+
+/**
+ * @brief Creates an empty transform_substructure_t object
+ *
+ * @return
+ * - created transform_substructure_t object, or
+ * - NULL if failed
+ */
+
+transform_substructure_t *transform_substructure_create();
+
+#endif /*TRANSFORM_SUBSTRUCTURE_H_*/