diff options
Diffstat (limited to 'src/libcharon/encoding/generator.c')
-rw-r--r-- | src/libcharon/encoding/generator.c | 426 |
1 files changed, 426 insertions, 0 deletions
diff --git a/src/libcharon/encoding/generator.c b/src/libcharon/encoding/generator.c index ce3844361..785f1430a 100644 --- a/src/libcharon/encoding/generator.c +++ b/src/libcharon/encoding/generator.c @@ -41,7 +41,10 @@ #include <encoding/payloads/cp_payload.h> #include <encoding/payloads/configuration_attribute.h> #include <encoding/payloads/eap_payload.h> +<<<<<<< HEAD +======= #include <encoding/payloads/unknown_payload.h> +>>>>>>> upstream/4.5.1 /** * Generating is done in a data buffer. @@ -90,10 +93,27 @@ struct private_generator_t { */ void *data_struct; +<<<<<<< HEAD + /* + * 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; +======= /** * Offset of the header length field in the buffer. */ u_int32_t header_length_offset; +>>>>>>> upstream/4.5.1 /** * Attribute format of the last generated transform attribute. @@ -184,6 +204,36 @@ static void write_bytes_to_buffer(private_generator_t *this, void *bytes, } /** +<<<<<<< HEAD + * 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++; + } +} + +/** +======= +>>>>>>> upstream/4.5.1 * Generates a U_INT-Field type and writes it to buffer. */ static void generate_u_int_type(private_generator_t *this, @@ -198,13 +248,19 @@ static void generate_u_int_type(private_generator_t *this, number_of_bits = 4; break; case TS_TYPE: +<<<<<<< HEAD +======= case RESERVED_BYTE: case SPI_SIZE: +>>>>>>> upstream/4.5.1 case U_INT_8: number_of_bits = 8; break; case U_INT_16: +<<<<<<< HEAD +======= case PAYLOAD_LENGTH: +>>>>>>> upstream/4.5.1 case CONFIGURATION_ATTRIBUTE_LENGTH: number_of_bits = 16; break; @@ -268,8 +324,11 @@ static void generate_u_int_type(private_generator_t *this, break; } case TS_TYPE: +<<<<<<< HEAD +======= case RESERVED_BYTE: case SPI_SIZE: +>>>>>>> upstream/4.5.1 case U_INT_8: { /* 8 bit values are written as they are */ @@ -307,7 +366,10 @@ static void generate_u_int_type(private_generator_t *this, } case U_INT_16: +<<<<<<< HEAD +======= case PAYLOAD_LENGTH: +>>>>>>> upstream/4.5.1 case CONFIGURATION_ATTRIBUTE_LENGTH: { u_int16_t val = htons(*((u_int16_t*)(this->data_struct + offset))); @@ -341,6 +403,52 @@ static void generate_u_int_type(private_generator_t *this, } /** +<<<<<<< HEAD + * 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++; + } +} + +/** +======= +>>>>>>> upstream/4.5.1 * Generate a FLAG filed */ static void generate_flag(private_generator_t *this, u_int32_t offset) @@ -395,7 +503,11 @@ METHOD(generator_t, get_chunk, chunk_t, { chunk_t data; +<<<<<<< HEAD + *lenpos = (u_int32_t*)(this->buffer + this->header_length_position_offset); +======= *lenpos = (u_int32_t*)(this->buffer + this->header_length_offset); +>>>>>>> upstream/4.5.1 data = chunk_create(this->buffer, get_length(this)); DBG3(DBG_ENC, "generated data of this generator %B", &data); return data; @@ -411,6 +523,11 @@ METHOD(generator_t, generate_payload, void, this->data_struct = payload; payload_type = payload->get_type(payload); +<<<<<<< HEAD + /* spi size has to get reseted */ + this->last_spi_size = 0; +======= +>>>>>>> upstream/4.5.1 offset_start = this->out_position - this->buffer; @@ -430,6 +547,58 @@ METHOD(generator_t, generate_payload, void, case U_INT_8: case U_INT_16: case U_INT_32: +<<<<<<< HEAD + 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 PAYLOAD_LENGTH: case IKE_SPI: case RESERVED_BYTE: @@ -449,6 +618,7 @@ METHOD(generator_t, generate_payload, void, break; case ADDRESS: case SPI: +>>>>>>> upstream/4.5.1 case KEY_EXCHANGE_DATA: case NOTIFICATION_DATA: case NONCE_DATA: @@ -460,6 +630,198 @@ METHOD(generator_t, generate_payload, void, case CONFIGURATION_ATTRIBUTE_VALUE: case VID_DATA: case EAP_DATA: +<<<<<<< HEAD + { + 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**)¤t_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**)¤t_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**)¤t_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**)¤t_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: + { +======= case ENCRYPTED_DATA: case UNKNOWN_DATA: generate_from_chunk(this, rules[i].offset); @@ -485,19 +847,41 @@ METHOD(generator_t, generate_payload, void, break; } case ATTRIBUTE_FORMAT: +>>>>>>> upstream/4.5.1 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; +<<<<<<< HEAD + } + + 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)); +======= case ATTRIBUTE_LENGTH_OR_VALUE: if (this->attribute_format) { generate_u_int_type(this, U_INT_16, rules[i].offset); +>>>>>>> upstream/4.5.1 } else { generate_u_int_type(this, U_INT_16, rules[i].offset); +<<<<<<< HEAD + } + break; + } + case ATTRIBUTE_VALUE: + { + if (this->attribute_format == FALSE) +======= /* this field hold the length of the attribute */ this->attribute_length = *((u_int16_t *)(this->data_struct + rules[i].offset)); @@ -506,6 +890,7 @@ METHOD(generator_t, generate_payload, void, case ATTRIBUTE_VALUE: { if (!this->attribute_format) +>>>>>>> upstream/4.5.1 { DBG2(DBG_ENC, "attribute value has not fixed size"); /* the attribute value is generated */ @@ -513,6 +898,47 @@ METHOD(generator_t, generate_payload, void, } break; } +<<<<<<< HEAD + 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 **)¤t_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; + } +======= +>>>>>>> upstream/4.5.1 default: DBG1(DBG_ENC, "field type %N is not supported", encoding_type_names, rules[i].type); |