aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Willi <martin@strongswan.org>2005-11-10 19:19:56 +0000
committerMartin Willi <martin@strongswan.org>2005-11-10 19:19:56 +0000
commit3d40ec7a68e6e318eb73dd80da206141877cb04e (patch)
treeb3bb446f96c65c781404cebbb811059dd54644d9
parent27e308739b5cde523a808bbbbfbefb41e83b4a70 (diff)
downloadstrongswan-3d40ec7a68e6e318eb73dd80da206141877cb04e.tar.bz2
strongswan-3d40ec7a68e6e318eb73dd80da206141877cb04e.tar.xz
- parser successfully parses an ike_header
- no doxygen yet
-rw-r--r--Source/charon/parser.c363
-rw-r--r--Source/charon/parser.h37
2 files changed, 388 insertions, 12 deletions
diff --git a/Source/charon/parser.c b/Source/charon/parser.c
index 0f4af57d9..0e01259af 100644
--- a/Source/charon/parser.c
+++ b/Source/charon/parser.c
@@ -21,10 +21,71 @@
*/
#include <stdlib.h>
+#include <arpa/inet.h>
#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 b25c94cf5..893917b8f 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_*/