From 3d40ec7a68e6e318eb73dd80da206141877cb04e Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Thu, 10 Nov 2005 19:19:56 +0000 Subject: [PATCH] - parser successfully parses an ike_header - no doxygen yet --- Source/charon/parser.c | 363 ++++++++++++++++++++++++++++++++++++++++++++++++- Source/charon/parser.h | 37 +++-- 2 files changed, 388 insertions(+), 12 deletions(-) diff --git a/Source/charon/parser.c b/Source/charon/parser.c index 0f4af57..0e01259 100644 --- a/Source/charon/parser.c +++ b/Source/charon/parser.c @@ -21,10 +21,71 @@ */ #include +#include #include "allocator.h" #include "types.h" #include "parser.h" +#include "logger.h" + + +typedef struct private_parser_context_s private_parser_context_t; + +struct private_parser_context_s { + /** + * Public members + */ + parser_context_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 + */ + u_int8_t *input_roof; + + +}; + +static status_t parser_context_destroy(private_parser_context_t *this) +{ + allocator_free(this); + + return SUCCESS; +} + +static private_parser_context_t *parser_context_create(chunk_t input) +{ + private_parser_context_t *this = allocator_alloc_thing(private_parser_context_t); + if (this == NULL) + { + return NULL; + } + + this->public.destroy = (status_t(*)(parser_context_t*)) parser_context_destroy; + + this->input = input.ptr; + this->byte_pos = input.ptr; + this->bit_pos = 0; + this->input_roof = input.ptr + input.len; + + return this; +} + + /** * Private data of a parser_t object @@ -37,8 +98,308 @@ struct private_parser_s { */ parser_t public; - /* private functions and fields */ + /** + * list of payloads and their description + */ + payload_info_t **payload_infos; + + /** + * logger object + */ + logger_t *logger; }; +static private_parser_context_t *create_context(private_parser_t *this, chunk_t data) +{ + private_parser_context_t *context = parser_context_create(data); + + return context; +} + +static status_t parse_payload(private_parser_t *this, private_parser_context_t *context, payload_type_t payload_type, void **data_struct) +{ + payload_info_t *payload_info = NULL; + + /* find payload in null terminated list*/ + payload_info = *(this->payload_infos); + while (payload_info) + { + if (payload_info->payload_type == payload_type) + { + void *output; + int current; + + /* ok, do the parsing */ + output = allocator_alloc(payload_info->data_struct_length); + + for (current = 0; current < payload_info->encoding_rules_count; current++) + { + encoding_rule_t *rule = &(payload_info->ecoding_rules[current]); + switch (rule->type) + { + case U_INT_4: + { + u_int8_t *output_pos = output + rule->offset; + if (context->byte_pos + sizeof(u_int8_t) > context->input_roof) + { + this->logger->log(this->logger, ERROR, "not enough input to parse U_INT_4"); + allocator_free(output); + return PARSE_ERROR; + } + switch (context->bit_pos) + { + case 0: + *output_pos = *(context->byte_pos) >> 4; + context->bit_pos = 4; + break; + case 4: + *output_pos = *(context->byte_pos) & 0x0F; + context->bit_pos = 0; + context->byte_pos++; + break; + default: + this->logger->log(this->logger, ERROR, "found rule U_INT_4 on bitpos %d", context->bit_pos); + allocator_free(output); + return PARSE_ERROR; + } + break; + } + case U_INT_8: + { + u_int8_t *output_pos = output + rule->offset; + if (context->byte_pos + sizeof(u_int8_t) > context->input_roof) + { + this->logger->log(this->logger, ERROR, "not enough input to parse U_INT_8"); + allocator_free(output); + return PARSE_ERROR; + } + if (context->bit_pos) + { + this->logger->log(this->logger, ERROR, "found rule U_INT_8 on bitpos %d", context->bit_pos); + allocator_free(output); + return PARSE_ERROR; + } + + *output_pos = *(context->byte_pos); + context->byte_pos++; + break; + } + case U_INT_16: + { + u_int16_t *output_pos = output + rule->offset; + if (context->byte_pos + sizeof(u_int16_t) > context->input_roof) + { + this->logger->log(this->logger, ERROR, "not enough input to parse U_INT_16"); + allocator_free(output); + return PARSE_ERROR; + } + if (context->bit_pos) + { + this->logger->log(this->logger, ERROR, "found rule U_INT_16 on bitpos %d", context->bit_pos); + allocator_free(output); + return PARSE_ERROR; + } + if ((int)context->byte_pos % 2) + { + this->logger->log(this->logger, ERROR, "found rule U_INT_16 on odd bytepos"); + allocator_free(output); + return PARSE_ERROR; + } + *output_pos = ntohs(*((u_int16_t*)context->byte_pos)); + context->byte_pos += 2; + break; + } + case U_INT_32: + { + u_int32_t *output_pos = output + rule->offset; + if (context->byte_pos + sizeof(u_int32_t) > context->input_roof) + { + this->logger->log(this->logger, ERROR, "not enough input to parse U_INT_32"); + allocator_free(output); + return PARSE_ERROR; + } + if (context->bit_pos) + { + this->logger->log(this->logger, ERROR, "found rule U_INT_32 on bitpos %d", context->bit_pos); + allocator_free(output); + return PARSE_ERROR; + } + if ((int)context->byte_pos % 4) + { + this->logger->log(this->logger, ERROR, "found rule U_INT_32 on unaligned bytepos"); + allocator_free(output); + return PARSE_ERROR; + } + *output_pos = ntohl(*((u_int32_t*)context->byte_pos)); + context->byte_pos += 4; + break; + } + case U_INT_64: + { + u_int32_t *output_pos = output + rule->offset; + if (context->byte_pos + 2 * sizeof(u_int32_t) > context->input_roof) + { + this->logger->log(this->logger, ERROR, "not enough input to parse U_INT_64"); + allocator_free(output); + return PARSE_ERROR; + } + if (context->bit_pos) + { + this->logger->log(this->logger, ERROR, "found rule U_INT_64 on bitpos %d", context->bit_pos); + allocator_free(output); + return PARSE_ERROR; + } + if ((int)context->byte_pos % 8) + { + this->logger->log(this->logger, ERROR, "found rule U_INT_64 on unaligned bytepos"); + allocator_free(output); + return PARSE_ERROR; + } + /* assuming little endian host order */ + *(output_pos + 1) = ntohl(*((u_int32_t*)context->byte_pos)); + context->byte_pos += 4; + *output_pos = ntohl(*((u_int32_t*)context->byte_pos)); + context->byte_pos += 4; + + break; + } + case RESERVED_BIT: + { + if (context->byte_pos > context->input_roof) + { + this->logger->log(this->logger, ERROR, "not enough input to parse RESERVED_BIT"); + allocator_free(output); + return PARSE_ERROR; + } + context->bit_pos = (context->bit_pos + 1) % 8; + if (context->bit_pos == 0) + { + context->byte_pos++; + } + break; + } + case RESERVED_BYTE: + { + if (context->byte_pos > context->input_roof) + { + this->logger->log(this->logger, ERROR, "not enough input to parse RESERVED_BYTE"); + allocator_free(output); + return PARSE_ERROR; + } + if (context->bit_pos) + { + this->logger->log(this->logger, ERROR, "found rule RESERVED_BYTE on bitpos %d", context->bit_pos); + allocator_free(output); + return PARSE_ERROR; + } + context->byte_pos++; + break; + } + case FLAG: + { + bool *output_pos = output + rule->offset; + u_int8_t mask; + if (context->byte_pos > context->input_roof) + { + this->logger->log(this->logger, ERROR, "not enough input to parse FLAG"); + allocator_free(output); + return PARSE_ERROR; + } + mask = 0x01 << (7 - context->bit_pos); + *output_pos = *context->byte_pos & mask; + + if (*output_pos) + { + /* set to a "clean", comparable true */ + *output_pos = TRUE; + } + context->bit_pos = (context->bit_pos + 1) % 8; + if (context->bit_pos == 0) + { + context->byte_pos++; + } + break; + } + case LENGTH: + { + u_int32_t *output_pos = output + rule->offset; + if (context->byte_pos + sizeof(u_int32_t) > context->input_roof) + { + this->logger->log(this->logger, ERROR, "not enough input to parse LENGTH"); + allocator_free(output); + return PARSE_ERROR; + } + if (context->bit_pos) + { + this->logger->log(this->logger, ERROR, "found rule LENGTH on bitpos %d", context->bit_pos); + allocator_free(output); + return PARSE_ERROR; + } + if ((int)context->byte_pos % 4) + { + this->logger->log(this->logger, ERROR, "found rule LENGTH on unaligned bytepos"); + allocator_free(output); + return PARSE_ERROR; + } + *output_pos = ntohl(*((u_int32_t*)context->byte_pos)); + context->byte_pos += 4; + break; + + } + case SPI_SIZE: + { + + } + default: + { + this->logger->log(this->logger, ERROR, "parser found unknown type"); + allocator_free(output); + return PARSE_ERROR; + } + } + } + + *data_struct = output; + return SUCCESS; + } + payload_info++; + } + + this->logger->log(this->logger, ERROR, "Payload not supported"); + return NOT_SUPPORTED; +} + +static status_t destroy(private_parser_t *this) +{ + this->logger->destroy(this->logger); + allocator_free(this); + + return SUCCESS; +} + +parser_t *parser_create(payload_info_t **payload_infos) +{ + private_parser_t *this = allocator_alloc_thing(private_parser_t); + + if (this == NULL) + { + return NULL; + } + + this->logger = logger_create("parser", ALL); + if (this->logger == NULL) + { + allocator_free(this); + return NULL; + } + this->public.create_context = (parser_context_t*(*)(parser_t*,chunk_t)) create_context; + this->public.parse_payload = (status_t(*)(parser_t*,parser_context_t*,payload_type_t,void**)) parse_payload; + this->public.destroy = (status_t(*)(parser_t*)) destroy; + + this->payload_infos = payload_infos; + + + return (parser_t*)this; +} diff --git a/Source/charon/parser.h b/Source/charon/parser.h index b25c94c..893917b 100644 --- a/Source/charon/parser.h +++ b/Source/charon/parser.h @@ -27,6 +27,14 @@ #include "encodings.h" +typedef struct parser_context_s parser_context_t; + +struct parser_context_s { + + status_t (*destroy) (parser_context_t *this); + +}; + /** * @brief A parser_t object which parses payloads of specific type @@ -36,22 +44,29 @@ typedef struct parser_s parser_t; struct parser_s { /** - * @brief Generates a specific payload from given data struct + * @brief parses a chunk and generates a usable data struct * * Remember: Header and substructures are also seen as payloads * - * @param generator generator object - * @return SUCCESSFUL if succeeded, - * NOT_SUPPORTED if payload_type is not supported - * OUT_OF_RES if out of ressources + * @param parser parser Object + * @param payload_type definition of payload including encoding_rule + * @param data chunk of data to parse + * @param[out] allocated structure with parsed data + * @return + * - SUCCESSFUL if succeeded, + * - NOT_SUPPORTED if payload_type is not supported + * - OUT_OF_RES if out of ressources + * - PARSE_ERROR if corrupted data found */ - status_t (*parse_payload) (parser_t *this, payload_type_t payload_type, chunk_t *data, void *data_struct); - + parser_context_t *(*create_context) (parser_t *this, chunk_t data); + status_t (*parse_payload) (parser_t *this, parser_context_t* context, payload_type_t payload_type, void **data_struct); + /** - * @brief Destroys a generator object + * @brief Destroys a parser object * - * @param generator generator object - * @return SUCCESSFUL if succeeded, FAILED otherwise + * @param parser parser object + * @return + * - SUCCESSFUL in any case */ status_t (*destroy) (parser_t *this); }; @@ -60,6 +75,6 @@ struct parser_s { * Constructor to create a parser * */ -parser_t *parser_create(payload_info_t ** payload_infos); +parser_t *parser_create(payload_info_t **payload_infos); #endif /*PARSER_H_*/ -- 2.7.4