aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon/encoding
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2010-03-12 16:45:46 +0100
committerTobias Brunner <tobias@strongswan.org>2010-03-19 13:34:52 +0100
commit08c5572602404675f5cba93d8bbaa8a6925c1b95 (patch)
tree0819425652f758e072e6f432a2d655d995879383 /src/libcharon/encoding
parent7c11d10eb8f16dd4ffa31dd7e61141cc80c56596 (diff)
downloadstrongswan-08c5572602404675f5cba93d8bbaa8a6925c1b95.tar.bz2
strongswan-08c5572602404675f5cba93d8bbaa8a6925c1b95.tar.xz
Moving charon to libcharon.
Diffstat (limited to 'src/libcharon/encoding')
-rw-r--r--src/libcharon/encoding/generator.c888
-rw-r--r--src/libcharon/encoding/generator.h85
-rw-r--r--src/libcharon/encoding/message.c1726
-rw-r--r--src/libcharon/encoding/message.h359
-rw-r--r--src/libcharon/encoding/parser.c862
-rw-r--r--src/libcharon/encoding/parser.h79
-rw-r--r--src/libcharon/encoding/payloads/auth_payload.c259
-rw-r--r--src/libcharon/encoding/payloads/auth_payload.h102
-rw-r--r--src/libcharon/encoding/payloads/cert_payload.c340
-rw-r--r--src/libcharon/encoding/payloads/cert_payload.h137
-rw-r--r--src/libcharon/encoding/payloads/certreq_payload.c298
-rw-r--r--src/libcharon/encoding/payloads/certreq_payload.h90
-rw-r--r--src/libcharon/encoding/payloads/configuration_attribute.c264
-rw-r--r--src/libcharon/encoding/payloads/configuration_attribute.h85
-rw-r--r--src/libcharon/encoding/payloads/cp_payload.c273
-rw-r--r--src/libcharon/encoding/payloads/cp_payload.h108
-rw-r--r--src/libcharon/encoding/payloads/delete_payload.c292
-rw-r--r--src/libcharon/encoding/payloads/delete_payload.h84
-rw-r--r--src/libcharon/encoding/payloads/eap_payload.c302
-rw-r--r--src/libcharon/encoding/payloads/eap_payload.h129
-rw-r--r--src/libcharon/encoding/payloads/encodings.c58
-rw-r--r--src/libcharon/encoding/payloads/encodings.h515
-rw-r--r--src/libcharon/encoding/payloads/encryption_payload.c619
-rw-r--r--src/libcharon/encoding/payloads/encryption_payload.h173
-rw-r--r--src/libcharon/encoding/payloads/endpoint_notify.c422
-rw-r--r--src/libcharon/encoding/payloads/endpoint_notify.h173
-rw-r--r--src/libcharon/encoding/payloads/id_payload.c293
-rw-r--r--src/libcharon/encoding/payloads/id_payload.h122
-rw-r--r--src/libcharon/encoding/payloads/ike_header.c415
-rw-r--r--src/libcharon/encoding/payloads/ike_header.h227
-rw-r--r--src/libcharon/encoding/payloads/ke_payload.c270
-rw-r--r--src/libcharon/encoding/payloads/ke_payload.h104
-rw-r--r--src/libcharon/encoding/payloads/nonce_payload.c225
-rw-r--r--src/libcharon/encoding/payloads/nonce_payload.h78
-rw-r--r--src/libcharon/encoding/payloads/notify_payload.c617
-rw-r--r--src/libcharon/encoding/payloads/notify_payload.h232
-rw-r--r--src/libcharon/encoding/payloads/payload.c184
-rw-r--r--src/libcharon/encoding/payloads/payload.h272
-rw-r--r--src/libcharon/encoding/payloads/proposal_substructure.c598
-rw-r--r--src/libcharon/encoding/payloads/proposal_substructure.h173
-rw-r--r--src/libcharon/encoding/payloads/sa_payload.c368
-rw-r--r--src/libcharon/encoding/payloads/sa_payload.h115
-rw-r--r--src/libcharon/encoding/payloads/traffic_selector_substructure.c276
-rw-r--r--src/libcharon/encoding/payloads/traffic_selector_substructure.h151
-rw-r--r--src/libcharon/encoding/payloads/transform_attribute.c325
-rw-r--r--src/libcharon/encoding/payloads/transform_attribute.h132
-rw-r--r--src/libcharon/encoding/payloads/transform_substructure.c402
-rw-r--r--src/libcharon/encoding/payloads/transform_substructure.h174
-rw-r--r--src/libcharon/encoding/payloads/ts_payload.c334
-rw-r--r--src/libcharon/encoding/payloads/ts_payload.h127
-rw-r--r--src/libcharon/encoding/payloads/unknown_payload.c201
-rw-r--r--src/libcharon/encoding/payloads/unknown_payload.h79
-rw-r--r--src/libcharon/encoding/payloads/vendor_id_payload.c195
-rw-r--r--src/libcharon/encoding/payloads/vendor_id_payload.h70
54 files changed, 15481 insertions, 0 deletions
diff --git a/src/libcharon/encoding/generator.c b/src/libcharon/encoding/generator.c
new file mode 100644
index 000000000..6485da492
--- /dev/null
+++ b/src/libcharon/encoding/generator.c
@@ -0,0 +1,888 @@
+/*
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 <library.h>
+#include <daemon.h>
+#include <utils/linked_list.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>
+#include <encoding/payloads/id_payload.h>
+#include <encoding/payloads/auth_payload.h>
+#include <encoding/payloads/cert_payload.h>
+#include <encoding/payloads/certreq_payload.h>
+#include <encoding/payloads/ts_payload.h>
+#include <encoding/payloads/delete_payload.h>
+#include <encoding/payloads/vendor_id_payload.h>
+#include <encoding/payloads/cp_payload.h>
+#include <encoding/payloads/configuration_attribute.h>
+#include <encoding/payloads/eap_payload.h>
+
+
+typedef struct private_generator_t private_generator_t;
+
+/**
+ * Private part of a generator_t object.
+ */
+struct private_generator_t {
+ /**
+ * Public part of a generator_t object.
+ */
+ generator_t public;
+
+ /**
+ * 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).
+ */
+ u_int8_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;
+};
+
+/**
+ * Get size of current buffer in bytes.
+ */
+static int get_size(private_generator_t *this)
+{
+ return this->roof_position - this->buffer;
+}
+
+/**
+ * Get free space of current buffer in bytes.
+ */
+static int get_space(private_generator_t *this)
+{
+ return this->roof_position - this->out_position;
+}
+
+/**
+ * Get length of data in buffer (in bytes).
+ */
+static int get_length(private_generator_t *this)
+{
+ return this->out_position - this->buffer;
+}
+
+/**
+ * Get current offset in buffer (in bytes).
+ */
+static u_int32_t get_offset(private_generator_t *this)
+{
+ return this->out_position - this->buffer;
+}
+
+/**
+ * Makes sure enough space is available in buffer to store amount of bits.
+ */
+static void make_space_available(private_generator_t *this, int bits)
+{
+ while ((get_space(this) * 8 - this->current_bit) < bits)
+ {
+ int old_buffer_size, new_buffer_size, out_position_offset;
+
+ old_buffer_size = get_size(this);
+ new_buffer_size = old_buffer_size + GENERATOR_DATA_BUFFER_INCREASE_VALUE;
+ out_position_offset = this->out_position - this->buffer;
+
+ DBG2(DBG_ENC, "increasing gen buffer from %d to %d byte",
+ old_buffer_size, new_buffer_size);
+
+ this->buffer = realloc(this->buffer,new_buffer_size);
+ this->out_position = (this->buffer + out_position_offset);
+ this->roof_position = (this->buffer + new_buffer_size);
+ }
+}
+
+/**
+ * Writes a specific amount of byte into the buffer.
+ */
+static void write_bytes_to_buffer(private_generator_t *this, void *bytes,
+ int number_of_bytes)
+{
+ int i;
+ u_int8_t *read_position = (u_int8_t *)bytes;
+
+ make_space_available(this, number_of_bytes * 8);
+
+ for (i = 0; i < number_of_bytes; i++)
+ {
+ *(this->out_position) = *(read_position);
+ read_position++;
+ this->out_position++;
+ }
+}
+
+/**
+ * Writes a specific amount of byte into the buffer at a specific offset.
+ */
+static void write_bytes_to_buffer_at_offset(private_generator_t *this,
+ void *bytes, int number_of_bytes, u_int32_t offset)
+{
+ int i;
+ u_int8_t *read_position = (u_int8_t *)bytes;
+ u_int8_t *write_position;
+ u_int32_t free_space_after_offset = get_size(this) - offset;
+
+ /* check first if enough space for new data is available */
+ if (number_of_bytes > free_space_after_offset)
+ {
+ 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++;
+ }
+}
+
+/**
+ * Generates a U_INT-Field type and writes it to buffer.
+ */
+static void generate_u_int_type(private_generator_t *this,
+ encoding_type_t int_type,u_int32_t offset)
+{
+ int number_of_bits = 0;
+
+ /* find out number of bits of each U_INT type to check for enough space */
+ switch (int_type)
+ {
+ case U_INT_4:
+ number_of_bits = 4;
+ break;
+ case TS_TYPE:
+ case U_INT_8:
+ number_of_bits = 8;
+ break;
+ case U_INT_16:
+ case CONFIGURATION_ATTRIBUTE_LENGTH:
+ number_of_bits = 16;
+ break;
+ case U_INT_32:
+ number_of_bits = 32;
+ break;
+ case ATTRIBUTE_TYPE:
+ number_of_bits = 15;
+ break;
+ case IKE_SPI:
+ number_of_bits = 64;
+ break;
+ default:
+ DBG1(DBG_ENC, "U_INT Type %N is not supported",
+ encoding_type_names, int_type);
+ return;
+ }
+ if ((number_of_bits % 8) == 0 && this->current_bit != 0)
+ {
+ DBG1(DBG_ENC, "U_INT Type %N is not 8 Bit aligned",
+ encoding_type_names, int_type);
+ return;
+ }
+
+ make_space_available(this, number_of_bits);
+ switch (int_type)
+ {
+ case U_INT_4:
+ {
+ u_int8_t high, low;
+
+ if (this->current_bit == 0)
+ {
+ /* high of current byte in buffer has to be set to the new value*/
+ high = *((u_int8_t *)(this->data_struct + offset)) << 4;
+ /* low in buffer is not changed */
+ low = *(this->out_position) & 0x0F;
+ /* high is set, low_val is not changed */
+ *(this->out_position) = high | low;
+ DBG3(DBG_ENC, " => %d", *(this->out_position));
+ /* write position is not changed, just bit position is moved */
+ this->current_bit = 4;
+ }
+ else if (this->current_bit == 4)
+ {
+ /* high in buffer is not changed */
+ high = *(this->out_position) & 0xF0;
+ /* low of current byte in buffer has to be set to the new value*/
+ low = *((u_int8_t *)(this->data_struct + offset)) & 0x0F;
+ *(this->out_position) = high | low;
+ DBG3(DBG_ENC, " => %d", *(this->out_position));
+ this->out_position++;
+ this->current_bit = 0;
+ }
+ else
+ {
+ DBG1(DBG_ENC, "U_INT_4 Type is not 4 Bit aligned");
+ /* 4 Bit integers must have a 4 bit alignment */
+ return;
+ }
+ break;
+ }
+ case TS_TYPE:
+ case U_INT_8:
+ {
+ /* 8 bit values are written as they are */
+ *this->out_position = *((u_int8_t *)(this->data_struct + offset));
+ DBG3(DBG_ENC, " => %d", *(this->out_position));
+ this->out_position++;
+ break;
+ }
+ case ATTRIBUTE_TYPE:
+ {
+ u_int8_t attribute_format_flag;
+ u_int16_t val;
+
+ /* attribute type must not change first bit of current byte */
+ if (this->current_bit != 1)
+ {
+ DBG1(DBG_ENC, "ATTRIBUTE FORMAT flag is not set");
+ return;
+ }
+ attribute_format_flag = *(this->out_position) & 0x80;
+ /* get attribute type value as 16 bit integer*/
+ val = *((u_int16_t*)(this->data_struct + offset));
+ /* unset most significant bit */
+ val &= 0x7FFF;
+ if (attribute_format_flag)
+ {
+ val |= 0x8000;
+ }
+ val = htons(val);
+ DBG3(DBG_ENC, " => %d", val);
+ /* write bytes to buffer (set bit is overwritten) */
+ write_bytes_to_buffer(this, &val, sizeof(u_int16_t));
+ this->current_bit = 0;
+ break;
+
+ }
+ case U_INT_16:
+ case CONFIGURATION_ATTRIBUTE_LENGTH:
+ {
+ u_int16_t val = htons(*((u_int16_t*)(this->data_struct + offset)));
+ DBG3(DBG_ENC, " => %b", &val, sizeof(u_int16_t));
+ write_bytes_to_buffer(this, &val, sizeof(u_int16_t));
+ break;
+ }
+ case U_INT_32:
+ {
+ u_int32_t val = htonl(*((u_int32_t*)(this->data_struct + offset)));
+ DBG3(DBG_ENC, " => %b", &val, sizeof(u_int32_t));
+ write_bytes_to_buffer(this, &val, sizeof(u_int32_t));
+ break;
+ }
+ case IKE_SPI:
+ {
+ /* 64 bit are written as-is, no host order conversion */
+ write_bytes_to_buffer(this, this->data_struct + offset,
+ sizeof(u_int64_t));
+ DBG3(DBG_ENC, " => %b", this->data_struct + offset,
+ sizeof(u_int64_t));
+ break;
+ }
+ default:
+ {
+ DBG1(DBG_ENC, "U_INT Type %N is not supported",
+ encoding_type_names, int_type);
+ return;
+ }
+ }
+}
+
+/**
+ * Generate a reserved bit or byte
+ */
+static void generate_reserved_field(private_generator_t *this, int bits)
+{
+ /* only one bit or 8 bit fields are supported */
+ if (bits != 1 && bits != 8)
+ {
+ DBG1(DBG_ENC, "reserved field of %d bits cannot be generated", bits);
+ return ;
+ }
+ make_space_available(this, bits);
+
+ if (bits == 1)
+ {
+ 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
+ {
+ if (this->current_bit > 0)
+ {
+ DBG1(DBG_ENC, "reserved field cannot be written cause "
+ "alignement of current bit is %d", this->current_bit);
+ return;
+ }
+ *(this->out_position) = 0x00;
+ this->out_position++;
+ }
+}
+
+/**
+ * Generate a FLAG filed
+ */
+static void generate_flag(private_generator_t *this, u_int32_t offset)
+{
+ u_int8_t flag_value;
+ u_int8_t flag;
+
+ 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 */
+ make_space_available(this, 1);
+ if (this->current_bit == 0)
+ {
+ /* memory must be zero */
+ *(this->out_position) = 0x00;
+ }
+
+ *(this->out_position) = *(this->out_position) | flag;
+ DBG3(DBG_ENC, " => %d", *this->out_position);
+
+ this->current_bit++;
+ if (this->current_bit >= 8)
+ {
+ this->current_bit = this->current_bit % 8;
+ this->out_position++;
+ }
+}
+
+/**
+ * Generates a bytestream from a chunk_t.
+ */
+static void generate_from_chunk(private_generator_t *this, u_int32_t offset)
+{
+ chunk_t *value;
+
+ if (this->current_bit != 0)
+ {
+ DBG1(DBG_ENC, "can not generate a chunk at Bitpos %d", this->current_bit);
+ return ;
+ }
+
+ value = (chunk_t *)(this->data_struct + offset);
+ DBG3(DBG_ENC, " => %B", value);
+
+ write_bytes_to_buffer(this, value->ptr, value->len);
+}
+
+/**
+ * Implementation of private_generator_t.write_to_chunk.
+ */
+static void write_to_chunk(private_generator_t *this,chunk_t *data)
+{
+ int data_length = get_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 val = htonl(header_length_field);
+ write_bytes_to_buffer_at_offset(this, &val, sizeof(u_int32_t),
+ this->header_length_position_offset);
+ }
+
+ if (this->current_bit > 0)
+ {
+ data_length++;
+ }
+ *data = chunk_alloc(data_length);
+ memcpy(data->ptr, this->buffer, data_length);
+
+ DBG3(DBG_ENC, "generated data of this generator %B", data);
+}
+
+/**
+ * Implementation of private_generator_t.generate_payload.
+ */
+static void generate_payload (private_generator_t *this,payload_t *payload)
+{
+ int i, offset_start;
+ size_t rule_count;
+ encoding_rule_t *rules;
+ payload_type_t payload_type;
+
+ this->data_struct = payload;
+ payload_type = payload->get_type(payload);
+ /* spi size has to get reseted */
+ this->last_spi_size = 0;
+
+ offset_start = this->out_position - this->buffer;
+
+ DBG2(DBG_ENC, "generating payload of type %N",
+ payload_type_names, payload_type);
+
+ /* each payload has its own encoding rules */
+ payload->get_encoding_rules(payload, &rules, &rule_count);
+
+ for (i = 0; i < rule_count;i++)
+ {
+ DBG2(DBG_ENC, " generating rule %d %N",
+ i, encoding_type_names, rules[i].type);
+ switch (rules[i].type)
+ {
+ case U_INT_4:
+ case U_INT_8:
+ case U_INT_16:
+ case U_INT_32:
+ case IKE_SPI:
+ case TS_TYPE:
+ case ATTRIBUTE_TYPE:
+ case CONFIGURATION_ATTRIBUTE_LENGTH:
+ {
+ generate_u_int_type(this, rules[i].type, rules[i].offset);
+ break;
+ }
+ case RESERVED_BIT:
+ {
+ generate_reserved_field(this, 1);
+ break;
+ }
+ case RESERVED_BYTE:
+ {
+ generate_reserved_field(this, 8);
+ break;
+ }
+ case FLAG:
+ {
+ generate_flag(this, rules[i].offset);
+ break;
+ }
+ case PAYLOAD_LENGTH:
+ {
+ this->last_payload_length_position_offset = get_offset(this);
+ generate_u_int_type(this, U_INT_16,rules[i].offset);
+ break;
+ }
+ case HEADER_LENGTH:
+ {
+ this->header_length_position_offset = get_offset(this);
+ generate_u_int_type(this ,U_INT_32, rules[i].offset);
+ break;
+ }
+ case SPI_SIZE:
+ generate_u_int_type(this, U_INT_8, rules[i].offset);
+ this->last_spi_size = *((u_int8_t *)(this->data_struct +
+ rules[i].offset));
+ break;
+ case ADDRESS:
+ {
+ generate_from_chunk(this, rules[i].offset);
+ break;
+ }
+ case SPI:
+ {
+ generate_from_chunk(this, rules[i].offset);
+ break;
+ }
+ case KEY_EXCHANGE_DATA:
+ case NOTIFICATION_DATA:
+ case NONCE_DATA:
+ case ID_DATA:
+ case AUTH_DATA:
+ case CERT_DATA:
+ case CERTREQ_DATA:
+ case SPIS:
+ case CONFIGURATION_ATTRIBUTE_VALUE:
+ case VID_DATA:
+ case EAP_DATA:
+ {
+ u_int32_t payload_length_position_offset;
+ u_int16_t length_of_payload;
+ u_int16_t header_length = 0;
+ u_int16_t length_in_network_order;
+
+ switch(rules[i].type)
+ {
+ case KEY_EXCHANGE_DATA:
+ header_length = KE_PAYLOAD_HEADER_LENGTH;
+ break;
+ case NOTIFICATION_DATA:
+ header_length = NOTIFY_PAYLOAD_HEADER_LENGTH +
+ this->last_spi_size;
+ break;
+ case NONCE_DATA:
+ header_length = NONCE_PAYLOAD_HEADER_LENGTH;
+ break;
+ case ID_DATA:
+ header_length = ID_PAYLOAD_HEADER_LENGTH;
+ break;
+ case AUTH_DATA:
+ header_length = AUTH_PAYLOAD_HEADER_LENGTH;
+ break;
+ case CERT_DATA:
+ header_length = CERT_PAYLOAD_HEADER_LENGTH;
+ break;
+ case CERTREQ_DATA:
+ header_length = CERTREQ_PAYLOAD_HEADER_LENGTH;
+ break;
+ case SPIS:
+ header_length = DELETE_PAYLOAD_HEADER_LENGTH;
+ break;
+ case VID_DATA:
+ header_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH;
+ break;
+ case CONFIGURATION_ATTRIBUTE_VALUE:
+ header_length = CONFIGURATION_ATTRIBUTE_HEADER_LENGTH;
+ break;
+ case EAP_DATA:
+ header_length = EAP_PAYLOAD_HEADER_LENGTH;
+ break;
+ default:
+ break;
+ }
+ generate_from_chunk(this, rules[i].offset);
+
+ payload_length_position_offset =
+ this->last_payload_length_position_offset;
+
+ length_of_payload = header_length +
+ ((chunk_t *)(this->data_struct + rules[i].offset))->len;
+
+ length_in_network_order = htons(length_of_payload);
+ write_bytes_to_buffer_at_offset(this, &length_in_network_order,
+ sizeof(u_int16_t), payload_length_position_offset);
+ break;
+ }
+ case PROPOSALS:
+ {
+ 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;
+ linked_list_t *proposals = *((linked_list_t **)
+ (this->data_struct + rules[i].offset));
+ iterator_t *iterator;
+ payload_t *current_proposal;
+
+ iterator = proposals->create_iterator(proposals,TRUE);
+ while (iterator->iterate(iterator, (void**)&current_proposal))
+ {
+ u_int32_t before_generate_position_offset;
+ u_int32_t after_generate_position_offset;
+
+ before_generate_position_offset = get_offset(this);
+ generate_payload(this, current_proposal);
+ after_generate_position_offset = get_offset(this);
+ length_of_sa_payload += (after_generate_position_offset -
+ before_generate_position_offset);
+ }
+ iterator->destroy(iterator);
+
+ int16_val = htons(length_of_sa_payload);
+ write_bytes_to_buffer_at_offset(this, &int16_val,
+ sizeof(u_int16_t),payload_length_position_offset);
+ break;
+ }
+ case TRANSFORMS:
+ {
+ 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));
+ iterator_t *iterator;
+ payload_t *current_transform;
+
+ iterator = transforms->create_iterator(transforms,TRUE);
+ while (iterator->iterate(iterator, (void**)&current_transform))
+ {
+ u_int32_t before_generate_position_offset;
+ u_int32_t after_generate_position_offset;
+
+ before_generate_position_offset = get_offset(this);
+ generate_payload(this, current_transform);
+ after_generate_position_offset = get_offset(this);
+
+ length_of_proposal += (after_generate_position_offset -
+ before_generate_position_offset);
+ }
+ iterator->destroy(iterator);
+
+ int16_val = htons(length_of_proposal);
+ write_bytes_to_buffer_at_offset(this, &int16_val,
+ sizeof(u_int16_t), payload_length_position_offset);
+ break;
+ }
+ case TRANSFORM_ATTRIBUTES:
+ {
+ 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));
+ iterator_t *iterator;
+ payload_t *current_attribute;
+
+ iterator = transform_attributes->create_iterator(
+ transform_attributes, TRUE);
+ while (iterator->iterate(iterator, (void**)&current_attribute))
+ {
+ u_int32_t before_generate_position_offset;
+ u_int32_t after_generate_position_offset;
+
+ before_generate_position_offset = get_offset(this);
+ generate_payload(this, current_attribute);
+ after_generate_position_offset = get_offset(this);
+
+ length_of_transform += (after_generate_position_offset -
+ before_generate_position_offset);
+ }
+
+ iterator->destroy(iterator);
+
+ int16_val = htons(length_of_transform);
+ write_bytes_to_buffer_at_offset(this, &int16_val,
+ sizeof(u_int16_t),transform_length_position_offset);
+ break;
+ }
+ case CONFIGURATION_ATTRIBUTES:
+ {
+ u_int32_t configurations_length_position_offset =
+ this->last_payload_length_position_offset;
+ u_int16_t length_of_configurations = CP_PAYLOAD_HEADER_LENGTH;
+ u_int16_t int16_val;
+ linked_list_t *configuration_attributes = *((linked_list_t **)
+ (this->data_struct + rules[i].offset));
+ iterator_t *iterator;
+ payload_t *current_attribute;
+
+ iterator = configuration_attributes->create_iterator(
+ configuration_attributes,TRUE);
+ while (iterator->iterate(iterator, (void**)&current_attribute))
+ {
+ u_int32_t before_generate_position_offset;
+ u_int32_t after_generate_position_offset;
+
+ before_generate_position_offset = get_offset(this);
+ generate_payload(this, current_attribute);
+ after_generate_position_offset = get_offset(this);
+
+ length_of_configurations += after_generate_position_offset -
+ before_generate_position_offset;
+ }
+
+ iterator->destroy(iterator);
+
+ int16_val = htons(length_of_configurations);
+ write_bytes_to_buffer_at_offset(this, &int16_val,
+ sizeof(u_int16_t),configurations_length_position_offset);
+ break;
+ }
+ case ATTRIBUTE_FORMAT:
+ {
+ 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)
+ {
+ 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
+ {
+ generate_u_int_type(this, U_INT_16, rules[i].offset);
+ }
+ break;
+ }
+ case ATTRIBUTE_VALUE:
+ {
+ if (this->attribute_format == FALSE)
+ {
+ DBG2(DBG_ENC, "attribute value has not fixed size");
+ /* the attribute value is generated */
+ generate_from_chunk(this, rules[i].offset);
+ }
+ break;
+ }
+ case TRAFFIC_SELECTORS:
+ {
+ u_int32_t payload_length_position_offset =
+ this->last_payload_length_position_offset;
+ u_int16_t length_of_ts_payload = TS_PAYLOAD_HEADER_LENGTH;
+ u_int16_t int16_val;
+ linked_list_t *traffic_selectors = *((linked_list_t **)
+ (this->data_struct + rules[i].offset));
+ iterator_t *iterator;
+ payload_t *current_tss;
+
+ iterator = traffic_selectors->create_iterator(
+ traffic_selectors,TRUE);
+ while (iterator->iterate(iterator, (void **)&current_tss))
+ {
+ u_int32_t before_generate_position_offset;
+ u_int32_t after_generate_position_offset;
+
+ before_generate_position_offset = get_offset(this);
+ generate_payload(this, current_tss);
+ after_generate_position_offset = get_offset(this);
+
+ length_of_ts_payload += (after_generate_position_offset -
+ before_generate_position_offset);
+ }
+ iterator->destroy(iterator);
+
+ int16_val = htons(length_of_ts_payload);
+ write_bytes_to_buffer_at_offset(this, &int16_val,
+ sizeof(u_int16_t),payload_length_position_offset);
+ break;
+ }
+
+ case ENCRYPTED_DATA:
+ {
+ generate_from_chunk(this, rules[i].offset);
+ break;
+ }
+ default:
+ DBG1(DBG_ENC, "field type %N is not supported",
+ encoding_type_names, rules[i].type);
+ return;
+ }
+ }
+ DBG2(DBG_ENC, "generating %N payload finished",
+ payload_type_names, payload_type);
+ DBG3(DBG_ENC, "generated data for this payload %b",
+ this->buffer + offset_start,
+ this->out_position - this->buffer - offset_start);
+}
+
+/**
+ * Implementation of generator_t.destroy.
+ */
+static status_t destroy(private_generator_t *this)
+{
+ free(this->buffer);
+ free(this);
+ return SUCCESS;
+}
+
+/*
+ * Described in header
+ */
+generator_t *generator_create()
+{
+ private_generator_t *this;
+
+ this = malloc_thing(private_generator_t);
+
+ /* initiate public functions */
+ this->public.generate_payload = (void(*)(generator_t*, payload_t *))generate_payload;
+ this->public.destroy = (void(*)(generator_t*)) destroy;
+ this->public.write_to_chunk = (void (*) (generator_t *,chunk_t *))write_to_chunk;
+
+ /* allocate memory for buffer */
+ this->buffer = malloc(GENERATOR_DATA_BUFFER_SIZE);
+
+ /* 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->attribute_format = FALSE;
+ this->attribute_length = 0;
+
+ return &(this->public);
+}
+
diff --git a/src/libcharon/encoding/generator.h b/src/libcharon/encoding/generator.h
new file mode 100644
index 000000000..2221c84af
--- /dev/null
+++ b/src/libcharon/encoding/generator.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup generator generator
+ * @{ @ingroup encoding
+ */
+
+#ifndef GENERATOR_H_
+#define GENERATOR_H_
+
+typedef struct generator_t generator_t;
+
+#include <library.h>
+#include <encoding/payloads/encodings.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * Generating is done in a data buffer.
+ * This is the start size of this buffer in bytes.
+ */
+#define GENERATOR_DATA_BUFFER_SIZE 500
+
+/**
+ * Number of bytes to increase the buffer, if it is too small.
+ */
+#define GENERATOR_DATA_BUFFER_INCREASE_VALUE 500
+
+
+/**
+ * A generator_t class used to generate IKEv2 payloads.
+ *
+ * After creation, multiple payloads can be generated with the generate_payload
+ * method. The generated bytes are appended. After all payloads are added,
+ * the write_to_chunk method writes out all generated data since
+ * the creation of the generator. After that, the generator must be destroyed.
+ * The generater uses a set of encoding rules, which it can get from
+ * the supplied payload. With this rules, the generater can generate
+ * the payload and all substructures automatically.
+ */
+struct generator_t {
+
+ /**
+ * Generates a specific payload from given payload object.
+ *
+ * Remember: Header and substructures are also handled as payloads.
+ *
+ * @param payload interface payload_t implementing object
+ */
+ void (*generate_payload) (generator_t *this,payload_t *payload);
+
+ /**
+ * Writes all generated data of the generator to a chunk.
+ *
+ * @param data chunk to write the data to
+ */
+ void (*write_to_chunk) (generator_t *this,chunk_t *data);
+
+ /**
+ * Destroys a generator_t object.
+ */
+ void (*destroy) (generator_t *this);
+};
+
+/**
+ * Constructor to create a generator.
+ *
+ * @return generator_t object.
+ */
+generator_t *generator_create(void);
+
+#endif /** GENERATOR_H_ @}*/
diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c
new file mode 100644
index 000000000..397a3c609
--- /dev/null
+++ b/src/libcharon/encoding/message.c
@@ -0,0 +1,1726 @@
+/*
+ * Copyright (C) 2006-2007 Tobias Brunner
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005 Jan Hutter
+ * 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 "message.h"
+
+#include <library.h>
+#include <daemon.h>
+#include <sa/ike_sa_id.h>
+#include <encoding/generator.h>
+#include <encoding/parser.h>
+#include <utils/linked_list.h>
+#include <encoding/payloads/encodings.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/encryption_payload.h>
+#include <encoding/payloads/unknown_payload.h>
+
+/**
+ * Max number of notify payloads per IKEv2 Message
+ */
+#define MAX_NOTIFY_PAYLOADS 20
+
+/**
+ * Max number of delete payloads per IKEv2 Message
+ */
+#define MAX_DELETE_PAYLOADS 20
+
+
+typedef struct payload_rule_t payload_rule_t;
+
+/**
+ * A payload rule defines the rules for a payload
+ * in a specific message rule. It defines if and how
+ * many times a payload must/can occur in a message
+ * and if it must be encrypted.
+ */
+struct payload_rule_t {
+ /**
+ * 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;
+
+ /**
+ * TRUE if payload must be encrypted
+ */
+ bool encrypted;
+
+ /**
+ * If this payload occurs, the message rule is
+ * fullfilled in any case. This applies e.g. to
+ * notify_payloads.
+ */
+ bool sufficient;
+};
+
+typedef struct payload_order_t payload_order_t;
+
+/**
+ * payload ordering structure allows us to reorder payloads according to RFC.
+ */
+struct payload_order_t {
+
+ /**
+ * payload type
+ */
+ payload_type_t type;
+
+ /**
+ * notify type, if payload == NOTIFY
+ */
+ notify_type_t notify;
+};
+
+
+typedef struct message_rule_t message_rule_t;
+
+/**
+ * A message rule defines the kind of a message,
+ * if it has encrypted contents and a list
+ * of payload ordering rules and payload parsing rules.
+ */
+struct message_rule_t {
+ /**
+ * Type of message.
+ */
+ exchange_type_t exchange_type;
+
+ /**
+ * Is message a request or response.
+ */
+ bool is_request;
+
+ /**
+ * Message contains encrypted content.
+ */
+ bool encrypted_content;
+
+ /**
+ * Number of payload rules which will follow
+ */
+ int payload_rule_count;
+
+ /**
+ * Pointer to first payload rule
+ */
+ payload_rule_t *payload_rules;
+
+ /**
+ * Number of payload order rules
+ */
+ int payload_order_count;
+
+ /**
+ * payload ordering rules
+ */
+ payload_order_t *payload_order;
+};
+
+/**
+ * Message rule for IKE_SA_INIT from initiator.
+ */
+static payload_rule_t ike_sa_init_i_payload_rules[] = {
+/* payload type min max encr suff */
+ {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE},
+ {SECURITY_ASSOCIATION, 1, 1, FALSE, FALSE},
+ {KEY_EXCHANGE, 1, 1, FALSE, FALSE},
+ {NONCE, 1, 1, FALSE, FALSE},
+ {VENDOR_ID, 0, 10, FALSE, FALSE},
+};
+
+/**
+ * payload order for IKE_SA_INIT initiator
+ */
+static payload_order_t ike_sa_init_i_payload_order[] = {
+/* payload type notify type */
+ {NOTIFY, COOKIE},
+ {SECURITY_ASSOCIATION, 0},
+ {KEY_EXCHANGE, 0},
+ {NONCE, 0},
+ {NOTIFY, NAT_DETECTION_SOURCE_IP},
+ {NOTIFY, NAT_DETECTION_DESTINATION_IP},
+ {NOTIFY, 0},
+ {VENDOR_ID, 0},
+};
+
+/**
+ * Message rule for IKE_SA_INIT from responder.
+ */
+static payload_rule_t ike_sa_init_r_payload_rules[] = {
+/* payload type min max encr suff */
+ {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, FALSE, TRUE},
+ {SECURITY_ASSOCIATION, 1, 1, FALSE, FALSE},
+ {KEY_EXCHANGE, 1, 1, FALSE, FALSE},
+ {NONCE, 1, 1, FALSE, FALSE},
+ {VENDOR_ID, 0, 10, FALSE, FALSE},
+};
+
+/**
+ * payload order for IKE_SA_INIT responder
+ */
+static payload_order_t ike_sa_init_r_payload_order[] = {
+/* payload type notify type */
+ {SECURITY_ASSOCIATION, 0},
+ {KEY_EXCHANGE, 0},
+ {NONCE, 0},
+ {NOTIFY, NAT_DETECTION_SOURCE_IP},
+ {NOTIFY, NAT_DETECTION_DESTINATION_IP},
+ {NOTIFY, HTTP_CERT_LOOKUP_SUPPORTED},
+ {CERTIFICATE_REQUEST, 0},
+ {NOTIFY, 0},
+ {VENDOR_ID, 0},
+};
+
+/**
+ * Message rule for IKE_AUTH from initiator.
+ */
+static payload_rule_t ike_auth_i_payload_rules[] = {
+/* payload type min max encr suff */
+ {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE},
+ {EXTENSIBLE_AUTHENTICATION, 0, 1, TRUE, TRUE},
+ {AUTHENTICATION, 0, 1, TRUE, TRUE},
+ {ID_INITIATOR, 0, 1, TRUE, FALSE},
+ {CERTIFICATE, 0, 4, TRUE, FALSE},
+ {CERTIFICATE_REQUEST, 0, 1, TRUE, FALSE},
+ {ID_RESPONDER, 0, 1, TRUE, FALSE},
+#ifdef ME
+ {SECURITY_ASSOCIATION, 0, 1, TRUE, FALSE},
+ {TRAFFIC_SELECTOR_INITIATOR, 0, 1, TRUE, FALSE},
+ {TRAFFIC_SELECTOR_RESPONDER, 0, 1, TRUE, FALSE},
+#else
+ {SECURITY_ASSOCIATION, 0, 1, TRUE, FALSE},
+ {TRAFFIC_SELECTOR_INITIATOR, 0, 1, TRUE, FALSE},
+ {TRAFFIC_SELECTOR_RESPONDER, 0, 1, TRUE, FALSE},
+#endif /* ME */
+ {CONFIGURATION, 0, 1, TRUE, FALSE},
+ {VENDOR_ID, 0, 10, TRUE, FALSE},
+};
+
+/**
+ * payload order for IKE_AUTH initiator
+ */
+static payload_order_t ike_auth_i_payload_order[] = {
+/* payload type notify type */
+ {ID_INITIATOR, 0},
+ {CERTIFICATE, 0},
+ {NOTIFY, INITIAL_CONTACT},
+ {NOTIFY, HTTP_CERT_LOOKUP_SUPPORTED},
+ {CERTIFICATE_REQUEST, 0},
+ {ID_RESPONDER, 0},
+ {AUTHENTICATION, 0},
+ {EXTENSIBLE_AUTHENTICATION, 0},
+ {CONFIGURATION, 0},
+ {NOTIFY, IPCOMP_SUPPORTED},
+ {NOTIFY, USE_TRANSPORT_MODE},
+ {NOTIFY, ESP_TFC_PADDING_NOT_SUPPORTED},
+ {NOTIFY, NON_FIRST_FRAGMENTS_ALSO},
+ {SECURITY_ASSOCIATION, 0},
+ {TRAFFIC_SELECTOR_INITIATOR, 0},
+ {TRAFFIC_SELECTOR_RESPONDER, 0},
+ {NOTIFY, MOBIKE_SUPPORTED},
+ {NOTIFY, ADDITIONAL_IP4_ADDRESS},
+ {NOTIFY, ADDITIONAL_IP6_ADDRESS},
+ {NOTIFY, NO_ADDITIONAL_ADDRESSES},
+ {NOTIFY, 0},
+ {VENDOR_ID, 0},
+};
+
+/**
+ * Message rule for IKE_AUTH from responder.
+ */
+static payload_rule_t ike_auth_r_payload_rules[] = {
+/* payload type min max encr suff */
+ {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE},
+ {EXTENSIBLE_AUTHENTICATION, 0, 1, TRUE, TRUE},
+ {AUTHENTICATION, 0, 1, TRUE, TRUE},
+ {CERTIFICATE, 0, 4, TRUE, FALSE},
+ {ID_RESPONDER, 0, 1, TRUE, FALSE},
+ {SECURITY_ASSOCIATION, 0, 1, TRUE, FALSE},
+ {TRAFFIC_SELECTOR_INITIATOR, 0, 1, TRUE, FALSE},
+ {TRAFFIC_SELECTOR_RESPONDER, 0, 1, TRUE, FALSE},
+ {CONFIGURATION, 0, 1, TRUE, FALSE},
+ {VENDOR_ID, 0, 10, TRUE, FALSE},
+};
+
+/**
+ * payload order for IKE_AUTH responder
+ */
+static payload_order_t ike_auth_r_payload_order[] = {
+/* payload type notify type */
+ {ID_RESPONDER, 0},
+ {CERTIFICATE, 0},
+ {AUTHENTICATION, 0},
+ {EXTENSIBLE_AUTHENTICATION, 0},
+ {CONFIGURATION, 0},
+ {NOTIFY, IPCOMP_SUPPORTED},
+ {NOTIFY, USE_TRANSPORT_MODE},
+ {NOTIFY, ESP_TFC_PADDING_NOT_SUPPORTED},
+ {NOTIFY, NON_FIRST_FRAGMENTS_ALSO},
+ {SECURITY_ASSOCIATION, 0},
+ {TRAFFIC_SELECTOR_INITIATOR, 0},
+ {TRAFFIC_SELECTOR_RESPONDER, 0},
+ {NOTIFY, AUTH_LIFETIME},
+ {NOTIFY, MOBIKE_SUPPORTED},
+ {NOTIFY, ADDITIONAL_IP4_ADDRESS},
+ {NOTIFY, ADDITIONAL_IP6_ADDRESS},
+ {NOTIFY, NO_ADDITIONAL_ADDRESSES},
+ {NOTIFY, 0},
+ {VENDOR_ID, 0},
+};
+
+/**
+ * Message rule for INFORMATIONAL from initiator.
+ */
+static payload_rule_t informational_i_payload_rules[] = {
+/* payload type min max encr suff */
+ {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE},
+ {CONFIGURATION, 0, 1, TRUE, FALSE},
+ {DELETE, 0, MAX_DELETE_PAYLOADS, TRUE, FALSE},
+ {VENDOR_ID, 0, 10, TRUE, FALSE},
+};
+
+/**
+ * payload order for INFORMATIONAL initiator
+ */
+static payload_order_t informational_i_payload_order[] = {
+/* payload type notify type */
+ {NOTIFY, UPDATE_SA_ADDRESSES},
+ {NOTIFY, NAT_DETECTION_SOURCE_IP},
+ {NOTIFY, NAT_DETECTION_DESTINATION_IP},
+ {NOTIFY, COOKIE2},
+ {NOTIFY, 0},
+ {DELETE, 0},
+ {CONFIGURATION, 0},
+};
+
+/**
+ * Message rule for INFORMATIONAL from responder.
+ */
+static payload_rule_t informational_r_payload_rules[] = {
+/* payload type min max encr suff */
+ {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE},
+ {CONFIGURATION, 0, 1, TRUE, FALSE},
+ {DELETE, 0, MAX_DELETE_PAYLOADS, TRUE, FALSE},
+ {VENDOR_ID, 0, 10, TRUE, FALSE},
+};
+
+/**
+ * payload order for INFORMATIONAL responder
+ */
+static payload_order_t informational_r_payload_order[] = {
+/* payload type notify type */
+ {NOTIFY, UPDATE_SA_ADDRESSES},
+ {NOTIFY, NAT_DETECTION_SOURCE_IP},
+ {NOTIFY, NAT_DETECTION_DESTINATION_IP},
+ {NOTIFY, COOKIE2},
+ {NOTIFY, 0},
+ {DELETE, 0},
+ {CONFIGURATION, 0},
+};
+
+/**
+ * Message rule for CREATE_CHILD_SA from initiator.
+ */
+static payload_rule_t create_child_sa_i_payload_rules[] = {
+/* payload type min max encr suff */
+ {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE},
+ {SECURITY_ASSOCIATION, 1, 1, TRUE, FALSE},
+ {NONCE, 1, 1, TRUE, FALSE},
+ {KEY_EXCHANGE, 0, 1, TRUE, FALSE},
+ {TRAFFIC_SELECTOR_INITIATOR, 0, 1, TRUE, FALSE},
+ {TRAFFIC_SELECTOR_RESPONDER, 0, 1, TRUE, FALSE},
+ {CONFIGURATION, 0, 1, TRUE, FALSE},
+ {VENDOR_ID, 0, 10, TRUE, FALSE},
+};
+
+/**
+ * payload order for CREATE_CHILD_SA from initiator.
+ */
+static payload_order_t create_child_sa_i_payload_order[] = {
+/* payload type notify type */
+ {NOTIFY, REKEY_SA},
+ {NOTIFY, IPCOMP_SUPPORTED},
+ {NOTIFY, USE_TRANSPORT_MODE},
+ {NOTIFY, ESP_TFC_PADDING_NOT_SUPPORTED},
+ {NOTIFY, NON_FIRST_FRAGMENTS_ALSO},
+ {SECURITY_ASSOCIATION, 0},
+ {NONCE, 0},
+ {KEY_EXCHANGE, 0},
+ {TRAFFIC_SELECTOR_INITIATOR, 0},
+ {TRAFFIC_SELECTOR_RESPONDER, 0},
+ {NOTIFY, 0},
+};
+
+/**
+ * Message rule for CREATE_CHILD_SA from responder.
+ */
+static payload_rule_t create_child_sa_r_payload_rules[] = {
+/* payload type min max encr suff */
+ {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE},
+ {SECURITY_ASSOCIATION, 1, 1, TRUE, FALSE},
+ {NONCE, 1, 1, TRUE, FALSE},
+ {KEY_EXCHANGE, 0, 1, TRUE, FALSE},
+ {TRAFFIC_SELECTOR_INITIATOR, 0, 1, TRUE, FALSE},
+ {TRAFFIC_SELECTOR_RESPONDER, 0, 1, TRUE, FALSE},
+ {CONFIGURATION, 0, 1, TRUE, FALSE},
+ {VENDOR_ID, 0, 10, TRUE, FALSE},
+};
+
+/**
+ * payload order for CREATE_CHILD_SA from responder.
+ */
+static payload_order_t create_child_sa_r_payload_order[] = {
+/* payload type notify type */
+ {NOTIFY, IPCOMP_SUPPORTED},
+ {NOTIFY, USE_TRANSPORT_MODE},
+ {NOTIFY, ESP_TFC_PADDING_NOT_SUPPORTED},
+ {NOTIFY, NON_FIRST_FRAGMENTS_ALSO},
+ {SECURITY_ASSOCIATION, 0},
+ {NONCE, 0},
+ {KEY_EXCHANGE, 0},
+ {TRAFFIC_SELECTOR_INITIATOR, 0},
+ {TRAFFIC_SELECTOR_RESPONDER, 0},
+ {NOTIFY, ADDITIONAL_TS_POSSIBLE},
+ {NOTIFY, 0},
+};
+
+#ifdef ME
+/**
+ * Message rule for ME_CONNECT from initiator.
+ */
+static payload_rule_t me_connect_i_payload_rules[] = {
+/* payload type min max encr suff */
+ {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE},
+ {ID_PEER, 1, 1, TRUE, FALSE},
+ {VENDOR_ID, 0, 10, TRUE, FALSE}
+};
+
+/**
+ * payload order for ME_CONNECT from initiator.
+ */
+static payload_order_t me_connect_i_payload_order[] = {
+/* payload type notify type */
+ {NOTIFY, 0},
+ {ID_PEER, 0},
+ {VENDOR_ID, 0},
+};
+
+/**
+ * Message rule for ME_CONNECT from responder.
+ */
+static payload_rule_t me_connect_r_payload_rules[] = {
+/* payload type min max encr suff */
+ {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE},
+ {VENDOR_ID, 0, 10, TRUE, FALSE}
+};
+
+/**
+ * payload order for ME_CONNECT from responder.
+ */
+static payload_order_t me_connect_r_payload_order[] = {
+/* payload type notify type */
+ {NOTIFY, 0},
+ {VENDOR_ID, 0},
+};
+#endif /* ME */
+
+/**
+ * Message rules, defines allowed payloads.
+ */
+static message_rule_t message_rules[] = {
+ {IKE_SA_INIT, TRUE, FALSE,
+ (sizeof(ike_sa_init_i_payload_rules)/sizeof(payload_rule_t)),
+ ike_sa_init_i_payload_rules,
+ (sizeof(ike_sa_init_i_payload_order)/sizeof(payload_order_t)),
+ ike_sa_init_i_payload_order,
+ },
+ {IKE_SA_INIT, FALSE, FALSE,
+ (sizeof(ike_sa_init_r_payload_rules)/sizeof(payload_rule_t)),
+ ike_sa_init_r_payload_rules,
+ (sizeof(ike_sa_init_r_payload_order)/sizeof(payload_order_t)),
+ ike_sa_init_r_payload_order,
+ },
+ {IKE_AUTH, TRUE, TRUE,
+ (sizeof(ike_auth_i_payload_rules)/sizeof(payload_rule_t)),
+ ike_auth_i_payload_rules,
+ (sizeof(ike_auth_i_payload_order)/sizeof(payload_order_t)),
+ ike_auth_i_payload_order,
+ },
+ {IKE_AUTH, FALSE, TRUE,
+ (sizeof(ike_auth_r_payload_rules)/sizeof(payload_rule_t)),
+ ike_auth_r_payload_rules,
+ (sizeof(ike_auth_r_payload_order)/sizeof(payload_order_t)),
+ ike_auth_r_payload_order,
+ },
+ {INFORMATIONAL, TRUE, TRUE,
+ (sizeof(informational_i_payload_rules)/sizeof(payload_rule_t)),
+ informational_i_payload_rules,
+ (sizeof(informational_i_payload_order)/sizeof(payload_order_t)),
+ informational_i_payload_order,
+ },
+ {INFORMATIONAL, FALSE, TRUE,
+ (sizeof(informational_r_payload_rules)/sizeof(payload_rule_t)),
+ informational_r_payload_rules,
+ (sizeof(informational_r_payload_order)/sizeof(payload_order_t)),
+ informational_r_payload_order,
+ },
+ {CREATE_CHILD_SA, TRUE, TRUE,
+ (sizeof(create_child_sa_i_payload_rules)/sizeof(payload_rule_t)),
+ create_child_sa_i_payload_rules,
+ (sizeof(create_child_sa_i_payload_order)/sizeof(payload_order_t)),
+ create_child_sa_i_payload_order,
+ },
+ {CREATE_CHILD_SA, FALSE, TRUE,
+ (sizeof(create_child_sa_r_payload_rules)/sizeof(payload_rule_t)),
+ create_child_sa_r_payload_rules,
+ (sizeof(create_child_sa_r_payload_order)/sizeof(payload_order_t)),
+ create_child_sa_r_payload_order,
+ },
+#ifdef ME
+ {ME_CONNECT, TRUE, TRUE,
+ (sizeof(me_connect_i_payload_rules)/sizeof(payload_rule_t)),
+ me_connect_i_payload_rules,
+ (sizeof(me_connect_i_payload_order)/sizeof(payload_order_t)),
+ me_connect_i_payload_order,
+ },
+ {ME_CONNECT, FALSE, TRUE,
+ (sizeof(me_connect_r_payload_rules)/sizeof(payload_rule_t)),
+ me_connect_r_payload_rules,
+ (sizeof(me_connect_r_payload_order)/sizeof(payload_order_t)),
+ me_connect_r_payload_order,
+ },
+#endif /* ME */
+};
+
+
+typedef struct private_message_t private_message_t;
+
+/**
+ * Private data of an message_t object.
+ */
+struct private_message_t {
+
+ /**
+ * 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 a request, FALSE if a 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;
+
+ /**
+ * The message rule for this message instance
+ */
+ message_rule_t *message_rule;
+};
+
+/**
+ * Implementation of private_message_t.set_message_rule.
+ */
+static status_t set_message_rule(private_message_t *this)
+{
+ int i;
+
+ for (i = 0; i < (sizeof(message_rules) / sizeof(message_rule_t)); i++)
+ {
+ if ((this->exchange_type == message_rules[i].exchange_type) &&
+ (this->is_request == message_rules[i].is_request))
+ {
+ /* found rule for given exchange_type*/
+ this->message_rule = &(message_rules[i]);
+ return SUCCESS;
+ }
+ }
+ this->message_rule = NULL;
+ return NOT_FOUND;
+}
+
+/**
+ * Implementation of private_message_t.get_payload_rule.
+ */
+static status_t get_payload_rule(private_message_t *this,
+ payload_type_t payload_type, payload_rule_t **payload_rule)
+{
+ int i;
+
+ for (i = 0; i < this->message_rule->payload_rule_count;i++)
+ {
+ if (this->message_rule->payload_rules[i].payload_type == payload_type)
+ {
+ *payload_rule = &(this->message_rule->payload_rules[i]);
+ return SUCCESS;
+ }
+ }
+
+ *payload_rule = NULL;
+ return NOT_FOUND;
+}
+
+/**
+ * Implementation of message_t.set_ike_sa_id.
+ */
+static void set_ike_sa_id(private_message_t *this,ike_sa_id_t *ike_sa_id)
+{
+ DESTROY_IF(this->ike_sa_id);
+ this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
+}
+
+/**
+ * Implementation of message_t.get_ike_sa_id.
+ */
+static ike_sa_id_t* get_ike_sa_id(private_message_t *this)
+{
+ return this->ike_sa_id;
+}
+
+/**
+ * Implementation of message_t.set_message_id.
+ */
+static void set_message_id(private_message_t *this,u_int32_t message_id)
+{
+ this->message_id = message_id;
+}
+
+/**
+ * Implementation of message_t.get_message_id.
+ */
+static u_int32_t get_message_id(private_message_t *this)
+{
+ return this->message_id;
+}
+
+/**
+ * Implementation of message_t.get_initiator_spi.
+ */
+static u_int64_t get_initiator_spi(private_message_t *this)
+{
+ return (this->ike_sa_id->get_initiator_spi(this->ike_sa_id));
+}
+
+/**
+ * Implementation of message_t.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));
+}
+
+/**
+ * Implementation of message_t.set_major_version.
+ */
+static void set_major_version(private_message_t *this,u_int8_t major_version)
+{
+ this->major_version = major_version;
+}
+
+/**
+ * Implementation of message_t.set_major_version.
+ */
+static u_int8_t get_major_version(private_message_t *this)
+{
+ return this->major_version;
+}
+
+/**
+ * Implementation of message_t.set_minor_version.
+ */
+static void set_minor_version(private_message_t *this,u_int8_t minor_version)
+{
+ this->minor_version = minor_version;
+}
+
+/**
+ * Implementation of message_t.get_minor_version.
+ */
+static u_int8_t get_minor_version(private_message_t *this)
+{
+ return this->minor_version;
+}
+
+/**
+ * Implementation of message_t.set_exchange_type.
+ */
+static void set_exchange_type(private_message_t *this,
+ exchange_type_t exchange_type)
+{
+ this->exchange_type = exchange_type;
+}
+
+/**
+ * Implementation of message_t.get_exchange_type.
+ */
+static exchange_type_t get_exchange_type(private_message_t *this)
+{
+ return this->exchange_type;
+}
+
+/**
+ * Implementation of message_t.get_first_payload_type.
+ */
+static payload_type_t get_first_payload_type(private_message_t *this)
+{
+ return this->first_payload;
+}
+
+/**
+ * Implementation of message_t.set_request.
+ */
+static void set_request(private_message_t *this, bool request)
+{
+ this->is_request = request;
+}
+
+/**
+ * Implementation of message_t.get_request.
+ */
+static exchange_type_t get_request(private_message_t *this)
+{
+ return this->is_request;
+}
+
+/**
+ * Is this message in an encoded form?
+ */
+static bool is_encoded(private_message_t *this)
+{
+ chunk_t data = this->packet->get_data(this->packet);
+
+ if (data.ptr == NULL)
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of message_t.add_payload.
+ */
+static void 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);
+ last_payload->set_next_type(last_payload, payload->get_type(payload));
+ }
+ else
+ {
+ this->first_payload = payload->get_type(payload);
+ }
+ payload->set_next_type(payload, NO_PAYLOAD);
+ this->payloads->insert_last(this->payloads, payload);
+
+ DBG2(DBG_ENC ,"added payload of type %N to message",
+ payload_type_names, payload->get_type(payload));
+}
+
+/**
+ * Implementation of message_t.add_notify.
+ */
+static void add_notify(private_message_t *this, bool flush, notify_type_t type,
+ chunk_t data)
+{
+ notify_payload_t *notify;
+ payload_t *payload;
+
+ if (flush)
+ {
+ while (this->payloads->remove_last(this->payloads,
+ (void**)&payload) == SUCCESS)
+ {
+ payload->destroy(payload);
+ }
+ }
+ notify = notify_payload_create();
+ notify->set_notify_type(notify, type);
+ notify->set_notification_data(notify, data);
+ add_payload(this, (payload_t*)notify);
+}
+
+/**
+ * Implementation of message_t.set_source.
+ */
+static void set_source(private_message_t *this, host_t *host)
+{
+ this->packet->set_source(this->packet, host);
+}
+
+/**
+ * Implementation of message_t.set_destination.
+ */
+static void set_destination(private_message_t *this, host_t *host)
+{
+ this->packet->set_destination(this->packet, host);
+}
+
+/**
+ * Implementation of message_t.get_source.
+ */
+static host_t* get_source(private_message_t *this)
+{
+ return this->packet->get_source(this->packet);
+}
+
+/**
+ * Implementation of message_t.get_destination.
+ */
+static host_t * get_destination(private_message_t *this)
+{
+ return this->packet->get_destination(this->packet);
+}
+
+/**
+ * Implementation of message_t.create_payload_enumerator.
+ */
+static enumerator_t *create_payload_enumerator(private_message_t *this)
+{
+ return this->payloads->create_enumerator(this->payloads);
+}
+
+/**
+ * Implementation of message_t.get_payload.
+ */
+static payload_t *get_payload(private_message_t *this, payload_type_t type)
+{
+ payload_t *current, *found = NULL;
+ enumerator_t *enumerator;
+
+ enumerator = create_payload_enumerator(this);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current->get_type(current) == type)
+ {
+ found = current;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+/**
+ * Implementation of message_t.get_notify
+ */
+static notify_payload_t* get_notify(private_message_t *this, notify_type_t type)
+{
+ enumerator_t *enumerator;
+ notify_payload_t *notify = NULL;
+ payload_t *payload;
+
+ enumerator = create_payload_enumerator(this);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == NOTIFY)
+ {
+ notify = (notify_payload_t*)payload;
+ if (notify->get_notify_type(notify) == type)
+ {
+ break;
+ }
+ notify = NULL;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return notify;
+}
+
+/**
+ * get a string representation of the message
+ */
+static char* get_string(private_message_t *this, char *buf, int len)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+ int written;
+ char *pos = buf;
+
+ memset(buf, 0, len);
+ len--;
+
+ written = snprintf(pos, len, "%N %s %d [",
+ exchange_type_names, this->exchange_type,
+ this->is_request ? "request" : "response",
+ this->message_id);
+ if (written >= len || written < 0)
+ {
+ return "";
+ }
+ pos += written;
+ len -= written;
+
+ enumerator = create_payload_enumerator(this);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ written = snprintf(pos, len, " %N", payload_type_short_names,
+ payload->get_type(payload));
+ if (written >= len || written < 0)
+ {
+ return buf;
+ }
+ pos += written;
+ len -= written;
+ if (payload->get_type(payload) == NOTIFY)
+ {
+ notify_payload_t *notify = (notify_payload_t*)payload;
+ written = snprintf(pos, len, "(%N)", notify_type_short_names,
+ notify->get_notify_type(notify));
+ if (written >= len || written < 0)
+ {
+ return buf;
+ }
+ pos += written;
+ len -= written;
+ }
+ if (payload->get_type(payload) == EXTENSIBLE_AUTHENTICATION)
+ {
+ eap_payload_t *eap = (eap_payload_t*)payload;
+ u_int32_t vendor;
+ eap_type_t type;
+ char method[64] = "";
+
+ type = eap->get_type(eap, &vendor);
+ if (type)
+ {
+ if (vendor)
+ {
+ snprintf(method, sizeof(method), "/%d-%d", type, vendor);
+ }
+ else
+ {
+ snprintf(method, sizeof(method), "/%N",
+ eap_type_short_names, type);
+ }
+ }
+ written = snprintf(pos, len, "/%N%s", eap_code_short_names,
+ eap->get_code(eap), method);
+ if (written >= len || written < 0)
+ {
+ return buf;
+ }
+ pos += written;
+ len -= written;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* remove last space */
+ snprintf(pos, len, " ]");
+ return buf;
+}
+
+/**
+ * reorder payloads depending on reordering rules
+ */
+static void order_payloads(private_message_t *this)
+{
+ linked_list_t *list;
+ payload_t *payload;
+ int i;
+
+ /* move to temp list */
+ list = linked_list_create();
+ while (this->payloads->remove_last(this->payloads,
+ (void**)&payload) == SUCCESS)
+ {
+ list->insert_first(list, payload);
+ }
+ /* for each rule, ... */
+ for (i = 0; i < this->message_rule->payload_order_count; i++)
+ {
+ enumerator_t *enumerator;
+ notify_payload_t *notify;
+ payload_order_t order = this->message_rule->payload_order[i];
+
+ /* ... find all payload ... */
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ /* ... with that type ... */
+ if (payload->get_type(payload) == order.type)
+ {
+ notify = (notify_payload_t*)payload;
+
+ /**... and check notify for type. */
+ if (order.type != NOTIFY || order.notify == 0 ||
+ order.notify == notify->get_notify_type(notify))
+ {
+ list->remove_at(list, enumerator);
+ add_payload(this, payload);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ /* append all payloads without a rule to the end */
+ while (list->remove_last(list, (void**)&payload) == SUCCESS)
+ {
+ /* do not complain about payloads in private use space */
+ if (payload->get_type(payload) < 128)
+ {
+ DBG1(DBG_ENC, "payload %N has no ordering rule in %N %s",
+ payload_type_names, payload->get_type(payload),
+ exchange_type_names, this->message_rule->exchange_type,
+ this->message_rule->is_request ? "request" : "response");
+ }
+ add_payload(this, payload);
+ }
+ list->destroy(list);
+}
+
+/**
+ * Implementation of private_message_t.encrypt_payloads.
+ */
+static status_t encrypt_payloads(private_message_t *this,
+ crypter_t *crypter, signer_t* signer)
+{
+ encryption_payload_t *encryption;
+ linked_list_t *payloads;
+ payload_t *current;
+ status_t status;
+
+ if (!this->message_rule->encrypted_content)
+ {
+ DBG2(DBG_ENC, "message doesn't have to be encrypted");
+ /* message contains no content to encrypt */
+ return SUCCESS;
+ }
+
+ if (!crypter || !signer)
+ {
+ DBG2(DBG_ENC, "no crypter or signer specified, do not encrypt message");
+ /* message contains no content to encrypt */
+ return SUCCESS;
+ }
+
+ DBG2(DBG_ENC, "copy all payloads to a temporary list");
+ payloads = linked_list_create();
+
+ /* first copy all payloads in a temporary list */
+ while (this->payloads->get_count(this->payloads) > 0)
+ {
+ this->payloads->remove_first(this->payloads, (void**)&current);
+ payloads->insert_last(payloads, current);
+ }
+
+ encryption = encryption_payload_create();
+
+ DBG2(DBG_ENC, "check each payloads if they have to get encrypted");
+ while (payloads->get_count(payloads) > 0)
+ {
+ payload_rule_t *rule;
+ payload_type_t type;
+ bool to_encrypt = TRUE;
+
+ payloads->remove_first(payloads, (void**)&current);
+
+ type = current->get_type(current);
+ if (get_payload_rule(this, type, &rule) == SUCCESS)
+ {
+ to_encrypt = rule->encrypted;
+ }
+ if (to_encrypt)
+ {
+ DBG2(DBG_ENC, "insert payload %N to encryption payload",
+ payload_type_names, current->get_type(current));
+ encryption->add_payload(encryption, current);
+ }
+ else
+ {
+ DBG2(DBG_ENC, "insert payload %N unencrypted",
+ payload_type_names, current->get_type(current));
+ add_payload(this, (payload_t*)current);
+ }
+ }
+
+ DBG2(DBG_ENC, "encrypting encryption payload");
+ encryption->set_transforms(encryption, crypter, signer);
+ status = encryption->encrypt(encryption);
+ DBG2(DBG_ENC, "add encrypted payload to payload list");
+ add_payload(this, (payload_t*)encryption);
+
+ payloads->destroy(payloads);
+
+ return status;
+}
+
+/**
+ * Implementation of message_t.generate.
+ */
+static status_t generate(private_message_t *this, crypter_t *crypter,
+ signer_t* signer, packet_t **packet)
+{
+ generator_t *generator;
+ ike_header_t *ike_header;
+ payload_t *payload, *next_payload;
+ enumerator_t *enumerator;
+ status_t status;
+ chunk_t packet_data;
+ char str[256];
+
+ if (is_encoded(this))
+ {
+ /* already generated, return a new packet clone */
+ *packet = this->packet->clone(this->packet);
+ return SUCCESS;
+ }
+
+ if (this->exchange_type == EXCHANGE_TYPE_UNDEFINED)
+ {
+ DBG1(DBG_ENC, "exchange type is not defined");
+ return INVALID_STATE;
+ }
+
+ if (this->packet->get_source(this->packet) == NULL ||
+ this->packet->get_destination(this->packet) == NULL)
+ {
+ DBG1(DBG_ENC, "%s not defined",
+ !this->packet->get_source(this->packet) ? "source" : "destination");
+ return INVALID_STATE;
+ }
+
+ /* set the rules for this messge */
+ status = set_message_rule(this);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "no message rules specified for this message type");
+ return NOT_SUPPORTED;
+ }
+
+ order_payloads(this);
+
+ DBG1(DBG_ENC, "generating %s", get_string(this, str, sizeof(str)));
+
+ /* going to encrypt all content which have to be encrypted */
+ status = encrypt_payloads(this, crypter, signer);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "payload encryption failed");
+ return status;
+ }
+
+ /* build ike header */
+ ike_header = ike_header_create();
+
+ 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();
+
+ payload = (payload_t*)ike_header;
+
+ /* generate every payload expect last one, this is done later*/
+ enumerator = create_payload_enumerator(this);
+ while (enumerator->enumerate(enumerator, &next_payload))
+ {
+ payload->set_next_type(payload, next_payload->get_type(next_payload));
+ generator->generate_payload(generator, payload);
+ payload = next_payload;
+ }
+ enumerator->destroy(enumerator);
+
+ /* last payload has no next payload*/
+ payload->set_next_type(payload, NO_PAYLOAD);
+
+ generator->generate_payload(generator, payload);
+
+ ike_header->destroy(ike_header);
+
+ /* build packet */
+ generator->write_to_chunk(generator, &packet_data);
+ generator->destroy(generator);
+
+ /* if last payload is of type encrypted, integrity checksum if necessary */
+ if (payload->get_type(payload) == ENCRYPTED)
+ {
+ DBG2(DBG_ENC, "build signature on whole message");
+ encryption_payload_t *encryption_payload = (encryption_payload_t*)payload;
+ status = encryption_payload->build_signature(encryption_payload, packet_data);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ }
+
+ this->packet->set_data(this->packet, packet_data);
+
+ /* clone packet for caller */
+ *packet = this->packet->clone(this->packet);
+
+ DBG2(DBG_ENC, "message generated successfully");
+ return SUCCESS;
+}
+
+/**
+ * Implementation of message_t.get_packet.
+ */
+static packet_t *get_packet(private_message_t *this)
+{
+ if (this->packet == NULL)
+ {
+ return NULL;
+ }
+ return this->packet->clone(this->packet);
+}
+
+/**
+ * Implementation of message_t.get_packet_data.
+ */
+static chunk_t get_packet_data(private_message_t *this)
+{
+ if (this->packet == NULL)
+ {
+ return chunk_empty;
+ }
+ return chunk_clone(this->packet->get_data(this->packet));
+}
+
+/**
+ * Implementation of message_t.parse_header.
+ */
+static status_t parse_header(private_message_t *this)
+{
+ ike_header_t *ike_header;
+ status_t status;
+
+ DBG2(DBG_ENC, "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)
+ {
+ DBG1(DBG_ENC, "header could not be parsed");
+ return status;
+
+ }
+
+ /* verify payload */
+ status = ike_header->payload_interface.verify(
+ &ike_header->payload_interface);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "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));
+
+ 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);
+
+ DBG2(DBG_ENC, "parsed a %N %s", exchange_type_names, this->exchange_type,
+ this->is_request ? "request" : "response");
+
+ ike_header->destroy(ike_header);
+
+ /* get the rules for this messge */
+ status = set_message_rule(this);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "no message rules specified for a %N %s",
+ exchange_type_names, this->exchange_type,
+ this->is_request ? "request" : "response");
+ }
+
+ return status;
+}
+
+/**
+ * Implementation of private_message_t.decrypt_and_verify_payloads.
+ */
+static status_t decrypt_payloads(private_message_t *this, crypter_t *crypter,
+ signer_t* signer)
+{
+ bool current_payload_was_encrypted = FALSE;
+ payload_t *previous_payload = NULL;
+ int payload_number = 1;
+ iterator_t *iterator;
+ payload_t *current_payload;
+ status_t status;
+
+ iterator = this->payloads->create_iterator(this->payloads,TRUE);
+
+ /* process each payload and decrypt a encryption payload */
+ while(iterator->iterate(iterator, (void**)&current_payload))
+ {
+ payload_rule_t *payload_rule;
+ payload_type_t current_payload_type;
+
+ /* needed to check */
+ current_payload_type = current_payload->get_type(current_payload);
+
+ DBG2(DBG_ENC, "process payload of type %N",
+ payload_type_names, current_payload_type);
+
+ if (current_payload_type == ENCRYPTED)
+ {
+ encryption_payload_t *encryption_payload;
+ payload_t *current_encrypted_payload;
+
+ encryption_payload = (encryption_payload_t*)current_payload;
+
+ DBG2(DBG_ENC, "found an encryption payload");
+
+ if (payload_number != this->payloads->get_count(this->payloads))
+ {
+ /* encrypted payload is not last one */
+ DBG1(DBG_ENC, "encrypted payload is not last payload");
+ iterator->destroy(iterator);
+ return VERIFY_ERROR;
+ }
+ /* decrypt */
+ encryption_payload->set_transforms(encryption_payload,
+ crypter, signer);
+ DBG2(DBG_ENC, "verify signature of encryption payload");
+ status = encryption_payload->verify_signature(encryption_payload,
+ this->packet->get_data(this->packet));
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "encryption payload signature invalid");
+ iterator->destroy(iterator);
+ return FAILED;
+ }
+ DBG2(DBG_ENC, "decrypting content of encryption payload");
+ status = encryption_payload->decrypt(encryption_payload);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "encrypted payload could not be decrypted and parsed");
+ iterator->destroy(iterator);
+ return PARSE_ERROR;
+ }
+
+ /* needed later to find out if a payload was encrypted */
+ current_payload_was_encrypted = TRUE;
+
+ /* check if there are payloads contained in the encryption payload */
+ if (encryption_payload->get_payload_count(encryption_payload) == 0)
+ {
+ DBG2(DBG_ENC, "encrypted payload is empty");
+ /* remove the encryption payload, is not needed anymore */
+ iterator->remove(iterator);
+ /* encrypted payload contains no other payload */
+ current_payload_type = NO_PAYLOAD;
+ }
+ else
+ {
+ /* encryption_payload is replaced with first payload contained
+ * in encryption_payload */
+ encryption_payload->remove_first_payload(encryption_payload,
+ &current_encrypted_payload);
+ iterator->replace(iterator, NULL,
+ (void *)current_encrypted_payload);
+ current_payload_type = current_encrypted_payload->get_type(
+ current_encrypted_payload);
+ }
+
+ /* is the current paylad the first in the message? */
+ if (previous_payload == NULL)
+ {
+ /* yes, set the first payload type of the message to the
+ * current type */
+ this->first_payload = current_payload_type;
+ }
+ else
+ {
+ /* no, set the next_type of the previous payload to the
+ * current type */
+ previous_payload->set_next_type(previous_payload,
+ current_payload_type);
+ }
+
+ /* all encrypted payloads are added to the payload list */
+ while (encryption_payload->get_payload_count(encryption_payload) > 0)
+ {
+ encryption_payload->remove_first_payload(encryption_payload,
+ &current_encrypted_payload);
+ DBG2(DBG_ENC, "insert unencrypted payload of type "
+ "%N at end of list", payload_type_names,
+ current_encrypted_payload->get_type(
+ current_encrypted_payload));
+ this->payloads->insert_last(this->payloads,
+ current_encrypted_payload);
+ }
+
+ /* encryption payload is processed, payloads are moved. Destroy it. */
+ encryption_payload->destroy(encryption_payload);
+ }
+
+ /* we allow unknown payloads of any type and don't bother if it was
+ * encrypted. Not our problem. */
+ if (current_payload_type != UNKNOWN_PAYLOAD &&
+ current_payload_type != NO_PAYLOAD)
+ {
+ /* get the ruleset for found payload */
+ status = get_payload_rule(this, current_payload_type, &payload_rule);
+ if (status != SUCCESS)
+ {
+ /* payload is not allowed */
+ DBG1(DBG_ENC, "payload type %N not allowed",
+ payload_type_names, current_payload_type);
+ iterator->destroy(iterator);
+ return VERIFY_ERROR;
+ }
+
+ /* check if the payload was encrypted, and if it should been have
+ * encrypted */
+ if (payload_rule->encrypted != current_payload_was_encrypted)
+ {
+ /* payload was not encrypted, but should have been.
+ * or vice-versa */
+ DBG1(DBG_ENC, "payload type %N should be %s!",
+ payload_type_names, current_payload_type,
+ (payload_rule->encrypted) ? "encrypted" : "not encrypted");
+ iterator->destroy(iterator);
+ return VERIFY_ERROR;
+ }
+ }
+ /* advance to the next payload */
+ payload_number++;
+ /* is stored to set next payload in case of found encryption payload */
+ previous_payload = current_payload;
+ }
+ iterator->destroy(iterator);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of private_message_t.verify.
+ */
+static status_t verify(private_message_t *this)
+{
+ int i;
+ enumerator_t *enumerator;
+ payload_t *current_payload;
+ size_t total_found_payloads = 0;
+
+ DBG2(DBG_ENC, "verifying message structure");
+
+ /* check for payloads with wrong count*/
+ for (i = 0; i < this->message_rule->payload_rule_count; i++)
+ {
+ size_t found_payloads = 0;
+ payload_rule_t *rule;
+
+ rule = &this->message_rule->payload_rules[i];
+ enumerator = create_payload_enumerator(this);
+
+ /* check all payloads for specific rule */
+ while (enumerator->enumerate(enumerator, &current_payload))
+ {
+ payload_type_t current_payload_type;
+ unknown_payload_t *unknown_payload;
+
+ current_payload_type = current_payload->get_type(current_payload);
+ if (current_payload_type == UNKNOWN_PAYLOAD)
+ {
+ /* unknown payloads are ignored, IF they are not critical */
+ unknown_payload = (unknown_payload_t*)current_payload;
+ if (unknown_payload->is_critical(unknown_payload))
+ {
+ DBG1(DBG_ENC, "%N is not supported, but its critical!",
+ payload_type_names, current_payload_type);
+ enumerator->destroy(enumerator);
+ return NOT_SUPPORTED;
+ }
+ }
+ else if (current_payload_type == rule->payload_type)
+ {
+ found_payloads++;
+ total_found_payloads++;
+ DBG2(DBG_ENC, "found payload of type %N", payload_type_names,
+ rule->payload_type);
+
+ /* as soon as ohe payload occures more then specified,
+ * the verification fails */
+ if (found_payloads >
+ rule->max_occurence)
+ {
+ DBG1(DBG_ENC, "payload of type %N more than %d times (%d) "
+ "occured in current message", payload_type_names,
+ current_payload_type, rule->max_occurence,
+ found_payloads);
+ enumerator->destroy(enumerator);
+ return VERIFY_ERROR;
+ }
+ }
+ }
+
+ if (found_payloads < rule->min_occurence)
+ {
+ DBG1(DBG_ENC, "payload of type %N not occured %d times (%d)",
+ payload_type_names, rule->payload_type, rule->min_occurence,
+ found_payloads);
+ enumerator->destroy(enumerator);
+ return VERIFY_ERROR;
+ }
+ if (rule->sufficient &&
+ this->payloads->get_count(this->payloads) == total_found_payloads)
+ {
+ enumerator->destroy(enumerator);
+ return SUCCESS;
+ }
+ enumerator->destroy(enumerator);
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of message_t.parse_body.
+ */
+static status_t parse_body(private_message_t *this, crypter_t *crypter,
+ signer_t *signer)
+{
+ status_t status = SUCCESS;
+ payload_type_t current_payload_type;
+ char str[256];
+
+ current_payload_type = this->first_payload;
+
+ DBG2(DBG_ENC, "parsing body of message, first payload is %N",
+ payload_type_names, current_payload_type);
+
+ /* parse payload for payload, while there are more available */
+ while ((current_payload_type != NO_PAYLOAD))
+ {
+ payload_t *current_payload;
+
+ DBG2(DBG_ENC, "starting parsing a %N payload",
+ payload_type_names, current_payload_type);
+
+ /* parse current payload */
+ status = this->parser->parse_payload(this->parser, current_payload_type,
+ (payload_t**)&current_payload);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "payload type %N could not be parsed",
+ payload_type_names, current_payload_type);
+ return PARSE_ERROR;
+ }
+
+ DBG2(DBG_ENC, "verifying payload of type %N",
+ payload_type_names, current_payload_type);
+
+ /* verify it, stop parsig if its invalid */
+ status = current_payload->verify(current_payload);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "%N payload verification failed",
+ payload_type_names, current_payload_type);
+ current_payload->destroy(current_payload);
+ return VERIFY_ERROR;
+ }
+
+ DBG2(DBG_ENC, "%N payload verified. Adding to payload list",
+ payload_type_names, current_payload_type);
+ this->payloads->insert_last(this->payloads,current_payload);
+
+ /* an encryption payload is the last one, so STOP here. decryption is
+ * done later */
+ if (current_payload_type == ENCRYPTED)
+ {
+ DBG2(DBG_ENC, "%N payload found. Stop parsing",
+ payload_type_names, current_payload_type);
+ break;
+ }
+
+ /* get next payload type */
+ current_payload_type = current_payload->get_next_type(current_payload);
+ }
+
+ if (current_payload_type == ENCRYPTED)
+ {
+ status = decrypt_payloads(this,crypter,signer);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "could not decrypt payloads");
+ return status;
+ }
+ }
+
+ status = verify(this);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+
+ DBG1(DBG_ENC, "parsed %s", get_string(this, str, sizeof(str)));
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of message_t.destroy.
+ */
+static void destroy (private_message_t *this)
+{
+ DESTROY_IF(this->ike_sa_id);
+ this->payloads->destroy_offset(this->payloads, offsetof(payload_t, destroy));
+ this->packet->destroy(this->packet);
+ this->parser->destroy(this->parser);
+ free(this);
+}
+
+/*
+ * Described in Header-File
+ */
+message_t *message_create_from_packet(packet_t *packet)
+{
+ private_message_t *this = malloc_thing(private_message_t);
+
+ /* public functions */
+ this->public.set_major_version = (void(*)(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 = (void(*)(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 = (void(*)(message_t*, u_int32_t))set_message_id;
+ this->public.get_message_id = (u_int32_t(*)(message_t*))get_message_id;
+ this->public.get_initiator_spi = (u_int64_t(*)(message_t*))get_initiator_spi;
+ this->public.get_responder_spi = (u_int64_t(*)(message_t*))get_responder_spi;
+ this->public.set_ike_sa_id = (void(*)(message_t*, ike_sa_id_t *))set_ike_sa_id;
+ this->public.get_ike_sa_id = (ike_sa_id_t*(*)(message_t*))get_ike_sa_id;
+ this->public.set_exchange_type = (void(*)(message_t*, exchange_type_t))set_exchange_type;
+ this->public.get_exchange_type = (exchange_type_t(*)(message_t*))get_exchange_type;
+ this->public.get_first_payload_type = (payload_type_t(*)(message_t*))get_first_payload_type;
+ this->public.set_request = (void(*)(message_t*, bool))set_request;
+ this->public.get_request = (bool(*)(message_t*))get_request;
+ this->public.add_payload = (void(*)(message_t*,payload_t*))add_payload;
+ this->public.add_notify = (void(*)(message_t*,bool,notify_type_t,chunk_t))add_notify;
+ this->public.generate = (status_t (*) (message_t *,crypter_t*,signer_t*,packet_t**)) generate;
+ this->public.set_source = (void (*) (message_t*,host_t*)) set_source;
+ this->public.get_source = (host_t * (*) (message_t*)) get_source;
+ this->public.set_destination = (void (*) (message_t*,host_t*)) set_destination;
+ this->public.get_destination = (host_t * (*) (message_t*)) get_destination;
+ this->public.create_payload_enumerator = (enumerator_t * (*) (message_t *)) create_payload_enumerator;
+ this->public.get_payload = (payload_t * (*) (message_t *, payload_type_t)) get_payload;
+ this->public.get_notify = (notify_payload_t*(*)(message_t*, notify_type_t type))get_notify;
+ this->public.parse_header = (status_t (*) (message_t *)) parse_header;
+ this->public.parse_body = (status_t (*) (message_t *,crypter_t*,signer_t*)) parse_body;
+ this->public.get_packet = (packet_t * (*) (message_t*)) get_packet;
+ this->public.get_packet_data = (chunk_t (*) (message_t *this)) get_packet_data;
+ this->public.destroy = (void(*)(message_t*))destroy;
+
+ /* private 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 values */
+ if (packet == NULL)
+ {
+ packet = packet_create();
+ }
+ this->message_rule = NULL;
+ this->packet = packet;
+ this->payloads = linked_list_create();
+
+ /* parser is created from data of packet */
+ this->parser = parser_create(this->packet->get_data(this->packet));
+
+ return (&this->public);
+}
+
+/*
+ * Described in Header.
+ */
+message_t *message_create()
+{
+ return message_create_from_packet(NULL);
+}
+
diff --git a/src/libcharon/encoding/message.h b/src/libcharon/encoding/message.h
new file mode 100644
index 000000000..2c7718f49
--- /dev/null
+++ b/src/libcharon/encoding/message.h
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2006-2007 Tobias Brunner
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup message message
+ * @{ @ingroup encoding
+ */
+
+#ifndef MESSAGE_H_
+#define MESSAGE_H_
+
+typedef struct message_t message_t;
+
+#include <library.h>
+#include <sa/ike_sa_id.h>
+#include <network/packet.h>
+#include <encoding/payloads/ike_header.h>
+#include <encoding/payloads/notify_payload.h>
+#include <utils/linked_list.h>
+#include <crypto/crypters/crypter.h>
+#include <crypto/signers/signer.h>
+
+/**
+ * This class is used to represent an IKEv2-Message.
+ *
+ * The message handles parsing and generation of payloads
+ * via parser_t/generator_t. Encryption is done transparently
+ * via the encryption_payload_t. A set of rules for messages
+ * and payloads does check parsed messages.
+ */
+struct message_t {
+
+ /**
+ * Sets the IKE major version of the message.
+ *
+ * @param major_version major version to set
+ */
+ void (*set_major_version) (message_t *this,u_int8_t major_version);
+
+ /**
+ * Gets the IKE major version of the message.
+ *
+ * @return major version of the message
+ */
+ u_int8_t (*get_major_version) (message_t *this);
+
+ /**
+ * Sets the IKE minor version of the message.
+ *
+ * @param minor_version minor version to set
+ */
+ void (*set_minor_version) (message_t *this,u_int8_t minor_version);
+
+ /**
+ * Gets the IKE minor version of the message.
+ *
+ * @return minor version of the message
+ */
+ u_int8_t (*get_minor_version) (message_t *this);
+
+ /**
+ * Sets the Message ID of the message.
+ *
+ * @param message_id message_id to set
+ */
+ void (*set_message_id) (message_t *this,u_int32_t message_id);
+
+ /**
+ * Gets the Message ID of the message.
+ *
+ * @return message_id type of the message
+ */
+ u_int32_t (*get_message_id) (message_t *this);
+
+ /**
+ * Gets the initiator SPI of the message.
+ *
+ * @return initiator spi of the message
+ */
+ u_int64_t (*get_initiator_spi) (message_t *this);
+
+ /**
+ * Gets the responder SPI of the message.
+ *
+ * @return responder spi of the message
+ */
+ u_int64_t (*get_responder_spi) (message_t *this);
+
+ /**
+ * Sets the IKE_SA ID of the message.
+ *
+ * ike_sa_id gets cloned.
+ *
+ * @param ike_sa_id ike_sa_id to set
+ */
+ void (*set_ike_sa_id) (message_t *this, ike_sa_id_t * ike_sa_id);
+
+ /**
+ * Gets the IKE_SA ID of the message.
+ *
+ * The ike_sa_id points to the message internal id, do not modify.
+ *
+ * @return ike_sa_id of message
+ */
+ ike_sa_id_t *(*get_ike_sa_id) (message_t *this);
+
+ /**
+ * Sets the exchange type of the message.
+ *
+ * @param exchange_type exchange_type to set
+ */
+ void (*set_exchange_type) (message_t *this,exchange_type_t exchange_type);
+
+ /**
+ * Gets the exchange type of the message.
+ *
+ * @return exchange type of the message
+ */
+ exchange_type_t (*get_exchange_type) (message_t *this);
+
+ /**
+ * Gets the payload type of the first payload.
+ *
+ * @return payload type of the first payload
+ */
+ payload_type_t (*get_first_payload_type) (message_t *this);
+
+ /**
+ * Sets the request flag.
+ *
+ * @param request TRUE if message is a request, FALSE if it is a reply
+ */
+ void (*set_request) (message_t *this, bool request);
+
+ /**
+ * Gets request flag.
+ *
+ * @return TRUE if message is a request, FALSE if it is a reply
+ */
+ bool (*get_request) (message_t *this);
+
+ /**
+ * Append a payload to the message.
+ *
+ * If the payload must be encrypted is not specified here. Encryption
+ * of payloads is evaluated via internal rules for the messages and
+ * is done before generation. The order of payloads may change, since
+ * all payloads to encrypt are added to the encryption payload, which is
+ * always the last one.
+ *
+ * @param payload payload to append
+ */
+ void (*add_payload) (message_t *this, payload_t *payload);
+
+ /**
+ * Build a notify payload and add it to the message.
+ *
+ * This is a helper method to create notify messages or add
+ * notify payload to messages. The flush parameter specifies if existing
+ * payloads should get removed before appending the notify.
+ *
+ * @param flush TRUE to remove existing payloads
+ * @param type type of the notify
+ * @param data a chunk of data to add to the notify, gets cloned
+ */
+ void (*add_notify) (message_t *this, bool flush, notify_type_t type,
+ chunk_t data);
+
+ /**
+ * Parses header of message.
+ *
+ * Begins parisng of a message created via message_create_from_packet().
+ * The parsing context is stored, so a subsequent call to parse_body()
+ * will continue the parsing process.
+ *
+ * @return
+ * - SUCCESS if header could be parsed
+ * - PARSE_ERROR if corrupted/invalid data found
+ * - FAILED if consistence check of header failed
+ */
+ status_t (*parse_header) (message_t *this);
+
+ /**
+ * Parses body of message.
+ *
+ * The body gets not only parsed, but rather it gets verified.
+ * All payloads are verified if they are allowed to exist in the message
+ * of this type and if their own structure is ok.
+ * If there are encrypted payloads, they get decrypted via the supplied
+ * crypter. Also the message integrity gets verified with the supplied
+ * signer.
+ * Crypter/signer can be omitted (by passing NULL) when no encryption
+ * payload is expected.
+ *
+ * @param crypter crypter to decrypt encryption payloads
+ * @param signer signer to verifiy a message with an encryption payload
+ * @return
+ * - SUCCESS if parsing successful
+ * - NOT_SUPPORTED if ciritcal unknown payloads found
+ * - NOT_SUPPORTED if message type is not supported!
+ * - PARSE_ERROR if message parsing failed
+ * - VERIFY_ERROR if message verification failed (bad syntax)
+ * - FAILED if integrity check failed
+ * - INVALID_STATE if crypter/signer not supplied, but needed
+ */
+ status_t (*parse_body) (message_t *this, crypter_t *crypter, signer_t *signer);
+
+ /**
+ * Generates the UDP packet of specific message.
+ *
+ * Payloads which must be encrypted are generated first and added to
+ * an encryption payload. This encryption payload will get encrypted via
+ * the supplied crypter. Then all other payloads and the header get generated.
+ * After that, the checksum is added to the encryption payload over the full
+ * message.
+ * Crypter/signer can be omitted (by passing NULL) when no encryption
+ * payload is expected.
+ * Generation is only done once, multiple calls will just return a packet copy.
+ *
+ * @param crypter crypter to use when a payload must be encrypted
+ * @param signer signer to build a mac
+ * @param packet copy of generated packet
+ * @return
+ * - SUCCESS if packet could be generated
+ * - INVALID_STATE if exchange type is currently not set
+ * - NOT_FOUND if no rules found for message generation
+ * - INVALID_STATE if crypter/signer not supplied but needed.
+ */
+ status_t (*generate) (message_t *this, crypter_t *crypter, signer_t *signer, packet_t **packet);
+
+ /**
+ * Gets the source host informations.
+ *
+ * @warning Returned host_t object is not getting cloned,
+ * do not destroy nor modify.
+ *
+ * @return host_t object representing source host
+ */
+ host_t * (*get_source) (message_t *this);
+
+ /**
+ * Sets the source host informations.
+ *
+ * @warning host_t object is not getting cloned and gets destroyed by
+ * message_t.destroy or next call of message_t.set_source.
+ *
+ * @param host host_t object representing source host
+ */
+ void (*set_source) (message_t *this, host_t *host);
+
+ /**
+ * Gets the destination host informations.
+ *
+ * @warning Returned host_t object is not getting cloned,
+ * do not destroy nor modify.
+ *
+ * @return host_t object representing destination host
+ */
+ host_t * (*get_destination) (message_t *this);
+
+ /**
+ * Sets the destination host informations.
+ *
+ * @warning host_t object is not getting cloned and gets destroyed by
+ * message_t.destroy or next call of message_t.set_destination.
+ *
+ * @param host host_t object representing destination host
+ */
+ void (*set_destination) (message_t *this, host_t *host);
+
+ /**
+ * Create an enumerator over all payloads.
+ *
+ * @return enumerator over payload_t
+ */
+ enumerator_t * (*create_payload_enumerator) (message_t *this);
+
+ /**
+ * Find a payload of a specific type.
+ *
+ * Returns the first occurance.
+ *
+ * @param type type of the payload to find
+ * @return payload, or NULL if no such payload found
+ */
+ payload_t* (*get_payload) (message_t *this, payload_type_t type);
+
+ /**
+ * Get the first notify payload of a specific type.
+ *
+ * @param type type of notification payload
+ * @return notify payload, NULL if no such notify found
+ */
+ notify_payload_t* (*get_notify)(message_t *this, notify_type_t type);
+
+ /**
+ * Returns a clone of the internal stored packet_t object.
+ *
+ * @return packet_t object as clone of internal one
+ */
+ packet_t * (*get_packet) (message_t *this);
+
+ /**
+ * Returns a clone of the internal stored packet_t data.
+ *
+ * @return clone of the internal stored packet_t data.
+ */
+ chunk_t (*get_packet_data) (message_t *this);
+
+ /**
+ * Destroys a message and all including objects.
+ */
+ void (*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.
+ *
+ * - exchange_type is set to NOT_SET
+ * - original_initiator is set to TRUE
+ * - is_request is set to TRUE
+ * Call message_t.parse_header afterwards.
+ *
+ * @param packet packet_t object which is assigned to message
+ * @return message_t object
+ */
+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 message_t object
+ */
+message_t * message_create(void);
+
+#endif /** MESSAGE_H_ @}*/
diff --git a/src/libcharon/encoding/parser.c b/src/libcharon/encoding/parser.c
new file mode 100644
index 000000000..9aa34b1bc
--- /dev/null
+++ b/src/libcharon/encoding/parser.c
@@ -0,0 +1,862 @@
+/*
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 <string.h>
+
+#include "parser.h"
+
+#include <library.h>
+#include <daemon.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/id_payload.h>
+#include <encoding/payloads/notify_payload.h>
+#include <encoding/payloads/encryption_payload.h>
+#include <encoding/payloads/auth_payload.h>
+#include <encoding/payloads/cert_payload.h>
+#include <encoding/payloads/certreq_payload.h>
+#include <encoding/payloads/ts_payload.h>
+#include <encoding/payloads/delete_payload.h>
+#include <encoding/payloads/vendor_id_payload.h>
+#include <encoding/payloads/cp_payload.h>
+#include <encoding/payloads/configuration_attribute.h>
+#include <encoding/payloads/eap_payload.h>
+#include <encoding/payloads/unknown_payload.h>
+
+
+typedef struct private_parser_t private_parser_t;
+
+/**
+ * Private data stored in a context.
+ *
+ * Contains pointers and counters to store current state.
+ */
+struct private_parser_t {
+ /**
+ * Public members, see parser_t.
+ */
+ parser_t public;
+
+ /**
+ * 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;
+};
+
+/**
+ * Forward declaration
+ */
+static status_t parse_payload(private_parser_t *this,
+ payload_type_t payload_type, payload_t **payload);
+
+/**
+ * Log invalid length error
+ */
+static bool short_input(private_parser_t *this, int number)
+{
+ DBG1(DBG_ENC, " not enough input to parse rule %d %N",
+ number, encoding_type_names, this->rules[number].type);
+ return FALSE;
+}
+
+/**
+ * Log unaligned rules
+ */
+static bool bad_bitpos(private_parser_t *this, int number)
+{
+ DBG1(DBG_ENC, " found rule %d %N on bitpos %d",
+ number, encoding_type_names, this->rules[number].type, this->bit_pos);
+ return FALSE;
+}
+
+/**
+ * Parse a 4-Bit unsigned integer from the current parsing position.
+ */
+static bool 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)
+ {
+ return short_input(this, rule_number);
+ }
+ switch (this->bit_pos)
+ {
+ case 0:
+ if (output_pos)
+ {
+ *output_pos = *(this->byte_pos) >> 4;
+ }
+ this->bit_pos = 4;
+ break;
+ case 4:
+ if (output_pos)
+ {
+ *output_pos = *(this->byte_pos) & 0x0F;
+ }
+ this->bit_pos = 0;
+ this->byte_pos++;
+ break;
+ default:
+ return bad_bitpos(this, rule_number);
+ }
+ if (output_pos)
+ {
+ DBG3(DBG_ENC, " => %d", *output_pos);
+ }
+ return TRUE;
+}
+
+/**
+ * Parse a 8-Bit unsigned integer from the current parsing position.
+ */
+static bool 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)
+ {
+ return short_input(this, rule_number);
+ }
+ if (this->bit_pos)
+ {
+ return bad_bitpos(this, rule_number);
+ }
+ if (output_pos)
+ {
+ *output_pos = *(this->byte_pos);
+ DBG3(DBG_ENC, " => %d", *output_pos);
+ }
+ this->byte_pos++;
+ return TRUE;
+}
+
+/**
+ * Parse a 15-Bit unsigned integer from the current parsing position.
+ */
+static bool 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)
+ {
+ return short_input(this, rule_number);
+ }
+ if (this->bit_pos != 1)
+ {
+ return bad_bitpos(this, rule_number);
+ }
+ if (output_pos)
+ {
+ memcpy(output_pos, this->byte_pos, sizeof(u_int16_t));
+ *output_pos = ntohs(*output_pos) & ~0x8000;
+ DBG3(DBG_ENC, " => %d", *output_pos);
+ }
+ this->byte_pos += sizeof(u_int16_t);
+ this->bit_pos = 0;
+ return TRUE;
+}
+
+/**
+ * Parse a 16-Bit unsigned integer from the current parsing position.
+ */
+static bool 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)
+ {
+ return short_input(this, rule_number);
+ }
+ if (this->bit_pos)
+ {
+ return bad_bitpos(this, rule_number);
+ }
+ if (output_pos)
+ {
+ memcpy(output_pos, this->byte_pos, sizeof(u_int16_t));
+ *output_pos = ntohs(*output_pos);
+ DBG3(DBG_ENC, " => %d", *output_pos);
+ }
+ this->byte_pos += sizeof(u_int16_t);
+ return TRUE;
+}
+/**
+ * Parse a 32-Bit unsigned integer from the current parsing position.
+ */
+static bool 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)
+ {
+ return short_input(this, rule_number);
+ }
+ if (this->bit_pos)
+ {
+ return bad_bitpos(this, rule_number);
+ }
+ if (output_pos)
+ {
+ memcpy(output_pos, this->byte_pos, sizeof(u_int32_t));
+ *output_pos = ntohl(*output_pos);
+ DBG3(DBG_ENC, " => %d", *output_pos);
+ }
+ this->byte_pos += sizeof(u_int32_t);
+ return TRUE;
+}
+
+/**
+ * Parse a given amount of bytes and writes them to a specific location
+ */
+static bool parse_bytes(private_parser_t *this, int rule_number,
+ u_int8_t *output_pos, int bytes)
+{
+ if (this->byte_pos + bytes > this->input_roof)
+ {
+ return short_input(this, rule_number);
+ }
+ if (this->bit_pos)
+ {
+ return bad_bitpos(this, rule_number);
+ }
+ if (output_pos)
+ {
+ memcpy(output_pos, this->byte_pos, bytes);
+ DBG3(DBG_ENC, " => %b", output_pos, bytes);
+ }
+ this->byte_pos += bytes;
+ return TRUE;
+}
+
+/**
+ * Parse a single Bit from the current parsing position
+ */
+static bool parse_bit(private_parser_t *this, int rule_number,
+ bool *output_pos)
+{
+ if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
+ {
+ return short_input(this, rule_number);
+ }
+ if (output_pos)
+ {
+ 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;
+ }
+ DBG3(DBG_ENC, " => %d", *output_pos);
+ }
+ this->bit_pos = (this->bit_pos + 1) % 8;
+ if (this->bit_pos == 0)
+ {
+ this->byte_pos++;
+ }
+ return TRUE;
+}
+
+/**
+ * Parse substructures in a list.
+ */
+static bool parse_list(private_parser_t *this, int rule_number,
+ linked_list_t **output_pos, payload_type_t payload_type, int length)
+{
+ linked_list_t *list = *output_pos;
+
+ if (length < 0)
+ {
+ return short_input(this, rule_number);
+ }
+ if (this->bit_pos)
+ {
+ return bad_bitpos(this, rule_number);
+ }
+ while (length > 0)
+ {
+ u_int8_t *pos_before = this->byte_pos;
+ payload_t *payload;
+
+ DBG2(DBG_ENC, " %d bytes left, parsing recursively %N",
+ length, payload_type_names, payload_type);
+
+ if (parse_payload(this, payload_type, &payload) != SUCCESS)
+ {
+ DBG1(DBG_ENC, " parsing of a %N substructure failed",
+ payload_type_names, payload_type);
+ return FALSE;
+ }
+ list->insert_last(list, payload);
+ length -= this->byte_pos - pos_before;
+ }
+ if (length != 0)
+ { /* must yield exactly to zero */
+ DBG1(DBG_ENC, " length of %N substructure list invalid",
+ payload_type_names, payload_type);
+ return FALSE;
+ }
+ *output_pos = list;
+ return TRUE;
+}
+
+/**
+ * Parse data from current parsing position in a chunk.
+ */
+static bool parse_chunk(private_parser_t *this, int rule_number,
+ chunk_t *output_pos, int length)
+{
+ if (this->byte_pos + length > this->input_roof)
+ {
+ return short_input(this, rule_number);
+ }
+ if (this->bit_pos)
+ {
+ return bad_bitpos(this, rule_number);
+ }
+ if (output_pos)
+ {
+ *output_pos = chunk_alloc(length);
+ memcpy(output_pos->ptr, this->byte_pos, length);
+ DBG3(DBG_ENC, " => %b", output_pos->ptr, length);
+ }
+ this->byte_pos += length;
+ return TRUE;
+}
+
+/**
+ * Implementation of parser_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;
+ int payload_length = 0, spi_size = 0, attribute_length = 0;
+ u_int16_t ts_type = 0;
+ bool attribute_format = FALSE;
+ int rule_number;
+ encoding_rule_t *rule;
+
+ /* create instance of the payload to parse */
+ pld = payload_create(payload_type);
+
+ DBG2(DBG_ENC, "parsing %N payload, %d bytes left",
+ payload_type_names, payload_type, this->input_roof - this->byte_pos);
+
+ DBG3(DBG_ENC, "parsing payload from %b",
+ this->byte_pos, this->input_roof - this->byte_pos);
+
+ if (pld->get_type(pld) == UNKNOWN_PAYLOAD)
+ {
+ DBG1(DBG_ENC, " payload type %d is unknown, handling as %N",
+ payload_type, payload_type_names, UNKNOWN_PAYLOAD);
+ }
+
+ /* base pointer for output, avoids casting in every rule */
+ output = pld;
+
+ /* parse the payload with its own rulse */
+ pld->get_encoding_rules(pld, &this->rules, &rule_count);
+ for (rule_number = 0; rule_number < rule_count; rule_number++)
+ {
+ rule = &(this->rules[rule_number]);
+ DBG2(DBG_ENC, " parsing rule %d %N",
+ rule_number, encoding_type_names, rule->type);
+ switch (rule->type)
+ {
+ case U_INT_4:
+ {
+ if (!parse_uint4(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case U_INT_8:
+ {
+ if (!parse_uint8(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case U_INT_16:
+ {
+ if (!parse_uint16(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case U_INT_32:
+ {
+ if (!parse_uint32(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case IKE_SPI:
+ {
+ if (!parse_bytes(this, rule_number, output + rule->offset, 8))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case RESERVED_BIT:
+ {
+ if (!parse_bit(this, rule_number, NULL))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case RESERVED_BYTE:
+ {
+ if (!parse_uint8(this, rule_number, NULL))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case FLAG:
+ {
+ if (!parse_bit(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case PAYLOAD_LENGTH:
+ {
+ if (!parse_uint16(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ /* parsed u_int16 should be aligned */
+ payload_length = *(u_int16_t*)(output + rule->offset);
+ if (payload_length < UNKNOWN_PAYLOAD_HEADER_LENGTH)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case HEADER_LENGTH:
+ {
+ if (!parse_uint32(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case SPI_SIZE:
+ {
+ if (!parse_uint8(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ spi_size = *(u_int8_t*)(output + rule->offset);
+ break;
+ }
+ case SPI:
+ {
+ if (!parse_chunk(this, rule_number, output + rule->offset,
+ spi_size))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case PROPOSALS:
+ {
+ if (payload_length < SA_PAYLOAD_HEADER_LENGTH ||
+ !parse_list(this, rule_number, output + rule->offset,
+ PROPOSAL_SUBSTRUCTURE,
+ payload_length - SA_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case TRANSFORMS:
+ {
+ if (payload_length <
+ spi_size + PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH ||
+ !parse_list(this, rule_number, output + rule->offset,
+ TRANSFORM_SUBSTRUCTURE, payload_length - spi_size -
+ PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case TRANSFORM_ATTRIBUTES:
+ {
+ if (payload_length < TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH ||
+ !parse_list(this, rule_number, output + rule->offset,
+ TRANSFORM_ATTRIBUTE,
+ payload_length - TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case CONFIGURATION_ATTRIBUTES:
+ {
+ if (payload_length < CP_PAYLOAD_HEADER_LENGTH ||
+ !parse_list(this, rule_number, output + rule->offset,
+ CONFIGURATION_ATTRIBUTE,
+ payload_length - CP_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case ATTRIBUTE_FORMAT:
+ {
+ if (!parse_bit(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ attribute_format = *(bool*)(output + rule->offset);
+ break;
+ }
+ case ATTRIBUTE_TYPE:
+ {
+ if (!parse_uint15(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case CONFIGURATION_ATTRIBUTE_LENGTH:
+ {
+ if (!parse_uint16(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ attribute_length = *(u_int16_t*)(output + rule->offset);
+ break;
+ }
+ case ATTRIBUTE_LENGTH_OR_VALUE:
+ {
+ if (!parse_uint16(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ attribute_length = *(u_int16_t*)(output + rule->offset);
+ break;
+ }
+ case ATTRIBUTE_VALUE:
+ {
+ if (attribute_format == FALSE &&
+ !parse_chunk(this, rule_number, output + rule->offset,
+ attribute_length))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case NONCE_DATA:
+ {
+ if (payload_length < NONCE_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - NONCE_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case ID_DATA:
+ {
+ if (payload_length < ID_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - ID_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case AUTH_DATA:
+ {
+ if (payload_length < AUTH_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - AUTH_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case CERT_DATA:
+ {
+ if (payload_length < CERT_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - CERT_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case CERTREQ_DATA:
+ {
+ if (payload_length < CERTREQ_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - CERTREQ_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case EAP_DATA:
+ {
+ if (payload_length < EAP_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - EAP_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case SPIS:
+ {
+ if (payload_length < DELETE_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - DELETE_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case VID_DATA:
+ {
+ if (payload_length < VENDOR_ID_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - VENDOR_ID_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case CONFIGURATION_ATTRIBUTE_VALUE:
+ {
+ if (!parse_chunk(this, rule_number, output + rule->offset,
+ attribute_length))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case KEY_EXCHANGE_DATA:
+ {
+ if (payload_length < KE_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - KE_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case NOTIFICATION_DATA:
+ {
+ if (payload_length < NOTIFY_PAYLOAD_HEADER_LENGTH + spi_size ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - NOTIFY_PAYLOAD_HEADER_LENGTH - spi_size))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case ENCRYPTED_DATA:
+ {
+ if (payload_length < ENCRYPTION_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - ENCRYPTION_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case TS_TYPE:
+ {
+ if (!parse_uint8(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ ts_type = *(u_int8_t*)(output + rule->offset);
+ break;
+ }
+ case ADDRESS:
+ {
+ int address_length = (ts_type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
+
+ if (!parse_chunk(this, rule_number, output + rule->offset,
+ address_length))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case TRAFFIC_SELECTORS:
+ {
+ if (payload_length < TS_PAYLOAD_HEADER_LENGTH ||
+ !parse_list(this, rule_number, output + rule->offset,
+ TRAFFIC_SELECTOR_SUBSTRUCTURE,
+ payload_length - TS_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case UNKNOWN_DATA:
+ {
+ if (payload_length < UNKNOWN_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - UNKNOWN_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ default:
+ {
+ DBG1(DBG_ENC, " no rule to parse rule %d %N",
+ rule_number, encoding_type_names, rule->type);
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ }
+ /* process next rulue */
+ rule++;
+ }
+
+ *payload = pld;
+ DBG2(DBG_ENC, "parsing %N payload finished",
+ payload_type_names, payload_type);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of parser_t.get_remaining_byte_count.
+ */
+static int get_remaining_byte_count (private_parser_t *this)
+{
+ return this->input_roof - this->byte_pos;
+}
+
+/**
+ * Implementation of parser_t.reset_context.
+ */
+static void reset_context (private_parser_t *this)
+{
+ this->byte_pos = this->input;
+ this->bit_pos = 0;
+}
+
+/**
+ * Implementation of parser_t.destroy.
+ */
+static void destroy(private_parser_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+parser_t *parser_create(chunk_t data)
+{
+ private_parser_t *this = malloc_thing(private_parser_t);
+
+ this->public.parse_payload = (status_t(*)(parser_t*,payload_type_t,payload_t**))parse_payload;
+ this->public.reset_context = (void(*)(parser_t*)) reset_context;
+ this->public.get_remaining_byte_count = (int (*) (parser_t *))get_remaining_byte_count;
+ this->public.destroy = (void(*)(parser_t*)) destroy;
+
+ this->input = data.ptr;
+ this->byte_pos = data.ptr;
+ this->bit_pos = 0;
+ this->input_roof = data.ptr + data.len;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/encoding/parser.h b/src/libcharon/encoding/parser.h
new file mode 100644
index 000000000..27c5f03fe
--- /dev/null
+++ b/src/libcharon/encoding/parser.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup parser parser
+ * @{ @ingroup encoding
+ */
+
+#ifndef PARSER_H_
+#define PARSER_H_
+
+typedef struct parser_t parser_t;
+
+#include <library.h>
+#include <encoding/payloads/encodings.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * A parser_t class to parse IKEv2 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.
+ */
+struct parser_t {
+
+ /**
+ * Parses the next payload.
+ *
+ * @warning Caller is responsible for freeing allocated payload.
+ *
+ * Rules for parsing are described in the payload definition.
+ *
+ * @param payload_type payload type to parse
+ * @param payload pointer where parsed payload was allocated
+ * @return
+ * - SUCCESSFUL if succeeded,
+ * - PARSE_ERROR if corrupted/invalid data found
+ */
+ status_t (*parse_payload) (parser_t *this, payload_type_t payload_type, payload_t **payload);
+
+ /**
+ * Gets the remaining byte count which is not currently parsed.
+ */
+ int (*get_remaining_byte_count) (parser_t *this);
+
+ /**
+ * Resets the current parser context.
+ */
+ void (*reset_context) (parser_t *this);
+
+ /**
+ * Destroys a parser_t object.
+ */
+ void (*destroy) (parser_t *this);
+};
+
+/**
+ * Constructor to create a parser_t object.
+ *
+ * @param data chunk of data to parse with this parser_t object
+ * @return parser_t object
+ */
+parser_t *parser_create(chunk_t data);
+
+#endif /** PARSER_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/auth_payload.c b/src/libcharon/encoding/payloads/auth_payload.c
new file mode 100644
index 000000000..d31208abb
--- /dev/null
+++ b/src/libcharon/encoding/payloads/auth_payload.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 "auth_payload.h"
+
+#include <encoding/payloads/encodings.h>
+
+
+typedef struct private_auth_payload_t private_auth_payload_t;
+
+/**
+ * Private data of an auth_payload_t object.
+ *
+ */
+struct private_auth_payload_t {
+
+ /**
+ * Public auth_payload_t interface.
+ */
+ auth_payload_t public;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * Method of the AUTH Data.
+ */
+ u_int8_t auth_method;
+
+ /**
+ * The contained auth data value.
+ */
+ chunk_t auth_data;
+};
+
+/**
+ * Encoding rules to parse or generate a AUTH payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_auth_payload_t.
+ */
+encoding_rule_t auth_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_auth_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_auth_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_auth_payload_t, payload_length)},
+ /* 1 Byte AUTH type*/
+ { U_INT_8, offsetof(private_auth_payload_t, auth_method) },
+ /* 3 reserved bytes */
+ { RESERVED_BYTE, 0 },
+ { RESERVED_BYTE, 0 },
+ { RESERVED_BYTE, 0 },
+ /* some auth data bytes, length is defined in PAYLOAD_LENGTH */
+ { AUTH_DATA, offsetof(private_auth_payload_t, auth_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 !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Auth Method ! RESERVED !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Authentication Data ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_auth_payload_t *this)
+{
+ if (this->auth_method == 0 ||
+ (this->auth_method >= 4 && this->auth_method <= 8) ||
+ (this->auth_method >= 12 && this->auth_method <= 200))
+ {
+ /* reserved IDs */
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of auth_payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_auth_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = auth_payload_encodings;
+ *rule_count = sizeof(auth_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_payload_type(private_auth_payload_t *this)
+{
+ return AUTHENTICATION;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_auth_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_auth_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_auth_payload_t *this)
+{
+ return this->payload_length;
+}
+
+/**
+ * Implementation of auth_payload_t.set_auth_method.
+ */
+static void set_auth_method (private_auth_payload_t *this, auth_method_t method)
+{
+ this->auth_method = method;
+}
+
+/**
+ * Implementation of auth_payload_t.get_auth_method.
+ */
+static auth_method_t get_auth_method (private_auth_payload_t *this)
+{
+ return (this->auth_method);
+}
+
+/**
+ * Implementation of auth_payload_t.set_data.
+ */
+static void set_data (private_auth_payload_t *this, chunk_t data)
+{
+ if (this->auth_data.ptr != NULL)
+ {
+ chunk_free(&(this->auth_data));
+ }
+ this->auth_data.ptr = clalloc(data.ptr,data.len);
+ this->auth_data.len = data.len;
+ this->payload_length = AUTH_PAYLOAD_HEADER_LENGTH + this->auth_data.len;
+}
+
+/**
+ * Implementation of auth_payload_t.get_data.
+ */
+static chunk_t get_data (private_auth_payload_t *this)
+{
+ return (this->auth_data);
+}
+
+/**
+ * Implementation of auth_payload_t.get_data_clone.
+ */
+static chunk_t get_data_clone (private_auth_payload_t *this)
+{
+ chunk_t cloned_data;
+ if (this->auth_data.ptr == NULL)
+ {
+ return (this->auth_data);
+ }
+ cloned_data.ptr = clalloc(this->auth_data.ptr,this->auth_data.len);
+ cloned_data.len = this->auth_data.len;
+ return cloned_data;
+}
+
+/**
+ * Implementation of payload_t.destroy and auth_payload_t.destroy.
+ */
+static void destroy(private_auth_payload_t *this)
+{
+ if (this->auth_data.ptr != NULL)
+ {
+ chunk_free(&(this->auth_data));
+ }
+
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+auth_payload_t *auth_payload_create()
+{
+ private_auth_payload_t *this = malloc_thing(private_auth_payload_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (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 = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.destroy = (void (*) (auth_payload_t *)) destroy;
+ this->public.set_auth_method = (void (*) (auth_payload_t *,auth_method_t)) set_auth_method;
+ this->public.get_auth_method = (auth_method_t (*) (auth_payload_t *)) get_auth_method;
+ this->public.set_data = (void (*) (auth_payload_t *,chunk_t)) set_data;
+ this->public.get_data_clone = (chunk_t (*) (auth_payload_t *)) get_data_clone;
+ this->public.get_data = (chunk_t (*) (auth_payload_t *)) get_data;
+
+ /* private variables */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length =AUTH_PAYLOAD_HEADER_LENGTH;
+ this->auth_data = chunk_empty;
+
+ return (&(this->public));
+}
diff --git a/src/libcharon/encoding/payloads/auth_payload.h b/src/libcharon/encoding/payloads/auth_payload.h
new file mode 100644
index 000000000..37ee149db
--- /dev/null
+++ b/src/libcharon/encoding/payloads/auth_payload.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup auth_payload auth_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef AUTH_PAYLOAD_H_
+#define AUTH_PAYLOAD_H_
+
+typedef struct auth_payload_t auth_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+#include <sa/authenticators/authenticator.h>
+
+/**
+ * Length of a auth payload without the auth data in bytes.
+ */
+#define AUTH_PAYLOAD_HEADER_LENGTH 8
+
+/**
+ * Class representing an IKEv2 AUTH payload.
+ *
+ * The AUTH payload format is described in RFC section 3.8.
+ */
+struct auth_payload_t {
+
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Set the AUTH method.
+ *
+ * @param method auth_method_t to use
+ */
+ void (*set_auth_method) (auth_payload_t *this, auth_method_t method);
+
+ /**
+ * Get the AUTH method.
+ *
+ * @return auth_method_t used
+ */
+ auth_method_t (*get_auth_method) (auth_payload_t *this);
+
+ /**
+ * Set the AUTH data.
+ *
+ * Data gets cloned.
+ *
+ * @param data AUTH data as chunk_t
+ */
+ void (*set_data) (auth_payload_t *this, chunk_t data);
+
+ /**
+ * Get the AUTH data.
+ *
+ * Returned data are a copy of the internal one.
+ *
+ * @return AUTH data as chunk_t
+ */
+ chunk_t (*get_data_clone) (auth_payload_t *this);
+
+ /**
+ * Get the AUTH data.
+ *
+ * Returned data are NOT copied
+ *
+ * @return AUTH data as chunk_t
+ */
+ chunk_t (*get_data) (auth_payload_t *this);
+
+ /**
+ * Destroys an auth_payload_t object.
+ */
+ void (*destroy) (auth_payload_t *this);
+};
+
+/**
+ * Creates an empty auth_payload_t object.
+ *
+ * @return auth_payload_t object
+ */
+auth_payload_t *auth_payload_create(void);
+
+#endif /** AUTH_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/cert_payload.c b/src/libcharon/encoding/payloads/cert_payload.c
new file mode 100644
index 000000000..6dd3141f0
--- /dev/null
+++ b/src/libcharon/encoding/payloads/cert_payload.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 <stddef.h>
+#include <ctype.h>
+
+#include <daemon.h>
+
+#include "cert_payload.h"
+
+ENUM(cert_encoding_names, ENC_PKCS7_WRAPPED_X509, ENC_OCSP_CONTENT,
+ "ENC_PKCS7_WRAPPED_X509",
+ "ENC_PGP",
+ "ENC_DNS_SIGNED_KEY",
+ "ENC_X509_SIGNATURE",
+ "ENC_X509_KEY_EXCHANGE",
+ "ENC_KERBEROS_TOKENS",
+ "ENC_CRL",
+ "ENC_ARL",
+ "ENC_SPKI",
+ "ENC_X509_ATTRIBUTE",
+ "ENC_RAW_RSA_KEY",
+ "ENC_X509_HASH_AND_URL",
+ "ENC_X509_HASH_AND_URL_BUNDLE",
+ "ENC_OCSP_CONTENT",
+);
+
+typedef struct private_cert_payload_t private_cert_payload_t;
+
+/**
+ * Private data of an cert_payload_t object.
+ *
+ */
+struct private_cert_payload_t {
+ /**
+ * Public cert_payload_t interface.
+ */
+ cert_payload_t public;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * Encoding of the CERT Data.
+ */
+ u_int8_t encoding;
+
+ /**
+ * The contained cert data value.
+ */
+ chunk_t data;
+
+ /**
+ * TRUE if the "Hash and URL" data is invalid
+ */
+ bool invalid_hash_and_url;
+};
+
+/**
+ * Encoding rules to parse or generate a CERT payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_cert_payload_t.
+ *
+ */
+encoding_rule_t cert_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_cert_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_cert_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_cert_payload_t, payload_length)},
+ /* 1 Byte CERT type*/
+ { U_INT_8, offsetof(private_cert_payload_t, encoding) },
+ /* some cert data bytes, length is defined in PAYLOAD_LENGTH */
+ { CERT_DATA, offsetof(private_cert_payload_t, 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 !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Cert Encoding ! !
+ +-+-+-+-+-+-+-+-+ !
+ ~ Certificate Data ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_cert_payload_t *this)
+{
+ if (this->encoding == ENC_X509_HASH_AND_URL ||
+ this->encoding == ENC_X509_HASH_AND_URL_BUNDLE)
+ {
+ /* coarse verification of "Hash and URL" encoded certificates */
+ if (this->data.len <= 20)
+ {
+ DBG1(DBG_ENC, "invalid payload length for hash-and-url (%d), ignore",
+ this->data.len);
+ this->invalid_hash_and_url = TRUE;
+ return SUCCESS;
+ }
+
+ int i = 20; /* skipping the hash */
+ for (; i < this->data.len; ++i)
+ {
+ if (this->data.ptr[i] == '\0')
+ {
+ /* null terminated, fine */
+ return SUCCESS;
+ }
+ else if (!isprint(this->data.ptr[i]))
+ {
+ DBG1(DBG_ENC, "non printable characters in url of hash-and-url"
+ " encoded certificate payload, ignore");
+ this->invalid_hash_and_url = TRUE;
+ return SUCCESS;
+ }
+ }
+
+ /* URL is not null terminated, correct that */
+ chunk_t data = chunk_alloc(this->data.len + 1);
+ memcpy(data.ptr, this->data.ptr, this->data.len);
+ data.ptr[this->data.len] = '\0';
+ chunk_free(&this->data);
+ this->data = data;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of cert_payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_cert_payload_t *this,
+ encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = cert_payload_encodings;
+ *rule_count = sizeof(cert_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_payload_type(private_cert_payload_t *this)
+{
+ return CERTIFICATE;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_cert_payload_t *this)
+{
+ return this->next_payload;
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_cert_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_cert_payload_t *this)
+{
+ return this->payload_length;
+}
+
+/**
+ * Implementation of cert_payload_t.get_cert_encoding.
+ */
+static cert_encoding_t get_cert_encoding(private_cert_payload_t *this)
+{
+ return this->encoding;
+}
+
+/**
+ * Implementation of cert_payload_t.get_cert.
+ */
+static certificate_t *get_cert(private_cert_payload_t *this)
+{
+ if (this->encoding != ENC_X509_SIGNATURE)
+ {
+ return NULL;
+ }
+ return lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_ASN1_DER, this->data,
+ BUILD_END);
+}
+
+/**
+ * Implementation of cert_payload_t.get_hash.
+ */
+static chunk_t get_hash(private_cert_payload_t *this)
+{
+ chunk_t hash = chunk_empty;
+ if ((this->encoding != ENC_X509_HASH_AND_URL &&
+ this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) ||
+ this->invalid_hash_and_url)
+ {
+ return hash;
+ }
+ hash.ptr = this->data.ptr;
+ hash.len = 20;
+ return hash;
+}
+
+/**
+ * Implementation of cert_payload_t.get_url.
+ */
+static char *get_url(private_cert_payload_t *this)
+{
+ if ((this->encoding != ENC_X509_HASH_AND_URL &&
+ this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) ||
+ this->invalid_hash_and_url)
+ {
+ return NULL;
+ }
+ return (char*)this->data.ptr + 20;
+}
+
+/**
+ * Implementation of payload_t.destroy and cert_payload_t.destroy.
+ */
+static void destroy(private_cert_payload_t *this)
+{
+ chunk_free(&this->data);
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+cert_payload_t *cert_payload_create()
+{
+ private_cert_payload_t *this = malloc_thing(private_cert_payload_t);
+
+ this->public.payload_interface.verify = (status_t (*) (payload_t*))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (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 = (void (*) (payload_t*,payload_type_t))set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t*))get_payload_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t*))destroy;
+
+ this->public.destroy = (void (*) (cert_payload_t*))destroy;
+ this->public.get_cert = (certificate_t* (*) (cert_payload_t*))get_cert;
+ this->public.get_cert_encoding = (cert_encoding_t (*) (cert_payload_t*))get_cert_encoding;
+ this->public.get_hash = (chunk_t (*) (cert_payload_t*))get_hash;
+ this->public.get_url = (char* (*) (cert_payload_t*))get_url;
+
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = CERT_PAYLOAD_HEADER_LENGTH;
+ this->data = chunk_empty;
+ this->encoding = 0;
+ this->invalid_hash_and_url = FALSE;
+
+ return &this->public;
+}
+
+/*
+ * Described in header
+ */
+cert_payload_t *cert_payload_create_from_cert(certificate_t *cert)
+{
+ private_cert_payload_t *this = (private_cert_payload_t*)cert_payload_create();
+
+ switch (cert->get_type(cert))
+ {
+ case CERT_X509:
+ this->encoding = ENC_X509_SIGNATURE;
+ break;
+ default:
+ DBG1(DBG_ENC, "embedding %N certificate in payload failed",
+ certificate_type_names, cert->get_type(cert));
+ free(this);
+ return NULL;
+ }
+ this->data = cert->get_encoding(cert);
+ this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->data.len;
+ return &this->public;
+}
+
+/*
+ * Described in header
+ */
+cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url)
+{
+ private_cert_payload_t *this = (private_cert_payload_t*)cert_payload_create();
+
+ this->encoding = ENC_X509_HASH_AND_URL;
+ this->data = chunk_cat("cc", hash, chunk_create(url, strlen(url)));
+ this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->data.len;
+ return &this->public;
+}
+
diff --git a/src/libcharon/encoding/payloads/cert_payload.h b/src/libcharon/encoding/payloads/cert_payload.h
new file mode 100644
index 000000000..aa1c7bf5a
--- /dev/null
+++ b/src/libcharon/encoding/payloads/cert_payload.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup cert_payload cert_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef CERT_PAYLOAD_H_
+#define CERT_PAYLOAD_H_
+
+typedef struct cert_payload_t cert_payload_t;
+typedef enum cert_encoding_t cert_encoding_t;
+
+#include <library.h>
+#include <credentials/certificates/certificate.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * Length of a cert payload without the cert data in bytes.
+ */
+#define CERT_PAYLOAD_HEADER_LENGTH 5
+
+/**
+ * Certifcate encodings, as in RFC4306
+ */
+enum cert_encoding_t {
+ ENC_PKCS7_WRAPPED_X509 = 1,
+ ENC_PGP = 2,
+ ENC_DNS_SIGNED_KEY = 3,
+ ENC_X509_SIGNATURE = 4,
+ ENC_KERBEROS_TOKEN = 6,
+ ENC_CRL = 7,
+ ENC_ARL = 8,
+ ENC_SPKI = 9,
+ ENC_X509_ATTRIBUTE = 10,
+ ENC_RAW_RSA_KEY = 11,
+ ENC_X509_HASH_AND_URL = 12,
+ ENC_X509_HASH_AND_URL_BUNDLE = 13,
+ ENC_OCSP_CONTENT = 14, /* from RFC 4806 */
+};
+
+/**
+ * Enum names for cert_encoding_t
+ */
+extern enum_name_t *cert_encoding_names;
+
+/**
+ * Class representing an IKEv2 CERT payload.
+ *
+ * The CERT payload format is described in RFC section 3.6.
+ */
+struct cert_payload_t {
+
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Get the playoads encoded certifcate.
+ *
+ * @return certifcate copy
+ */
+ certificate_t *(*get_cert)(cert_payload_t *this);
+
+ /**
+ * Get the encoding of the certificate.
+ *
+ * @return encoding
+ */
+ cert_encoding_t (*get_cert_encoding)(cert_payload_t *this);
+
+ /**
+ * Get the hash if this is a hash and URL encoded certificate.
+ *
+ * This function returns internal data, do not free.
+ *
+ * @return hash
+ */
+ chunk_t (*get_hash)(cert_payload_t *this);
+
+ /**
+ * Get the URL if this is a hash and URL encoded certificate.
+ *
+ * This function returns internal data, do not free.
+ *
+ * @return url
+ */
+ char *(*get_url)(cert_payload_t *this);
+
+
+ /**
+ * Destroys the cert_payload object.
+ */
+ void (*destroy) (cert_payload_t *this);
+};
+
+/**
+ * Creates an empty certificate payload.
+ *
+ * @return cert_payload_t object
+ */
+cert_payload_t *cert_payload_create(void);
+
+/**
+ * Creates a certificate payload with an embedded certificate.
+ *
+ * @param cert certificate to embed
+ * @return cert_payload_t object
+ */
+cert_payload_t *cert_payload_create_from_cert(certificate_t *cert);
+
+/**
+ * Creates a certificate payload with hash and URL encoding of a certificate.
+ *
+ * @param hash hash of the DER encoded certificate (get's cloned)
+ * @param url the URL to locate the certificate (get's cloned)
+ * @return cert_payload_t object
+ */
+cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url);
+
+#endif /** CERT_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/certreq_payload.c b/src/libcharon/encoding/payloads/certreq_payload.c
new file mode 100644
index 000000000..9ff0bdde0
--- /dev/null
+++ b/src/libcharon/encoding/payloads/certreq_payload.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 <stddef.h>
+
+#include <daemon.h>
+#include <crypto/hashers/hasher.h>
+#include <encoding/payloads/cert_payload.h>
+
+#include "certreq_payload.h"
+
+
+typedef struct private_certreq_payload_t private_certreq_payload_t;
+
+/**
+ * Private data of an certreq_payload_t object.
+ *
+ */
+struct private_certreq_payload_t {
+ /**
+ * Public certreq_payload_t interface.
+ */
+ certreq_payload_t public;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * Encoding of the CERT Data.
+ */
+ u_int8_t encoding;
+
+ /**
+ * The contained certreq data value.
+ */
+ chunk_t data;
+};
+
+/**
+ * Encoding rules to parse or generate a CERTREQ payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_certreq_payload_t.
+ *
+ */
+encoding_rule_t certreq_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_certreq_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_certreq_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_certreq_payload_t, payload_length) },
+ /* 1 Byte CERTREQ type*/
+ { U_INT_8, offsetof(private_certreq_payload_t, encoding) },
+ /* some certreq data bytes, length is defined in PAYLOAD_LENGTH */
+ { CERTREQ_DATA, offsetof(private_certreq_payload_t, 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 !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Cert Encoding ! !
+ +-+-+-+-+-+-+-+-+ !
+ ~ Certification Authority ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_certreq_payload_t *this)
+{
+ if (this->encoding == ENC_X509_SIGNATURE)
+ {
+ if (this->data.len < HASH_SIZE_SHA1 ||
+ this->data.len % HASH_SIZE_SHA1)
+ {
+ DBG1(DBG_ENC, "invalid X509 hash length (%d) in certreq",
+ this->data.len);
+ return FAILED;
+ }
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of certreq_payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_certreq_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = certreq_payload_encodings;
+ *rule_count = sizeof(certreq_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_payload_type(private_certreq_payload_t *this)
+{
+ return CERTIFICATE_REQUEST;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_certreq_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_certreq_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_certreq_payload_t *this)
+{
+ return this->payload_length;
+}
+
+/**
+ * Implementation of certreq_payload_t.add_keyid.
+ */
+static void add_keyid(private_certreq_payload_t *this, chunk_t keyid)
+{
+ this->data = chunk_cat("mc", this->data, keyid);
+ this->payload_length += keyid.len;
+}
+
+typedef struct keyid_enumerator_t keyid_enumerator_t;
+
+/**
+ * enumerator to enumerate keyids
+ */
+struct keyid_enumerator_t {
+ enumerator_t public;
+ chunk_t full;
+ u_char *pos;
+};
+
+/**
+ * enumerate function for keyid_enumerator
+ */
+static bool keyid_enumerate(keyid_enumerator_t *this, chunk_t *chunk)
+{
+ if (this->pos == NULL)
+ {
+ this->pos = this->full.ptr;
+ }
+ else
+ {
+ this->pos += HASH_SIZE_SHA1;
+ if (this->pos > (this->full.ptr + this->full.len - HASH_SIZE_SHA1))
+ {
+ this->pos = NULL;
+ }
+ }
+ if (this->pos)
+ {
+ chunk->ptr = this->pos;
+ chunk->len = HASH_SIZE_SHA1;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Implementation of certreq_payload_t.create_keyid_enumerator.
+ */
+static enumerator_t* create_keyid_enumerator(private_certreq_payload_t *this)
+{
+ keyid_enumerator_t *enumerator = malloc_thing(keyid_enumerator_t);
+ enumerator->public.enumerate = (void*)keyid_enumerate;
+ enumerator->public.destroy = (void*)free;
+ enumerator->full = this->data;
+ enumerator->pos = NULL;
+ return &enumerator->public;
+}
+
+/**
+ * Implementation of certreq_payload_t.get_cert_type.
+ */
+static certificate_type_t get_cert_type(private_certreq_payload_t *this)
+{
+ switch (this->encoding)
+ {
+ case ENC_X509_SIGNATURE:
+ return CERT_X509;
+ default:
+ return CERT_ANY;
+ }
+}
+
+/**
+ * Implementation of payload_t.destroy and certreq_payload_t.destroy.
+ */
+static void destroy(private_certreq_payload_t *this)
+{
+ chunk_free(&this->data);
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+certreq_payload_t *certreq_payload_create()
+{
+ private_certreq_payload_t *this = malloc_thing(private_certreq_payload_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t*))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (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 = (void (*) (payload_t*,payload_type_t))set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t*))get_payload_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t*))destroy;
+
+ /* public functions */
+ this->public.destroy = (void (*) (certreq_payload_t*)) destroy;
+ this->public.create_keyid_enumerator = (enumerator_t*(*)(certreq_payload_t*))create_keyid_enumerator;
+ this->public.get_cert_type = (certificate_type_t(*)(certreq_payload_t*))get_cert_type;
+ this->public.add_keyid = (void(*)(certreq_payload_t*, chunk_t keyid))add_keyid;
+
+ /* private variables */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = CERTREQ_PAYLOAD_HEADER_LENGTH;
+ this->data = chunk_empty;
+ this->encoding = 0;
+
+ return &this->public;
+}
+
+/*
+ * Described in header
+ */
+certreq_payload_t *certreq_payload_create_type(certificate_type_t type)
+{
+ private_certreq_payload_t *this = (private_certreq_payload_t*)certreq_payload_create();
+
+ switch (type)
+ {
+ case CERT_X509:
+ this->encoding = ENC_X509_SIGNATURE;
+ break;
+ default:
+ DBG1(DBG_ENC, "certificate type %N not supported in requests",
+ certificate_type_names, type);
+ free(this);
+ return NULL;
+ }
+ return &this->public;
+}
+
diff --git a/src/libcharon/encoding/payloads/certreq_payload.h b/src/libcharon/encoding/payloads/certreq_payload.h
new file mode 100644
index 000000000..914063628
--- /dev/null
+++ b/src/libcharon/encoding/payloads/certreq_payload.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup certreq_payload certreq_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef CERTREQ_PAYLOAD_H_
+#define CERTREQ_PAYLOAD_H_
+
+typedef struct certreq_payload_t certreq_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/cert_payload.h>
+
+/**
+ * Length of a CERTREQ payload without the CERTREQ data in bytes.
+ */
+#define CERTREQ_PAYLOAD_HEADER_LENGTH 5
+
+/**
+ * Class representing an IKEv2 CERTREQ payload.
+ *
+ * The CERTREQ payload format is described in RFC section 3.7.
+ */
+struct certreq_payload_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Create an enumerator over contained keyids.
+ *
+ * @return enumerator over chunk_t's.
+ */
+ enumerator_t* (*create_keyid_enumerator)(certreq_payload_t *this);
+
+ /**
+ * Get the type of contained certificate keyids.
+ *
+ * @return certificate keyid type
+ */
+ certificate_type_t (*get_cert_type)(certreq_payload_t *this);
+
+ /**
+ * Add a certificates keyid to the payload.
+ *
+ * @param keyid keyid of the trusted certifcate
+ * @return
+ */
+ void (*add_keyid)(certreq_payload_t *this, chunk_t keyid);
+
+ /**
+ * Destroys an certreq_payload_t object.
+ */
+ void (*destroy) (certreq_payload_t *this);
+};
+
+/**
+ * Creates an empty certreq_payload_t object.
+ *
+ * @return certreq payload
+ */
+certreq_payload_t *certreq_payload_create(void);
+
+/**
+ * Creates an empty certreq_payload_t for a kind of certificates.
+ *
+ * @param type type of the added keyids
+ * @return certreq payload
+ */
+certreq_payload_t *certreq_payload_create_type(certificate_type_t type);
+
+#endif /** CERTREQ_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/configuration_attribute.c b/src/libcharon/encoding/payloads/configuration_attribute.c
new file mode 100644
index 000000000..9094fd44d
--- /dev/null
+++ b/src/libcharon/encoding/payloads/configuration_attribute.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 <stddef.h>
+
+#include "configuration_attribute.h"
+
+#include <encoding/payloads/encodings.h>
+#include <library.h>
+#include <daemon.h>
+
+
+typedef struct private_configuration_attribute_t private_configuration_attribute_t;
+
+/**
+ * Private data of an configuration_attribute_t object.
+ *
+ */
+struct private_configuration_attribute_t {
+ /**
+ * Public configuration_attribute_t interface.
+ */
+ configuration_attribute_t public;
+
+ /**
+ * Type of the attribute.
+ */
+ u_int16_t type;
+
+ /**
+ * Length of the attribute.
+ */
+ u_int16_t length;
+
+ /**
+ * Attribute value as chunk.
+ */
+ chunk_t value;
+};
+
+/**
+ * Encoding rules to parse or generate a configuration attribute.
+ *
+ * The defined offsets are the positions in a object of type
+ * private_configuration_attribute_t.
+ */
+encoding_rule_t configuration_attribute_encodings[] = {
+
+ { RESERVED_BIT, 0 },
+ /* type of the attribute as 15 bit unsigned integer */
+ { ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, type) },
+ /* Length of attribute value */
+ { CONFIGURATION_ATTRIBUTE_LENGTH, offsetof(private_configuration_attribute_t, length) },
+ /* Value of attribute if attribute format flag is zero */
+ { CONFIGURATION_ATTRIBUTE_VALUE, offsetof(private_configuration_attribute_t, 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
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ !R| Attribute Type ! Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ ~ Value ~
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_configuration_attribute_t *this)
+{
+ bool failed = FALSE;
+
+ if (this->length != this->value.len)
+ {
+ DBG1(DBG_ENC, "invalid attribute length");
+ return FAILED;
+ }
+
+ switch (this->type)
+ {
+ case INTERNAL_IP4_ADDRESS:
+ case INTERNAL_IP4_NETMASK:
+ case INTERNAL_IP4_DNS:
+ case INTERNAL_IP4_NBNS:
+ case INTERNAL_ADDRESS_EXPIRY:
+ case INTERNAL_IP4_DHCP:
+ if (this->length != 0 && this->length != 4)
+ {
+ failed = TRUE;
+ }
+ break;
+ case INTERNAL_IP4_SUBNET:
+ if (this->length != 0 && this->length != 8)
+ {
+ failed = TRUE;
+ }
+ break;
+ case INTERNAL_IP6_ADDRESS:
+ case INTERNAL_IP6_SUBNET:
+ if (this->length != 0 && this->length != 17)
+ {
+ failed = TRUE;
+ }
+ break;
+ case INTERNAL_IP6_DNS:
+ case INTERNAL_IP6_NBNS:
+ case INTERNAL_IP6_DHCP:
+ if (this->length != 0 && this->length != 16)
+ {
+ failed = TRUE;
+ }
+ break;
+ case SUPPORTED_ATTRIBUTES:
+ if (this->length % 2)
+ {
+ failed = TRUE;
+ }
+ break;
+ case APPLICATION_VERSION:
+ /* any length acceptable */
+ break;
+ default:
+ DBG1(DBG_ENC, "unknown attribute type %N",
+ configuration_attribute_type_names, this->type);
+ break;
+ }
+
+ if (failed)
+ {
+ DBG1(DBG_ENC, "invalid attribute length %d for %N",
+ this->length, configuration_attribute_type_names, this->type);
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_configuration_attribute_t *this,
+ encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = configuration_attribute_encodings;
+ *rule_count = sizeof(configuration_attribute_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(private_configuration_attribute_t *this)
+{
+ return CONFIGURATION_ATTRIBUTE;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_configuration_attribute_t *this)
+{
+ return NO_PAYLOAD;
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_configuration_attribute_t *this,
+ payload_type_t type)
+{
+}
+
+/**
+ * Implementation of configuration_attribute_t.get_length.
+ */
+static size_t get_length(private_configuration_attribute_t *this)
+{
+ return this->value.len + CONFIGURATION_ATTRIBUTE_HEADER_LENGTH;
+}
+
+/**
+ * Implementation of configuration_attribute_t.get_type.
+ */
+static configuration_attribute_type_t get_configuration_attribute_type(
+ private_configuration_attribute_t *this)
+{
+ return this->type;
+}
+
+/**
+ * Implementation of configuration_attribute_t.get_value.
+ */
+static chunk_t get_value(private_configuration_attribute_t *this)
+{
+ return this->value;
+}
+
+/**
+ * Implementation of configuration_attribute_t.destroy and payload_t.destroy.
+ */
+static void destroy(private_configuration_attribute_t *this)
+{
+ free(this->value.ptr);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+configuration_attribute_t *configuration_attribute_create()
+{
+ private_configuration_attribute_t *this;
+
+ this = malloc_thing(private_configuration_attribute_t);
+ this->public.payload_interface.verify = (status_t(*)(payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void(*)(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 = (void(*)(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 = (void(*)(payload_t*))destroy;
+
+ this->public.get_value = (chunk_t(*)(configuration_attribute_t *))get_value;
+ this->public.get_type = (configuration_attribute_type_t(*)(configuration_attribute_t *))get_configuration_attribute_type;
+ this->public.destroy = (void (*)(configuration_attribute_t*))destroy;
+
+ this->type = 0;
+ this->value = chunk_empty;
+ this->length = 0;
+
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+configuration_attribute_t *configuration_attribute_create_value(
+ configuration_attribute_type_t type, chunk_t value)
+{
+ private_configuration_attribute_t *this;
+
+ this = (private_configuration_attribute_t*)configuration_attribute_create();
+ this->type = ((u_int16_t)type) & 0x7FFF;
+ this->value = chunk_clone(value);
+ this->length = value.len;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/encoding/payloads/configuration_attribute.h b/src/libcharon/encoding/payloads/configuration_attribute.h
new file mode 100644
index 000000000..6e4b018bb
--- /dev/null
+++ b/src/libcharon/encoding/payloads/configuration_attribute.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup configuration_attribute configuration_attribute
+ * @{ @ingroup payloads
+ */
+
+#ifndef CONFIGURATION_ATTRIBUTE_H_
+#define CONFIGURATION_ATTRIBUTE_H_
+
+typedef struct configuration_attribute_t configuration_attribute_t;
+
+#include <library.h>
+#include <attributes/attributes.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * Configuration attribute header length in bytes.
+ */
+#define CONFIGURATION_ATTRIBUTE_HEADER_LENGTH 4
+
+/**
+ * Class representing an IKEv2-CONFIGURATION Attribute.
+ *
+ * The CONFIGURATION ATTRIBUTE format is described in RFC section 3.15.1.
+ */
+struct configuration_attribute_t {
+
+ /**
+ * Implements payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Get the type of the attribute.
+ *
+ * @return type of the configuration attribute
+ */
+ configuration_attribute_type_t (*get_type)(configuration_attribute_t *this);
+
+ /**
+ * Returns the value of the attribute.
+ *
+ * @return chunk_t pointing to the internal value
+ */
+ chunk_t (*get_value) (configuration_attribute_t *this);
+
+ /**
+ * Destroys an configuration_attribute_t object.
+ */
+ void (*destroy) (configuration_attribute_t *this);
+};
+
+/**
+ * Creates an empty configuration attribute.
+ *
+ * @return created configuration attribute
+ */
+configuration_attribute_t *configuration_attribute_create();
+
+/**
+ * Creates a configuration attribute with type and value.
+ *
+ * @param type type of configuration attribute
+ * @param value value, gets cloned
+ * @return created configuration attribute
+ */
+configuration_attribute_t *configuration_attribute_create_value(
+ configuration_attribute_type_t type, chunk_t value);
+
+#endif /** CONFIGURATION_ATTRIBUTE_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/cp_payload.c b/src/libcharon/encoding/payloads/cp_payload.c
new file mode 100644
index 000000000..f0a26eee2
--- /dev/null
+++ b/src/libcharon/encoding/payloads/cp_payload.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 <stddef.h>
+
+#include "cp_payload.h"
+
+#include <encoding/payloads/encodings.h>
+#include <utils/linked_list.h>
+
+ENUM(config_type_names, CFG_REQUEST, CFG_ACK,
+ "CFG_REQUEST",
+ "CFG_REPLY",
+ "CFG_SET",
+ "CFG_ACK",
+);
+
+typedef struct private_cp_payload_t private_cp_payload_t;
+
+/**
+ * Private data of an cp_payload_t object.
+ *
+ */
+struct private_cp_payload_t {
+ /**
+ * Public cp_payload_t interface.
+ */
+ cp_payload_t public;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * List of attributes, as configuration_attribute_t
+ */
+ linked_list_t *attributes;
+
+ /**
+ * Config Type.
+ */
+ u_int8_t type;
+};
+
+/**
+ * Encoding rules to parse or generate a IKEv2-CP Payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_cp_payload_t.
+ *
+ */
+encoding_rule_t cp_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_cp_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_cp_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 CP payload*/
+ { PAYLOAD_LENGTH, offsetof(private_cp_payload_t, payload_length) },
+ /* Proposals are stored in a proposal substructure,
+ offset points to a linked_list_t pointer */
+ { U_INT_8, offsetof(private_cp_payload_t, type) },
+ { RESERVED_BYTE,0 },
+ { RESERVED_BYTE,0 },
+ { RESERVED_BYTE,0 },
+ { CONFIGURATION_ATTRIBUTES, offsetof(private_cp_payload_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
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! CFG Type ! RESERVED !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Configuration Attributes ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_cp_payload_t *this)
+{
+ status_t status = SUCCESS;
+ enumerator_t *enumerator;
+ payload_t *attribute;
+
+ enumerator = this->attributes->create_enumerator(this->attributes);
+ while (enumerator->enumerate(enumerator, &attribute))
+ {
+ status = attribute->verify(attribute);
+ if (status != SUCCESS)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return status;
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_cp_payload_t *this,
+ encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = cp_payload_encodings;
+ *rule_count = sizeof(cp_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(private_cp_payload_t *this)
+{
+ return CONFIGURATION;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_cp_payload_t *this)
+{
+ return this->next_payload;
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_cp_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * recompute the length of the payload.
+ */
+static void compute_length(private_cp_payload_t *this)
+{
+ enumerator_t *enumerator;
+ payload_t *attribute;
+
+ this->payload_length = CP_PAYLOAD_HEADER_LENGTH;
+
+ enumerator = this->attributes->create_enumerator(this->attributes);
+ while (enumerator->enumerate(enumerator, &attribute))
+ {
+ this->payload_length += attribute->get_length(attribute);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_cp_payload_t *this)
+{
+ return this->payload_length;
+}
+
+/**
+ * Implementation of cp_payload_t.create_attribute_enumerator.
+ */
+static enumerator_t *create_attribute_enumerator(private_cp_payload_t *this)
+{
+ return this->attributes->create_enumerator(this->attributes);
+}
+
+/**
+ * Implementation of cp_payload_t.add_attribute.
+ */
+static void add_attribute(private_cp_payload_t *this,
+ configuration_attribute_t *attribute)
+{
+ this->attributes->insert_last(this->attributes, attribute);
+ compute_length(this);
+}
+
+/**
+ * Implementation of cp_payload_t.get_type.
+ */
+static config_type_t get_config_type(private_cp_payload_t *this)
+{
+ return this->type;
+}
+
+/**
+ * Implementation of payload_t.destroy and cp_payload_t.destroy.
+ */
+static void destroy(private_cp_payload_t *this)
+{
+ this->attributes->destroy_offset(this->attributes,
+ offsetof(configuration_attribute_t, destroy));
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+cp_payload_t *cp_payload_create()
+{
+ private_cp_payload_t *this = malloc_thing(private_cp_payload_t);
+
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (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 = (void (*) (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 = (void (*) (payload_t *))destroy;
+
+ this->public.create_attribute_enumerator = (enumerator_t*(*)(cp_payload_t *))create_attribute_enumerator;
+ this->public.add_attribute = (void (*) (cp_payload_t *,configuration_attribute_t*))add_attribute;
+ this->public.get_type = (config_type_t (*) (cp_payload_t *))get_config_type;
+ this->public.destroy = (void (*)(cp_payload_t *))destroy;
+
+ /* set default values of the fields */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = CP_PAYLOAD_HEADER_LENGTH;
+ this->attributes = linked_list_create();
+ this->type = CFG_REQUEST;
+
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+cp_payload_t *cp_payload_create_type(config_type_t type)
+{
+ private_cp_payload_t *this = (private_cp_payload_t*)cp_payload_create();
+
+ this->type = type;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/encoding/payloads/cp_payload.h b/src/libcharon/encoding/payloads/cp_payload.h
new file mode 100644
index 000000000..c0760885a
--- /dev/null
+++ b/src/libcharon/encoding/payloads/cp_payload.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup cp_payload cp_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef CP_PAYLOAD_H_
+#define CP_PAYLOAD_H_
+
+typedef enum config_type_t config_type_t;
+typedef struct cp_payload_t cp_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/configuration_attribute.h>
+#include <utils/enumerator.h>
+
+/**
+ * CP_PAYLOAD length in bytes without any proposal substructure.
+ */
+#define CP_PAYLOAD_HEADER_LENGTH 8
+
+/**
+ * Config Type of an Configuration Payload.
+ */
+enum config_type_t {
+ CFG_REQUEST = 1,
+ CFG_REPLY = 2,
+ CFG_SET = 3,
+ CFG_ACK = 4,
+};
+
+/**
+ * enum name for config_type_t.
+ */
+extern enum_name_t *config_type_names;
+
+/**
+ * Class representing an IKEv2-CP Payload.
+ *
+ * The CP Payload format is described in RFC section 3.15.
+ */
+struct cp_payload_t {
+
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Creates an iterator of stored configuration_attribute_t objects.
+ *
+ * @return enumerator over configration_attribute_T
+ */
+ enumerator_t *(*create_attribute_enumerator) (cp_payload_t *this);
+
+ /**
+ * Adds a configuration attribute to the configuration payload.
+ *
+ * @param attribute attribute to add
+ */
+ void (*add_attribute)(cp_payload_t *this,
+ configuration_attribute_t *attribute);
+
+ /**
+ * Get the configuration payload type.
+ *
+ * @return type of configuration payload
+ */
+ config_type_t (*get_type) (cp_payload_t *this);
+
+ /**
+ * Destroys an cp_payload_t object.
+ */
+ void (*destroy) (cp_payload_t *this);
+};
+
+/**
+ * Creates an empty configuration payload
+ *
+ * @return empty configuration payload
+ */
+cp_payload_t *cp_payload_create();
+
+/**
+ * Creates an cp_payload_t with type and value
+ *
+ * @param type type of configuration payload to create
+ * @return created configuration payload
+ */
+cp_payload_t *cp_payload_create_type(config_type_t config_type);
+
+#endif /** CP_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/delete_payload.c b/src/libcharon/encoding/payloads/delete_payload.c
new file mode 100644
index 000000000..97b4743b2
--- /dev/null
+++ b/src/libcharon/encoding/payloads/delete_payload.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 <stddef.h>
+
+#include "delete_payload.h"
+
+
+typedef struct private_delete_payload_t private_delete_payload_t;
+
+/**
+ * Private data of an delete_payload_t object.
+ *
+ */
+struct private_delete_payload_t {
+ /**
+ * Public delete_payload_t interface.
+ */
+ delete_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;
+
+ /**
+ * Number of SPI's.
+ */
+ u_int16_t spi_count;
+
+ /**
+ * The contained SPI's.
+ */
+ chunk_t spis;
+
+ /**
+ * List containing u_int32_t spis
+ */
+ linked_list_t *spi_list;
+};
+
+/**
+ * Encoding rules to parse or generate a DELETE payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_delete_payload_t.
+ *
+ */
+encoding_rule_t delete_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_delete_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_delete_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_delete_payload_t, payload_length)},
+ { U_INT_8, offsetof(private_delete_payload_t, protocol_id) },
+ { U_INT_8, offsetof(private_delete_payload_t, spi_size) },
+ { U_INT_16, offsetof(private_delete_payload_t, spi_count) },
+ /* some delete data bytes, length is defined in PAYLOAD_LENGTH */
+ { SPIS, offsetof(private_delete_payload_t, spis) }
+};
+
+/*
+ 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 ! # of SPIs !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Security Parameter Index(es) (SPI) ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_delete_payload_t *this)
+{
+ switch (this->protocol_id)
+ {
+ case PROTO_AH:
+ case PROTO_ESP:
+ if (this->spi_size != 4)
+ {
+ return FAILED;
+ }
+ break;
+ case PROTO_IKE:
+ case 0:
+ /* IKE deletion has no spi assigned! */
+ if (this->spi_size != 0)
+ {
+ return FAILED;
+ }
+ break;
+ default:
+ return FAILED;
+ }
+ if (this->spis.len != (this->spi_count * this->spi_size))
+ {
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of delete_payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_delete_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = delete_payload_encodings;
+ *rule_count = sizeof(delete_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_payload_type(private_delete_payload_t *this)
+{
+ return DELETE;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_delete_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_delete_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_delete_payload_t *this)
+{
+ return this->payload_length;
+}
+
+/**
+ * Implementation of delete_payload_t.get_protocol_id.
+ */
+static protocol_id_t get_protocol_id (private_delete_payload_t *this)
+{
+ return (this->protocol_id);
+}
+
+/**
+ * Implementation of delete_payload_t.add_spi.
+ */
+static void add_spi(private_delete_payload_t *this, u_int32_t spi)
+{
+ /* only add SPIs if AH|ESP, ignore others */
+ if (this->protocol_id == PROTO_AH || this->protocol_id == PROTO_ESP)
+ {
+ this->spi_count += 1;
+ this->spis.len += this->spi_size;
+ this->spis.ptr = realloc(this->spis.ptr, this->spis.len);
+ *(u_int32_t*)(this->spis.ptr + (this->spis.len / this->spi_size - 1)) = spi;
+ if (this->spi_list)
+ {
+ /* reset SPI iterator list */
+ this->spi_list->destroy(this->spi_list);
+ this->spi_list = NULL;
+ }
+ }
+}
+
+/**
+ * Implementation of delete_payload_t.create_spi_iterator.
+ */
+static iterator_t* create_spi_iterator(private_delete_payload_t *this)
+{
+ int i;
+
+ if (this->spi_list == NULL)
+ {
+ this->spi_list = linked_list_create();
+ /* only parse SPIs if AH|ESP */
+ if (this->protocol_id == PROTO_AH || this->protocol_id == PROTO_ESP)
+ {
+ for (i = 0; i < this->spi_count; i++)
+ {
+ this->spi_list->insert_last(this->spi_list, this->spis.ptr + i *
+ this->spi_size);
+ }
+ }
+ }
+ return this->spi_list->create_iterator(this->spi_list, TRUE);
+}
+
+/**
+ * Implementation of payload_t.destroy and delete_payload_t.destroy.
+ */
+static void destroy(private_delete_payload_t *this)
+{
+ if (this->spis.ptr != NULL)
+ {
+ chunk_free(&this->spis);
+ }
+ if (this->spi_list)
+ {
+ this->spi_list->destroy(this->spi_list);
+ }
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+delete_payload_t *delete_payload_create(protocol_id_t protocol_id)
+{
+ private_delete_payload_t *this = malloc_thing(private_delete_payload_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (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 = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.destroy = (void (*) (delete_payload_t *)) destroy;
+ this->public.get_protocol_id = (protocol_id_t (*) (delete_payload_t *)) get_protocol_id;
+ this->public.add_spi = (void (*) (delete_payload_t *,u_int32_t))add_spi;
+ this->public.create_spi_iterator = (iterator_t* (*) (delete_payload_t *)) create_spi_iterator;
+
+ /* private variables */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = DELETE_PAYLOAD_HEADER_LENGTH;
+ this->protocol_id = protocol_id;
+ this->spi_size = protocol_id == PROTO_AH || protocol_id == PROTO_ESP ? 4 : 0;
+ this->spi_count = 0;
+ this->spis = chunk_empty;
+ this->spi_list = NULL;
+
+ return (&this->public);
+}
diff --git a/src/libcharon/encoding/payloads/delete_payload.h b/src/libcharon/encoding/payloads/delete_payload.h
new file mode 100644
index 000000000..3b62c1af1
--- /dev/null
+++ b/src/libcharon/encoding/payloads/delete_payload.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup delete_payload delete_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef DELETE_PAYLOAD_H_
+#define DELETE_PAYLOAD_H_
+
+typedef struct delete_payload_t delete_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/proposal_substructure.h>
+
+/**
+ * Length of a delete payload without the SPI in bytes.
+ */
+#define DELETE_PAYLOAD_HEADER_LENGTH 8
+
+/**
+ * Class representing an IKEv2 DELETE payload.
+ *
+ * The DELETE payload format is described in RFC section 3.11.
+ */
+struct delete_payload_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Get the protocol ID.
+ *
+ * @return protocol ID
+ */
+ protocol_id_t (*get_protocol_id) (delete_payload_t *this);
+
+ /**
+ * Add an SPI to the list of deleted SAs.
+ *
+ * @param spi spi to add
+ */
+ void (*add_spi) (delete_payload_t *this, u_int32_t spi);
+
+ /**
+ * Get an iterator over the SPIs.
+ *
+ * The iterate() function returns a pointer to a u_int32_t SPI.
+ *
+ * @return iterator over SPIs
+ */
+ iterator_t *(*create_spi_iterator) (delete_payload_t *this);
+
+ /**
+ * Destroys an delete_payload_t object.
+ */
+ void (*destroy) (delete_payload_t *this);
+};
+
+/**
+ * Creates an empty delete_payload_t object.
+ *
+ * @param protocol_id protocol, such as AH|ESP
+ * @return delete_payload_t object
+ */
+delete_payload_t *delete_payload_create(protocol_id_t protocol_id);
+
+#endif /** DELETE_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/eap_payload.c b/src/libcharon/encoding/payloads/eap_payload.c
new file mode 100644
index 000000000..21f34a642
--- /dev/null
+++ b/src/libcharon/encoding/payloads/eap_payload.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 <stddef.h>
+
+#include "eap_payload.h"
+
+#include <daemon.h>
+
+typedef struct private_eap_payload_t private_eap_payload_t;
+
+/**
+ * Private data of an eap_payload_t object.
+ *
+ */
+struct private_eap_payload_t {
+ /**
+ * Public eap_payload_t interface.
+ */
+ eap_payload_t public;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * EAP message data, if available
+ */
+ chunk_t data;
+};
+
+/**
+ * Encoding rules to parse or generate a EAP payload.
+ *
+ * The defined offsets are the positions in a object of type
+ * private_eap_payload_t.
+ *
+ */
+static encoding_rule_t eap_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_eap_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_eap_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_eap_payload_t, payload_length) },
+ /* chunt to data, starting at "code" */
+ { EAP_DATA, offsetof(private_eap_payload_t, 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 !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Code ! Identifier ! Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Type ! Type_Data...
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+*/
+
+METHOD(payload_t, verify, status_t,
+ private_eap_payload_t *this)
+{
+ u_int16_t length;
+ u_int8_t code;
+
+ if (this->data.len < 4)
+ {
+ DBG1(DBG_ENC, "EAP payloads EAP message too short (%d)", this->data.len);
+ return FAILED;
+ }
+ length = untoh16(this->data.ptr + 2);
+ if (this->data.len != length)
+ {
+ DBG1(DBG_ENC, "EAP payload length (%d) does not match contained "
+ "message length (%d)", this->data.len, length);
+ return FAILED;
+ }
+ code = this->data.ptr[0];
+ switch (code)
+ {
+ case EAP_REQUEST:
+ case EAP_RESPONSE:
+ {
+ if (this->data.len < 4)
+ {
+ DBG1(DBG_ENC, "EAP Request/Response does not have any data");
+ return FAILED;
+ }
+ break;
+ }
+ case EAP_SUCCESS:
+ case EAP_FAILURE:
+ {
+ if (this->data.len != 4)
+ {
+ DBG1(DBG_ENC, "EAP Success/Failure has data");
+ return FAILED;
+ }
+ break;
+ }
+ default:
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+METHOD(payload_t, get_encoding_rules, void,
+ private_eap_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = eap_payload_encodings;
+ *rule_count = sizeof(eap_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+METHOD(payload_t, get_payload_type, payload_type_t,
+ private_eap_payload_t *this)
+{
+ return EXTENSIBLE_AUTHENTICATION;
+}
+
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_eap_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+METHOD(payload_t, set_next_type, void,
+ private_eap_payload_t *this, payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+METHOD(payload_t, get_length, size_t,
+ private_eap_payload_t *this)
+{
+ return this->payload_length;
+}
+
+METHOD(eap_payload_t, get_data, chunk_t,
+ private_eap_payload_t *this)
+{
+ return this->data;
+}
+
+METHOD(eap_payload_t, set_data, void,
+ private_eap_payload_t *this, chunk_t data)
+{
+ free(this->data.ptr);
+ this->data = chunk_clone(data);
+ this->payload_length = this->data.len + 4;
+}
+
+METHOD(eap_payload_t, get_code, eap_code_t,
+ private_eap_payload_t *this)
+{
+ if (this->data.len > 0)
+ {
+ return this->data.ptr[0];
+ }
+ /* should not happen, as it is verified */
+ return 0;
+}
+
+METHOD(eap_payload_t, get_identifier, u_int8_t,
+ private_eap_payload_t *this)
+{
+ if (this->data.len > 1)
+ {
+ return this->data.ptr[1];
+ }
+ /* should not happen, as it is verified */
+ return 0;
+}
+
+METHOD(eap_payload_t, get_type, eap_type_t,
+ private_eap_payload_t *this, u_int32_t *vendor)
+{
+ eap_type_t type;
+
+ *vendor = 0;
+ if (this->data.len > 4)
+ {
+ type = this->data.ptr[4];
+ if (type != EAP_EXPANDED)
+ {
+ return type;
+ }
+ if (this->data.len >= 12)
+ {
+ *vendor = untoh32(this->data.ptr + 4) & 0x00FFFFFF;
+ return untoh32(this->data.ptr + 8);
+ }
+ }
+ return 0;
+}
+
+METHOD2(payload_t, eap_payload_t, destroy, void,
+ private_eap_payload_t *this)
+{
+ chunk_free(&this->data);
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+eap_payload_t *eap_payload_create()
+{
+ private_eap_payload_t *this;
+
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .get_length = _get_length,
+ .get_next_type = _get_next_type,
+ .set_next_type = _set_next_type,
+ .get_type = _get_payload_type,
+ .destroy = _destroy,
+ },
+ .get_data = _get_data,
+ .set_data = _set_data,
+ .get_code = _get_code,
+ .get_identifier = _get_identifier,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ .next_payload = NO_PAYLOAD,
+ .payload_length = EAP_PAYLOAD_HEADER_LENGTH,
+ );
+ return &this->public;
+}
+
+/*
+ * Described in header
+ */
+eap_payload_t *eap_payload_create_data(chunk_t data)
+{
+ eap_payload_t *this = eap_payload_create();
+
+ this->set_data(this, data);
+ return this;
+}
+
+/*
+ * Described in header
+ */
+eap_payload_t *eap_payload_create_code(eap_code_t code, u_int8_t identifier)
+{
+ chunk_t data;
+
+ data = chunk_from_chars(code, identifier, 0, 0);
+ htoun16(data.ptr + 2, data.len);
+ return eap_payload_create_data(data);
+}
+
+/*
+ * Described in header
+ */
+eap_payload_t *eap_payload_create_nak(u_int8_t identifier)
+{
+ chunk_t data;
+
+ data = chunk_from_chars(EAP_RESPONSE, identifier, 0, 0, EAP_NAK);
+ htoun16(data.ptr + 2, data.len);
+ return eap_payload_create_data(data);
+}
+
diff --git a/src/libcharon/encoding/payloads/eap_payload.h b/src/libcharon/encoding/payloads/eap_payload.h
new file mode 100644
index 000000000..0bde4b15e
--- /dev/null
+++ b/src/libcharon/encoding/payloads/eap_payload.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup eap_payload eap_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef EAP_PAYLOAD_H_
+#define EAP_PAYLOAD_H_
+
+typedef struct eap_payload_t eap_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+#include <sa/authenticators/eap/eap_method.h>
+
+/**
+ * Length of a EAP payload without the EAP Message in bytes.
+ */
+#define EAP_PAYLOAD_HEADER_LENGTH 4
+
+/**
+ * Class representing an IKEv2 EAP payload.
+ *
+ * The EAP payload format is described in RFC section 3.16.
+ */
+struct eap_payload_t {
+
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Set the contained EAP data.
+ *
+ * This contains the FULL EAP message starting with "code".
+ * Chunk gets cloned.
+ *
+ * @param message EAP data
+ */
+ void (*set_data) (eap_payload_t *this, chunk_t data);
+
+ /**
+ * Get the contained EAP data.
+ *
+ * This contains the FULL EAP message starting with "code".
+ *
+ * @return EAP data (pointer to internal data)
+ */
+ chunk_t (*get_data) (eap_payload_t *this);
+
+ /**
+ * Get the EAP code.
+ *
+ * @return EAP message as chunk_t
+ */
+ eap_code_t (*get_code) (eap_payload_t *this);
+
+ /**
+ * Get the EAP identifier.
+ *
+ * @return unique identifier
+ */
+ u_int8_t (*get_identifier) (eap_payload_t *this);
+
+ /**
+ * Get the EAP method type.
+ *
+ * @param vendor pointer receiving vendor identifier
+ * @return EAP method type, vendor specific if vendor != 0
+ */
+ eap_type_t (*get_type) (eap_payload_t *this, u_int32_t *vendor);
+
+ /**
+ * Destroys an eap_payload_t object.
+ */
+ void (*destroy) (eap_payload_t *this);
+};
+
+/**
+ * Creates an empty eap_payload_t object.
+ *
+ * @return eap_payload_t object
+ */
+eap_payload_t *eap_payload_create(void);
+
+/**
+ * Creates an eap_payload_t object with data.
+ *
+ * @return eap_payload_t object
+ */
+eap_payload_t *eap_payload_create_data(chunk_t data);
+
+/**
+ * Creates an eap_payload_t object with a code.
+ *
+ * Could should be either EAP_SUCCESS/EAP_FAILURE, use
+ * constructor above otherwise.
+ *
+ * @param code EAP status code
+ * @param identifier EAP identifier to use in payload
+ * @return eap_payload_t object
+ */
+eap_payload_t *eap_payload_create_code(eap_code_t code, u_int8_t identifier);
+
+/**
+ * Creates an eap_payload_t EAP_RESPONSE containing an EAP_NAK.
+ *
+ * @param identifier EAP identifier to use in payload
+ * @return eap_payload_t object
+ */
+eap_payload_t *eap_payload_create_nak(u_int8_t identifier);
+
+#endif /** EAP_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/encodings.c b/src/libcharon/encoding/payloads/encodings.c
new file mode 100644
index 000000000..85caeda82
--- /dev/null
+++ b/src/libcharon/encoding/payloads/encodings.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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"
+
+ENUM(encoding_type_names, U_INT_4, ENCRYPTED_DATA,
+ "U_INT_4",
+ "U_INT_8",
+ "U_INT_16",
+ "U_INT_32",
+ "RESERVED_BIT",
+ "RESERVED_BYTE",
+ "FLAG",
+ "PAYLOAD_LENGTH",
+ "HEADER_LENGTH",
+ "SPI_SIZE",
+ "SPI",
+ "KEY_EXCHANGE_DATA",
+ "NOTIFICATION_DATA",
+ "PROPOSALS",
+ "TRANSFORMS",
+ "TRANSFORM_ATTRIBUTES",
+ "CONFIGURATION_ATTRIBUTES",
+ "CONFIGURATION_ATTRIBUTE_VALUE",
+ "ATTRIBUTE_FORMAT",
+ "ATTRIBUTE_TYPE",
+ "ATTRIBUTE_LENGTH_OR_VALUE",
+ "CONFIGURATION_ATTRIBUTE_LENGTH",
+ "ATTRIBUTE_VALUE",
+ "TRAFFIC_SELECTORS",
+ "TS_TYPE",
+ "ADDRESS",
+ "NONCE_DATA",
+ "ID_DATA",
+ "AUTH_DATA",
+ "CERT_DATA",
+ "CERTREQ_DATA",
+ "EAP_DATA",
+ "SPIS",
+ "VID_DATA",
+ "UNKNOWN_DATA",
+ "IKE_SPI",
+ "ENCRYPTED_DATA",
+);
diff --git a/src/libcharon/encoding/payloads/encodings.h b/src/libcharon/encoding/payloads/encodings.h
new file mode 100644
index 000000000..52af4a984
--- /dev/null
+++ b/src/libcharon/encoding/payloads/encodings.h
@@ -0,0 +1,515 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup encodings encodings
+ * @{ @ingroup payloads
+ */
+
+#ifndef ENCODINGS_H_
+#define ENCODINGS_H_
+
+typedef enum encoding_type_t encoding_type_t;
+typedef struct encoding_rule_t encoding_rule_t;
+
+#include <library.h>
+
+/**
+ * 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.
+ *
+ * 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 IKEv2-Draft for more informations.
+ */
+enum encoding_type_t {
+
+ /**
+ * 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,
+
+ /**
+ * 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,
+
+ /**
+ * 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,
+
+ /**
+ * Representating one or more Attributes of a configuration payload.
+ *
+ * The offset points to a linked_list_t pointer.
+ *
+ * When generating the configuration_attribute_t objects are stored
+ * in the pointed linked_list.
+ *
+ * When parsing the parsed configuration_attribute_t objects have
+ * to be stored in the pointed linked_list.
+ */
+ CONFIGURATION_ATTRIBUTES,
+
+ /**
+ *
+ * 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.
+ */
+ CONFIGURATION_ATTRIBUTE_VALUE,
+
+ /**
+ * 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,
+
+ /**
+ * This field contains the length or the value of an configuration 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.
+ */
+ CONFIGURATION_ATTRIBUTE_LENGTH,
+
+ /**
+ * 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 one or more Traffic selectors of a TS payload.
+ *
+ * The offset points to a linked_list_t pointer.
+ *
+ * When generating the traffic_selector_substructure_t objects are stored
+ * in the pointed linked_list.
+ *
+ * When parsing the parsed traffic_selector_substructure_t objects have
+ * to be stored in the pointed linked_list.
+ */
+ TRAFFIC_SELECTORS,
+
+ /**
+ * Representating a Traffic selector type 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.
+ */
+ TS_TYPE,
+
+ /**
+ * Representating an address field in a traffic selector.
+ *
+ * Depending on the last field of type TS_TYPE
+ * this field is either 4 or 16 byte long.
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing 4 or 16 bytes are read and written into the chunk pointing to.
+ */
+ ADDRESS,
+
+ /**
+ * 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 a ID 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.
+ */
+ ID_DATA,
+
+ /**
+ * Representating a AUTH 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.
+ */
+ AUTH_DATA,
+
+ /**
+ * Representating a CERT Data field.
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing (Payload Length - 5) bytes are read and written into the chunk pointing to.
+ */
+ CERT_DATA,
+
+ /**
+ * Representating a CERTREQ Data field.
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing (Payload Length - 5) bytes are read and written into the chunk pointing to.
+ */
+ CERTREQ_DATA,
+
+ /**
+ * Representating an EAP message 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.
+ */
+ EAP_DATA,
+
+ /**
+ * Representating the SPIS field in a DELETE payload.
+ *
+ * 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.
+ */
+ SPIS,
+
+ /**
+ * Representating the VID DATA field in a VENDOR ID payload.
+ *
+ * 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.
+ */
+ VID_DATA,
+
+ /**
+ * Representating the DATA of an unknown payload.
+ *
+ * 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.
+ */
+ UNKNOWN_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,
+
+ /**
+ * Representing the encrypted data body of a encryption payload.
+ */
+ ENCRYPTED_DATA,
+};
+
+/**
+ * enum name for encoding_type_t
+ */
+extern enum_name_t *encoding_type_names;
+
+/**
+ * Rule how to en-/decode a payload field.
+ *
+ * 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.
+ * This rules are used by parser and generator.
+ */
+struct encoding_rule_t {
+
+ /**
+ * 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/src/libcharon/encoding/payloads/encryption_payload.c b/src/libcharon/encoding/payloads/encryption_payload.c
new file mode 100644
index 000000000..2adbb88b9
--- /dev/null
+++ b/src/libcharon/encoding/payloads/encryption_payload.c
@@ -0,0 +1,619 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 <stddef.h>
+#include <string.h>
+
+#include "encryption_payload.h"
+
+#include <daemon.h>
+#include <encoding/payloads/encodings.h>
+#include <utils/linked_list.h>
+#include <encoding/generator.h>
+#include <encoding/parser.h>
+#include <utils/iterator.h>
+#include <crypto/signers/signer.h>
+
+
+typedef struct private_encryption_payload_t private_encryption_payload_t;
+
+/**
+ * Private data of an encryption_payload_t' Object.
+ *
+ */
+struct private_encryption_payload_t {
+
+ /**
+ * Public encryption_payload_t interface.
+ */
+ encryption_payload_t public;
+
+ /**
+ * There is no next payload for an encryption payload,
+ * since encryption payload MUST be the last one.
+ * next_payload means here the first payload of the
+ * contained, encrypted payload.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload
+ */
+ u_int16_t payload_length;
+
+ /**
+ * Chunk containing the iv, data, padding,
+ * and (an eventually not calculated) signature.
+ */
+ chunk_t encrypted;
+
+ /**
+ * Chunk containing the data in decrypted (unpadded) form.
+ */
+ chunk_t decrypted;
+
+ /**
+ * Signer set by set_signer.
+ */
+ signer_t *signer;
+
+ /**
+ * Crypter, supplied by encrypt/decrypt
+ */
+ crypter_t *crypter;
+
+ /**
+ * Contained payloads of this encrpytion_payload.
+ */
+ linked_list_t *payloads;
+};
+
+/**
+ * Encoding rules to parse or generate a IKEv2-Encryption Payload.
+ *
+ * The defined offsets are the positions in a object of type
+ * private_encryption_payload_t.
+ *
+ */
+encoding_rule_t encryption_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_encryption_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_encryption_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 encryption payload*/
+ { PAYLOAD_LENGTH, offsetof(private_encryption_payload_t, payload_length) },
+ /* encrypted data, stored in a chunk. contains iv, data, padding */
+ { ENCRYPTED_DATA, offsetof(private_encryption_payload_t, encrypted) },
+};
+
+/*
+ 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 !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Initialization Vector !
+ ! (length is block size for encryption algorithm) !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Encrypted IKE Payloads !
+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! ! Padding (0-255 octets) !
+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
+ ! ! Pad Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ~ Integrity Checksum Data ~
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_encryption_payload_t *this)
+{
+ return SUCCESS;
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_encryption_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = encryption_payload_encodings;
+ *rule_count = sizeof(encryption_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(private_encryption_payload_t *this)
+{
+ return ENCRYPTED;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_encryption_payload_t *this)
+{
+ /* returns first contained payload here */
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_encryption_payload_t *this, payload_type_t type)
+{
+ /* set next type is not allowed, since this payload MUST be the last one
+ * and so nothing is done in here*/
+}
+
+/**
+ * (re-)compute the lenght of the whole payload
+ */
+static void compute_length(private_encryption_payload_t *this)
+{
+ iterator_t *iterator;
+ payload_t *current_payload;
+ size_t block_size, length = 0;
+ iterator = this->payloads->create_iterator(this->payloads, TRUE);
+
+ /* count payload length */
+ while (iterator->iterate(iterator, (void **) &current_payload))
+ {
+ length += current_payload->get_length(current_payload);
+ }
+ iterator->destroy(iterator);
+
+ if (this->crypter && this->signer)
+ {
+ /* append one byte for padding length */
+ length++;
+ /* append padding */
+ block_size = this->crypter->get_block_size(this->crypter);
+ length += block_size - length % block_size;
+ /* add iv */
+ length += block_size;
+ /* add signature */
+ length += this->signer->get_block_size(this->signer);
+ }
+ length += ENCRYPTION_PAYLOAD_HEADER_LENGTH;
+ this->payload_length = length;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_encryption_payload_t *this)
+{
+ compute_length(this);
+ return this->payload_length;
+}
+
+/**
+ * Implementation of payload_t.create_payload_iterator.
+ */
+static iterator_t *create_payload_iterator (private_encryption_payload_t *this, bool forward)
+{
+ return (this->payloads->create_iterator(this->payloads, forward));
+}
+
+/**
+ * Implementation of payload_t.add_payload.
+ */
+static void add_payload(private_encryption_payload_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);
+ last_payload->set_next_type(last_payload, payload->get_type(payload));
+ }
+ else
+ {
+ this->next_payload = payload->get_type(payload);
+ }
+ payload->set_next_type(payload, NO_PAYLOAD);
+ this->payloads->insert_last(this->payloads, (void*)payload);
+ compute_length(this);
+}
+
+/**
+ * Implementation of encryption_payload_t.remove_first_payload.
+ */
+static status_t remove_first_payload(private_encryption_payload_t *this, payload_t **payload)
+{
+ return this->payloads->remove_first(this->payloads, (void**)payload);
+}
+
+/**
+ * Implementation of encryption_payload_t.get_payload_count.
+ */
+static size_t get_payload_count(private_encryption_payload_t *this)
+{
+ return this->payloads->get_count(this->payloads);
+}
+
+/**
+ * Generate payload before encryption.
+ */
+static void generate(private_encryption_payload_t *this)
+{
+ payload_t *current_payload, *next_payload;
+ generator_t *generator;
+ iterator_t *iterator;
+
+ /* recalculate length before generating */
+ compute_length(this);
+
+ /* create iterator */
+ iterator = this->payloads->create_iterator(this->payloads, TRUE);
+
+ /* get first payload */
+ if (iterator->iterate(iterator, (void**)&current_payload))
+ {
+ this->next_payload = current_payload->get_type(current_payload);
+ }
+ else
+ {
+ /* no paylads? */
+ DBG2(DBG_ENC, "generating contained payloads, but none available");
+ free(this->decrypted.ptr);
+ this->decrypted = chunk_empty;
+ iterator->destroy(iterator);
+ return;
+ }
+
+ generator = generator_create();
+
+ /* build all payload, except last */
+ while(iterator->iterate(iterator, (void**)&next_payload))
+ {
+ current_payload->set_next_type(current_payload, next_payload->get_type(next_payload));
+ generator->generate_payload(generator, current_payload);
+ current_payload = next_payload;
+ }
+ iterator->destroy(iterator);
+
+ /* build last payload */
+ current_payload->set_next_type(current_payload, NO_PAYLOAD);
+ generator->generate_payload(generator, current_payload);
+
+ /* free already generated data */
+ free(this->decrypted.ptr);
+
+ generator->write_to_chunk(generator, &(this->decrypted));
+ generator->destroy(generator);
+ DBG2(DBG_ENC, "successfully generated content in encryption payload");
+}
+
+/**
+ * Implementation of encryption_payload_t.encrypt.
+ */
+static status_t encrypt(private_encryption_payload_t *this)
+{
+ chunk_t iv, padding, to_crypt, result;
+ rng_t *rng;
+ size_t block_size;
+
+ if (this->signer == NULL || this->crypter == NULL)
+ {
+ DBG1(DBG_ENC, "could not encrypt, signer/crypter not set");
+ return INVALID_STATE;
+ }
+
+ /* for random data in iv and padding */
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng)
+ {
+ DBG1(DBG_ENC, "could not encrypt, no RNG found");
+ return FAILED;
+ }
+ /* build payload chunk */
+ generate(this);
+
+ DBG2(DBG_ENC, "encrypting payloads");
+ DBG3(DBG_ENC, "data to encrypt %B", &this->decrypted);
+
+ /* build padding */
+ block_size = this->crypter->get_block_size(this->crypter);
+ padding.len = block_size - ((this->decrypted.len + 1) % block_size);
+ rng->allocate_bytes(rng, padding.len, &padding);
+
+ /* concatenate payload data, padding, padding len */
+ to_crypt.len = this->decrypted.len + padding.len + 1;
+ to_crypt.ptr = malloc(to_crypt.len);
+
+ memcpy(to_crypt.ptr, this->decrypted.ptr, this->decrypted.len);
+ memcpy(to_crypt.ptr + this->decrypted.len, padding.ptr, padding.len);
+ *(to_crypt.ptr + to_crypt.len - 1) = padding.len;
+
+ /* build iv */
+ iv.len = block_size;
+ rng->allocate_bytes(rng, iv.len, &iv);
+ rng->destroy(rng);
+
+ DBG3(DBG_ENC, "data before encryption with padding %B", &to_crypt);
+
+ /* encrypt to_crypt chunk */
+ free(this->encrypted.ptr);
+ this->crypter->encrypt(this->crypter, to_crypt, iv, &result);
+ free(padding.ptr);
+ free(to_crypt.ptr);
+
+ DBG3(DBG_ENC, "data after encryption %B", &result);
+
+ /* build encrypted result with iv and signature */
+ this->encrypted.len = iv.len + result.len + this->signer->get_block_size(this->signer);
+ free(this->encrypted.ptr);
+ this->encrypted.ptr = malloc(this->encrypted.len);
+
+ /* fill in result, signature is left out */
+ memcpy(this->encrypted.ptr, iv.ptr, iv.len);
+ memcpy(this->encrypted.ptr + iv.len, result.ptr, result.len);
+
+ free(result.ptr);
+ free(iv.ptr);
+ DBG3(DBG_ENC, "data after encryption with IV and (invalid) signature %B",
+ &this->encrypted);
+
+ return SUCCESS;
+}
+
+/**
+ * Parse the payloads after decryption.
+ */
+static status_t parse(private_encryption_payload_t *this)
+{
+ parser_t *parser;
+ status_t status;
+ payload_type_t current_payload_type;
+
+ /* build a parser on the decrypted data */
+ parser = parser_create(this->decrypted);
+
+ current_payload_type = this->next_payload;
+ /* parse all payloads */
+ while (current_payload_type != NO_PAYLOAD)
+ {
+ payload_t *current_payload;
+
+ status = parser->parse_payload(parser, current_payload_type, (payload_t**)&current_payload);
+ if (status != SUCCESS)
+ {
+ parser->destroy(parser);
+ return PARSE_ERROR;
+ }
+
+ status = current_payload->verify(current_payload);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "%N verification failed",
+ payload_type_names, current_payload->get_type(current_payload));
+ current_payload->destroy(current_payload);
+ parser->destroy(parser);
+ return VERIFY_ERROR;
+ }
+
+ /* get next payload type */
+ current_payload_type = current_payload->get_next_type(current_payload);
+
+ this->payloads->insert_last(this->payloads,current_payload);
+ }
+ parser->destroy(parser);
+ DBG2(DBG_ENC, "succesfully parsed content of encryption payload");
+ return SUCCESS;
+}
+
+/**
+ * Implementation of encryption_payload_t.encrypt.
+ */
+static status_t decrypt(private_encryption_payload_t *this)
+{
+ chunk_t iv, concatenated;
+ u_int8_t padding_length;
+
+ DBG2(DBG_ENC, "decrypting encryption payload");
+ DBG3(DBG_ENC, "data before decryption with IV and (invalid) signature %B",
+ &this->encrypted);
+
+ if (this->signer == NULL || this->crypter == NULL)
+ {
+ DBG1(DBG_ENC, "could not decrypt, no crypter/signer set");
+ return INVALID_STATE;
+ }
+
+ /* get IV */
+ iv.len = this->crypter->get_block_size(this->crypter);
+
+ iv.ptr = this->encrypted.ptr;
+
+ /* point concatenated to data + padding + padding_length*/
+ concatenated.ptr = this->encrypted.ptr + iv.len;
+ concatenated.len = this->encrypted.len - iv.len -
+ this->signer->get_block_size(this->signer);
+
+ /* concatenated must be a multiple of block_size of crypter */
+ if (concatenated.len < iv.len || concatenated.len % iv.len)
+ {
+ DBG1(DBG_ENC, "could not decrypt, invalid input");
+ return FAILED;
+ }
+
+ /* free previus data, if any */
+ free(this->decrypted.ptr);
+
+ DBG3(DBG_ENC, "data before decryption %B", &concatenated);
+
+ this->crypter->decrypt(this->crypter, concatenated, iv, &this->decrypted);
+
+ DBG3(DBG_ENC, "data after decryption with padding %B", &this->decrypted);
+
+ /* get padding length, sits just bevore signature */
+ padding_length = *(this->decrypted.ptr + this->decrypted.len - 1);
+ /* add one byte to the padding length, since the padding_length field is
+ * not included */
+ padding_length++;
+
+ /* check size again */
+ if (padding_length > concatenated.len || padding_length > this->decrypted.len)
+ {
+ DBG1(DBG_ENC, "decryption failed, invalid padding length found. Invalid key?");
+ /* decryption failed :-/ */
+ return FAILED;
+ }
+ this->decrypted.len -= padding_length;
+
+ /* free padding */
+ this->decrypted.ptr = realloc(this->decrypted.ptr, this->decrypted.len);
+ DBG3(DBG_ENC, "data after decryption without padding %B", &this->decrypted);
+ DBG2(DBG_ENC, "decryption successful, trying to parse content");
+ return parse(this);
+}
+
+/**
+ * Implementation of encryption_payload_t.set_transforms.
+ */
+static void set_transforms(private_encryption_payload_t *this, crypter_t* crypter, signer_t* signer)
+{
+ this->signer = signer;
+ this->crypter = crypter;
+}
+
+/**
+ * Implementation of encryption_payload_t.build_signature.
+ */
+static status_t build_signature(private_encryption_payload_t *this, chunk_t data)
+{
+ chunk_t data_without_sig = data;
+ chunk_t sig;
+
+ if (this->signer == NULL)
+ {
+ DBG1(DBG_ENC, "unable to build signature, no signer set");
+ return INVALID_STATE;
+ }
+
+ sig.len = this->signer->get_block_size(this->signer);
+ data_without_sig.len -= sig.len;
+ sig.ptr = data.ptr + data_without_sig.len;
+ DBG2(DBG_ENC, "building signature");
+ this->signer->get_signature(this->signer, data_without_sig, sig.ptr);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of encryption_payload_t.verify_signature.
+ */
+static status_t verify_signature(private_encryption_payload_t *this, chunk_t data)
+{
+ chunk_t sig, data_without_sig;
+ bool valid;
+
+ if (this->signer == NULL)
+ {
+ DBG1(DBG_ENC, "unable to verify signature, no signer set");
+ return INVALID_STATE;
+ }
+ /* find signature in data chunk */
+ sig.len = this->signer->get_block_size(this->signer);
+ if (data.len <= sig.len)
+ {
+ DBG1(DBG_ENC, "unable to verify signature, invalid input");
+ return FAILED;
+ }
+ sig.ptr = data.ptr + data.len - sig.len;
+
+ /* verify it */
+ data_without_sig.len = data.len - sig.len;
+ data_without_sig.ptr = data.ptr;
+ valid = this->signer->verify_signature(this->signer, data_without_sig, sig);
+
+ if (!valid)
+ {
+ DBG1(DBG_ENC, "signature verification failed");
+ return FAILED;
+ }
+
+ DBG2(DBG_ENC, "signature verification successful");
+ return SUCCESS;
+}
+
+/**
+ * Implementation of payload_t.destroy.
+ */
+static void destroy(private_encryption_payload_t *this)
+{
+ this->payloads->destroy_offset(this->payloads, offsetof(payload_t, destroy));
+ free(this->encrypted.ptr);
+ free(this->decrypted.ptr);
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+encryption_payload_t *encryption_payload_create()
+{
+ private_encryption_payload_t *this = malloc_thing(private_encryption_payload_t);
+
+ /* payload_t interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (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 = (void (*) (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 = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.create_payload_iterator = (iterator_t * (*) (encryption_payload_t *,bool)) create_payload_iterator;
+ this->public.add_payload = (void (*) (encryption_payload_t *,payload_t *)) add_payload;
+ this->public.remove_first_payload = (status_t (*)(encryption_payload_t*, payload_t **)) remove_first_payload;
+ this->public.get_payload_count = (size_t (*)(encryption_payload_t*)) get_payload_count;
+
+ this->public.encrypt = (status_t (*) (encryption_payload_t *)) encrypt;
+ this->public.decrypt = (status_t (*) (encryption_payload_t *)) decrypt;
+ this->public.set_transforms = (void (*) (encryption_payload_t*,crypter_t*,signer_t*)) set_transforms;
+ this->public.build_signature = (status_t (*) (encryption_payload_t*, chunk_t)) build_signature;
+ this->public.verify_signature = (status_t (*) (encryption_payload_t*, chunk_t)) verify_signature;
+ this->public.destroy = (void (*) (encryption_payload_t *)) destroy;
+
+ /* set default values of the fields */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = ENCRYPTION_PAYLOAD_HEADER_LENGTH;
+ this->encrypted = chunk_empty;
+ this->decrypted = chunk_empty;
+ this->signer = NULL;
+ this->crypter = NULL;
+ this->payloads = linked_list_create();
+
+ return (&(this->public));
+}
diff --git a/src/libcharon/encoding/payloads/encryption_payload.h b/src/libcharon/encoding/payloads/encryption_payload.h
new file mode 100644
index 000000000..ac5326b87
--- /dev/null
+++ b/src/libcharon/encoding/payloads/encryption_payload.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup encryption_payload encryption_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef ENCRYPTION_PAYLOAD_H_
+#define ENCRYPTION_PAYLOAD_H_
+
+typedef struct encryption_payload_t encryption_payload_t;
+
+#include <library.h>
+#include <crypto/crypters/crypter.h>
+#include <crypto/signers/signer.h>
+#include <encoding/payloads/payload.h>
+#include <utils/linked_list.h>
+
+/**
+ * Encrpytion payload length in bytes without IV and following data.
+ */
+#define ENCRYPTION_PAYLOAD_HEADER_LENGTH 4
+
+
+/**
+ * The encryption payload as described in RFC section 3.14.
+ *
+ * Before any crypt/decrypt/sign/verify operation can occur,
+ * the transforms must be set. After that, a parsed encryption payload
+ * can be decrypted, which also will parse the contained payloads.
+ * Encryption is done the same way, added payloads will get generated
+ * and then encrypted.
+ * For signature building, there is the FULL packet needed. Meaning it
+ * must be builded after generation of all payloads and the encryption
+ * of the encryption payload.
+ * Signature verificatin is done before decryption.
+ */
+struct encryption_payload_t {
+ /**
+ * Implements payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Creates an iterator for all contained payloads.
+ *
+ * iterator_t object has to get destroyed by the caller.
+ *
+ * @param forward iterator direction (TRUE: front to end)
+ * return created iterator_t object
+ */
+ iterator_t *(*create_payload_iterator) (encryption_payload_t *this, bool forward);
+
+ /**
+ * Adds a payload to this encryption payload.
+ *
+ * @param payload payload_t object to add
+ */
+ void (*add_payload) (encryption_payload_t *this, payload_t *payload);
+
+ /**
+ * Reove the last payload in the contained payload list.
+ *
+ * @param payload removed payload
+ * @return
+ * - SUCCESS, or
+ * - NOT_FOUND if list empty
+ */
+ status_t (*remove_first_payload) (encryption_payload_t *this, payload_t **payload);
+
+ /**
+ * Get the number of payloads.
+ *
+ * @return number of contained payloads
+ */
+ size_t (*get_payload_count) (encryption_payload_t *this);
+
+ /**
+ * Set transforms to use.
+ *
+ * To decryption, encryption, signature building and verifying,
+ * the payload needs a crypter and a signer object.
+ *
+ * @warning Do NOT call this function again after encryption, since
+ * the signer must be the same while encrypting and signature building!
+ *
+ * @param crypter crypter_t to use for data de-/encryption
+ * @param signer signer_t to use for data signing/verifying
+ */
+ void (*set_transforms) (encryption_payload_t *this, crypter_t *crypter, signer_t *signer);
+
+ /**
+ * Generate and encrypt contained payloads.
+ *
+ * This function generates the content for added payloads
+ * and encrypts them. Signature is not built, since we need
+ * additional data (the full message).
+ *
+ * @return SUCCESS, or INVALID_STATE if transforms not set
+ */
+ status_t (*encrypt) (encryption_payload_t *this);
+
+ /**
+ * Decrypt and parse contained payloads.
+ *
+ * This function decrypts the contained data. After,
+ * the payloads are parsed internally and are accessible
+ * via the iterator.
+ *
+ * @return
+ * - SUCCESS, or
+ * - INVALID_STATE if transforms not set, or
+ * - FAILED if data is invalid
+ */
+ status_t (*decrypt) (encryption_payload_t *this);
+
+ /**
+ * Build the signature.
+ *
+ * The signature is built over the FULL message, so the header
+ * and every payload (inclusive this one) must already be generated.
+ * The generated message is supplied via the data paramater.
+ *
+ * @param data chunk contains the already generated message
+ * @return
+ * - SUCCESS, or
+ * - INVALID_STATE if transforms not set
+ */
+ status_t (*build_signature) (encryption_payload_t *this, chunk_t data);
+
+ /**
+ * Verify the signature.
+ *
+ * Since the signature is built over the full message, we need
+ * this data to do the verification. The message data
+ * is supplied via the data argument.
+ *
+ * @param data chunk contains the message
+ * @return
+ * - SUCCESS, or
+ * - FAILED if signature invalid, or
+ * - INVALID_STATE if transforms not set
+ */
+ status_t (*verify_signature) (encryption_payload_t *this, chunk_t data);
+
+ /**
+ * Destroys an encryption_payload_t object.
+ */
+ void (*destroy) (encryption_payload_t *this);
+};
+
+/**
+ * Creates an empty encryption_payload_t object.
+ *
+ * @return encryption_payload_t object
+ */
+encryption_payload_t *encryption_payload_create(void);
+
+#endif /** ENCRYPTION_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/endpoint_notify.c b/src/libcharon/encoding/payloads/endpoint_notify.c
new file mode 100644
index 000000000..faec1ea71
--- /dev/null
+++ b/src/libcharon/encoding/payloads/endpoint_notify.c
@@ -0,0 +1,422 @@
+/*
+ * Copyright (C) 2007 Tobias Brunner
+ * 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 "endpoint_notify.h"
+
+#include <math.h>
+
+#include <daemon.h>
+
+typedef struct private_endpoint_notify_t private_endpoint_notify_t;
+
+/**
+ * Private data of an notify_payload_t object.
+ */
+struct private_endpoint_notify_t {
+ /**
+ * Public endpoint_notify_t interface.
+ */
+ endpoint_notify_t public;
+
+ /**
+ * Priority
+ */
+ u_int32_t priority;
+
+ /**
+ * Family
+ */
+ me_endpoint_family_t family;
+
+ /**
+ * Endpoint type
+ */
+ me_endpoint_type_t type;
+
+ /**
+ * Endpoint
+ */
+ host_t *endpoint;
+
+ /**
+ * Base (used for server reflexive endpoints)
+ */
+ host_t *base;
+};
+
+/* 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
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Priority !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Family ! Type ! Port !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! IP Address (variable) !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+ENUM(me_endpoint_type_names, HOST, RELAYED,
+ "HOST",
+ "PEER_REFLEXIVE",
+ "SERVER_REFLEXIVE",
+ "RELAYED"
+);
+
+/**
+ * Helper functions to parse integer values
+ */
+static status_t parse_uint8(u_int8_t **cur, u_int8_t *top, u_int8_t *val)
+{
+ if (*cur + sizeof(u_int8_t) > top)
+ {
+ return FAILED;
+ }
+ *val = *(u_int8_t*)*cur;
+ *cur += sizeof(u_int8_t);
+ return SUCCESS;
+}
+
+static status_t parse_uint16(u_int8_t **cur, u_int8_t *top, u_int16_t *val)
+{
+ if (*cur + sizeof(u_int16_t) > top)
+ {
+ return FAILED;
+ }
+ *val = ntohs(*(u_int16_t*)*cur);
+ *cur += sizeof(u_int16_t);
+ return SUCCESS;
+}
+
+static status_t parse_uint32(u_int8_t **cur, u_int8_t *top, u_int32_t *val)
+{
+ if (*cur + sizeof(u_int32_t) > top)
+ {
+ return FAILED;
+ }
+ *val = ntohl(*(u_int32_t*)*cur);
+ *cur += sizeof(u_int32_t);
+ return SUCCESS;
+}
+
+/**
+ * Parses the notification data of a ME_ENDPOINT notify
+ */
+static status_t parse_notification_data(private_endpoint_notify_t *this, chunk_t data)
+{
+ u_int8_t family, type, addr_family;
+ u_int16_t port;
+ chunk_t addr;
+ u_int8_t *cur = data.ptr;
+ u_int8_t *top = data.ptr + data.len;
+
+ DBG3(DBG_IKE, "me_endpoint_data %B", &data);
+
+ if (parse_uint32(&cur, top, &this->priority) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid priority");
+ return FAILED;
+ }
+
+ if (parse_uint8(&cur, top, &family) != SUCCESS || family >= MAX_FAMILY)
+ {
+ DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid family");
+ return FAILED;
+ }
+ this->family = (me_endpoint_family_t)family;
+
+ if (parse_uint8(&cur, top, &type) != SUCCESS ||
+ type == NO_TYPE || type >= MAX_TYPE)
+ {
+ DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid type");
+ return FAILED;
+ }
+ this->type = (me_endpoint_type_t)type;
+
+ addr_family = AF_INET;
+ addr.len = 4;
+
+ switch(this->family)
+ {
+ case IPv6:
+ addr_family = AF_INET6;
+ addr.len = 16;
+ /* fall-through */
+ case IPv4:
+ if (parse_uint16(&cur, top, &port) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid port");
+ return FAILED;
+ }
+
+ if (cur + addr.len > top)
+ {
+ DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid IP address");
+ return FAILED;
+ }
+
+ addr.ptr = cur;
+ this->endpoint = host_create_from_chunk(addr_family, addr, port);
+ break;
+ case NO_FAMILY:
+ default:
+ this->endpoint = NULL;
+ break;
+ }
+ return SUCCESS;
+}
+
+
+/**
+ * Generates the notification data of a ME_ENDPOINT notify
+ */
+static chunk_t build_notification_data(private_endpoint_notify_t *this)
+{
+ chunk_t prio_chunk, family_chunk, type_chunk, port_chunk, addr_chunk;
+ chunk_t data;
+ u_int32_t prio;
+ u_int16_t port;
+ u_int8_t family, type;
+
+ prio = htonl(this->priority);
+ prio_chunk = chunk_from_thing(prio);
+ family = this->family;
+ family_chunk = chunk_from_thing(family);
+ type = this->type;
+ type_chunk = chunk_from_thing(type);
+
+ if (this->endpoint)
+ {
+ port = htons(this->endpoint->get_port(this->endpoint));
+ addr_chunk = this->endpoint->get_address(this->endpoint);
+ }
+ else
+ {
+ port = 0;
+ addr_chunk = chunk_empty;
+ }
+ port_chunk = chunk_from_thing(port);
+
+ /* data = prio | family | type | port | addr */
+ data = chunk_cat("ccccc", prio_chunk, family_chunk, type_chunk,
+ port_chunk, addr_chunk);
+ DBG3(DBG_IKE, "me_endpoint_data %B", &data);
+ return data;
+}
+
+/**
+ * Implementation of endpoint_notify_t.build_notify
+ */
+static notify_payload_t *build_notify(private_endpoint_notify_t *this)
+{
+ chunk_t data;
+ notify_payload_t *notify;
+
+ notify = notify_payload_create();
+ notify->set_notify_type(notify, ME_ENDPOINT);
+ data = build_notification_data(this);
+ notify->set_notification_data(notify, data);
+ chunk_free(&data);
+
+ return notify;
+}
+
+/**
+ * Implementation of endpoint_notify_t.get_priority.
+ */
+static u_int32_t get_priority(private_endpoint_notify_t *this)
+{
+ return this->priority;
+}
+
+/**
+ * Implementation of endpoint_notify_t.set_priority.
+ */
+static void set_priority(private_endpoint_notify_t *this, u_int32_t priority)
+{
+ this->priority = priority;
+}
+
+/**
+ * Implementation of endpoint_notify_t.get_type.
+ */
+static me_endpoint_type_t get_type(private_endpoint_notify_t *this)
+{
+ return this->type;
+}
+
+/**
+ * Implementation of endpoint_notify_t.get_family.
+ */
+static me_endpoint_family_t get_family(private_endpoint_notify_t *this)
+{
+ return this->family;
+}
+
+/**
+ * Implementation of endpoint_notify_t.get_host.
+ */
+static host_t *get_host(private_endpoint_notify_t *this)
+{
+ return this->endpoint;
+}
+
+/**
+ * Implementation of endpoint_notify_t.get_base.
+ */
+static host_t *get_base(private_endpoint_notify_t *this)
+{
+ return (!this->base) ? this->endpoint : this->base;
+}
+
+/**
+ * Implementation of endpoint_notify_t.clone.
+ */
+static endpoint_notify_t *_clone(private_endpoint_notify_t *this)
+{
+ private_endpoint_notify_t *clone = (private_endpoint_notify_t*)endpoint_notify_create();
+
+ clone->priority = this->priority;
+ clone->type = this->type;
+ clone->family = this->family;
+ if (this->endpoint)
+ {
+ clone->endpoint = this->endpoint->clone(this->endpoint);
+ }
+
+ if (this->base)
+ {
+ clone->base = this->base->clone(this->base);
+ }
+
+ return &clone->public;
+}
+
+/**
+ * Implementation of endpoint_notify_t.destroy.
+ */
+static status_t destroy(private_endpoint_notify_t *this)
+{
+ DESTROY_IF(this->endpoint);
+ DESTROY_IF(this->base);
+ free(this);
+ return SUCCESS;
+}
+
+/*
+ * Described in header
+ */
+endpoint_notify_t *endpoint_notify_create()
+{
+ private_endpoint_notify_t *this = malloc_thing(private_endpoint_notify_t);
+
+ /* public functions */
+ this->public.get_priority = (u_int32_t (*) (endpoint_notify_t *)) get_priority;
+ this->public.set_priority = (void (*) (endpoint_notify_t *, u_int32_t)) set_priority;
+ this->public.get_type = (me_endpoint_type_t (*) (endpoint_notify_t *)) get_type;
+ this->public.get_family = (me_endpoint_family_t (*) (endpoint_notify_t *)) get_family;
+ this->public.get_host = (host_t *(*) (endpoint_notify_t *)) get_host;
+ this->public.get_base = (host_t *(*) (endpoint_notify_t *)) get_base;
+ this->public.build_notify = (notify_payload_t *(*) (endpoint_notify_t *)) build_notify;
+ this->public.clone = (endpoint_notify_t *(*) (endpoint_notify_t *)) _clone;
+ this->public.destroy = (void (*) (endpoint_notify_t *)) destroy;
+
+ /* set default values of the fields */
+ this->priority = 0;
+ this->family = NO_FAMILY;
+ this->type = NO_TYPE;
+ this->endpoint = NULL;
+ this->base = NULL;
+
+ return &this->public;
+}
+
+/**
+ * Described in header
+ */
+endpoint_notify_t *endpoint_notify_create_from_host(me_endpoint_type_t type, host_t *host, host_t *base)
+{
+ private_endpoint_notify_t *this = (private_endpoint_notify_t*)endpoint_notify_create();
+
+ this->type = type;
+
+ switch(type)
+ {
+ case HOST:
+ this->priority = pow(2, 16) * ME_PRIO_HOST;
+ break;
+ case PEER_REFLEXIVE:
+ this->priority = pow(2, 16) * ME_PRIO_PEER;
+ break;
+ case SERVER_REFLEXIVE:
+ this->priority = pow(2, 16) * ME_PRIO_SERVER;
+ break;
+ case RELAYED:
+ default:
+ this->priority = pow(2, 16) * ME_PRIO_RELAY;
+ break;
+ }
+
+ /* FIXME: if there is more than one ip address we should vary this priority */
+ this->priority += 65535;
+
+ if (!host)
+ {
+ return &this->public;
+ }
+
+ switch(host->get_family(host))
+ {
+ case AF_INET:
+ this->family = IPv4;
+ break;
+ case AF_INET6:
+ this->family = IPv6;
+ break;
+ default:
+ /* unsupported family type, we do not set the host
+ * (family is set to NO_FAMILY) */
+ return &this->public;
+ }
+
+ this->endpoint = host->clone(host);
+
+ if (base)
+ {
+ this->base = base->clone(base);
+ }
+
+ return &this->public;
+}
+
+/**
+ * Described in header
+ */
+endpoint_notify_t *endpoint_notify_create_from_payload(notify_payload_t *notify)
+{
+ if (notify->get_notify_type(notify) != ME_ENDPOINT)
+ {
+ return NULL;
+ }
+
+ private_endpoint_notify_t *this = (private_endpoint_notify_t*)endpoint_notify_create();
+ chunk_t data = notify->get_notification_data(notify);
+ if (parse_notification_data(this, data) != SUCCESS)
+ {
+ destroy(this);
+ return NULL;
+ }
+ return &this->public;
+}
diff --git a/src/libcharon/encoding/payloads/endpoint_notify.h b/src/libcharon/encoding/payloads/endpoint_notify.h
new file mode 100644
index 000000000..120eef49a
--- /dev/null
+++ b/src/libcharon/encoding/payloads/endpoint_notify.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2007 Tobias Brunner
+ * 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.
+ */
+
+/**
+ * @defgroup endpoint_notify endpoint_notify
+ * @{ @ingroup payloads
+ */
+
+#ifndef ENDPOINT_NOTIFY_H_
+#define ENDPOINT_NOTIFY_H_
+
+#define ME_PRIO_HOST 255
+#define ME_PRIO_PEER 128
+#define ME_PRIO_SERVER 64
+#define ME_PRIO_RELAY 0
+
+typedef enum me_endpoint_family_t me_endpoint_family_t;
+typedef enum me_endpoint_type_t me_endpoint_type_t;
+typedef struct endpoint_notify_t endpoint_notify_t;
+
+#include <encoding/payloads/notify_payload.h>
+
+/**
+ * ME endpoint families.
+ */
+enum me_endpoint_family_t {
+
+ NO_FAMILY = 0,
+
+ IPv4 = 1,
+
+ IPv6 = 2,
+
+ MAX_FAMILY = 3
+
+};
+
+/**
+ * ME endpoint types.
+ */
+enum me_endpoint_type_t {
+
+ NO_TYPE = 0,
+
+ HOST = 1,
+
+ PEER_REFLEXIVE = 2,
+
+ SERVER_REFLEXIVE = 3,
+
+ RELAYED = 4,
+
+ MAX_TYPE = 5
+
+};
+
+/**
+ * enum name for me_endpoint_type_t.
+ */
+extern enum_name_t *me_endpoint_type_names;
+
+/**
+ * Class representing a ME_ENDPOINT Notify payload. In fact it's not
+ * the notify per se, but the notification data of that notify that is
+ * handled with this class.
+ */
+struct endpoint_notify_t {
+ /**
+ * Returns the priority of this endpoint.
+ *
+ * @return priority
+ */
+ u_int32_t (*get_priority) (endpoint_notify_t *this);
+
+ /**
+ * Sets the priority of this endpoint.
+ *
+ * @param priority priority
+ */
+ void (*set_priority) (endpoint_notify_t *this, u_int32_t priority);
+
+ /**
+ * Returns the endpoint type of this endpoint.
+ *
+ * @return endpoint type
+ */
+ me_endpoint_type_t (*get_type) (endpoint_notify_t *this);
+
+ /**
+ * Returns the endpoint family of this endpoint.
+ *
+ * @return endpoint family
+ */
+ me_endpoint_family_t (*get_family) (endpoint_notify_t *this);
+
+ /**
+ * Returns the host of this endpoint.
+ *
+ * @return host
+ */
+ host_t *(*get_host) (endpoint_notify_t *this);
+
+ /**
+ * Returns the base of this endpoint.
+ *
+ * If this is not a SERVER_REFLEXIVE endpoint, the returned host is the same
+ * as the one returned by get_host.
+ *
+ * @return host
+ */
+ host_t *(*get_base) (endpoint_notify_t *this);
+
+ /**
+ * Generates a notification payload from this endpoint.
+ *
+ * @return built notify_payload_t
+ */
+ notify_payload_t *(*build_notify) (endpoint_notify_t *this);
+
+ /**
+ * Clones an endpoint_notify_t object.
+ *
+ * @return cloned object
+ */
+ endpoint_notify_t *(*clone) (endpoint_notify_t *this);
+
+ /**
+ * Destroys an endpoint_notify_t object.
+ */
+ void (*destroy) (endpoint_notify_t *this);
+};
+
+/**
+ * Creates an empty endpoint_notify_t object.
+ *
+ * @return created endpoint_notify_t object
+ */
+endpoint_notify_t *endpoint_notify_create(void);
+
+
+/**
+ * Creates an endpoint_notify_t object from a host.
+ *
+ * @param type the endpoint type
+ * @param host host to base the notify on (gets cloned)
+ * @param base base of the endpoint, applies only to reflexive endpoints (gets cloned)
+ * @return created endpoint_notify_t object
+ */
+endpoint_notify_t *endpoint_notify_create_from_host(me_endpoint_type_t type,
+ host_t *host, host_t *base);
+
+/**
+ * Creates an endpoint_notify_t object from a notify payload.
+ *
+ * @param notify the notify payload
+ * @return - created endpoint_notify_t object
+ * - NULL if invalid payload
+ */
+endpoint_notify_t *endpoint_notify_create_from_payload(notify_payload_t *notify);
+
+#endif /** ENDPOINT_NOTIFY_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/id_payload.c b/src/libcharon/encoding/payloads/id_payload.c
new file mode 100644
index 000000000..4158c3e07
--- /dev/null
+++ b/src/libcharon/encoding/payloads/id_payload.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ *
+ * 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 <stddef.h>
+
+#include "id_payload.h"
+
+#include <daemon.h>
+#include <encoding/payloads/encodings.h>
+
+typedef struct private_id_payload_t private_id_payload_t;
+
+/**
+ * Private data of an id_payload_t object.
+ *
+ */
+struct private_id_payload_t {
+ /**
+ * Public id_payload_t interface.
+ */
+ id_payload_t public;
+
+ /**
+ * one of ID_INITIATOR, ID_RESPONDER
+ */
+ payload_type_t payload_type;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * Type of the ID Data.
+ */
+ u_int8_t id_type;
+
+ /**
+ * The contained id data value.
+ */
+ chunk_t id_data;
+};
+
+/**
+ * Encoding rules to parse or generate a ID payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_id_payload_t.
+ *
+ */
+encoding_rule_t id_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_id_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_id_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_id_payload_t, payload_length) },
+ /* 1 Byte ID type*/
+ { U_INT_8, offsetof(private_id_payload_t, id_type) },
+ /* 3 reserved bytes */
+ { RESERVED_BYTE, 0 },
+ { RESERVED_BYTE, 0 },
+ { RESERVED_BYTE, 0 },
+ /* some id data bytes, length is defined in PAYLOAD_LENGTH */
+ { ID_DATA, offsetof(private_id_payload_t, id_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 !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! ID Type ! RESERVED |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Identification Data ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_id_payload_t *this)
+{
+ if ((this->id_type == 0) ||
+ (this->id_type == 4) ||
+ ((this->id_type >= 6) && (this->id_type <= 8)) ||
+ ((this->id_type >= 12) && (this->id_type <= 200)))
+ {
+ /* reserved IDs */
+ DBG1(DBG_ENC, "received ID with reserved type %d", this->id_type);
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of id_payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_id_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = id_payload_encodings;
+ *rule_count = sizeof(id_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_payload_type(private_id_payload_t *this)
+{
+ return this->payload_type;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_id_payload_t *this)
+{
+ return this->next_payload;
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_id_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_id_payload_t *this)
+{
+ return this->payload_length;
+}
+
+/**
+ * Implementation of id_payload_t.set_type.
+ */
+static void set_id_type (private_id_payload_t *this, id_type_t type)
+{
+ this->id_type = type;
+}
+
+/**
+ * Implementation of id_payload_t.get_id_type.
+ */
+static id_type_t get_id_type (private_id_payload_t *this)
+{
+ return (this->id_type);
+}
+
+/**
+ * Implementation of id_payload_t.set_data.
+ */
+static void set_data (private_id_payload_t *this, chunk_t data)
+{
+ if (this->id_data.ptr != NULL)
+ {
+ chunk_free(&(this->id_data));
+ }
+ this->id_data.ptr = clalloc(data.ptr,data.len);
+ this->id_data.len = data.len;
+ this->payload_length = ID_PAYLOAD_HEADER_LENGTH + this->id_data.len;
+}
+
+
+/**
+ * Implementation of id_payload_t.get_data_clone.
+ */
+static chunk_t get_data (private_id_payload_t *this)
+{
+ return (this->id_data);
+}
+
+/**
+ * Implementation of id_payload_t.get_data_clone.
+ */
+static chunk_t get_data_clone (private_id_payload_t *this)
+{
+ chunk_t cloned_data;
+ if (this->id_data.ptr == NULL)
+ {
+ return (this->id_data);
+ }
+ cloned_data.ptr = clalloc(this->id_data.ptr,this->id_data.len);
+ cloned_data.len = this->id_data.len;
+ return cloned_data;
+}
+
+/**
+ * Implementation of id_payload_t.get_identification.
+ */
+static identification_t *get_identification (private_id_payload_t *this)
+{
+ return identification_create_from_encoding(this->id_type,this->id_data);
+}
+
+/**
+ * Implementation of payload_t.destroy and id_payload_t.destroy.
+ */
+static void destroy(private_id_payload_t *this)
+{
+ if (this->id_data.ptr != NULL)
+ {
+ chunk_free(&(this->id_data));
+ }
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+id_payload_t *id_payload_create(payload_type_t payload_type)
+{
+ private_id_payload_t *this = malloc_thing(private_id_payload_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (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 = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.destroy = (void (*) (id_payload_t *)) destroy;
+ this->public.set_id_type = (void (*) (id_payload_t *,id_type_t)) set_id_type;
+ this->public.get_id_type = (id_type_t (*) (id_payload_t *)) get_id_type;
+ this->public.set_data = (void (*) (id_payload_t *,chunk_t)) set_data;
+ this->public.get_data = (chunk_t (*) (id_payload_t *)) get_data;
+ this->public.get_data_clone = (chunk_t (*) (id_payload_t *)) get_data_clone;
+
+ this->public.get_identification = (identification_t * (*) (id_payload_t *this)) get_identification;
+
+ /* private variables */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length =ID_PAYLOAD_HEADER_LENGTH;
+ this->id_data = chunk_empty;
+ this->payload_type = payload_type;
+
+ return (&(this->public));
+}
+
+/*
+ * Described in header.
+ */
+id_payload_t *id_payload_create_from_identification(payload_type_t payload_type, identification_t *identification)
+{
+ id_payload_t *this= id_payload_create(payload_type);
+ this->set_data(this,identification->get_encoding(identification));
+ this->set_id_type(this,identification->get_type(identification));
+ return this;
+}
diff --git a/src/libcharon/encoding/payloads/id_payload.h b/src/libcharon/encoding/payloads/id_payload.h
new file mode 100644
index 000000000..5502dc961
--- /dev/null
+++ b/src/libcharon/encoding/payloads/id_payload.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup id_payload id_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef ID_PAYLOAD_H_
+#define ID_PAYLOAD_H_
+
+typedef struct id_payload_t id_payload_t;
+
+#include <library.h>
+#include <utils/identification.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * Length of a id payload without the data in bytes.
+ */
+#define ID_PAYLOAD_HEADER_LENGTH 8
+
+/**
+ * Object representing an IKEv2 ID payload.
+ *
+ * The ID payload format is described in RFC section 3.5.
+ */
+struct id_payload_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Set the ID type.
+ *
+ * @param type Type of ID
+ */
+ void (*set_id_type) (id_payload_t *this, id_type_t type);
+
+ /**
+ * Get the ID type.
+ *
+ * @return type of the ID
+ */
+ id_type_t (*get_id_type) (id_payload_t *this);
+
+ /**
+ * Set the ID data.
+ *
+ * Data are getting cloned.
+ *
+ * @param data ID data as chunk_t
+ */
+ void (*set_data) (id_payload_t *this, chunk_t data);
+
+ /**
+ * Get the ID data.
+ *
+ * Returned data are a copy of the internal one
+ *
+ * @return ID data as chunk_t
+ */
+ chunk_t (*get_data_clone) (id_payload_t *this);
+
+ /**
+ * Get the ID data.
+ *
+ * Returned data are NOT copied.
+ *
+ * @return ID data as chunk_t
+ */
+ chunk_t (*get_data) (id_payload_t *this);
+
+ /**
+ * Creates an identification object of this id payload.
+ *
+ * Returned object has to get destroyed by the caller.
+ *
+ * @return identification_t object
+ */
+ identification_t *(*get_identification) (id_payload_t *this);
+
+ /**
+ * Destroys an id_payload_t object.
+ */
+ void (*destroy) (id_payload_t *this);
+};
+
+/**
+ * Creates an empty id_payload_t object.
+ *
+ * @param payload_type one of ID_INITIATOR, ID_RESPONDER
+ * @return id_payload_t object
+ */
+id_payload_t *id_payload_create(payload_type_t payload_type);
+
+/**
+ * Creates an id_payload_t from an existing identification_t object.
+ *
+ * @param payload_type one of ID_INITIATOR, ID_RESPONDER
+ * @param identification identification_t object
+ * @return id_payload_t object
+ */
+id_payload_t *id_payload_create_from_identification(payload_type_t payload_type,
+ identification_t *identification);
+
+#endif /** ID_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/ike_header.c b/src/libcharon/encoding/payloads/ike_header.c
new file mode 100644
index 000000000..735f01304
--- /dev/null
+++ b/src/libcharon/encoding/payloads/ike_header.c
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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>
+
+
+typedef struct private_ike_header_t private_ike_header_t;
+
+/**
+ * Private data of an ike_header_t object.
+ */
+struct private_ike_header_t {
+ /**
+ * 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;
+};
+
+ENUM_BEGIN(exchange_type_names, EXCHANGE_TYPE_UNDEFINED, EXCHANGE_TYPE_UNDEFINED,
+ "EXCHANGE_TYPE_UNDEFINED");
+ENUM_NEXT(exchange_type_names, IKE_SA_INIT, INFORMATIONAL, EXCHANGE_TYPE_UNDEFINED,
+ "IKE_SA_INIT",
+ "IKE_AUTH",
+ "CREATE_CHILD_SA",
+ "INFORMATIONAL");
+#ifdef ME
+ENUM_NEXT(exchange_type_names, ME_CONNECT, ME_CONNECT, INFORMATIONAL,
+ "ME_CONNECT");
+ENUM_END(exchange_type_names, ME_CONNECT);
+#else
+ENUM_END(exchange_type_names, INFORMATIONAL);
+#endif /* ME */
+
+/**
+ * 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 !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_ike_header_t *this)
+{
+ if ((this->exchange_type < IKE_SA_INIT) ||
+ ((this->exchange_type > INFORMATIONAL)
+#ifdef ME
+ && (this->exchange_type != ME_CONNECT)
+#endif /* ME */
+ ))
+ {
+ /* unsupported exchange type */
+ return FAILED;
+ }
+
+ if (this->initiator_spi == 0
+#ifdef ME
+ /* we allow zero spi for INFORMATIONAL exchanges,
+ * to allow connectivity checks */
+ && this->exchange_type != INFORMATIONAL
+#endif /* ME */
+ )
+ {
+ /* initiator spi not set */
+ return FAILED;
+ }
+
+ /* verification of version is not done in here */
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(payload_t *this,payload_type_t type)
+{
+ ((private_ike_header_t *)this)->next_payload = type;
+}
+/**
+ * Implementation of ike_header_t.get_initiator_spi.
+ */
+static u_int64_t get_initiator_spi(private_ike_header_t *this)
+{
+ return this->initiator_spi;
+}
+
+/**
+ * Implementation of ike_header_t.set_initiator_spi.
+ */
+static void set_initiator_spi(private_ike_header_t *this, u_int64_t initiator_spi)
+{
+ this->initiator_spi = initiator_spi;
+}
+
+/**
+ * Implementation of ike_header_t.get_responder_spi.
+ */
+static u_int64_t get_responder_spi(private_ike_header_t *this)
+{
+ return this->responder_spi;
+}
+
+/**
+ * Implementation of ike_header_t.set_responder_spi.
+ */
+static void set_responder_spi(private_ike_header_t *this, u_int64_t responder_spi)
+{
+ this->responder_spi = responder_spi;
+}
+
+/**
+ * Implementation of ike_header_t.get_maj_version.
+ */
+static u_int8_t get_maj_version(private_ike_header_t *this)
+{
+ return this->maj_version;
+}
+
+/**
+ * Implementation of ike_header_t.get_min_version.
+ */
+static u_int8_t get_min_version(private_ike_header_t *this)
+{
+ return this->min_version;
+}
+
+/**
+ * Implementation of ike_header_t.get_response_flag.
+ */
+static bool get_response_flag(private_ike_header_t *this)
+{
+ return this->flags.response;
+}
+
+/**
+ * Implementation of ike_header_t.set_response_flag.
+ */
+static void set_response_flag(private_ike_header_t *this, bool response)
+{
+ this->flags.response = response;
+}
+
+/**
+ * Implementation of ike_header_t.get_version_flag.
+ */
+static bool get_version_flag(private_ike_header_t *this)
+{
+ return this->flags.version;
+}
+
+/**
+ * Implementation of ike_header_t.get_initiator_flag.
+ */
+static bool get_initiator_flag(private_ike_header_t *this)
+{
+ return this->flags.initiator;
+}
+
+/**
+ * Implementation of ike_header_t.set_initiator_flag.
+ */
+static void set_initiator_flag(private_ike_header_t *this, bool initiator)
+{
+ this->flags.initiator = initiator;
+}
+
+/**
+ * Implementation of ike_header_t.get_exchange_type.
+ */
+static u_int8_t get_exchange_type(private_ike_header_t *this)
+{
+ return this->exchange_type;
+}
+
+/**
+ * Implementation of ike_header_t.set_exchange_type.
+ */
+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;
+}
+
+/**
+ * Implementation of ike_header_t.set_message_id.
+ */
+static void set_message_id(private_ike_header_t *this, u_int32_t message_id)
+{
+ this->message_id = message_id;
+}
+
+/**
+ * Implementation of ike_header_t.destroy and payload_t.destroy.
+ */
+static void destroy(ike_header_t *this)
+{
+ free(this);
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void 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);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(payload_t *this)
+{
+ return HEADER;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(payload_t *this)
+{
+ return (((private_ike_header_t*)this)->next_payload);
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+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 = malloc_thing(private_ike_header_t);
+
+ 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 = (void (*) (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/src/libcharon/encoding/payloads/ike_header.h b/src/libcharon/encoding/payloads/ike_header.h
new file mode 100644
index 000000000..e63e8bf06
--- /dev/null
+++ b/src/libcharon/encoding/payloads/ike_header.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup ike_header ike_header
+ * @{ @ingroup payloads
+ */
+
+#ifndef IKE_HEADER_H_
+#define IKE_HEADER_H_
+
+typedef enum exchange_type_t exchange_type_t;
+typedef struct ike_header_t ike_header_t;
+
+#include <library.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
+
+/**
+ * Different types of IKE-Exchanges.
+ *
+ * See RFC for different types.
+ */
+enum exchange_type_t{
+
+ /**
+ * EXCHANGE_TYPE_UNDEFINED. In private space, since not a official message type.
+ */
+ EXCHANGE_TYPE_UNDEFINED = 255,
+
+ /**
+ * IKE_SA_INIT.
+ */
+ IKE_SA_INIT = 34,
+
+ /**
+ * IKE_AUTH.
+ */
+ IKE_AUTH = 35,
+
+ /**
+ * CREATE_CHILD_SA.
+ */
+ CREATE_CHILD_SA = 36,
+
+ /**
+ * INFORMATIONAL.
+ */
+ INFORMATIONAL = 37,
+#ifdef ME
+ /**
+ * ME_CONNECT
+ */
+ ME_CONNECT = 240
+#endif /* ME */
+};
+
+/**
+ * enum name for exchange_type_t
+ */
+extern enum_name_t *exchange_type_names;
+
+/**
+ * An object of this type represents an IKEv2 header and is used to
+ * generate and parse IKEv2 headers.
+ *
+ * The header format of an IKEv2-Message is compatible to the
+ * ISAKMP-Header format to allow implementations supporting
+ * both versions of the IKE-protocol.
+ */
+struct ike_header_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Get the initiator spi.
+ *
+ * @return initiator_spi
+ */
+ u_int64_t (*get_initiator_spi) (ike_header_t *this);
+
+ /**
+ * Set the initiator spi.
+ *
+ * @param initiator_spi initiator_spi
+ */
+ void (*set_initiator_spi) (ike_header_t *this, u_int64_t initiator_spi);
+
+ /**
+ * Get the responder spi.
+ *
+ * @return responder_spi
+ */
+ u_int64_t (*get_responder_spi) (ike_header_t *this);
+
+ /**
+ * Set the responder spi.
+ *
+ * @param responder_spi responder_spi
+ */
+ void (*set_responder_spi) (ike_header_t *this, u_int64_t responder_spi);
+
+ /**
+ * Get the major version.
+ *
+ * @return major version
+ */
+ u_int8_t (*get_maj_version) (ike_header_t *this);
+
+ /**
+ * Get the minor version.
+ *
+ * @return minor version
+ */
+ u_int8_t (*get_min_version) (ike_header_t *this);
+
+ /**
+ * Get the response flag.
+ *
+ * @return response flag
+ */
+ bool (*get_response_flag) (ike_header_t *this);
+
+ /**
+ * Set the response flag-
+ *
+ * @param response response flag
+ */
+ void (*set_response_flag) (ike_header_t *this, bool response);
+ /**
+ * Get "higher version supported"-flag.
+ *
+ * @return version flag
+ */
+ bool (*get_version_flag) (ike_header_t *this);
+
+ /**
+ * Get the initiator flag.
+ *
+ * @return initiator flag
+ */
+ bool (*get_initiator_flag) (ike_header_t *this);
+
+ /**
+ * Set the initiator flag.
+ *
+ * @param initiator initiator flag
+ */
+ void (*set_initiator_flag) (ike_header_t *this, bool initiator);
+
+ /**
+ * Get the exchange type.
+ *
+ * @return exchange type
+ */
+ u_int8_t (*get_exchange_type) (ike_header_t *this);
+
+ /**
+ * Set the exchange type.
+ *
+ * @param exchange_type exchange type
+ */
+ void (*set_exchange_type) (ike_header_t *this, u_int8_t exchange_type);
+
+ /**
+ * Get the message id.
+ *
+ * @return message id
+ */
+ u_int32_t (*get_message_id) (ike_header_t *this);
+
+ /**
+ * Set the message id.
+ *
+ * @param initiator_spi message id
+ */
+ void (*set_message_id) (ike_header_t *this, u_int32_t message_id);
+
+ /**
+ * Destroys a ike_header_t object.
+ */
+ void (*destroy) (ike_header_t *this);
+};
+
+/**
+ * Create an ike_header_t object
+ *
+ * @return ike_header_t object
+ */
+ike_header_t *ike_header_create(void);
+
+#endif /** IKE_HEADER_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/ke_payload.c b/src/libcharon/encoding/payloads/ke_payload.c
new file mode 100644
index 000000000..1bc79f084
--- /dev/null
+++ b/src/libcharon/encoding/payloads/ke_payload.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 <stddef.h>
+
+#include "ke_payload.h"
+
+#include <encoding/payloads/encodings.h>
+
+
+typedef struct private_ke_payload_t private_ke_payload_t;
+
+/**
+ * Private data of an ke_payload_t object.
+ *
+ */
+struct private_ke_payload_t {
+ /**
+ * 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.
+ */
+ u_int16_t dh_group_number;
+
+ /**
+ * Key Exchange Data of this KE payload.
+ */
+ chunk_t key_exchange_data;
+};
+
+/**
+ * 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 ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_ke_payload_t *this)
+{
+ /* dh group is not verified in here */
+ return SUCCESS;
+}
+
+/**
+ * Implementation of payload_t.destroy.
+ */
+static void destroy(private_ke_payload_t *this)
+{
+ if (this->key_exchange_data.ptr != NULL)
+ {
+ free(this->key_exchange_data.ptr);
+ }
+ free(this);
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void 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);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(private_ke_payload_t *this)
+{
+ return KEY_EXCHANGE;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_ke_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_ke_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * recompute the length of the payload.
+ */
+static void 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;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_ke_payload_t *this)
+{
+ compute_length(this);
+ return this->payload_length;
+}
+
+/**
+ * Implementation of ke_payload_t.get_key_exchange_data.
+ */
+static chunk_t get_key_exchange_data(private_ke_payload_t *this)
+{
+ return (this->key_exchange_data);
+}
+
+/**
+ * Implementation of ke_payload_t.set_key_exchange_data.
+ */
+static void 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 */
+ free(this->key_exchange_data.ptr);
+ this->key_exchange_data.ptr = NULL;
+ this->key_exchange_data.len = 0;
+
+ }
+
+ this->key_exchange_data = chunk_clone(key_exchange_data);
+ compute_length(this);
+}
+
+/**
+ * Implementation of ke_payload_t.get_dh_group_number.
+ */
+static diffie_hellman_group_t get_dh_group_number(private_ke_payload_t *this)
+{
+ return this->dh_group_number;
+}
+
+/**
+ * Implementation of ke_payload_t.set_dh_group_number.
+ */
+static void set_dh_group_number(private_ke_payload_t *this, diffie_hellman_group_t dh_group_number)
+{
+ this->dh_group_number = dh_group_number;
+}
+
+/*
+ * Described in header
+ */
+ke_payload_t *ke_payload_create()
+{
+ private_ke_payload_t *this = malloc_thing(private_ke_payload_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (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 = (void (*) (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 = (void (*) (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 = (void (*) (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 =(void (*) (ke_payload_t *,diffie_hellman_group_t)) set_dh_group_number;
+ this->public.destroy = (void (*) (ke_payload_t *)) destroy;
+
+ /* set default values of the fields */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = KE_PAYLOAD_HEADER_LENGTH;
+ this->key_exchange_data = chunk_empty;
+ this->dh_group_number = MODP_NONE;
+
+ return &this->public;
+}
+
+/*
+ * Described in header
+ */
+ke_payload_t *ke_payload_create_from_diffie_hellman(diffie_hellman_t *dh)
+{
+ private_ke_payload_t *this = (private_ke_payload_t*)ke_payload_create();
+
+ dh->get_my_public_value(dh, &this->key_exchange_data);
+ this->dh_group_number = dh->get_dh_group(dh);
+ compute_length(this);
+
+ return &this->public;
+}
diff --git a/src/libcharon/encoding/payloads/ke_payload.h b/src/libcharon/encoding/payloads/ke_payload.h
new file mode 100644
index 000000000..3ca05009e
--- /dev/null
+++ b/src/libcharon/encoding/payloads/ke_payload.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup ke_payload ke_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef KE_PAYLOAD_H_
+#define KE_PAYLOAD_H_
+
+typedef struct ke_payload_t ke_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/transform_substructure.h>
+#include <utils/linked_list.h>
+#include <crypto/diffie_hellman.h>
+
+/**
+ * KE payload length in bytes without any key exchange data.
+ */
+#define KE_PAYLOAD_HEADER_LENGTH 8
+
+/**
+ * Class representing an IKEv2-KE Payload.
+ *
+ * The KE Payload format is described in RFC section 3.4.
+ */
+struct ke_payload_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Returns the currently set key exchange data of this KE payload.
+ *
+ * @warning Returned data are not copied.
+ *
+ * @return chunk_t pointing to the value
+ */
+ chunk_t (*get_key_exchange_data) (ke_payload_t *this);
+
+ /**
+ * Sets the key exchange data of this KE payload.
+ *
+ * Value is getting copied.
+ *
+ * @param key_exchange_data chunk_t pointing to the value to set
+ */
+ void (*set_key_exchange_data) (ke_payload_t *this, chunk_t key_exchange_data);
+
+ /**
+ * Gets the Diffie-Hellman Group Number of this KE payload.
+ *
+ * @return DH Group Number of this payload
+ */
+ diffie_hellman_group_t (*get_dh_group_number) (ke_payload_t *this);
+
+ /**
+ * Sets the Diffie-Hellman Group Number of this KE payload.
+ *
+ * @param dh_group_number DH Group to set
+ */
+ void (*set_dh_group_number) (ke_payload_t *this,
+ diffie_hellman_group_t dh_group_number);
+
+ /**
+ * Destroys an ke_payload_t object.
+ */
+ void (*destroy) (ke_payload_t *this);
+};
+
+/**
+ * Creates an empty ke_payload_t object
+ *
+ * @return ke_payload_t object
+ */
+ke_payload_t *ke_payload_create(void);
+
+/**
+ * Creates a ke_payload_t from a diffie_hellman_t
+ *
+ * @param diffie_hellman diffie hellman object containing group and key
+ * @return ke_payload_t object
+ */
+ke_payload_t *ke_payload_create_from_diffie_hellman(
+ diffie_hellman_t *diffie_hellman);
+
+#endif /** KE_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/nonce_payload.c b/src/libcharon/encoding/payloads/nonce_payload.c
new file mode 100644
index 000000000..4ad5ce9dd
--- /dev/null
+++ b/src/libcharon/encoding/payloads/nonce_payload.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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>
+
+
+typedef struct private_nonce_payload_t private_nonce_payload_t;
+
+/**
+ * Private data of an nonce_payload_t object.
+ *
+ */
+struct private_nonce_payload_t {
+ /**
+ * 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;
+};
+
+/**
+ * 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 ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_nonce_payload_t *this)
+{
+ if ((this->nonce.len < 16) || ((this->nonce.len > 256)))
+ {
+ /* nonce length is wrong */
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of nonce_payload_t.set_nonce.
+ */
+static status_t set_nonce(private_nonce_payload_t *this, chunk_t nonce)
+{
+ this->nonce.ptr = clalloc(nonce.ptr, nonce.len);
+ this->nonce.len = nonce.len;
+ this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH + nonce.len;
+ return SUCCESS;
+}
+
+/**
+ * Implementation of nonce_payload_t.get_nonce.
+ */
+static chunk_t get_nonce(private_nonce_payload_t *this)
+{
+ chunk_t nonce;
+ nonce.ptr = clalloc(this->nonce.ptr,this->nonce.len);
+ nonce.len = this->nonce.len;
+ return nonce;
+}
+
+/**
+ * Implementation of nonce_payload_t.get_encoding_rules.
+ */
+static void 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);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(private_nonce_payload_t *this)
+{
+ return NONCE;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_nonce_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_nonce_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * recompute the length of the payload.
+ */
+static void compute_length(private_nonce_payload_t *this)
+{
+ this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH + this->nonce.len;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_nonce_payload_t *this)
+{
+ compute_length(this);
+ return this->payload_length;
+}
+
+/**
+ * Implementation of payload_t.destroy and nonce_payload_t.destroy.
+ */
+static void destroy(private_nonce_payload_t *this)
+{
+ if (this->nonce.ptr != NULL)
+ {
+ free(this->nonce.ptr);
+ }
+
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+nonce_payload_t *nonce_payload_create()
+{
+ private_nonce_payload_t *this = malloc_thing(private_nonce_payload_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (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 = (void (*) (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 = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.destroy = (void (*) (nonce_payload_t *)) destroy;
+ this->public.set_nonce = (void (*) (nonce_payload_t *,chunk_t)) set_nonce;
+ this->public.get_nonce = (chunk_t (*) (nonce_payload_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/src/libcharon/encoding/payloads/nonce_payload.h b/src/libcharon/encoding/payloads/nonce_payload.h
new file mode 100644
index 000000000..e9212202e
--- /dev/null
+++ b/src/libcharon/encoding/payloads/nonce_payload.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup nonce_payload nonce_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef NONCE_PAYLOAD_H_
+#define NONCE_PAYLOAD_H_
+
+typedef struct nonce_payload_t nonce_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * Nonce size in bytes for nonces sending to other peer.
+ */
+#define NONCE_SIZE 32
+
+/**
+ * Length of a nonce payload without a nonce in bytes.
+ */
+#define NONCE_PAYLOAD_HEADER_LENGTH 4
+
+/**
+ * Object representing an IKEv2 Nonce payload.
+ *
+ * The Nonce payload format is described in RFC section 3.3.
+ */
+struct nonce_payload_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Set the nonce value.
+ *
+ * @param nonce chunk containing the nonce, will be cloned
+ */
+ void (*set_nonce) (nonce_payload_t *this, chunk_t nonce);
+
+ /**
+ * Get the nonce value.
+ *
+ * @return a chunk containing the cloned nonce
+ */
+ chunk_t (*get_nonce) (nonce_payload_t *this);
+
+ /**
+ * Destroys an nonce_payload_t object.
+ */
+ void (*destroy) (nonce_payload_t *this);
+};
+
+/**
+ * Creates an empty nonce_payload_t object
+ *
+ * @return nonce_payload_t object
+ */
+nonce_payload_t *nonce_payload_create(void);
+
+#endif /** NONCE_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/notify_payload.c b/src/libcharon/encoding/payloads/notify_payload.c
new file mode 100644
index 000000000..469698ef5
--- /dev/null
+++ b/src/libcharon/encoding/payloads/notify_payload.c
@@ -0,0 +1,617 @@
+/*
+ * Copyright (C) 2006-2008 Tobias Brunner
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 <stddef.h>
+
+#include "notify_payload.h"
+
+#include <daemon.h>
+#include <encoding/payloads/encodings.h>
+#include <crypto/hashers/hasher.h>
+
+ENUM_BEGIN(notify_type_names, UNSUPPORTED_CRITICAL_PAYLOAD, UNSUPPORTED_CRITICAL_PAYLOAD,
+ "UNSUPPORTED_CRITICAL_PAYLOAD");
+ENUM_NEXT(notify_type_names, INVALID_IKE_SPI, INVALID_MAJOR_VERSION, UNSUPPORTED_CRITICAL_PAYLOAD,
+ "INVALID_IKE_SPI",
+ "INVALID_MAJOR_VERSION");
+ENUM_NEXT(notify_type_names, INVALID_SYNTAX, INVALID_SYNTAX, INVALID_MAJOR_VERSION,
+ "INVALID_SYNTAX");
+ENUM_NEXT(notify_type_names, INVALID_MESSAGE_ID, INVALID_MESSAGE_ID, INVALID_SYNTAX,
+ "INVALID_MESSAGE_ID");
+ENUM_NEXT(notify_type_names, INVALID_SPI, INVALID_SPI, INVALID_MESSAGE_ID,
+ "INVALID_SPI");
+ENUM_NEXT(notify_type_names, NO_PROPOSAL_CHOSEN, NO_PROPOSAL_CHOSEN, INVALID_SPI,
+ "NO_PROPOSAL_CHOSEN");
+ENUM_NEXT(notify_type_names, INVALID_KE_PAYLOAD, INVALID_KE_PAYLOAD, NO_PROPOSAL_CHOSEN,
+ "INVALID_KE_PAYLOAD");
+ENUM_NEXT(notify_type_names, AUTHENTICATION_FAILED, AUTHENTICATION_FAILED, INVALID_KE_PAYLOAD,
+ "AUTHENTICATION_FAILED");
+ENUM_NEXT(notify_type_names, SINGLE_PAIR_REQUIRED, USE_ASSIGNED_HoA, AUTHENTICATION_FAILED,
+ "SINGLE_PAIR_REQUIRED",
+ "NO_ADDITIONAL_SAS",
+ "INTERNAL_ADDRESS_FAILURE",
+ "FAILED_CP_REQUIRED",
+ "TS_UNACCEPTABLE",
+ "INVALID_SELECTORS",
+ "UNACCEPTABLE_ADDRESSES",
+ "UNEXPECTED_NAT_DETECTED",
+ "USE_ASSIGNED_HoA");
+ENUM_NEXT(notify_type_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, USE_ASSIGNED_HoA,
+ "ME_CONNECT_FAILED");
+ENUM_NEXT(notify_type_names, INITIAL_CONTACT, LINK_ID, ME_CONNECT_FAILED,
+ "INITIAL_CONTACT",
+ "SET_WINDOW_SIZE",
+ "ADDITIONAL_TS_POSSIBLE",
+ "IPCOMP_SUPPORTED",
+ "NAT_DETECTION_SOURCE_IP",
+ "NAT_DETECTION_DESTINATION_IP",
+ "COOKIE",
+ "USE_TRANSPORT_MODE",
+ "HTTP_CERT_LOOKUP_SUPPORTED",
+ "REKEY_SA",
+ "ESP_TFC_PADDING_NOT_SUPPORTED",
+ "NON_FIRST_FRAGMENTS_ALSO",
+ "MOBIKE_SUPPORTED",
+ "ADDITIONAL_IP4_ADDRESS",
+ "ADDITIONAL_IP6_ADDRESS",
+ "NO_ADDITIONAL_ADDRESSES",
+ "UPDATE_SA_ADDRESSES",
+ "COOKIE2",
+ "NO_NATS_ALLOWED",
+ "AUTH_LIFETIME",
+ "MULTIPLE_AUTH_SUPPORTED",
+ "ANOTHER_AUTH_FOLLOWS",
+ "REDIRECT_SUPPORTED",
+ "REDIRECT",
+ "REDIRECTED_FROM",
+ "TICKET_LT_OPAQUE",
+ "TICKET_REQUEST",
+ "TICKET_ACK",
+ "TICKET_NACK",
+ "TICKET_OPAQUE",
+ "LINK_ID");
+ENUM_NEXT(notify_type_names, EAP_ONLY_AUTHENTICATION, EAP_ONLY_AUTHENTICATION, LINK_ID,
+ "EAP_ONLY_AUTHENTICATION");
+ENUM_NEXT(notify_type_names, USE_BEET_MODE, USE_BEET_MODE, EAP_ONLY_AUTHENTICATION,
+ "USE_BEET_MODE");
+ENUM_NEXT(notify_type_names, ME_MEDIATION, ME_RESPONSE, USE_BEET_MODE,
+ "ME_MEDIATION",
+ "ME_ENDPOINT",
+ "ME_CALLBACK",
+ "ME_CONNECTID",
+ "ME_CONNECTKEY",
+ "ME_CONNECTAUTH",
+ "ME_RESPONSE");
+ENUM_END(notify_type_names, ME_RESPONSE);
+
+
+ENUM_BEGIN(notify_type_short_names, UNSUPPORTED_CRITICAL_PAYLOAD, UNSUPPORTED_CRITICAL_PAYLOAD,
+ "CRIT");
+ENUM_NEXT(notify_type_short_names, INVALID_IKE_SPI, INVALID_MAJOR_VERSION, UNSUPPORTED_CRITICAL_PAYLOAD,
+ "INVAL_IKE_SPI",
+ "INVAL_MAJOR");
+ENUM_NEXT(notify_type_short_names, INVALID_SYNTAX, INVALID_SYNTAX, INVALID_MAJOR_VERSION,
+ "INVAL_SYN");
+ENUM_NEXT(notify_type_short_names, INVALID_MESSAGE_ID, INVALID_MESSAGE_ID, INVALID_SYNTAX,
+ "INVAL_MID");
+ENUM_NEXT(notify_type_short_names, INVALID_SPI, INVALID_SPI, INVALID_MESSAGE_ID,
+ "INVAL_SPI");
+ENUM_NEXT(notify_type_short_names, NO_PROPOSAL_CHOSEN, NO_PROPOSAL_CHOSEN, INVALID_SPI,
+ "NO_PROP");
+ENUM_NEXT(notify_type_short_names, INVALID_KE_PAYLOAD, INVALID_KE_PAYLOAD, NO_PROPOSAL_CHOSEN,
+ "INVAL_KE");
+ENUM_NEXT(notify_type_short_names, AUTHENTICATION_FAILED, AUTHENTICATION_FAILED, INVALID_KE_PAYLOAD,
+ "AUTH_FAILED");
+ENUM_NEXT(notify_type_short_names, SINGLE_PAIR_REQUIRED, USE_ASSIGNED_HoA, AUTHENTICATION_FAILED,
+ "SINGLE_PAIR",
+ "NO_ADD_SAS",
+ "INT_ADDR_FAIL",
+ "FAIL_CP_REQ",
+ "TS_UNACCEPT",
+ "INVAL_SEL",
+ "UNACCEPT_ADDR",
+ "UNEXPECT_NAT",
+ "ASSIGNED_HoA");
+ENUM_NEXT(notify_type_short_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, USE_ASSIGNED_HoA,
+ "ME_CONN_FAIL");
+ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, LINK_ID, ME_CONNECT_FAILED,
+ "INIT_CONTACT",
+ "SET_WINSIZE",
+ "ADD_TS_POSS",
+ "IPCOMP_SUPP",
+ "NATD_S_IP",
+ "NATD_D_IP",
+ "COOKIE",
+ "USE_TRANSP",
+ "HTTP_CERT_LOOK",
+ "REKEY_SA",
+ "ESP_TFC_PAD_N",
+ "NON_FIRST_FRAG",
+ "MOBIKE_SUP",
+ "ADD_4_ADDR",
+ "ADD_6_ADDR",
+ "NO_ADD_ADDR",
+ "UPD_SA_ADDR",
+ "COOKIE2",
+ "NO_NATS",
+ "AUTH_LFT",
+ "MULT_AUTH",
+ "AUTH_FOLLOWS",
+ "REDIR_SUP",
+ "REDIR",
+ "REDIR_FROM",
+ "TKT_LT_OPAK",
+ "TKT_REQ",
+ "TKT_ACK",
+ "TKT_NACK",
+ "TKT_OPAK",
+ "LINK_ID");
+ENUM_NEXT(notify_type_short_names, EAP_ONLY_AUTHENTICATION, EAP_ONLY_AUTHENTICATION, LINK_ID,
+ "EAP_ONLY");
+ENUM_NEXT(notify_type_short_names, USE_BEET_MODE, USE_BEET_MODE, EAP_ONLY_AUTHENTICATION,
+ "BEET_MODE");
+ENUM_NEXT(notify_type_short_names, ME_MEDIATION, ME_RESPONSE, USE_BEET_MODE,
+ "ME_MED",
+ "ME_EP",
+ "ME_CB",
+ "ME_CID",
+ "ME_CKEY",
+ "ME_CAUTH",
+ "ME_R");
+ENUM_END(notify_type_short_names, ME_RESPONSE);
+
+
+typedef struct private_notify_payload_t private_notify_payload_t;
+
+/**
+ * Private data of an notify_payload_t object.
+ *
+ */
+struct private_notify_payload_t {
+ /**
+ * 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_type;
+
+ /**
+ * Security parameter index (spi).
+ */
+ chunk_t spi;
+
+ /**
+ * Notification data.
+ */
+ chunk_t notification_data;
+};
+
+/**
+ * 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_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 ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_notify_payload_t *this)
+{
+ bool bad_length = FALSE;
+
+ switch (this->protocol_id)
+ {
+ case PROTO_NONE:
+ case PROTO_IKE:
+ case PROTO_AH:
+ case PROTO_ESP:
+ break;
+ default:
+ DBG1(DBG_ENC, "Unknown protocol (%d)", this->protocol_id);
+ return FAILED;
+ }
+
+ switch (this->notify_type)
+ {
+ case INVALID_KE_PAYLOAD:
+ {
+ if (this->notification_data.len != 2)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ }
+ case NAT_DETECTION_SOURCE_IP:
+ case NAT_DETECTION_DESTINATION_IP:
+ case ME_CONNECTAUTH:
+ {
+ if (this->notification_data.len != HASH_SIZE_SHA1)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ }
+ case INVALID_SYNTAX:
+ case INVALID_MAJOR_VERSION:
+ case NO_PROPOSAL_CHOSEN:
+ {
+ if (this->notification_data.len != 0)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ }
+ case ADDITIONAL_IP4_ADDRESS:
+ {
+ if (this->notification_data.len != 4)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ }
+ case ADDITIONAL_IP6_ADDRESS:
+ {
+ if (this->notification_data.len != 16)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ }
+ case AUTH_LIFETIME:
+ {
+ if (this->notification_data.len != 4)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ }
+ case IPCOMP_SUPPORTED:
+ {
+ if (this->notification_data.len != 3)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ }
+ case ME_ENDPOINT:
+ if (this->notification_data.len != 8 &&
+ this->notification_data.len != 12 &&
+ this->notification_data.len != 24)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ case ME_CONNECTID:
+ if (this->notification_data.len < 4 ||
+ this->notification_data.len > 16)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ case ME_CONNECTKEY:
+ if (this->notification_data.len < 16 ||
+ this->notification_data.len > 32)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ default:
+ /* TODO: verify */
+ break;
+ }
+ if (bad_length)
+ {
+ DBG1(DBG_ENC, "invalid notify data length for %N (%d)",
+ notify_type_names, this->notify_type,
+ this->notification_data.len);
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void 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);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(private_notify_payload_t *this)
+{
+ return NOTIFY;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_notify_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_notify_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * recompute the payloads length.
+ */
+static void 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;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_notify_payload_t *this)
+{
+ compute_length(this);
+ return this->payload_length;
+}
+
+/**
+ * Implementation of notify_payload_t.get_protocol_id.
+ */
+static u_int8_t get_protocol_id(private_notify_payload_t *this)
+{
+ return this->protocol_id;
+}
+
+/**
+ * Implementation of notify_payload_t.set_protocol_id.
+ */
+static void set_protocol_id(private_notify_payload_t *this, u_int8_t protocol_id)
+{
+ this->protocol_id = protocol_id;
+}
+
+/**
+ * Implementation of notify_payload_t.get_notify_type.
+ */
+static notify_type_t get_notify_type(private_notify_payload_t *this)
+{
+ return this->notify_type;
+}
+
+/**
+ * Implementation of notify_payload_t.set_notify_type.
+ */
+static void set_notify_type(private_notify_payload_t *this, u_int16_t notify_type)
+{
+ this->notify_type = notify_type;
+}
+
+/**
+ * Implementation of notify_payload_t.get_spi.
+ */
+static u_int32_t get_spi(private_notify_payload_t *this)
+{
+ switch (this->protocol_id)
+ {
+ case PROTO_AH:
+ case PROTO_ESP:
+ if (this->spi.len == 4)
+ {
+ return *((u_int32_t*)this->spi.ptr);
+ }
+ default:
+ break;
+ }
+ return 0;
+}
+
+/**
+ * Implementation of notify_payload_t.set_spi.
+ */
+static void set_spi(private_notify_payload_t *this, u_int32_t spi)
+{
+ chunk_free(&this->spi);
+ switch (this->protocol_id)
+ {
+ case PROTO_AH:
+ case PROTO_ESP:
+ this->spi = chunk_alloc(4);
+ *((u_int32_t*)this->spi.ptr) = spi;
+ break;
+ default:
+ break;
+ }
+ this->spi_size = this->spi.len;
+ compute_length(this);
+}
+
+/**
+ * Implementation of notify_payload_t.get_notification_data.
+ */
+static chunk_t get_notification_data(private_notify_payload_t *this)
+{
+ return (this->notification_data);
+}
+
+/**
+ * Implementation of notify_payload_t.set_notification_data.
+ */
+static status_t set_notification_data(private_notify_payload_t *this, chunk_t notification_data)
+{
+ chunk_free(&this->notification_data);
+ if (notification_data.len > 0)
+ {
+ this->notification_data = chunk_clone(notification_data);
+ }
+ compute_length(this);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of notify_payload_t.destroy and notify_payload_t.destroy.
+ */
+static status_t destroy(private_notify_payload_t *this)
+{
+ chunk_free(&this->notification_data);
+ chunk_free(&this->spi);
+ free(this);
+ return SUCCESS;
+}
+
+/*
+ * Described in header
+ */
+notify_payload_t *notify_payload_create()
+{
+ private_notify_payload_t *this = malloc_thing(private_notify_payload_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (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 = (void (*) (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 = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.get_protocol_id = (u_int8_t (*) (notify_payload_t *)) get_protocol_id;
+ this->public.set_protocol_id = (void (*) (notify_payload_t *,u_int8_t)) set_protocol_id;
+ this->public.get_notify_type = (notify_type_t (*) (notify_payload_t *)) get_notify_type;
+ this->public.set_notify_type = (void (*) (notify_payload_t *,notify_type_t)) set_notify_type;
+ this->public.get_spi = (u_int32_t (*) (notify_payload_t *)) get_spi;
+ this->public.set_spi = (void (*) (notify_payload_t *,u_int32_t)) set_spi;
+ this->public.get_notification_data = (chunk_t (*) (notify_payload_t *)) get_notification_data;
+ this->public.set_notification_data = (void (*) (notify_payload_t *,chunk_t)) set_notification_data;
+ this->public.destroy = (void (*) (notify_payload_t *)) destroy;
+
+ /* set default values of the fields */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = NOTIFY_PAYLOAD_HEADER_LENGTH;
+ this->protocol_id = 0;
+ this->notify_type = 0;
+ this->spi.ptr = NULL;
+ this->spi.len = 0;
+ this->spi_size = 0;
+ this->notification_data.ptr = NULL;
+ this->notification_data.len = 0;
+
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_type_t notify_type)
+{
+ notify_payload_t *notify = notify_payload_create();
+
+ notify->set_notify_type(notify,notify_type);
+ notify->set_protocol_id(notify,protocol_id);
+
+ return notify;
+}
diff --git a/src/libcharon/encoding/payloads/notify_payload.h b/src/libcharon/encoding/payloads/notify_payload.h
new file mode 100644
index 000000000..0e1bc23b8
--- /dev/null
+++ b/src/libcharon/encoding/payloads/notify_payload.h
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2006-2008 Tobias Brunner
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup notify_payload notify_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef NOTIFY_PAYLOAD_H_
+#define NOTIFY_PAYLOAD_H_
+
+typedef enum notify_type_t notify_type_t;
+typedef struct notify_payload_t notify_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/proposal_substructure.h>
+#include <utils/linked_list.h>
+
+/**
+ * Notify payload length in bytes without any spi and notification data.
+ */
+#define NOTIFY_PAYLOAD_HEADER_LENGTH 8
+
+/**
+ * Notify message types.
+ *
+ * See IKEv2 RFC 3.10.1.
+ */
+enum notify_type_t {
+ /* notify error messages */
+ UNSUPPORTED_CRITICAL_PAYLOAD = 1,
+ INVALID_IKE_SPI = 4,
+ INVALID_MAJOR_VERSION = 5,
+ INVALID_SYNTAX = 7,
+ INVALID_MESSAGE_ID = 9,
+ INVALID_SPI = 11,
+ NO_PROPOSAL_CHOSEN = 14,
+ INVALID_KE_PAYLOAD = 17,
+ AUTHENTICATION_FAILED = 24,
+ SINGLE_PAIR_REQUIRED = 34,
+ NO_ADDITIONAL_SAS = 35,
+ INTERNAL_ADDRESS_FAILURE = 36,
+ FAILED_CP_REQUIRED = 37,
+ TS_UNACCEPTABLE = 38,
+ INVALID_SELECTORS = 39,
+ /* mobile extension, RFC 4555 */
+ UNACCEPTABLE_ADDRESSES = 40,
+ UNEXPECTED_NAT_DETECTED = 41,
+ /* mobile IPv6 bootstrapping, RFC 5026 */
+ USE_ASSIGNED_HoA = 42,
+
+ /* IKE-ME, private use */
+ ME_CONNECT_FAILED = 8192,
+
+ /* notify status messages */
+ INITIAL_CONTACT = 16384,
+ SET_WINDOW_SIZE = 16385,
+ ADDITIONAL_TS_POSSIBLE = 16386,
+ IPCOMP_SUPPORTED = 16387,
+ NAT_DETECTION_SOURCE_IP = 16388,
+ NAT_DETECTION_DESTINATION_IP = 16389,
+ COOKIE = 16390,
+ USE_TRANSPORT_MODE = 16391,
+ HTTP_CERT_LOOKUP_SUPPORTED = 16392,
+ REKEY_SA = 16393,
+ ESP_TFC_PADDING_NOT_SUPPORTED = 16394,
+ NON_FIRST_FRAGMENTS_ALSO = 16395,
+ /* mobike extension, RFC4555 */
+ MOBIKE_SUPPORTED = 16396,
+ ADDITIONAL_IP4_ADDRESS = 16397,
+ ADDITIONAL_IP6_ADDRESS = 16398,
+ NO_ADDITIONAL_ADDRESSES = 16399,
+ UPDATE_SA_ADDRESSES = 16400,
+ COOKIE2 = 16401,
+ NO_NATS_ALLOWED = 16402,
+ /* repeated authentication extension, RFC4478 */
+ AUTH_LIFETIME = 16403,
+ /* multiple authentication exchanges, RFC 4739 */
+ MULTIPLE_AUTH_SUPPORTED = 16404,
+ ANOTHER_AUTH_FOLLOWS = 16405,
+ /* redirect mechanism, RFC 5685 */
+ REDIRECT_SUPPORTED = 16406,
+ REDIRECT = 16407,
+ REDIRECTED_FROM = 16408,
+ /* draft-ietf-ipsecme-ikev2-resumption, assigned by IANA */
+ TICKET_LT_OPAQUE = 16409,
+ TICKET_REQUEST = 16410,
+ TICKET_ACK = 16411,
+ TICKET_NACK = 16412,
+ TICKET_OPAQUE = 16413,
+ LINK_ID = 16414,
+
+ /* draft-eronen-ipsec-ikev2-eap-auth, not assigned by IANA yet */
+ EAP_ONLY_AUTHENTICATION = 40960,
+ /* BEET mode, not even a draft yet. private use */
+ USE_BEET_MODE = 40961,
+ /* IKE-ME, private use */
+ ME_MEDIATION = 40962,
+ ME_ENDPOINT = 40963,
+ ME_CALLBACK = 40964,
+ ME_CONNECTID = 40965,
+ ME_CONNECTKEY = 40966,
+ ME_CONNECTAUTH = 40967,
+ ME_RESPONSE = 40968
+};
+
+/**
+ * enum name for notify_type_t.
+ */
+extern enum_name_t *notify_type_names;
+
+/**
+ * enum name for notify_type_t (shorter strings).
+ */
+extern enum_name_t *notify_type_short_names;
+
+/**
+ * Class representing an IKEv2-Notify Payload.
+ *
+ * The Notify Payload format is described in Draft section 3.10.
+ */
+struct notify_payload_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Gets the protocol id of this payload.
+ *
+ * @return protocol id of this payload
+ */
+ u_int8_t (*get_protocol_id) (notify_payload_t *this);
+
+ /**
+ * Sets the protocol id of this payload.
+ *
+ * @param protocol_id protocol id to set
+ */
+ void (*set_protocol_id) (notify_payload_t *this, u_int8_t protocol_id);
+
+ /**
+ * Gets the notify message type of this payload.
+ *
+ * @return notify message type of this payload
+ */
+ notify_type_t (*get_notify_type) (notify_payload_t *this);
+
+ /**
+ * Sets notify message type of this payload.
+ *
+ * @param type notify message type to set
+ */
+ void (*set_notify_type) (notify_payload_t *this, notify_type_t type);
+
+ /**
+ * Returns the currently set spi of this payload.
+ *
+ * This is only valid for notifys with protocol AH|ESP
+ *
+ * @return SPI value
+ */
+ u_int32_t (*get_spi) (notify_payload_t *this);
+
+ /**
+ * Sets the spi of this payload.
+ *
+ * This is only valid for notifys with protocol AH|ESP
+ *
+ * @param spi SPI value
+ */
+ void (*set_spi) (notify_payload_t *this, u_int32_t spi);
+
+ /**
+ * Returns the currently set notification data of payload.
+ *
+ * Returned data are not copied.
+ *
+ * @return chunk_t pointing to the value
+ */
+ chunk_t (*get_notification_data) (notify_payload_t *this);
+
+ /**
+ * Sets the notification data of this payload.
+ *
+ * @warning Value is getting copied.
+ *
+ * @param notification_data chunk_t pointing to the value to set
+ */
+ void (*set_notification_data) (notify_payload_t *this,
+ chunk_t notification_data);
+
+ /**
+ * Destroys an notify_payload_t object.
+ */
+ void (*destroy) (notify_payload_t *this);
+};
+
+/**
+ * Creates an empty notify_payload_t object
+ *
+ * @return created notify_payload_t object
+ */
+notify_payload_t *notify_payload_create(void);
+
+/**
+ * Creates an notify_payload_t object of specific type for specific protocol id.
+ *
+ * @param protocol_id protocol id (IKE, AH or ESP)
+ * @param type notify type (see notify_type_t)
+ * @return notify_payload_t object
+ */
+notify_payload_t *notify_payload_create_from_protocol_and_type(
+ protocol_id_t protocol_id, notify_type_t type);
+
+#endif /** NOTIFY_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/payload.c b/src/libcharon/encoding/payloads/payload.c
new file mode 100644
index 000000000..1cee6d2aa
--- /dev/null
+++ b/src/libcharon/encoding/payloads/payload.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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/id_payload.h>
+#include <encoding/payloads/ke_payload.h>
+#include <encoding/payloads/notify_payload.h>
+#include <encoding/payloads/auth_payload.h>
+#include <encoding/payloads/cert_payload.h>
+#include <encoding/payloads/certreq_payload.h>
+#include <encoding/payloads/encryption_payload.h>
+#include <encoding/payloads/ts_payload.h>
+#include <encoding/payloads/delete_payload.h>
+#include <encoding/payloads/vendor_id_payload.h>
+#include <encoding/payloads/cp_payload.h>
+#include <encoding/payloads/configuration_attribute.h>
+#include <encoding/payloads/eap_payload.h>
+#include <encoding/payloads/unknown_payload.h>
+
+
+ENUM_BEGIN(payload_type_names, NO_PAYLOAD, NO_PAYLOAD,
+ "NO_PAYLOAD");
+ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICATION, NO_PAYLOAD,
+ "SECURITY_ASSOCIATION",
+ "KEY_EXCHANGE",
+ "ID_INITIATOR",
+ "ID_RESPONDER",
+ "CERTIFICATE",
+ "CERTIFICATE_REQUEST",
+ "AUTHENTICATION",
+ "NONCE",
+ "NOTIFY",
+ "DELETE",
+ "VENDOR_ID",
+ "TRAFFIC_SELECTOR_INITIATOR",
+ "TRAFFIC_SELECTOR_RESPONDER",
+ "ENCRYPTED",
+ "CONFIGURATION",
+ "EXTENSIBLE_AUTHENTICATION");
+#ifdef ME
+ENUM_NEXT(payload_type_names, ID_PEER, ID_PEER, EXTENSIBLE_AUTHENTICATION,
+ "ID_PEER");
+ENUM_NEXT(payload_type_names, HEADER, UNKNOWN_PAYLOAD, ID_PEER,
+ "HEADER",
+ "PROPOSAL_SUBSTRUCTURE",
+ "TRANSFORM_SUBSTRUCTURE",
+ "TRANSFORM_ATTRIBUTE",
+ "TRAFFIC_SELECTOR_SUBSTRUCTURE",
+ "CONFIGURATION_ATTRIBUTE",
+ "UNKNOWN_PAYLOAD");
+#else
+ENUM_NEXT(payload_type_names, HEADER, UNKNOWN_PAYLOAD, EXTENSIBLE_AUTHENTICATION,
+ "HEADER",
+ "PROPOSAL_SUBSTRUCTURE",
+ "TRANSFORM_SUBSTRUCTURE",
+ "TRANSFORM_ATTRIBUTE",
+ "TRAFFIC_SELECTOR_SUBSTRUCTURE",
+ "CONFIGURATION_ATTRIBUTE",
+ "UNKNOWN_PAYLOAD");
+#endif /* ME */
+ENUM_END(payload_type_names, UNKNOWN_PAYLOAD);
+
+/* short forms of payload names */
+ENUM_BEGIN(payload_type_short_names, NO_PAYLOAD, NO_PAYLOAD,
+ "--");
+ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICATION, NO_PAYLOAD,
+ "SA",
+ "KE",
+ "IDi",
+ "IDr",
+ "CERT",
+ "CERTREQ",
+ "AUTH",
+ "No",
+ "N",
+ "D",
+ "V",
+ "TSi",
+ "TSr",
+ "E",
+ "CP",
+ "EAP");
+#ifdef ME
+ENUM_NEXT(payload_type_short_names, ID_PEER, ID_PEER, EXTENSIBLE_AUTHENTICATION,
+ "IDp");
+ENUM_NEXT(payload_type_short_names, HEADER, UNKNOWN_PAYLOAD, ID_PEER,
+ "HDR",
+ "PROP",
+ "TRANS",
+ "TRANSATTR",
+ "TSSUB",
+ "CPATTR",
+ "??");
+#else
+ENUM_NEXT(payload_type_short_names, HEADER, UNKNOWN_PAYLOAD, EXTENSIBLE_AUTHENTICATION,
+ "HDR",
+ "PROP",
+ "TRANS",
+ "TRANSATTR",
+ "TSSUB",
+ "CPATTR",
+ "??");
+#endif /* ME */
+ENUM_END(payload_type_short_names, UNKNOWN_PAYLOAD);
+
+/*
+ * 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 ID_INITIATOR:
+ return (payload_t*)id_payload_create(ID_INITIATOR);
+ case ID_RESPONDER:
+ return (payload_t*)id_payload_create(ID_RESPONDER);
+#ifdef ME
+ case ID_PEER:
+ return (payload_t*)id_payload_create(ID_PEER);
+#endif /* ME */
+ case AUTHENTICATION:
+ return (payload_t*)auth_payload_create();
+ case CERTIFICATE:
+ return (payload_t*)cert_payload_create();
+ case CERTIFICATE_REQUEST:
+ return (payload_t*)certreq_payload_create();
+ case TRAFFIC_SELECTOR_SUBSTRUCTURE:
+ return (payload_t*)traffic_selector_substructure_create();
+ case TRAFFIC_SELECTOR_INITIATOR:
+ return (payload_t*)ts_payload_create(TRUE);
+ case TRAFFIC_SELECTOR_RESPONDER:
+ return (payload_t*)ts_payload_create(FALSE);
+ case KEY_EXCHANGE:
+ return (payload_t*)ke_payload_create();
+ case NOTIFY:
+ return (payload_t*)notify_payload_create();
+ case DELETE:
+ return (payload_t*)delete_payload_create(0);
+ case VENDOR_ID:
+ return (payload_t*)vendor_id_payload_create();
+ case CONFIGURATION:
+ return (payload_t*)cp_payload_create();
+ case CONFIGURATION_ATTRIBUTE:
+ return (payload_t*)configuration_attribute_create();
+ case EXTENSIBLE_AUTHENTICATION:
+ return (payload_t*)eap_payload_create();
+ case ENCRYPTED:
+ return (payload_t*)encryption_payload_create();
+ default:
+ return (payload_t*)unknown_payload_create();
+ }
+}
+
diff --git a/src/libcharon/encoding/payloads/payload.h b/src/libcharon/encoding/payloads/payload.h
new file mode 100644
index 000000000..2e783cb30
--- /dev/null
+++ b/src/libcharon/encoding/payloads/payload.h
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup payload payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef PAYLOAD_H_
+#define PAYLOAD_H_
+
+typedef enum payload_type_t payload_type_t;
+typedef struct payload_t payload_t;
+
+#include <library.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.
+ */
+enum payload_type_t{
+
+ /**
+ * End of payload list in next_payload
+ */
+ NO_PAYLOAD = 0,
+
+ /**
+ * The security association (SA) payload containing proposals.
+ */
+ SECURITY_ASSOCIATION = 33,
+
+ /**
+ * The key exchange (KE) payload containing diffie-hellman values.
+ */
+ KEY_EXCHANGE = 34,
+
+ /**
+ * Identification for the original initiator (IDi).
+ */
+ ID_INITIATOR = 35,
+
+ /**
+ * Identification for the original responder (IDr).
+ */
+ ID_RESPONDER = 36,
+
+ /**
+ * Certificate payload with certificates (CERT).
+ */
+ CERTIFICATE = 37,
+
+ /**
+ * Certificate request payload (CERTREQ).
+ */
+ CERTIFICATE_REQUEST = 38,
+
+ /**
+ * Authentication payload contains auth data (AUTH).
+ */
+ AUTHENTICATION = 39,
+
+ /**
+ * Nonces, for initator and responder (Ni, Nr, N)
+ */
+ NONCE = 40,
+
+ /**
+ * Notify paylaod (N).
+ */
+ NOTIFY = 41,
+
+ /**
+ * Delete payload (D)
+ */
+ DELETE = 42,
+
+ /**
+ * Vendor id paylpoad (V).
+ */
+ VENDOR_ID = 43,
+
+ /**
+ * Traffic selector for the original initiator (TSi).
+ */
+ TRAFFIC_SELECTOR_INITIATOR = 44,
+
+ /**
+ * Traffic selector for the original responser (TSr).
+ */
+ TRAFFIC_SELECTOR_RESPONDER = 45,
+
+ /**
+ * Encryption payload, contains other payloads (E).
+ */
+ ENCRYPTED = 46,
+
+ /**
+ * Configuration payload (CP).
+ */
+ CONFIGURATION = 47,
+
+ /**
+ * Extensible authentication payload (EAP).
+ */
+ EXTENSIBLE_AUTHENTICATION = 48,
+
+#ifdef ME
+ /**
+ * Identification payload for peers has a value from
+ * the PRIVATE USE space.
+ */
+ ID_PEER = 128,
+#endif /* ME */
+
+ /**
+ * Header has a value of PRIVATE USE space.
+ *
+ * This payload type is not sent 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 sent 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 sent 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 sent over wire and just
+ * used internally to handle a transform attribute like a payload.
+ */
+ TRANSFORM_ATTRIBUTE = 143,
+
+ /**
+ * TRAFFIC_SELECTOR_SUBSTRUCTURE has a value of PRIVATE USE space.
+ *
+ * This payload type is not sent over wire and just
+ * used internally to handle a transform selector like a payload.
+ */
+ TRAFFIC_SELECTOR_SUBSTRUCTURE = 144,
+
+ /**
+ * CONFIGURATION_ATTRIBUTE has a value of PRIVATE USE space.
+ *
+ * This payload type is not sent over wire and just
+ * used internally to handle a transform attribute like a payload.
+ */
+ CONFIGURATION_ATTRIBUTE = 145,
+
+ /**
+ * A unknown payload has a value of PRIVATE USE space.
+ *
+ * This payload type is not sent over wire and just
+ * used internally to handle a unknown payload.
+ */
+ UNKNOWN_PAYLOAD = 146,
+};
+
+
+/**
+ * enum names for payload_type_t.
+ */
+extern enum_name_t *payload_type_names;
+
+/**
+ * enum names for payload_type_t in a short form.
+ */
+extern enum_name_t *payload_type_short_names;
+
+/**
+ * Generic interface for all payload types (incl.header and substructures).
+ *
+ * To handle all kinds of payloads on a generic way, this interface must
+ * be implemented by every payload. This allows parser_t/generator_t a simple
+ * handling of all payloads.
+ */
+struct payload_t {
+
+ /**
+ * Get encoding rules for this payload.
+ *
+ * @param rules location to store pointer of first rule
+ * @param rule_count location to store number of rules
+ */
+ void (*get_encoding_rules) (payload_t *this, encoding_rule_t **rules, size_t *rule_count);
+
+ /**
+ * Get type of payload.
+ *
+ * @return type of this payload
+ */
+ payload_type_t (*get_type) (payload_t *this);
+
+ /**
+ * Get type of next payload or NO_PAYLOAD (0) if this is the last one.
+ *
+ * @return type of next payload
+ */
+ payload_type_t (*get_next_type) (payload_t *this);
+
+ /**
+ * Set type of next payload.
+ *
+ * @param type type of next payload
+ */
+ void (*set_next_type) (payload_t *this,payload_type_t type);
+
+ /**
+ * Get length of payload.
+ *
+ * @return length of this payload
+ */
+ size_t (*get_length) (payload_t *this);
+
+ /**
+ * Verifies payload structure and makes consistence check.
+ *
+ * @return SUCCESS, FAILED if consistence not given
+ */
+ status_t (*verify) (payload_t *this);
+
+ /**
+ * Destroys a payload and all included substructures.
+ */
+ void (*destroy) (payload_t *this);
+};
+
+/**
+ * Create an empty payload.
+ *
+ * Useful for the parser, who wants a generic constructor for all payloads.
+ * It supports all payload_t methods. If a payload type is not known,
+ * an unknwon_paylod is created with the chunk of data in it.
+ *
+ * @param type type of the payload to create
+ * @return payload_t object
+ */
+payload_t *payload_create(payload_type_t type);
+
+#endif /** PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/proposal_substructure.c b/src/libcharon/encoding/payloads/proposal_substructure.c
new file mode 100644
index 000000000..c93f73a68
--- /dev/null
+++ b/src/libcharon/encoding/payloads/proposal_substructure.c
@@ -0,0 +1,598 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 <stddef.h>
+
+#include "proposal_substructure.h"
+
+#include <encoding/payloads/encodings.h>
+#include <encoding/payloads/transform_substructure.h>
+#include <library.h>
+#include <utils/linked_list.h>
+#include <daemon.h>
+
+
+/**
+ * IKEv1 Value for a proposal payload.
+ */
+#define PROPOSAL_TYPE_VALUE 2
+
+
+typedef struct private_proposal_substructure_t private_proposal_substructure_t;
+
+/**
+ * Private data of an proposal_substructure_t object.
+ *
+ */
+struct private_proposal_substructure_t {
+ /**
+ * 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;
+};
+
+/**
+ * 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> ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_proposal_substructure_t *this)
+{
+ status_t status = SUCCESS;
+ iterator_t *iterator;
+ payload_t *current_transform;
+
+ if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != 2))
+ {
+ /* must be 0 or 2 */
+ DBG1(DBG_ENC, "inconsistent next payload");
+ return FAILED;
+ }
+ if (this->transforms_count != this->transforms->get_count(this->transforms))
+ {
+ /* must be the same! */
+ DBG1(DBG_ENC, "transform count invalid");
+ return FAILED;
+ }
+
+ switch (this->protocol_id)
+ {
+ case PROTO_AH:
+ case PROTO_ESP:
+ if (this->spi.len != 4)
+ {
+ DBG1(DBG_ENC, "invalid SPI length in %N proposal",
+ protocol_id_names, this->protocol_id);
+ return FAILED;
+ }
+ break;
+ case PROTO_IKE:
+ if (this->spi.len != 0 && this->spi.len != 8)
+ {
+ DBG1(DBG_ENC, "invalid SPI length in IKE proposal");
+ return FAILED;
+ }
+ break;
+ default:
+ DBG1(DBG_ENC, "invalid proposal protocol (%d)", this->protocol_id);
+ return FAILED;
+ }
+ if ((this->protocol_id == 0) || (this->protocol_id >= 4))
+ {
+ /* reserved are not supported */
+ DBG1(DBG_ENC, "invalid protocol");
+ return FAILED;
+ }
+
+ iterator = this->transforms->create_iterator(this->transforms,TRUE);
+ while(iterator->iterate(iterator, (void**)&current_transform))
+ {
+ status = current_transform->verify(current_transform);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "TRANSFORM_SUBSTRUCTURE verification failed");
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+
+ /* proposal number is checked in SA payload */
+ return status;
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void 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);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(private_proposal_substructure_t *this)
+{
+ return PROPOSAL_SUBSTRUCTURE;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_proposal_substructure_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_proposal_substructure_t *this,payload_type_t type)
+{
+}
+
+/**
+ * (re-)compute the length of the payload.
+ */
+static void compute_length(private_proposal_substructure_t *this)
+{
+ iterator_t *iterator;
+ payload_t *current_transform;
+ size_t transforms_count = 0;
+ size_t length = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH;
+
+ iterator = this->transforms->create_iterator(this->transforms,TRUE);
+ while (iterator->iterate(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;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_proposal_substructure_t *this)
+{
+ compute_length(this);
+ return this->proposal_length;
+}
+
+/**
+ * Implementation of proposal_substructure_t.create_transform_substructure_iterator.
+ */
+static iterator_t *create_transform_substructure_iterator (private_proposal_substructure_t *this,bool forward)
+{
+ return (this->transforms->create_iterator(this->transforms,forward));
+}
+
+/**
+ * Implementation of proposal_substructure_t.add_transform_substructure.
+ */
+static void 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);
+
+ this->transforms->insert_last(this->transforms,(void *) transform);
+ compute_length(this);
+}
+
+/**
+ * Implementation of proposal_substructure_t.proposal_substructure_t.
+ */
+static void set_is_last_proposal (private_proposal_substructure_t *this, bool is_last)
+{
+ this->next_payload = (is_last) ? 0: PROPOSAL_TYPE_VALUE;
+}
+
+/**
+ * Implementation of proposal_substructure_t.set_proposal_number.
+ */
+static void set_proposal_number(private_proposal_substructure_t *this,u_int8_t proposal_number)
+{
+ this->proposal_number = proposal_number;
+}
+
+/**
+ * Implementation of proposal_substructure_t.get_proposal_number.
+ */
+static u_int8_t get_proposal_number (private_proposal_substructure_t *this)
+{
+ return (this->proposal_number);
+}
+
+/**
+ * Implementation of proposal_substructure_t.set_protocol_id.
+ */
+static void set_protocol_id(private_proposal_substructure_t *this,u_int8_t protocol_id)
+{
+ this->protocol_id = protocol_id;
+}
+
+/**
+ * Implementation of proposal_substructure_t.get_protocol_id.
+ */
+static u_int8_t get_protocol_id(private_proposal_substructure_t *this)
+{
+ return (this->protocol_id);
+}
+
+/**
+ * Implementation of proposal_substructure_t.set_spi.
+ */
+static void set_spi(private_proposal_substructure_t *this, chunk_t spi)
+{
+ /* first delete already set spi value */
+ if (this->spi.ptr != NULL)
+ {
+ free(this->spi.ptr);
+ this->spi.ptr = NULL;
+ this->spi.len = 0;
+ compute_length(this);
+ }
+
+ this->spi.ptr = clalloc(spi.ptr,spi.len);
+ this->spi.len = spi.len;
+ this->spi_size = spi.len;
+ compute_length(this);
+}
+
+/**
+ * Implementation of proposal_substructure_t.get_spi.
+ */
+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;
+}
+
+/**
+ * Implementation of proposal_substructure_t.get_transform_count.
+ */
+static size_t get_transform_count (private_proposal_substructure_t *this)
+{
+ return this->transforms->get_count(this->transforms);
+}
+
+/**
+ * Implementation of proposal_substructure_t.get_spi_size.
+ */
+static size_t get_spi_size (private_proposal_substructure_t *this)
+{
+ return this->spi.len;
+}
+
+/**
+ * Implementation of proposal_substructure_t.get_proposal.
+ */
+proposal_t* get_proposal(private_proposal_substructure_t *this)
+{
+ iterator_t *iterator;
+ transform_substructure_t *transform;
+ proposal_t *proposal;
+ u_int64_t spi;
+
+ proposal = proposal_create(this->protocol_id);
+
+ iterator = this->transforms->create_iterator(this->transforms, TRUE);
+ while (iterator->iterate(iterator, (void**)&transform))
+ {
+ transform_type_t transform_type;
+ u_int16_t transform_id;
+ u_int16_t key_length = 0;
+
+ transform_type = transform->get_transform_type(transform);
+ transform_id = transform->get_transform_id(transform);
+ transform->get_key_length(transform, &key_length);
+
+ proposal->add_algorithm(proposal, transform_type, transform_id, key_length);
+ }
+ iterator->destroy(iterator);
+
+ switch (this->spi.len)
+ {
+ case 4:
+ spi = *((u_int32_t*)this->spi.ptr);
+ break;
+ case 8:
+ spi = *((u_int64_t*)this->spi.ptr);
+ break;
+ default:
+ spi = 0;
+ }
+ proposal->set_spi(proposal, spi);
+
+ return proposal;
+}
+
+/**
+ * Implementation of proposal_substructure_t.clone.
+ */
+static private_proposal_substructure_t* clone_(private_proposal_substructure_t *this)
+{
+ private_proposal_substructure_t *clone;
+ iterator_t *transforms;
+ transform_substructure_t *current_transform;
+
+ clone = (private_proposal_substructure_t *) proposal_substructure_create();
+ clone->next_payload = this->next_payload;
+ clone->proposal_number = this->proposal_number;
+ clone->protocol_id = this->protocol_id;
+ clone->spi_size = this->spi_size;
+ if (this->spi.ptr != NULL)
+ {
+ clone->spi.ptr = clalloc(this->spi.ptr,this->spi.len);
+ clone->spi.len = this->spi.len;
+ }
+
+ transforms = this->transforms->create_iterator(this->transforms,FALSE);
+ while (transforms->iterate(transforms, (void**)&current_transform))
+ {
+ current_transform = current_transform->clone(current_transform);
+ clone->public.add_transform_substructure(&clone->public, current_transform);
+ }
+ transforms->destroy(transforms);
+
+ return clone;
+}
+
+/**
+ * Implements payload_t's and proposal_substructure_t's destroy function.
+ * See #payload_s.destroy or proposal_substructure_s.destroy for description.
+ */
+static void destroy(private_proposal_substructure_t *this)
+{
+ this->transforms->destroy_offset(this->transforms,
+ offsetof(transform_substructure_t, destroy));
+ chunk_free(&this->spi);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+proposal_substructure_t *proposal_substructure_create()
+{
+ private_proposal_substructure_t *this = malloc_thing(private_proposal_substructure_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (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 = (void (*) (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 = (void (*) (payload_t *))destroy;
+
+
+ /* public functions */
+ this->public.create_transform_substructure_iterator = (iterator_t* (*) (proposal_substructure_t *,bool)) create_transform_substructure_iterator;
+ this->public.add_transform_substructure = (void (*) (proposal_substructure_t *,transform_substructure_t *)) add_transform_substructure;
+ this->public.set_proposal_number = (void (*) (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 = (void (*) (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_is_last_proposal = (void (*) (proposal_substructure_t *,bool)) set_is_last_proposal;
+ this->public.get_proposal = (proposal_t* (*) (proposal_substructure_t*))get_proposal;
+ this->public.set_spi = (void (*) (proposal_substructure_t *,chunk_t))set_spi;
+ this->public.get_spi = (chunk_t (*) (proposal_substructure_t *)) get_spi;
+ this->public.get_transform_count = (size_t (*) (proposal_substructure_t *)) get_transform_count;
+ this->public.get_spi_size = (size_t (*) (proposal_substructure_t *)) get_spi_size;
+ this->public.clone = (proposal_substructure_t * (*) (proposal_substructure_t *)) clone_;
+ this->public.destroy = (void (*) (proposal_substructure_t *)) destroy;
+
+ /* 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();
+
+ return (&(this->public));
+}
+
+/*
+ * Described in header.
+ */
+proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t *proposal)
+{
+ transform_substructure_t *transform;
+ private_proposal_substructure_t *this;
+ u_int16_t alg, key_size;
+ enumerator_t *enumerator;
+
+ this = (private_proposal_substructure_t*)proposal_substructure_create();
+
+ /* encryption algorithm is only availble in ESP */
+ enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM);
+ while (enumerator->enumerate(enumerator, &alg, &key_size))
+ {
+ transform = transform_substructure_create_type(ENCRYPTION_ALGORITHM,
+ alg, key_size);
+ add_transform_substructure(this, transform);
+ }
+ enumerator->destroy(enumerator);
+
+ /* integrity algorithms */
+ enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM);
+ while (enumerator->enumerate(enumerator, &alg, &key_size))
+ {
+ transform = transform_substructure_create_type(INTEGRITY_ALGORITHM,
+ alg, key_size);
+ add_transform_substructure(this, transform);
+ }
+ enumerator->destroy(enumerator);
+
+ /* prf algorithms */
+ enumerator = proposal->create_enumerator(proposal, PSEUDO_RANDOM_FUNCTION);
+ while (enumerator->enumerate(enumerator, &alg, &key_size))
+ {
+ transform = transform_substructure_create_type(PSEUDO_RANDOM_FUNCTION,
+ alg, key_size);
+ add_transform_substructure(this, transform);
+ }
+ enumerator->destroy(enumerator);
+
+ /* dh groups */
+ enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP);
+ while (enumerator->enumerate(enumerator, &alg, NULL))
+ {
+ transform = transform_substructure_create_type(DIFFIE_HELLMAN_GROUP,
+ alg, 0);
+ add_transform_substructure(this, transform);
+ }
+ enumerator->destroy(enumerator);
+
+ /* extended sequence numbers */
+ enumerator = proposal->create_enumerator(proposal, EXTENDED_SEQUENCE_NUMBERS);
+ while (enumerator->enumerate(enumerator, &alg, NULL))
+ {
+ transform = transform_substructure_create_type(EXTENDED_SEQUENCE_NUMBERS,
+ alg, 0);
+ add_transform_substructure(this, transform);
+ }
+ enumerator->destroy(enumerator);
+
+ /* add SPI, if necessary */
+ switch (proposal->get_protocol(proposal))
+ {
+ case PROTO_AH:
+ case PROTO_ESP:
+ this->spi_size = this->spi.len = 4;
+ this->spi.ptr = malloc(this->spi_size);
+ *((u_int32_t*)this->spi.ptr) = proposal->get_spi(proposal);
+ break;
+ case PROTO_IKE:
+ if (proposal->get_spi(proposal))
+ { /* IKE only uses SPIS when rekeying, but on initial setup */
+ this->spi_size = this->spi.len = 8;
+ this->spi.ptr = malloc(this->spi_size);
+ *((u_int64_t*)this->spi.ptr) = proposal->get_spi(proposal);
+ }
+ break;
+ default:
+ break;
+ }
+ this->proposal_number = 0;
+ this->protocol_id = proposal->get_protocol(proposal);
+
+ return &this->public;
+}
diff --git a/src/libcharon/encoding/payloads/proposal_substructure.h b/src/libcharon/encoding/payloads/proposal_substructure.h
new file mode 100644
index 000000000..4934802af
--- /dev/null
+++ b/src/libcharon/encoding/payloads/proposal_substructure.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup proposal_substructure proposal_substructure
+ * @{ @ingroup payloads
+ */
+
+#ifndef PROPOSAL_SUBSTRUCTURE_H_
+#define PROPOSAL_SUBSTRUCTURE_H_
+
+typedef struct proposal_substructure_t proposal_substructure_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/transform_substructure.h>
+#include <config/proposal.h>
+#include <utils/linked_list.h>
+
+
+/**
+ * Length of the proposal substructure header (without spi).
+ */
+#define PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH 8
+
+/**
+ * Class representing an IKEv2-PROPOSAL SUBSTRUCTURE.
+ *
+ * The PROPOSAL SUBSTRUCTURE format is described in RFC section 3.3.1.
+ */
+struct proposal_substructure_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Creates an iterator of stored transform_substructure_t objects.
+ *
+ * @param forward iterator direction (TRUE: front to end)
+ * @return created iterator_t object
+ */
+ iterator_t *(*create_transform_substructure_iterator) (
+ proposal_substructure_t *this, bool forward);
+
+ /**
+ * Adds a transform_substructure_t object to this object.
+ *
+ * @param transform transform_substructure_t object to add
+ */
+ void (*add_transform_substructure) (proposal_substructure_t *this,
+ transform_substructure_t *transform);
+
+ /**
+ * Sets the proposal number of current proposal.
+ *
+ * @param id proposal number to set
+ */
+ void (*set_proposal_number) (proposal_substructure_t *this,
+ u_int8_t proposal_number);
+
+ /**
+ * get proposal number of current proposal.
+ *
+ * @return proposal number of current proposal substructure.
+ */
+ u_int8_t (*get_proposal_number) (proposal_substructure_t *this);
+
+ /**
+ * get the number of transforms in current proposal.
+ *
+ * @return transform count in current proposal
+ */
+ size_t (*get_transform_count) (proposal_substructure_t *this);
+
+ /**
+ * get size of the set spi in bytes.
+ *
+ * @return size of the spi in bytes
+ */
+ size_t (*get_spi_size) (proposal_substructure_t *this);
+
+ /**
+ * Sets the protocol id of current proposal.
+ *
+ * @param id protocol id to set
+ */
+ void (*set_protocol_id) (proposal_substructure_t *this,
+ u_int8_t protocol_id);
+
+ /**
+ * get protocol id of current proposal.
+ *
+ * @return protocol id of current proposal substructure.
+ */
+ u_int8_t (*get_protocol_id) (proposal_substructure_t *this);
+
+ /**
+ * Sets the next_payload field of this substructure
+ *
+ * If this is the last proposal, next payload field is set to 0,
+ * otherwise to 2
+ *
+ * @param is_last When TRUE, next payload field is set to 0, otherwise to 2
+ */
+ void (*set_is_last_proposal) (proposal_substructure_t *this, bool is_last);
+
+ /**
+ * Returns the currently set SPI of this proposal.
+ *
+ * @return chunk_t pointing to the value
+ */
+ chunk_t (*get_spi) (proposal_substructure_t *this);
+
+ /**
+ * Sets the SPI of the current proposal.
+ *
+ * @warning SPI is getting copied
+ *
+ * @param spi chunk_t pointing to the value to set
+ */
+ void (*set_spi) (proposal_substructure_t *this, chunk_t spi);
+
+ /**
+ * Get a proposal_t from the propsal_substructure_t.
+ *
+ * @return proposal_t
+ */
+ proposal_t * (*get_proposal) (proposal_substructure_t *this);
+
+ /**
+ * Clones an proposal_substructure_t object.
+ *
+ * @return cloned object
+ */
+ proposal_substructure_t* (*clone) (proposal_substructure_t *this);
+
+ /**
+ * Destroys an proposal_substructure_t object.
+ */
+ void (*destroy) (proposal_substructure_t *this);
+};
+
+/**
+ * Creates an empty proposal_substructure_t object
+ *
+ * @return proposal_substructure_t object
+ */
+proposal_substructure_t *proposal_substructure_create(void);
+
+/**
+ * Creates a proposal_substructure_t from a proposal_t.
+ *
+ * @param proposal proposal to build a substruct out of it
+ * @return proposal_substructure_t object
+ */
+proposal_substructure_t *proposal_substructure_create_from_proposal(
+ proposal_t *proposal);
+
+#endif /** PROPOSAL_SUBSTRUCTURE_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/sa_payload.c b/src/libcharon/encoding/payloads/sa_payload.c
new file mode 100644
index 000000000..187a8fee0
--- /dev/null
+++ b/src/libcharon/encoding/payloads/sa_payload.c
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 <stddef.h>
+
+#include "sa_payload.h"
+
+#include <encoding/payloads/encodings.h>
+#include <utils/linked_list.h>
+#include <daemon.h>
+
+
+typedef struct private_sa_payload_t private_sa_payload_t;
+
+/**
+ * Private data of an sa_payload_t object.
+ *
+ */
+struct private_sa_payload_t {
+ /**
+ * 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;
+};
+
+/**
+ * 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> ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_sa_payload_t *this)
+{
+ int expected_number = 1, current_number;
+ status_t status = SUCCESS;
+ iterator_t *iterator;
+ proposal_substructure_t *current_proposal;
+ bool first = TRUE;
+
+ /* check proposal numbering */
+ iterator = this->proposals->create_iterator(this->proposals,TRUE);
+
+ while(iterator->iterate(iterator, (void**)&current_proposal))
+ {
+ current_number = current_proposal->get_proposal_number(current_proposal);
+ if (current_number < expected_number)
+ {
+ if (current_number != (expected_number + 1))
+ {
+ DBG1(DBG_ENC, "proposal number is %d, expected %d or %d",
+ current_number, expected_number, expected_number + 1);
+ status = FAILED;
+ break;
+ }
+ }
+ else if (current_number < expected_number)
+ {
+ /* must not be smaller then proceeding one */
+ DBG1(DBG_ENC, "proposal number smaller than that of previous proposal");
+ status = FAILED;
+ break;
+ }
+
+ status = current_proposal->payload_interface.verify(&(current_proposal->payload_interface));
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "PROPOSAL_SUBSTRUCTURE verification failed");
+ break;
+ }
+ first = FALSE;
+ expected_number = current_number;
+ }
+
+ iterator->destroy(iterator);
+ return status;
+}
+
+
+/**
+ * Implementation of payload_t.destroy and sa_payload_t.destroy.
+ */
+static status_t destroy(private_sa_payload_t *this)
+{
+ this->proposals->destroy_offset(this->proposals,
+ offsetof(proposal_substructure_t, destroy));
+ free(this);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void 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);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(private_sa_payload_t *this)
+{
+ return SECURITY_ASSOCIATION;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_sa_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_sa_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * recompute length of the payload.
+ */
+static void compute_length (private_sa_payload_t *this)
+{
+ iterator_t *iterator;
+ payload_t *current_proposal;
+ size_t length = SA_PAYLOAD_HEADER_LENGTH;
+
+ iterator = this->proposals->create_iterator(this->proposals,TRUE);
+ while (iterator->iterate(iterator, (void **)&current_proposal))
+ {
+ length += current_proposal->get_length(current_proposal);
+ }
+ iterator->destroy(iterator);
+
+ this->payload_length = length;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_sa_payload_t *this)
+{
+ compute_length(this);
+ return this->payload_length;
+}
+
+/**
+ * Implementation of sa_payload_t.create_proposal_substructure_iterator.
+ */
+static iterator_t *create_proposal_substructure_iterator (private_sa_payload_t *this,bool forward)
+{
+ return this->proposals->create_iterator(this->proposals,forward);
+}
+
+/**
+ * Implementation of sa_payload_t.add_proposal_substructure.
+ */
+static void add_proposal_substructure(private_sa_payload_t *this,proposal_substructure_t *proposal)
+{
+ status_t status;
+ u_int proposal_count = this->proposals->get_count(this->proposals);
+
+ if (proposal_count > 0)
+ {
+ proposal_substructure_t *last_proposal;
+ status = this->proposals->get_last(this->proposals,(void **) &last_proposal);
+ /* last transform is now not anymore last one */
+ last_proposal->set_is_last_proposal(last_proposal, FALSE);
+ }
+ proposal->set_is_last_proposal(proposal, TRUE);
+ proposal->set_proposal_number(proposal, proposal_count + 1);
+ this->proposals->insert_last(this->proposals,(void *) proposal);
+ compute_length(this);
+}
+
+/**
+ * Implementation of sa_payload_t.add_proposal.
+ */
+static void add_proposal(private_sa_payload_t *this, proposal_t *proposal)
+{
+ proposal_substructure_t *substructure;
+
+ substructure = proposal_substructure_create_from_proposal(proposal);
+ add_proposal_substructure(this, substructure);
+}
+
+/**
+ * Implementation of sa_payload_t.get_proposals.
+ */
+static linked_list_t *get_proposals(private_sa_payload_t *this)
+{
+ int struct_number = 0;
+ int ignore_struct_number = 0;
+ iterator_t *iterator;
+ proposal_substructure_t *proposal_struct;
+ linked_list_t *proposal_list;
+
+ /* this list will hold our proposals */
+ proposal_list = linked_list_create();
+
+ /* we do not support proposals split up to two proposal substructures, as
+ * AH+ESP bundles are not supported in RFC4301 anymore.
+ * To handle such structures safely, we just skip proposals with multiple
+ * protocols.
+ */
+ iterator = this->proposals->create_iterator(this->proposals, TRUE);
+ while (iterator->iterate(iterator, (void **)&proposal_struct))
+ {
+ proposal_t *proposal;
+
+ /* check if a proposal has a single protocol */
+ if (proposal_struct->get_proposal_number(proposal_struct) == struct_number)
+ {
+ if (ignore_struct_number < struct_number)
+ {
+ /* remova an already added, if first of series */
+ proposal_list->remove_last(proposal_list, (void**)&proposal);
+ proposal->destroy(proposal);
+ ignore_struct_number = struct_number;
+ }
+ continue;
+ }
+ struct_number++;
+ proposal = proposal_struct->get_proposal(proposal_struct);
+ if (proposal)
+ {
+ proposal_list->insert_last(proposal_list, proposal);
+ }
+ }
+ iterator->destroy(iterator);
+ return proposal_list;
+}
+
+/*
+ * Described in header.
+ */
+sa_payload_t *sa_payload_create()
+{
+ private_sa_payload_t *this = malloc_thing(private_sa_payload_t);
+
+ /* public interface */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (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 = (void (*) (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 = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.create_proposal_substructure_iterator = (iterator_t* (*) (sa_payload_t *,bool)) create_proposal_substructure_iterator;
+ this->public.add_proposal_substructure = (void (*) (sa_payload_t *,proposal_substructure_t *)) add_proposal_substructure;
+ this->public.add_proposal = (void (*) (sa_payload_t*,proposal_t*))add_proposal;
+ this->public.get_proposals = (linked_list_t* (*) (sa_payload_t *)) get_proposals;
+ this->public.destroy = (void (*) (sa_payload_t *)) destroy;
+
+ /* set default values of the fields */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = SA_PAYLOAD_HEADER_LENGTH;
+ this->proposals = linked_list_create();
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals)
+{
+ iterator_t *iterator;
+ proposal_t *proposal;
+ sa_payload_t *sa_payload = sa_payload_create();
+
+ /* add every payload from the list */
+ iterator = proposals->create_iterator(proposals, TRUE);
+ while (iterator->iterate(iterator, (void**)&proposal))
+ {
+ add_proposal((private_sa_payload_t*)sa_payload, proposal);
+ }
+ iterator->destroy(iterator);
+
+ return sa_payload;
+}
+
+/*
+ * Described in header.
+ */
+sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal)
+{
+ sa_payload_t *sa_payload = sa_payload_create();
+
+ add_proposal((private_sa_payload_t*)sa_payload, proposal);
+
+ return sa_payload;
+}
diff --git a/src/libcharon/encoding/payloads/sa_payload.h b/src/libcharon/encoding/payloads/sa_payload.h
new file mode 100644
index 000000000..25f5a2407
--- /dev/null
+++ b/src/libcharon/encoding/payloads/sa_payload.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup sa_payload sa_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef SA_PAYLOAD_H_
+#define SA_PAYLOAD_H_
+
+typedef struct sa_payload_t sa_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/proposal_substructure.h>
+#include <utils/linked_list.h>
+
+/**
+ * SA_PAYLOAD length in bytes without any proposal substructure.
+ */
+#define SA_PAYLOAD_HEADER_LENGTH 4
+
+/**
+ * Class representing an IKEv2-SA Payload.
+ *
+ * The SA Payload format is described in RFC section 3.3.
+ */
+struct sa_payload_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Creates an iterator of stored proposal_substructure_t objects.
+ *
+ * When deleting an proposal using this iterator,
+ * the length of this transform substructure has to be refreshed
+ * by calling get_length()!
+ *
+ * @param forward iterator direction (TRUE: front to end)
+ * @return created iterator_t object
+ */
+ iterator_t *(*create_proposal_substructure_iterator) (sa_payload_t *this,
+ bool forward);
+
+ /**
+ * Adds a proposal_substructure_t object to this object.
+ *
+ * @param proposal proposal_substructure_t object to add
+ */
+ void (*add_proposal_substructure) (sa_payload_t *this,
+ proposal_substructure_t *proposal);
+
+ /**
+ * Gets the proposals in this payload as a list.
+ *
+ * @return a list containing proposal_t s
+ */
+ linked_list_t *(*get_proposals) (sa_payload_t *this);
+
+ /**
+ * Add a child proposal (AH/ESP) to the payload.
+ *
+ * @param proposal child proposal to add to the payload
+ */
+ void (*add_proposal) (sa_payload_t *this, proposal_t *proposal);
+
+ /**
+ * Destroys an sa_payload_t object.
+ */
+ void (*destroy) (sa_payload_t *this);
+};
+
+/**
+ * Creates an empty sa_payload_t object
+ *
+ * @return created sa_payload_t object
+ */
+sa_payload_t *sa_payload_create(void);
+
+/**
+ * Creates a sa_payload_t object from a list of proposals.
+ *
+ * @param proposals list of proposals to build the payload from
+ * @return sa_payload_t object
+ */
+sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals);
+
+/**
+ * Creates a sa_payload_t object from a single proposal.
+ *
+ * This is only for convenience. Use sa_payload_create_from_proposal_list
+ * if you want to add more than one proposal.
+ *
+ * @param proposal proposal from which the payload should be built.
+ * @return sa_payload_t object
+ */
+sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal);
+
+#endif /** SA_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/traffic_selector_substructure.c b/src/libcharon/encoding/payloads/traffic_selector_substructure.c
new file mode 100644
index 000000000..f24857591
--- /dev/null
+++ b/src/libcharon/encoding/payloads/traffic_selector_substructure.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 "traffic_selector_substructure.h"
+
+#include <encoding/payloads/encodings.h>
+#include <utils/linked_list.h>
+
+
+typedef struct private_traffic_selector_substructure_t private_traffic_selector_substructure_t;
+
+/**
+ * Private data of an traffic_selector_substructure_t object.
+ *
+ */
+struct private_traffic_selector_substructure_t {
+ /**
+ * Public traffic_selector_substructure_t interface.
+ */
+ traffic_selector_substructure_t public;
+
+ /**
+ * Type of traffic selector.
+ */
+ u_int8_t ts_type;
+
+ /**
+ * IP Protocol ID.
+ */
+ u_int8_t ip_protocol_id;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * Start port number.
+ */
+ u_int16_t start_port;
+
+ /**
+ * End port number.
+ */
+ u_int16_t end_port;
+
+ /**
+ * Starting address.
+ */
+ chunk_t starting_address;
+
+ /**
+ * Ending address.
+ */
+ chunk_t ending_address;
+};
+
+/**
+ * Encoding rules to parse or generate a TS payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_traffic_selector_substructure_t.
+ *
+ */
+encoding_rule_t traffic_selector_substructure_encodings[] = {
+ /* 1 Byte next ts type*/
+ { TS_TYPE, offsetof(private_traffic_selector_substructure_t, ts_type) },
+ /* 1 Byte IP protocol id*/
+ { U_INT_8, offsetof(private_traffic_selector_substructure_t, ip_protocol_id) },
+ /* Length of the whole payload*/
+ { PAYLOAD_LENGTH, offsetof(private_traffic_selector_substructure_t, payload_length) },
+ /* 2 Byte start port*/
+ { U_INT_16, offsetof(private_traffic_selector_substructure_t, start_port) },
+ /* 2 Byte end port*/
+ { U_INT_16, offsetof(private_traffic_selector_substructure_t, end_port) },
+ /* starting address is either 4 or 16 byte */
+ { ADDRESS, offsetof(private_traffic_selector_substructure_t, starting_address) },
+ /* ending address is either 4 or 16 byte */
+ { ADDRESS, offsetof(private_traffic_selector_substructure_t, ending_address) }
+
+};
+
+/*
+ 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
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! TS Type !IP Protocol ID*| Selector Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Start Port* | End Port* |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Starting Address* ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Ending Address* ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_traffic_selector_substructure_t *this)
+{
+ if (this->start_port > this->end_port)
+ {
+ return FAILED;
+ }
+ switch (this->ts_type)
+ {
+ case TS_IPV4_ADDR_RANGE:
+ {
+ if ((this->starting_address.len != 4) ||
+ (this->ending_address.len != 4))
+ {
+ /* ipv4 address must be 4 bytes long */
+ return FAILED;
+ }
+ break;
+ }
+ case TS_IPV6_ADDR_RANGE:
+ {
+ if ((this->starting_address.len != 16) ||
+ (this->ending_address.len != 16))
+ {
+ /* ipv6 address must be 16 bytes long */
+ return FAILED;
+ }
+ break;
+ }
+ default:
+ {
+ /* not supported ts type */
+ return FAILED;
+ }
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of traffic_selector_substructure_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_traffic_selector_substructure_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = traffic_selector_substructure_encodings;
+ *rule_count = sizeof(traffic_selector_substructure_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_payload_type(private_traffic_selector_substructure_t *this)
+{
+ return TRAFFIC_SELECTOR_SUBSTRUCTURE;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_traffic_selector_substructure_t *this)
+{
+ return 0;
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_traffic_selector_substructure_t *this,payload_type_t type)
+{
+
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_traffic_selector_substructure_t *this)
+{
+ return this->payload_length;
+}
+
+/**
+ * Implementation of traffic_selector_substructure_t.get_traffic_selector.
+ */
+static traffic_selector_t *get_traffic_selector(private_traffic_selector_substructure_t *this)
+{
+ traffic_selector_t *ts;
+ ts = traffic_selector_create_from_bytes(this->ip_protocol_id, this->ts_type,
+ this->starting_address, this->start_port,
+ this->ending_address, this->end_port);
+ return ts;
+}
+
+/**
+ * recompute length field of the payload
+ */
+void compute_length(private_traffic_selector_substructure_t *this)
+{
+ this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH +
+ this->ending_address.len + this->starting_address.len;
+}
+
+/**
+ * Implementation of payload_t.destroy and traffic_selector_substructure_t.destroy.
+ */
+static void destroy(private_traffic_selector_substructure_t *this)
+{
+ free(this->starting_address.ptr);
+ free(this->ending_address.ptr);
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+traffic_selector_substructure_t *traffic_selector_substructure_create()
+{
+ private_traffic_selector_substructure_t *this = malloc_thing(private_traffic_selector_substructure_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (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 = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.get_traffic_selector = (traffic_selector_t* (*)(traffic_selector_substructure_t*))get_traffic_selector;
+ this->public.destroy = (void (*) (traffic_selector_substructure_t *)) destroy;
+
+ /* private variables */
+ this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH;
+ this->start_port = 0;
+ this->end_port = 0;
+ this->starting_address = chunk_empty;
+ this->ending_address = chunk_empty;
+ this->ip_protocol_id = 0;
+ /* must be set to be valid */
+ this->ts_type = TS_IPV4_ADDR_RANGE;
+
+ return (&(this->public));
+}
+
+/*
+ * Described in header
+ */
+traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector(traffic_selector_t *traffic_selector)
+{
+ private_traffic_selector_substructure_t *this = (private_traffic_selector_substructure_t*)traffic_selector_substructure_create();
+ this->ts_type = traffic_selector->get_type(traffic_selector);
+ this->ip_protocol_id = traffic_selector->get_protocol(traffic_selector);
+ this->start_port = traffic_selector->get_from_port(traffic_selector);
+ this->end_port = traffic_selector->get_to_port(traffic_selector);
+ this->starting_address = chunk_clone(traffic_selector->get_from_address(traffic_selector));
+ this->ending_address = chunk_clone(traffic_selector->get_to_address(traffic_selector));
+
+ compute_length(this);
+
+ return &(this->public);
+}
diff --git a/src/libcharon/encoding/payloads/traffic_selector_substructure.h b/src/libcharon/encoding/payloads/traffic_selector_substructure.h
new file mode 100644
index 000000000..0109fd7f5
--- /dev/null
+++ b/src/libcharon/encoding/payloads/traffic_selector_substructure.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup traffic_selector_substructure traffic_selector_substructure
+ * @{ @ingroup payloads
+ */
+
+#ifndef TRAFFIC_SELECTOR_SUBSTRUCTURE_H_
+#define TRAFFIC_SELECTOR_SUBSTRUCTURE_H_
+
+typedef struct traffic_selector_substructure_t traffic_selector_substructure_t;
+
+#include <library.h>
+#include <utils/host.h>
+#include <selectors/traffic_selector.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * Length of a TRAFFIC SELECTOR SUBSTRUCTURE without start and end address.
+ */
+#define TRAFFIC_SELECTOR_HEADER_LENGTH 8
+
+/**
+ * Class representing an IKEv2 TRAFFIC SELECTOR.
+ *
+ * The TRAFFIC SELECTOR format is described in RFC section 3.13.1.
+ */
+struct traffic_selector_substructure_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Get the type of Traffic selector.
+ *
+ * @return type of traffic selector
+ *
+ */
+ ts_type_t (*get_ts_type) (traffic_selector_substructure_t *this);
+
+ /**
+ * Set the type of Traffic selector.
+ *
+ * @param ts_type type of traffic selector
+ */
+ void (*set_ts_type) (traffic_selector_substructure_t *this,
+ ts_type_t ts_type);
+
+ /**
+ * Get the IP protocol ID of Traffic selector.
+ *
+ * @return type of traffic selector
+ *
+ */
+ u_int8_t (*get_protocol_id) (traffic_selector_substructure_t *this);
+
+ /**
+ * Set the IP protocol ID of Traffic selector
+ *
+ * @param protocol_id protocol ID of traffic selector
+ */
+ void (*set_protocol_id) (traffic_selector_substructure_t *this,
+ u_int8_t protocol_id);
+
+ /**
+ * Get the start port and address as host_t object.
+ *
+ * Returned host_t object has to get destroyed by the caller.
+ *
+ * @return start host as host_t object
+ *
+ */
+ host_t *(*get_start_host) (traffic_selector_substructure_t *this);
+
+ /**
+ * Set the start port and address as host_t object.
+ *
+ * @param start_host start host as host_t object
+ */
+ void (*set_start_host) (traffic_selector_substructure_t *this,
+ host_t *start_host);
+
+ /**
+ * Get the end port and address as host_t object.
+ *
+ * Returned host_t object has to get destroyed by the caller.
+ *
+ * @return end host as host_t object
+ *
+ */
+ host_t *(*get_end_host) (traffic_selector_substructure_t *this);
+
+ /**
+ * Set the end port and address as host_t object.
+ *
+ * @param end_host end host as host_t object
+ */
+ void (*set_end_host) (traffic_selector_substructure_t *this,
+ host_t *end_host);
+
+ /**
+ * Get a traffic_selector_t from this substructure.
+ *
+ * @warning traffic_selector_t must be destroyed after usage.
+ *
+ * @return contained traffic_selector_t
+ */
+ traffic_selector_t *(*get_traffic_selector) (
+ traffic_selector_substructure_t *this);
+
+ /**
+ * Destroys an traffic_selector_substructure_t object.
+ */
+ void (*destroy) (traffic_selector_substructure_t *this);
+};
+
+/**
+ * Creates an empty traffic_selector_substructure_t object.
+ *
+ * TS type is set to default TS_IPV4_ADDR_RANGE!
+ *
+ * @return traffic_selector_substructure_t object
+ */
+traffic_selector_substructure_t *traffic_selector_substructure_create(void);
+
+/**
+ * Creates an initialized traffif selector substructure using
+ * the values from a traffic_selector_t.
+ *
+ * @param traffic_selector traffic_selector_t to use for initialization
+ * @return traffic_selector_substructure_t object
+ */
+traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector(
+ traffic_selector_t *traffic_selector);
+
+#endif /** TRAFFIC_SELECTOR_SUBSTRUCTURE_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/transform_attribute.c b/src/libcharon/encoding/payloads/transform_attribute.c
new file mode 100644
index 000000000..8bf2ddef4
--- /dev/null
+++ b/src/libcharon/encoding/payloads/transform_attribute.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 <string.h>
+#include <stddef.h>
+
+#include "transform_attribute.h"
+
+#include <encoding/payloads/encodings.h>
+#include <library.h>
+
+typedef struct private_transform_attribute_t private_transform_attribute_t;
+
+/**
+ * Private data of an transform_attribute_t object.
+ *
+ */
+struct private_transform_attribute_t {
+ /**
+ * 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;
+};
+
+
+ENUM_BEGIN(transform_attribute_type_name, ATTRIBUTE_UNDEFINED, ATTRIBUTE_UNDEFINED,
+ "ATTRIBUTE_UNDEFINED");
+ENUM_NEXT(transform_attribute_type_name, KEY_LENGTH, KEY_LENGTH, ATTRIBUTE_UNDEFINED,
+ "KEY_LENGTH");
+ENUM_END(transform_attribute_type_name, KEY_LENGTH);
+
+/**
+ * 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 !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_transform_attribute_t *this)
+{
+ if (this->attribute_type != KEY_LENGTH)
+ {
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void 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);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(private_transform_attribute_t *this)
+{
+ return TRANSFORM_ATTRIBUTE;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_transform_attribute_t *this)
+{
+ return (NO_PAYLOAD);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_transform_attribute_t *this,payload_type_t type)
+{
+}
+
+/**
+ * Implementation of transform_attribute_t.get_length.
+ */
+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);
+}
+
+/**
+ * Implementation of transform_attribute_t.set_value_chunk.
+ */
+static void set_value_chunk(private_transform_attribute_t *this, chunk_t value)
+{
+ if (this->attribute_value.ptr != NULL)
+ {
+ /* free existing value */
+ free(this->attribute_value.ptr);
+ this->attribute_value.ptr = NULL;
+ this->attribute_value.len = 0;
+
+ }
+
+ if (value.len > 2)
+ {
+ this->attribute_value.ptr = clalloc(value.ptr,value.len);
+ 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);
+ }
+}
+
+/**
+ * Implementation of transform_attribute_t.set_value.
+ */
+static void set_value(private_transform_attribute_t *this, u_int16_t value)
+{
+ if (this->attribute_value.ptr != NULL)
+ {
+ /* free existing value */
+ free(this->attribute_value.ptr);
+ this->attribute_value.ptr = NULL;
+ this->attribute_value.len = 0;
+
+ }
+ this->attribute_length_or_value = value;
+}
+
+/**
+ * Implementation of transform_attribute_t.get_value_chunk.
+ */
+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;
+}
+
+/**
+ * Implementation of transform_attribute_t.get_value.
+ */
+static u_int16_t get_value (private_transform_attribute_t *this)
+{
+ return this->attribute_length_or_value;
+}
+
+
+/**
+ * Implementation of transform_attribute_t.set_attribute_type.
+ */
+static void set_attribute_type (private_transform_attribute_t *this, u_int16_t type)
+{
+ this->attribute_type = type & 0x7FFF;
+}
+
+/**
+ * Implementation of transform_attribute_t.get_attribute_type.
+ */
+static u_int16_t get_attribute_type (private_transform_attribute_t *this)
+{
+ return this->attribute_type;
+}
+
+/**
+ * Implementation of transform_attribute_t.clone.
+ */
+static transform_attribute_t * _clone(private_transform_attribute_t *this)
+{
+ 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 = clalloc(this->attribute_value.ptr,this->attribute_value.len);
+ new_clone->attribute_value.len = this->attribute_value.len;
+ }
+
+ return (transform_attribute_t *) new_clone;
+}
+
+/**
+ * Implementation of transform_attribute_t.destroy and payload_t.destroy.
+ */
+static void destroy(private_transform_attribute_t *this)
+{
+ if (this->attribute_value.ptr != NULL)
+ {
+ free(this->attribute_value.ptr);
+ }
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+transform_attribute_t *transform_attribute_create()
+{
+ private_transform_attribute_t *this = malloc_thing(private_transform_attribute_t);
+
+ /* payload interface */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (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 = (void (*) (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 = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.set_value_chunk = (void (*) (transform_attribute_t *,chunk_t)) set_value_chunk;
+ this->public.set_value = (void (*) (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 = (void (*) (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 = (transform_attribute_t * (*) (transform_attribute_t *)) _clone;
+ this->public.destroy = (void (*) (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));
+}
+
+/*
+ * Described in header.
+ */
+transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length)
+{
+ transform_attribute_t *attribute = transform_attribute_create();
+ attribute->set_attribute_type(attribute,KEY_LENGTH);
+ attribute->set_value(attribute,key_length);
+ return attribute;
+}
diff --git a/src/libcharon/encoding/payloads/transform_attribute.h b/src/libcharon/encoding/payloads/transform_attribute.h
new file mode 100644
index 000000000..a5fe0154b
--- /dev/null
+++ b/src/libcharon/encoding/payloads/transform_attribute.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup transform_attribute transform_attribute
+ * @{ @ingroup payloads
+ */
+
+#ifndef TRANSFORM_ATTRIBUTE_H_
+#define TRANSFORM_ATTRIBUTE_H_
+
+typedef enum transform_attribute_type_t transform_attribute_type_t;
+typedef struct transform_attribute_t transform_attribute_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+
+
+/**
+ * Type of the attribute, as in IKEv2 RFC 3.3.5.
+ */
+enum transform_attribute_type_t {
+ ATTRIBUTE_UNDEFINED = 16384,
+ KEY_LENGTH = 14
+};
+
+/**
+ * enum name for transform_attribute_type_t.
+ */
+extern enum_name_t *transform_attribute_type_names;
+
+/**
+ * Class representing an IKEv2- TRANSFORM Attribute.
+ *
+ * The TRANSFORM ATTRIBUTE format is described in RFC section 3.3.5.
+ */
+struct transform_attribute_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Returns the currently set value of the attribute.
+ *
+ * Returned data are not copied.
+ *
+ * @return chunk_t pointing to the value
+ */
+ chunk_t (*get_value_chunk) (transform_attribute_t *this);
+
+ /**
+ * Returns the currently set value of the attribute.
+ *
+ * Returned data are not copied.
+ *
+ * @return value
+ */
+ u_int16_t (*get_value) (transform_attribute_t *this);
+
+ /**
+ * Sets the value of the attribute.
+ *
+ * Value is getting copied.
+ *
+ * @param value chunk_t pointing to the value to set
+ */
+ void (*set_value_chunk) (transform_attribute_t *this, chunk_t value);
+
+ /**
+ * Sets the value of the attribute.
+ *
+ * @param value value to set
+ */
+ void (*set_value) (transform_attribute_t *this, u_int16_t value);
+
+ /**
+ * Sets the type of the attribute.
+ *
+ * @param type type to set (most significant bit is set to zero)
+ */
+ void (*set_attribute_type) (transform_attribute_t *this, u_int16_t type);
+
+ /**
+ * get the type of the attribute.
+ *
+ * @return type of the value
+ */
+ u_int16_t (*get_attribute_type) (transform_attribute_t *this);
+
+ /**
+ * Clones an transform_attribute_t object.
+ *
+ * @return cloned transform_attribute_t object
+ */
+ transform_attribute_t * (*clone) (transform_attribute_t *this);
+
+ /**
+ * Destroys an transform_attribute_t object.
+ */
+ void (*destroy) (transform_attribute_t *this);
+};
+
+/**
+ * Creates an empty transform_attribute_t object.
+ *
+ * @return transform_attribute_t object
+ */
+transform_attribute_t *transform_attribute_create(void);
+
+/**
+ * Creates an transform_attribute_t of type KEY_LENGTH.
+ *
+ * @param key_length key length in bytes
+ * @return transform_attribute_t object
+ */
+transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length);
+
+#endif /** TRANSFORM_ATTRIBUTE_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/transform_substructure.c b/src/libcharon/encoding/payloads/transform_substructure.c
new file mode 100644
index 000000000..c94f6c1a2
--- /dev/null
+++ b/src/libcharon/encoding/payloads/transform_substructure.c
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 <stddef.h>
+
+#include "transform_substructure.h"
+
+#include <encoding/payloads/transform_attribute.h>
+#include <encoding/payloads/encodings.h>
+#include <library.h>
+#include <utils/linked_list.h>
+#include <daemon.h>
+
+
+typedef struct private_transform_substructure_t private_transform_substructure_t;
+
+/**
+ * Private data of an transform_substructure_t object.
+ *
+ */
+struct private_transform_substructure_t {
+ /**
+ * 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;
+};
+
+
+/**
+ * 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 ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_transform_substructure_t *this)
+{
+ status_t status = SUCCESS;
+ iterator_t *iterator;
+ payload_t *current_attributes;
+
+ if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != 3))
+ {
+ /* must be 0 or 3 */
+ DBG1(DBG_ENC, "inconsistent next payload");
+ return FAILED;
+ }
+
+ switch (this->transform_type)
+ {
+ case ENCRYPTION_ALGORITHM:
+ case PSEUDO_RANDOM_FUNCTION:
+ case INTEGRITY_ALGORITHM:
+ case DIFFIE_HELLMAN_GROUP:
+ case EXTENDED_SEQUENCE_NUMBERS:
+ /* we don't check transform ID, we want to reply
+ * cleanly with NO_PROPOSAL_CHOSEN or so if we don't support it */
+ break;
+ default:
+ {
+ DBG1(DBG_ENC, "invalid transform type: %d", this->transform_type);
+ return FAILED;
+ }
+ }
+ iterator = this->attributes->create_iterator(this->attributes,TRUE);
+
+ while(iterator->iterate(iterator, (void**)&current_attributes))
+ {
+ status = current_attributes->verify(current_attributes);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "TRANSFORM_ATTRIBUTE verification failed");
+ }
+ }
+ iterator->destroy(iterator);
+
+ /* proposal number is checked in SA payload */
+ return status;
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void 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);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(private_transform_substructure_t *this)
+{
+ return TRANSFORM_SUBSTRUCTURE;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_transform_substructure_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * recompute the length of the payload.
+ */
+static void compute_length (private_transform_substructure_t *this)
+{
+ iterator_t *iterator;
+ payload_t *current_attribute;
+ size_t length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
+
+ iterator = this->attributes->create_iterator(this->attributes,TRUE);
+ while (iterator->iterate(iterator, (void**)&current_attribute))
+ {
+ length += current_attribute->get_length(current_attribute);
+ }
+ iterator->destroy(iterator);
+
+ this->transform_length = length;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_transform_substructure_t *this)
+{
+ compute_length(this);
+ return this->transform_length;
+}
+
+/**
+ * Implementation of transform_substructure_t.create_transform_attribute_iterator.
+ */
+static iterator_t *create_transform_attribute_iterator (private_transform_substructure_t *this,bool forward)
+{
+ return this->attributes->create_iterator(this->attributes,forward);
+}
+
+/**
+ * Implementation of transform_substructure_t.add_transform_attribute.
+ */
+static void add_transform_attribute (private_transform_substructure_t *this,transform_attribute_t *attribute)
+{
+ this->attributes->insert_last(this->attributes,(void *) attribute);
+ compute_length(this);
+}
+
+/**
+ * Implementation of transform_substructure_t.set_is_last_transform.
+ */
+static void set_is_last_transform (private_transform_substructure_t *this, bool is_last)
+{
+ this->next_payload = (is_last) ? 0: TRANSFORM_TYPE_VALUE;
+}
+
+/**
+ * Implementation of transform_substructure_t.get_is_last_transform.
+ */
+static bool get_is_last_transform (private_transform_substructure_t *this)
+{
+ return ((this->next_payload == TRANSFORM_TYPE_VALUE) ? FALSE : TRUE);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_transform_substructure_t *this,payload_type_t type)
+{
+}
+
+/**
+ * Implementation of transform_substructure_t.set_transform_type.
+ */
+static void set_transform_type (private_transform_substructure_t *this,u_int8_t type)
+{
+ this->transform_type = type;
+}
+
+/**
+ * Implementation of transform_substructure_t.get_transform_type.
+ */
+static u_int8_t get_transform_type (private_transform_substructure_t *this)
+{
+ return this->transform_type;
+}
+
+/**
+ * Implementation of transform_substructure_t.set_transform_id.
+ */
+static void set_transform_id (private_transform_substructure_t *this,u_int16_t id)
+{
+ this->transform_id = id;
+}
+
+/**
+ * Implementation of transform_substructure_t.get_transform_id.
+ */
+static u_int16_t get_transform_id (private_transform_substructure_t *this)
+{
+ return this->transform_id;
+}
+
+/**
+ * Implementation of transform_substructure_t.clone.
+ */
+static transform_substructure_t *clone_(private_transform_substructure_t *this)
+{
+ private_transform_substructure_t *clone;
+ iterator_t *attributes;
+ transform_attribute_t *current_attribute;
+
+ clone = (private_transform_substructure_t *) transform_substructure_create();
+ clone->next_payload = this->next_payload;
+ clone->transform_type = this->transform_type;
+ clone->transform_id = this->transform_id;
+
+ attributes = this->attributes->create_iterator(this->attributes, FALSE);
+ while (attributes->iterate(attributes, (void**)&current_attribute))
+ {
+ current_attribute = current_attribute->clone(current_attribute);
+ clone->public.add_transform_attribute(&clone->public, current_attribute);
+ }
+ attributes->destroy(attributes);
+
+ return &clone->public;
+}
+
+
+/**
+ * Implementation of transform_substructure_t.get_key_length.
+ */
+static status_t get_key_length(private_transform_substructure_t *this, u_int16_t *key_length)
+{
+ iterator_t *attributes;
+ transform_attribute_t *current_attribute;
+
+ attributes = this->attributes->create_iterator(this->attributes, TRUE);
+ while (attributes->iterate(attributes, (void**)&current_attribute))
+ {
+ if (current_attribute->get_attribute_type(current_attribute) == KEY_LENGTH)
+ {
+ *key_length = current_attribute->get_value(current_attribute);
+ attributes->destroy(attributes);
+ return SUCCESS;
+ }
+ }
+ attributes->destroy(attributes);
+ return FAILED;
+}
+
+
+/**
+ * Implementation of transform_substructure_t.destroy and payload_t.destroy.
+ */
+static void destroy(private_transform_substructure_t *this)
+{
+ this->attributes->destroy_offset(this->attributes,
+ offsetof(transform_attribute_t, destroy));
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+transform_substructure_t *transform_substructure_create()
+{
+ private_transform_substructure_t *this = malloc_thing(private_transform_substructure_t);
+
+ /* payload interface */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (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 = (void (*) (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 = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.create_transform_attribute_iterator = (iterator_t * (*) (transform_substructure_t *,bool)) create_transform_attribute_iterator;
+ this->public.add_transform_attribute = (void (*) (transform_substructure_t *,transform_attribute_t *)) add_transform_attribute;
+ this->public.set_is_last_transform = (void (*) (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 = (void (*) (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 = (void (*) (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.get_key_length = (status_t (*) (transform_substructure_t *,u_int16_t *)) get_key_length;
+ this->public.clone = (transform_substructure_t* (*) (transform_substructure_t *)) clone_;
+ this->public.destroy = (void (*) (transform_substructure_t *)) destroy;
+
+ /* 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();
+
+ return (&(this->public));
+}
+
+/*
+ * Described in header
+ */
+transform_substructure_t *transform_substructure_create_type(
+ transform_type_t transform_type,
+ u_int16_t transform_id, u_int16_t key_length)
+{
+ transform_substructure_t *transform = transform_substructure_create();
+
+ transform->set_transform_type(transform,transform_type);
+ transform->set_transform_id(transform,transform_id);
+
+ if (key_length)
+ {
+ transform_attribute_t *attribute;
+
+ attribute = transform_attribute_create_key_length(key_length);
+ transform->add_transform_attribute(transform, attribute);
+
+ }
+ return transform;
+}
+
diff --git a/src/libcharon/encoding/payloads/transform_substructure.h b/src/libcharon/encoding/payloads/transform_substructure.h
new file mode 100644
index 000000000..5d31f8c0a
--- /dev/null
+++ b/src/libcharon/encoding/payloads/transform_substructure.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup transform_substructure transform_substructure
+ * @{ @ingroup payloads
+ */
+
+#ifndef TRANSFORM_SUBSTRUCTURE_H_
+#define TRANSFORM_SUBSTRUCTURE_H_
+
+typedef struct transform_substructure_t transform_substructure_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/transform_attribute.h>
+#include <utils/linked_list.h>
+#include <crypto/diffie_hellman.h>
+#include <crypto/signers/signer.h>
+#include <crypto/prfs/prf.h>
+#include <crypto/crypters/crypter.h>
+#include <config/proposal.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
+
+
+/**
+ * Class representing an IKEv2- TRANSFORM SUBSTRUCTURE.
+ *
+ * The TRANSFORM SUBSTRUCTURE format is described in RFC section 3.3.2.
+ */
+struct transform_substructure_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Creates an iterator of stored transform_attribute_t objects.
+ *
+ * When deleting an transform attribute using this iterator,
+ * the length of this transform substructure has to be refreshed
+ * by calling get_length().
+ *
+ * @param forward iterator direction (TRUE: front to end)
+ * @return created iterator_t object.
+ */
+ iterator_t * (*create_transform_attribute_iterator) (
+ transform_substructure_t *this, bool forward);
+
+ /**
+ * Adds a transform_attribute_t object to this object.
+ *
+ * @param proposal transform_attribute_t object to add
+ */
+ void (*add_transform_attribute) (transform_substructure_t *this,
+ transform_attribute_t *attribute);
+
+ /**
+ * Sets the next_payload field of this substructure
+ *
+ * If this is the last transform, next payload field is set to 0,
+ * otherwise to 3
+ *
+ * @param is_last When TRUE, next payload field is set to 0, otherwise to 3
+ */
+ void (*set_is_last_transform) (transform_substructure_t *this, bool is_last);
+
+ /**
+ * Checks if this is the last transform.
+ *
+ * @return TRUE if this is the last Transform, FALSE otherwise
+ */
+ bool (*get_is_last_transform) (transform_substructure_t *this);
+
+ /**
+ * Sets transform type of the current transform substructure.
+ *
+ * @param type type value to set
+ */
+ void (*set_transform_type) (transform_substructure_t *this, u_int8_t type);
+
+ /**
+ * get transform type of the current transform.
+ *
+ * @return Transform type of current transform substructure.
+ */
+ u_int8_t (*get_transform_type) (transform_substructure_t *this);
+
+ /**
+ * Sets transform id of the current transform substructure.
+ *
+ * @param id transform id to set
+ */
+ void (*set_transform_id) (transform_substructure_t *this, u_int16_t id);
+
+ /**
+ * get transform id of the current transform.
+ *
+ * @return Transform id of current transform substructure.
+ */
+ u_int16_t (*get_transform_id) (transform_substructure_t *this);
+
+ /**
+ * get transform id of the current transform.
+ *
+ * @param key_length The key length is written to this location
+ * @return
+ * - SUCCESS if a key length attribute is contained
+ * - FAILED if no key length attribute is part of this
+ * transform or key length uses more then 16 bit!
+ */
+ status_t (*get_key_length) (transform_substructure_t *this,
+ u_int16_t *key_length);
+
+ /**
+ * Clones an transform_substructure_t object.
+ *
+ * @return cloned transform_substructure_t object
+ */
+ transform_substructure_t* (*clone) (transform_substructure_t *this);
+
+ /**
+ * Destroys an transform_substructure_t object.
+ */
+ void (*destroy) (transform_substructure_t *this);
+};
+
+/**
+ * Creates an empty transform_substructure_t object.
+ *
+ * @return created transform_substructure_t object
+ */
+transform_substructure_t *transform_substructure_create(void);
+
+/**
+ * Creates an empty transform_substructure_t object.
+ *
+ * The key length is used for the transport types ENCRYPTION_ALGORITHM,
+ * PSEUDO_RANDOM_FUNCTION, INTEGRITY_ALGORITHM. For all
+ * other transport types the key_length parameter is not used
+ *
+ * @param transform_type type of transform to create
+ * @param transform_id transform id specifying the specific algorithm of a transform type
+ * @param key_length Key length for key lenght attribute
+ * @return transform_substructure_t object
+ */
+transform_substructure_t *transform_substructure_create_type(
+ transform_type_t transform_type, u_int16_t transform_id,
+ u_int16_t key_length);
+
+#endif /** TRANSFORM_SUBSTRUCTURE_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/ts_payload.c b/src/libcharon/encoding/payloads/ts_payload.c
new file mode 100644
index 000000000..6bf3e4293
--- /dev/null
+++ b/src/libcharon/encoding/payloads/ts_payload.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 <stddef.h>
+
+#include "ts_payload.h"
+
+#include <encoding/payloads/encodings.h>
+#include <utils/linked_list.h>
+
+typedef struct private_ts_payload_t private_ts_payload_t;
+
+/**
+ * Private data of an ts_payload_t object.
+ *
+ */
+struct private_ts_payload_t {
+ /**
+ * Public ts_payload_t interface.
+ */
+ ts_payload_t public;
+
+ /**
+ * TRUE if this TS payload is of type TSi, FALSE for TSr.
+ */
+ bool is_initiator;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * Number of traffic selectors
+ */
+ u_int8_t number_of_traffic_selectors;
+
+ /**
+ * Contains the traffic selectors of type traffic_selector_substructure_t.
+ */
+ linked_list_t *traffic_selectors;
+};
+
+/**
+ * Encoding rules to parse or generate a TS payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_ts_payload_t.
+ *
+ */
+encoding_rule_t ts_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_ts_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_ts_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_ts_payload_t, payload_length)},
+ /* 1 Byte TS type*/
+ { U_INT_8, offsetof(private_ts_payload_t, number_of_traffic_selectors) },
+ /* 3 reserved bytes */
+ { RESERVED_BYTE, 0 },
+ { RESERVED_BYTE, 0 },
+ { RESERVED_BYTE, 0 },
+ /* some ts data bytes, length is defined in PAYLOAD_LENGTH */
+ { TRAFFIC_SELECTORS, offsetof(private_ts_payload_t, traffic_selectors) }
+};
+
+/*
+ 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 !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Number of TSs ! RESERVED !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ <Traffic Selectors> ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_ts_payload_t *this)
+{
+ iterator_t *iterator;
+ payload_t *current_traffic_selector;
+ status_t status = SUCCESS;
+
+ if (this->number_of_traffic_selectors != (this->traffic_selectors->get_count(this->traffic_selectors)))
+ {
+ /* must be the same */
+ return FAILED;
+ }
+
+ iterator = this->traffic_selectors->create_iterator(this->traffic_selectors,TRUE);
+ while(iterator->iterate(iterator, (void**)&current_traffic_selector))
+ {
+ status = current_traffic_selector->verify(current_traffic_selector);
+ if (status != SUCCESS)
+ {
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+
+ return status;
+}
+
+/**
+ * Implementation of ts_payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_ts_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = ts_payload_encodings;
+ *rule_count = sizeof(ts_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_payload_type(private_ts_payload_t *this)
+{
+ if (this->is_initiator)
+ {
+ return TRAFFIC_SELECTOR_INITIATOR;
+ }
+ else
+ {
+ return TRAFFIC_SELECTOR_RESPONDER;
+ }
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_ts_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_ts_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * recompute the length of the payload.
+ */
+static void compute_length (private_ts_payload_t *this)
+{
+ iterator_t *iterator;
+ size_t ts_count = 0;
+ size_t length = TS_PAYLOAD_HEADER_LENGTH;
+ payload_t *current_traffic_selector;
+
+ iterator = this->traffic_selectors->create_iterator(this->traffic_selectors,TRUE);
+ while (iterator->iterate(iterator, (void**)&current_traffic_selector))
+ {
+ length += current_traffic_selector->get_length(current_traffic_selector);
+ ts_count++;
+ }
+ iterator->destroy(iterator);
+
+ this->number_of_traffic_selectors= ts_count;
+ this->payload_length = length;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_ts_payload_t *this)
+{
+ compute_length(this);
+ return this->payload_length;
+}
+
+/**
+ * Implementation of ts_payload_t.get_initiator.
+ */
+static bool get_initiator (private_ts_payload_t *this)
+{
+ return (this->is_initiator);
+}
+
+/**
+ * Implementation of ts_payload_t.set_initiator.
+ */
+static void set_initiator (private_ts_payload_t *this,bool is_initiator)
+{
+ this->is_initiator = is_initiator;
+}
+
+/**
+ * Implementation of ts_payload_t.add_traffic_selector_substructure.
+ */
+static void add_traffic_selector_substructure (private_ts_payload_t *this,traffic_selector_substructure_t *traffic_selector)
+{
+ this->traffic_selectors->insert_last(this->traffic_selectors,traffic_selector);
+ this->number_of_traffic_selectors = this->traffic_selectors->get_count(this->traffic_selectors);
+}
+
+/**
+ * Implementation of ts_payload_t.create_traffic_selector_substructure_iterator.
+ */
+static iterator_t * create_traffic_selector_substructure_iterator (private_ts_payload_t *this, bool forward)
+{
+ return this->traffic_selectors->create_iterator(this->traffic_selectors,forward);
+}
+
+/**
+ * Implementation of ts_payload_t.get_traffic_selectors.
+ */
+static linked_list_t *get_traffic_selectors(private_ts_payload_t *this)
+{
+ traffic_selector_t *ts;
+ iterator_t *iterator;
+ traffic_selector_substructure_t *ts_substructure;
+ linked_list_t *ts_list = linked_list_create();
+
+ iterator = this->traffic_selectors->create_iterator(this->traffic_selectors, TRUE);
+ while (iterator->iterate(iterator, (void**)&ts_substructure))
+ {
+ ts = ts_substructure->get_traffic_selector(ts_substructure);
+ ts_list->insert_last(ts_list, (void*)ts);
+ }
+ iterator->destroy(iterator);
+
+ return ts_list;
+}
+
+/**
+ * Implementation of payload_t.destroy and ts_payload_t.destroy.
+ */
+static void destroy(private_ts_payload_t *this)
+{
+ this->traffic_selectors->destroy_offset(this->traffic_selectors,
+ offsetof(payload_t, destroy));
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+ts_payload_t *ts_payload_create(bool is_initiator)
+{
+ private_ts_payload_t *this = malloc_thing(private_ts_payload_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (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 = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.destroy = (void (*) (ts_payload_t *)) destroy;
+ this->public.get_initiator = (bool (*) (ts_payload_t *)) get_initiator;
+ this->public.set_initiator = (void (*) (ts_payload_t *,bool)) set_initiator;
+ this->public.add_traffic_selector_substructure = (void (*) (ts_payload_t *,traffic_selector_substructure_t *)) add_traffic_selector_substructure;
+ this->public.create_traffic_selector_substructure_iterator = (iterator_t* (*) (ts_payload_t *,bool)) create_traffic_selector_substructure_iterator;
+ this->public.get_traffic_selectors = (linked_list_t *(*) (ts_payload_t *)) get_traffic_selectors;
+
+ /* private variables */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length =TS_PAYLOAD_HEADER_LENGTH;
+ this->is_initiator = is_initiator;
+ this->number_of_traffic_selectors = 0;
+ this->traffic_selectors = linked_list_create();
+
+ return &(this->public);
+}
+
+/*
+ * Described in header
+ */
+ts_payload_t *ts_payload_create_from_traffic_selectors(bool is_initiator, linked_list_t *traffic_selectors)
+{
+ iterator_t *iterator;
+ traffic_selector_t *ts;
+ traffic_selector_substructure_t *ts_substructure;
+ private_ts_payload_t *this;
+
+ this = (private_ts_payload_t*)ts_payload_create(is_initiator);
+
+ iterator = traffic_selectors->create_iterator(traffic_selectors, TRUE);
+ while (iterator->iterate(iterator, (void**)&ts))
+ {
+ ts_substructure = traffic_selector_substructure_create_from_traffic_selector(ts);
+ this->public.add_traffic_selector_substructure(&(this->public), ts_substructure);
+ }
+ iterator->destroy(iterator);
+
+ return &(this->public);
+}
+
diff --git a/src/libcharon/encoding/payloads/ts_payload.h b/src/libcharon/encoding/payloads/ts_payload.h
new file mode 100644
index 000000000..d322ff1a8
--- /dev/null
+++ b/src/libcharon/encoding/payloads/ts_payload.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup ts_payload ts_payload
+ * @{ @ingroup payloads
+ */
+
+
+#ifndef TS_PAYLOAD_H_
+#define TS_PAYLOAD_H_
+
+typedef struct ts_payload_t ts_payload_t;
+
+#include <library.h>
+#include <utils/linked_list.h>
+#include <selectors/traffic_selector.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/traffic_selector_substructure.h>
+
+/**
+ * Length of a TS payload without the Traffic selectors.
+ */
+#define TS_PAYLOAD_HEADER_LENGTH 8
+
+
+/**
+ * Class representing an IKEv2 TS payload.
+ *
+ * The TS payload format is described in RFC section 3.13.
+ */
+struct ts_payload_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Get the type of TSpayload (TSi or TSr).
+ *
+ * @return
+ * - TRUE if this payload is of type TSi
+ * - FALSE if this payload is of type TSr
+ */
+ bool (*get_initiator) (ts_payload_t *this);
+
+ /**
+ * Set the type of TS payload (TSi or TSr).
+ *
+ * @param is_initiator
+ * - TRUE if this payload is of type TSi
+ * - FALSE if this payload is of type TSr
+ */
+ void (*set_initiator) (ts_payload_t *this,bool is_initiator);
+
+ /**
+ * Adds a traffic_selector_substructure_t object to this object.
+ *
+ * @param traffic_selector traffic_selector_substructure_t object to add
+ */
+ void (*add_traffic_selector_substructure) (ts_payload_t *this,
+ traffic_selector_substructure_t *traffic_selector);
+
+ /**
+ * Creates an iterator of stored traffic_selector_substructure_t objects.
+ *
+ * When removing an traffic_selector_substructure_t object
+ * using this iterator, the length of this payload
+ * has to get refreshed by calling payload_t.get_length!
+ *
+ * @param forward iterator direction (TRUE: front to end)
+ * @return created iterator_t object
+ */
+ iterator_t *(*create_traffic_selector_substructure_iterator) (
+ ts_payload_t *this, bool forward);
+
+ /**
+ * Get a list of nested traffic selectors as traffic_selector_t.
+ *
+ * Resulting list and its traffic selectors must be destroyed after usage
+ *
+ * @return list of traffic selectors
+ */
+ linked_list_t *(*get_traffic_selectors) (ts_payload_t *this);
+
+ /**
+ * Destroys an ts_payload_t object.
+ */
+ void (*destroy) (ts_payload_t *this);
+};
+
+/**
+ * Creates an empty ts_payload_t object.
+ *
+ * @param is_initiator
+ * - TRUE if this payload is of type TSi
+ * - FALSE if this payload is of type TSr
+ * @return ts_payload_t object
+ */
+ts_payload_t *ts_payload_create(bool is_initiator);
+
+/**
+ * Creates ts_payload with a list of traffic_selector_t
+ *
+ * @param is_initiator
+ * - TRUE if this payload is of type TSi
+ * - FALSE if this payload is of type TSr
+ * @param traffic_selectors list of traffic selectors to include
+ * @return ts_payload_t object
+ */
+ts_payload_t *ts_payload_create_from_traffic_selectors(bool is_initiator,
+ linked_list_t *traffic_selectors);
+
+#endif /** TS_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/unknown_payload.c b/src/libcharon/encoding/payloads/unknown_payload.c
new file mode 100644
index 000000000..dd5547dc3
--- /dev/null
+++ b/src/libcharon/encoding/payloads/unknown_payload.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 <stddef.h>
+
+#include "unknown_payload.h"
+
+
+
+typedef struct private_unknown_payload_t private_unknown_payload_t;
+
+/**
+ * Private data of an unknown_payload_t object.
+ */
+struct private_unknown_payload_t {
+
+ /**
+ * Public unknown_payload_t interface.
+ */
+ unknown_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 data.
+ */
+ chunk_t data;
+};
+
+/**
+ * Encoding rules to parse an payload which is not further specified.
+ *
+ * The defined offsets are the positions in a object of type
+ * private_unknown_payload_t.
+ *
+ */
+encoding_rule_t unknown_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_unknown_payload_t, next_payload)},
+ /* the critical bit */
+ { FLAG, offsetof(private_unknown_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_unknown_payload_t, payload_length)},
+ /* some unknown data bytes, length is defined in PAYLOAD_LENGTH */
+ { UNKNOWN_DATA, offsetof(private_unknown_payload_t, 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 !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Data of any type ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_unknown_payload_t *this)
+{
+ /* can't do any checks, so we assume its good */
+ return SUCCESS;
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_unknown_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = unknown_payload_encodings;
+ *rule_count = sizeof(unknown_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_payload_type(private_unknown_payload_t *this)
+{
+ return UNKNOWN_PAYLOAD;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_unknown_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_unknown_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_unknown_payload_t *this)
+{
+ return this->payload_length;
+}
+
+/**
+ * Implementation of unknown_payload_t.get_data.
+ */
+static bool is_critical(private_unknown_payload_t *this)
+{
+ return this->critical;
+}
+
+/**
+ * Implementation of unknown_payload_t.get_data.
+ */
+static chunk_t get_data (private_unknown_payload_t *this)
+{
+ return (this->data);
+}
+
+/**
+ * Implementation of payload_t.destroy and unknown_payload_t.destroy.
+ */
+static void destroy(private_unknown_payload_t *this)
+{
+ if (this->data.ptr != NULL)
+ {
+ chunk_free(&(this->data));
+ }
+
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+unknown_payload_t *unknown_payload_create()
+{
+ private_unknown_payload_t *this = malloc_thing(private_unknown_payload_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (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 = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.destroy = (void (*) (unknown_payload_t *)) destroy;
+ this->public.is_critical = (bool (*) (unknown_payload_t *)) is_critical;
+ this->public.get_data = (chunk_t (*) (unknown_payload_t *)) get_data;
+
+ /* private variables */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = UNKNOWN_PAYLOAD_HEADER_LENGTH;
+ this->data = chunk_empty;
+
+ return (&(this->public));
+}
diff --git a/src/libcharon/encoding/payloads/unknown_payload.h b/src/libcharon/encoding/payloads/unknown_payload.h
new file mode 100644
index 000000000..c761ed2b6
--- /dev/null
+++ b/src/libcharon/encoding/payloads/unknown_payload.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup unknown_payload unknown_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef UNKNOWN_PAYLOAD_H_
+#define UNKNOWN_PAYLOAD_H_
+
+typedef struct unknown_payload_t unknown_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * Header length of the unknown payload.
+ */
+#define UNKNOWN_PAYLOAD_HEADER_LENGTH 4
+
+/**
+ * Payload which can't be processed further.
+ *
+ * When the parser finds an unknown payload, he builds an instance of
+ * this class. This allows further processing of this payload, such as
+ * a check for the critical bit in the header.
+ */
+struct unknown_payload_t {
+
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Get the raw data of this payload, without
+ * the generic payload header.
+ *
+ * Returned data are NOT copied and must not be freed.
+ *
+ * @return data as chunk_t
+ */
+ chunk_t (*get_data) (unknown_payload_t *this);
+
+ /**
+ * Get the critical flag.
+ *
+ * @return TRUE if payload is critical, FALSE if not
+ */
+ bool (*is_critical) (unknown_payload_t *this);
+
+ /**
+ * Destroys an unknown_payload_t object.
+ */
+ void (*destroy) (unknown_payload_t *this);
+};
+
+/**
+ * Creates an empty unknown_payload_t object.
+ *
+ * @return unknown_payload_t object
+ */
+unknown_payload_t *unknown_payload_create(void);
+
+#endif /** UNKNOWN_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/vendor_id_payload.c b/src/libcharon/encoding/payloads/vendor_id_payload.c
new file mode 100644
index 000000000..bf33d2418
--- /dev/null
+++ b/src/libcharon/encoding/payloads/vendor_id_payload.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 <stddef.h>
+
+#include "vendor_id_payload.h"
+
+typedef struct private_vendor_id_payload_t private_vendor_id_payload_t;
+
+/**
+ * Private data of an vendor_id_payload_t object.
+ */
+struct private_vendor_id_payload_t {
+
+ /**
+ * Public vendor_id_payload_t interface.
+ */
+ vendor_id_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 data.
+ */
+ chunk_t data;
+};
+
+/**
+ * Encoding rules to parse or generate a VENDOR ID payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_vendor_id_payload_t.
+ */
+encoding_rule_t vendor_id_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_vendor_id_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_vendor_id_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_vendor_id_payload_t, payload_length)},
+ /* some vendor_id data bytes, length is defined in PAYLOAD_LENGTH */
+ { VID_DATA, offsetof(private_vendor_id_payload_t, 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 !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ + !
+ ~ VID Data ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_vendor_id_payload_t *this)
+{
+ return SUCCESS;
+}
+
+/**
+ * Implementation of vendor_id_payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_vendor_id_payload_t *this,
+ encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = vendor_id_payload_encodings;
+ *rule_count = sizeof(vendor_id_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_payload_type(private_vendor_id_payload_t *this)
+{
+ return VENDOR_ID;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_vendor_id_payload_t *this)
+{
+ return this->next_payload;
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_vendor_id_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_vendor_id_payload_t *this)
+{
+ return this->payload_length;
+}
+
+/**
+ * Implementation of vendor_id_payload_t.get_data.
+ */
+static chunk_t get_data(private_vendor_id_payload_t *this)
+{
+ return this->data;
+}
+
+/**
+ * Implementation of payload_t.destroy and vendor_id_payload_t.destroy.
+ */
+static void destroy(private_vendor_id_payload_t *this)
+{
+ free(this->data.ptr);
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+vendor_id_payload_t *vendor_id_payload_create()
+{
+ private_vendor_id_payload_t *this = malloc_thing(private_vendor_id_payload_t);
+
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (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 = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+ this->public.get_data = (chunk_t (*) (vendor_id_payload_t *)) get_data;
+
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH;
+ this->data = chunk_empty;
+
+ return &this->public;
+}
+
+/*
+ * Described in header
+ */
+vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data)
+{
+ private_vendor_id_payload_t *this;
+
+ this = (private_vendor_id_payload_t*)vendor_id_payload_create();
+ this->payload_length += data.len;
+ this->data = data;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/encoding/payloads/vendor_id_payload.h b/src/libcharon/encoding/payloads/vendor_id_payload.h
new file mode 100644
index 000000000..241535cac
--- /dev/null
+++ b/src/libcharon/encoding/payloads/vendor_id_payload.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/**
+ * @defgroup vendor_id_payload vendor_id_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef VENDOR_ID_PAYLOAD_H_
+#define VENDOR_ID_PAYLOAD_H_
+
+typedef struct vendor_id_payload_t vendor_id_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * Length of a VENDOR ID payload without the VID data in bytes.
+ */
+#define VENDOR_ID_PAYLOAD_HEADER_LENGTH 4
+
+/**
+ * Class representing an IKEv2 VENDOR ID payload.
+ *
+ * The VENDOR ID payload format is described in RFC section 3.12.
+ */
+struct vendor_id_payload_t {
+
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Get the VID data.
+ *
+ * @return VID data, pointing to an internal chunk_t
+ */
+ chunk_t (*get_data)(vendor_id_payload_t *this);
+};
+
+/**
+ * Creates an empty Vendor ID payload.
+ *
+ * @return vendor ID payload
+ */
+vendor_id_payload_t *vendor_id_payload_create();
+
+/**
+ * Creates a vendor ID payload using a chunk of data
+ *
+ * @param data data to use in vendor ID payload, gets owned by payload
+ * @return vendor ID payload
+ */
+vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data);
+
+#endif /** VENDOR_ID_PAYLOAD_H_ @}*/