diff options
Diffstat (limited to 'Source/charon/encoding/payloads')
-rw-r--r-- | Source/charon/encoding/payloads/Makefile.payloads | 10 | ||||
-rw-r--r-- | Source/charon/encoding/payloads/encodings.c | 3 | ||||
-rw-r--r-- | Source/charon/encoding/payloads/encodings.h | 39 | ||||
-rw-r--r-- | Source/charon/encoding/payloads/payload.c | 12 | ||||
-rw-r--r-- | Source/charon/encoding/payloads/payload.h | 8 | ||||
-rw-r--r-- | Source/charon/encoding/payloads/traffic_selector_substructure.c | 338 | ||||
-rw-r--r-- | Source/charon/encoding/payloads/traffic_selector_substructure.h | 175 | ||||
-rw-r--r-- | Source/charon/encoding/payloads/ts_payload.c | 317 | ||||
-rw-r--r-- | Source/charon/encoding/payloads/ts_payload.h | 127 |
9 files changed, 1022 insertions, 7 deletions
diff --git a/Source/charon/encoding/payloads/Makefile.payloads b/Source/charon/encoding/payloads/Makefile.payloads index c9046a089..91cd2307e 100644 --- a/Source/charon/encoding/payloads/Makefile.payloads +++ b/Source/charon/encoding/payloads/Makefile.payloads @@ -42,9 +42,13 @@ OBJS+= $(BUILD_DIR)auth_payload.o $(BUILD_DIR)auth_payload.o : $(PAYLOADS_DIR)auth_payload.c $(PAYLOADS_DIR)auth_payload.h $(CC) $(CFLAGS) -c -o $@ $< -#OBJS+= $(BUILD_DIR)ts_payload.o -#$(BUILD_DIR)ts_payload.o : $(PAYLOADS_DIR)ts_payload.c $(PAYLOADS_DIR)ts_payload.h -# $(CC) $(CFLAGS) -c -o $@ $< +OBJS+= $(BUILD_DIR)ts_payload.o +$(BUILD_DIR)ts_payload.o : $(PAYLOADS_DIR)ts_payload.c $(PAYLOADS_DIR)ts_payload.h + $(CC) $(CFLAGS) -c -o $@ $< + +OBJS+= $(BUILD_DIR)traffic_selector_substructure.o +$(BUILD_DIR)traffic_selector_substructure.o : $(PAYLOADS_DIR)traffic_selector_substructure.c $(PAYLOADS_DIR)traffic_selector_substructure.h + $(CC) $(CFLAGS) -c -o $@ $< OBJS+= $(BUILD_DIR)payload.o $(BUILD_DIR)payload.o : $(PAYLOADS_DIR)payload.c $(PAYLOADS_DIR)payload.h diff --git a/Source/charon/encoding/payloads/encodings.c b/Source/charon/encoding/payloads/encodings.c index 1619dde49..5d952121f 100644 --- a/Source/charon/encoding/payloads/encodings.c +++ b/Source/charon/encoding/payloads/encodings.c @@ -51,5 +51,8 @@ mapping_t encoding_type_m[] = { {ID_DATA, "ID_DATA"}, {AUTH_DATA, "AUTH_DATA"}, {ENCRYPTED_DATA, "ENCRYPTED_DATA"}, + {TS_TYPE, "TS_TYPE"}, + {ADDRESS, "ADDRESS"}, + {TRAFFIC_SELECTORS, "TRAFFIC_SELECTORS"}, {MAPPING_END, NULL} }; diff --git a/Source/charon/encoding/payloads/encodings.h b/Source/charon/encoding/payloads/encodings.h index 106419bf2..edc26990b 100644 --- a/Source/charon/encoding/payloads/encodings.h +++ b/Source/charon/encoding/payloads/encodings.h @@ -298,6 +298,45 @@ enum encoding_type_t{ * 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. diff --git a/Source/charon/encoding/payloads/payload.c b/Source/charon/encoding/payloads/payload.c index fd25aa4c6..bc68cb11f 100644 --- a/Source/charon/encoding/payloads/payload.c +++ b/Source/charon/encoding/payloads/payload.c @@ -31,10 +31,7 @@ #include <encoding/payloads/ke_payload.h> #include <encoding/payloads/notify_payload.h> #include <encoding/payloads/auth_payload.h> - - - - +#include <encoding/payloads/ts_payload.h> /* * build the mappings for payload_type_t @@ -61,6 +58,7 @@ mapping_t payload_type_m[] = { {PROPOSAL_SUBSTRUCTURE, "PROPOSAL_SUBSTRUCTURE"}, {TRANSFORM_SUBSTRUCTURE, "TRANSFORM_SUBSTRUCTURE"}, {TRANSFORM_ATTRIBUTE, "TRANSFORM_ATTRIBUTE"}, + {TRAFFIC_SELECTOR_SUBSTRUCTURE, "TRAFFIC_SELECTOR_SUBSTRUCTURE"}, {MAPPING_END, NULL} }; @@ -89,6 +87,12 @@ payload_t *payload_create(payload_type_t type) return (payload_t*)id_payload_create(FALSE); case AUTHENTICATION: return (payload_t*)auth_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: diff --git a/Source/charon/encoding/payloads/payload.h b/Source/charon/encoding/payloads/payload.h index 1bd3bf00a..6fceaa2ad 100644 --- a/Source/charon/encoding/payloads/payload.h +++ b/Source/charon/encoding/payloads/payload.h @@ -158,6 +158,14 @@ enum payload_type_t{ * 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 send over wire and just + * used internally to handle a transform selector like a payload. + */ + TRAFFIC_SELECTOR_SUBSTRUCTURE = 144, }; diff --git a/Source/charon/encoding/payloads/traffic_selector_substructure.c b/Source/charon/encoding/payloads/traffic_selector_substructure.c new file mode 100644 index 000000000..d2c9af54d --- /dev/null +++ b/Source/charon/encoding/payloads/traffic_selector_substructure.c @@ -0,0 +1,338 @@ +/** + * @file traffic_selector_substructure.c + * + * @brief Interface of traffic_selector_substructure_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "traffic_selector_substructure.h" + +#include <encoding/payloads/encodings.h> +#include <utils/allocator.h> +#include <utils/linked_list.h> + +/** + * String mappings for ts_type_t. + */ +mapping_t ts_type_m[] = { +{TS_IPV4_ADDR_RANGE, "TS_IPV4_ADDR_RANGE"}, +{TS_IPV6_ADDR_RANGE, "TS_IPV6_ADDR_RANGE"}, +{MAPPING_END, NULL} +}; + + +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: + 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_ts_type. + */ +static ts_type_t get_ts_type (private_traffic_selector_substructure_t *this) +{ + return this->ts_type; +} + +/** + * Implementation of traffic_selector_substructure_t.set_ts_type. + */ +static void set_ts_type (private_traffic_selector_substructure_t *this,ts_type_t ts_type) +{ + this->ts_type = ts_type; +} + +/** + * Implementation of traffic_selector_substructure_t.get_protocol_id. + */ +static u_int8_t get_protocol_id (private_traffic_selector_substructure_t *this) +{ + return this->ip_protocol_id; +} + +/** + * Implementation of traffic_selector_substructure_t.set_protocol_id. + */ +static void set_protocol_id (private_traffic_selector_substructure_t *this,u_int8_t protocol_id) +{ + this->ip_protocol_id = protocol_id; +} + +/** + * Implementation of traffic_selector_substructure_t.get_start_host. + */ +static host_t * get_start_host (private_traffic_selector_substructure_t *this) +{ + return (host_create_from_chunk(AF_INET,this->starting_address, this->start_port)); +} + +/** + * Implementation of traffic_selector_substructure_t.set_start_host. + */ +static void set_start_host (private_traffic_selector_substructure_t *this,host_t *start_host) +{ + this->start_port = start_host->get_port(start_host); + if (this->starting_address.ptr != NULL) + { + allocator_free_chunk(&(this->starting_address)); + } + this->starting_address = start_host->get_address_as_chunk(start_host); + this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH + this->starting_address.len + this->ending_address.len; +} + +/** + * Implementation of traffic_selector_substructure_t.get_end_host. + */ +static host_t *get_end_host (private_traffic_selector_substructure_t *this) +{ + return (host_create_from_chunk(AF_INET,this->ending_address, this->end_port)); +} + +/** + * Implementation of traffic_selector_substructure_t.set_end_host. + */ +static void set_end_host (private_traffic_selector_substructure_t *this,host_t *end_host) +{ + this->end_port = end_host->get_port(end_host); + if (this->ending_address.ptr != NULL) + { + allocator_free_chunk(&(this->ending_address)); + } + this->ending_address = end_host->get_address_as_chunk(end_host); + this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH + this->starting_address.len + this->ending_address.len; +} + +/** + * Implementation of payload_t.destroy and traffic_selector_substructure_t.destroy. + */ +static void destroy(private_traffic_selector_substructure_t *this) +{ + + if (this->starting_address.ptr != NULL) + { + allocator_free_chunk(&(this->starting_address)); + } + + if (this->ending_address.ptr != NULL) + { + allocator_free_chunk(&(this->ending_address)); + } + + allocator_free(this); +} + +/* + * Described in header + */ +traffic_selector_substructure_t *traffic_selector_substructure_create(bool is_initiator) +{ + private_traffic_selector_substructure_t *this = allocator_alloc_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.destroy = (void (*) (traffic_selector_substructure_t *)) destroy; + this->public.get_ts_type = (ts_type_t (*) (traffic_selector_substructure_t *)) get_ts_type; + this->public.set_ts_type = (void (*) (traffic_selector_substructure_t *,ts_type_t)) set_ts_type; + this->public.get_protocol_id = (u_int8_t (*) (traffic_selector_substructure_t *)) get_protocol_id; + this->public.set_protocol_id = (void (*) (traffic_selector_substructure_t *,u_int8_t)) set_protocol_id; + this->public.get_start_host = (host_t * (*) (traffic_selector_substructure_t *))get_start_host; + this->public.set_start_host = (void (*) (traffic_selector_substructure_t *, host_t *))set_start_host; + this->public.get_end_host = (host_t * (*) (traffic_selector_substructure_t *))get_end_host; + this->public.set_end_host = (void (*) (traffic_selector_substructure_t *, host_t *))set_end_host; + + + /* private variables */ + this->payload_length =TRAFFIC_SELECTOR_HEADER_LENGTH; + this->start_port = 0; + this->end_port = 0; + this->starting_address = CHUNK_INITIALIZER; + this->ending_address = CHUNK_INITIALIZER; + this->ip_protocol_id = 0; + /* must be set to be valid */ + this->ts_type = TS_IPV4_ADDR_RANGE; + + return (&(this->public)); +} diff --git a/Source/charon/encoding/payloads/traffic_selector_substructure.h b/Source/charon/encoding/payloads/traffic_selector_substructure.h new file mode 100644 index 000000000..43e697415 --- /dev/null +++ b/Source/charon/encoding/payloads/traffic_selector_substructure.h @@ -0,0 +1,175 @@ +/** + * @file traffic_selector_substructure.h + * + * @brief Interface of traffic_selector_substructure_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + + +#ifndef TRAFFIC_SELECTOR_SUBSTRUCTURE_H_ +#define TRAFFIC_SELECTOR_SUBSTRUCTURE_H_ + +#include <types.h> +#include <encoding/payloads/payload.h> +#include <network/host.h> + +/** + * Length of a TRAFFIC SELECTOR SUBSTRUCTURE without start and end address. + * + * @ingroup payloads + */ +#define TRAFFIC_SELECTOR_HEADER_LENGTH 8 + + +typedef enum ts_type_t ts_type_t; + +/** + * Traffic selector Types. + * + * @ingroup payloads + */ +enum ts_type_t { + /* + * A range of IPv4 addresses, represented by two four (4) octet + * values. The first value is the beginning IPv4 address + * (inclusive) and the second value is the ending IPv4 address + * (inclusive). All addresses falling between the two specified + * addresses are considered to be within the list. + */ + TS_IPV4_ADDR_RANGE = 7, + /* + * A range of IPv6 addresses, represented by two sixteen (16) + * octet values. The first value is the beginning IPv6 address + * (inclusive) and the second value is the ending IPv6 address + * (inclusive). All addresses falling between the two specified + * addresses are considered to be within the list. + */ + TS_IPV6_ADDR_RANGE = 8 +}; + +extern mapping_t ts_type_m[]; + +typedef struct traffic_selector_substructure_t traffic_selector_substructure_t; + +/** + * Object representing an IKEv2 TRAFFIC SELECTOR. + * + * The TRAFFIC SELECTOR format is described in draft section 3.13.1. + * + * @ingroup payloads + * + */ +struct traffic_selector_substructure_t { + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Get the type of Traffic selector. + * + * @param this calling traffic_selector_substructure_t object + * @return type of traffic selector + * + */ + ts_type_t (*get_ts_type) (traffic_selector_substructure_t *this); + + /** + * @brief Set the type of Traffic selector. + * + * @param this calling traffic_selector_substructure_t object + * @param ts_type type of traffic selector + */ + void (*set_ts_type) (traffic_selector_substructure_t *this,ts_type_t ts_type); + + /** + * @brief Get the IP protocol ID of Traffic selector. + * + * @param this calling traffic_selector_substructure_t object + * @return type of traffic selector + * + */ + u_int8_t (*get_protocol_id) (traffic_selector_substructure_t *this); + + /** + * @brief Set the IP protocol ID of Traffic selector + * + * @param this calling traffic_selector_substructure_t object + * @param protocol_id protocol ID of traffic selector + */ + void (*set_protocol_id) (traffic_selector_substructure_t *this,u_int8_t protocol_id); + + /** + * @brief Get the start port and address as host_t object. + * + * Returned host_t object has to get destroyed by the caller. + * + * @param this calling traffic_selector_substructure_t object + * @return start host as host_t object + * + */ + host_t *(*get_start_host) (traffic_selector_substructure_t *this); + + /** + * @brief Set the start port and address as host_t object. + * + * @param this calling traffic_selector_substructure_t object + * @param start_host start host as host_t object + */ + void (*set_start_host) (traffic_selector_substructure_t *this,host_t *start_host); + + /** + * @brief Get the end port and address as host_t object. + * + * Returned host_t object has to get destroyed by the caller. + * + * @param this calling traffic_selector_substructure_t object + * @return end host as host_t object + * + */ + host_t *(*get_end_host) (traffic_selector_substructure_t *this); + + /** + * @brief Set the end port and address as host_t object. + * + * @param this calling traffic_selector_substructure_t object + * @param end_host end host as host_t object + */ + void (*set_end_host) (traffic_selector_substructure_t *this,host_t *end_host); + + /** + * @brief Destroys an traffic_selector_substructure_t object. + * + * @param this traffic_selector_substructure_t object to destroy + */ + void (*destroy) (traffic_selector_substructure_t *this); +}; + +/** + * @brief Creates an empty traffic_selector_substructure_t object. + * + * TS type is set to default TS_IPV4_ADDR_RANGE! + * + * @return created traffic_selector_substructure_t object + * + * @ingroup payloads + */ +traffic_selector_substructure_t *traffic_selector_substructure_create(); + + +#endif //TRAFFIC_SELECTOR_SUBSTRUCTURE_H_ diff --git a/Source/charon/encoding/payloads/ts_payload.c b/Source/charon/encoding/payloads/ts_payload.c new file mode 100644 index 000000000..2e7df5b6d --- /dev/null +++ b/Source/charon/encoding/payloads/ts_payload.c @@ -0,0 +1,317 @@ +/** + * @file ts_payload.c + * + * @brief Implementation of ts_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "ts_payload.h" + +#include <encoding/payloads/encodings.h> +#include <utils/allocator.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; + + /** + * @brief Computes the length of this payload. + * + * @param this calling private_ts_payload_t object + */ + void (*compute_length) (private_ts_payload_t *this); +}; + +/** + * 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; + status_t status; + + if (this->critical) + { + /* critical bit is set! */ + return FAILED; + } + 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->has_next(iterator)) + { + payload_t *current_traffic_selector; + iterator->current(iterator,(void **)¤t_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) +{ + return ((this->is_initiator) ? TRAFFIC_SELECTOR_INITIATOR : 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; +} + +/** + * Implementation of payload_t.get_length. + */ +static size_t get_length(private_ts_payload_t *this) +{ + 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 private_ts_payload_t.compute_length. + */ +static void compute_length (private_ts_payload_t *this) +{ + iterator_t *iterator; + size_t ts_count = 0; + size_t length = TS_PAYLOAD_HEADER_LENGTH; + iterator = this->traffic_selectors->create_iterator(this->traffic_selectors,TRUE); + while (iterator->has_next(iterator)) + { + payload_t * current_traffic_selector; + iterator->current(iterator,(void **) ¤t_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.destroy and ts_payload_t.destroy. + */ +static void destroy(private_ts_payload_t *this) +{ + while (this->traffic_selectors->get_count(this->traffic_selectors) > 0) + { + payload_t *current_traffic_selector; + + this->traffic_selectors->remove_last(this->traffic_selectors,(void **) ¤t_traffic_selector); + + current_traffic_selector->destroy(current_traffic_selector); + } + + this->traffic_selectors->destroy(this->traffic_selectors); + + allocator_free(this); +} + +/* + * Described in header + */ +ts_payload_t *ts_payload_create(bool is_initiator) +{ + private_ts_payload_t *this = allocator_alloc_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; + + /* private functions */ + this->compute_length = compute_length; + + /* 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)); +} diff --git a/Source/charon/encoding/payloads/ts_payload.h b/Source/charon/encoding/payloads/ts_payload.h new file mode 100644 index 000000000..02cd3a410 --- /dev/null +++ b/Source/charon/encoding/payloads/ts_payload.h @@ -0,0 +1,127 @@ +/** + * @file ts_payload.h + * + * @brief Interface of ts_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + + +#ifndef TS_PAYLOAD_H_ +#define TS_PAYLOAD_H_ + +#include <types.h> +#include <utils/iterator.h> +#include <encoding/payloads/payload.h> +#include <encoding/payloads/traffic_selector_substructure.h> + +/** + * Length of a TS payload without the Traffic selectors. + * + * @ingroup payloads + */ +#define TS_PAYLOAD_HEADER_LENGTH 8 + + +typedef struct ts_payload_t ts_payload_t; + +/** + * Object representing an IKEv2 TS payload. + * + * The TS payload format is described in draft section 3.13. + * + * @ingroup payloads + * + */ +struct ts_payload_t { + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Get the type of TSpayload (TSi or TSr). + * + * @param this calling id_payload_t object + * @return + * - TRUE if this payload is of type TSi + * - FALSE if this payload is of type TSr + * + */ + bool (*get_initiator) (ts_payload_t *this); + + /** + * @brief Set the type of TS payload (TSi or TSr). + * + * @param this calling id_payload_t object + * @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); + + /** + * @brief Adds a traffic_selector_substructure_t object to this object. + * + * @warning The added traffic_selector_substructure_t object is + * getting destroyed in destroy function of ts_payload_t. + * + * @param this calling ts_payload_t 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); + + /** + * @brief Creates an iterator of stored traffic_selector_substructure_t objects. + * + * @warning The created iterator has to get destroyed by the caller! + * + * @warning 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 this calling ts_payload_t object + * @param[in] 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); + + /** + * @brief Destroys an ts_payload_t object. + * + * @param this ts_payload_t object to destroy + */ + void (*destroy) (ts_payload_t *this); +}; + +/** + * @brief Creates an empty id_payload_t object. + * + * + * @param is_initiator + * - TRUE if this payload is of type TSi + * - FALSE if this payload is of type TSr + * + * @return created id_payload_t object + * + * @ingroup payloads + */ +ts_payload_t *ts_payload_create(bool is_initiator); + + +#endif //TS_PAYLOAD_H_ |