Reverting eba28948a584b9d02474cf5d256b04b8d2adbe6a which was only necessary when...
[strongswan.git] / src / charon / encoding / parser.c
index d002629..9aa34b1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2009 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
  *
@@ -12,8 +12,6 @@
  * 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.
- *
- * $Id$
  */
 
 #include <stdlib.h>
@@ -52,7 +50,7 @@ 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 {
@@ -60,168 +58,27 @@ struct private_parser_t {
         * Public members, see parser_t.
         */
        parser_t public;
-       
-       /**
-        * Parse a 4-Bit unsigned integer from the current parsing position.
-        * 
-        * @param this                          parser_t object
-        * @param rule_number           number of current rule
-        * @param[out] output_pos       pointer where to write the parsed result
-        * @return                                      
-        *                                                      - SUCCESS or
-        *                                                      - PARSE_ERROR when not successful
-        */
-       status_t (*parse_uint4)  (private_parser_t *this, int rule_number, u_int8_t *output_pos);
-       
-       /**
-        * Parse a 8-Bit unsigned integer from the current parsing position.
-        * 
-        * @param this                          parser_t object
-        * @param rule_number           number of current rule
-        * @param[out] output_pos       pointer where to write the parsed result
-        * @return                                      
-        *                                                      - SUCCESS or
-        *                                                      - PARSE_ERROR when not successful
-        */
-       status_t (*parse_uint8)  (private_parser_t *this, int rule_number, u_int8_t *output_pos);
-       
-       /**
-        * Parse a 15-Bit unsigned integer from the current parsing position.
-        * 
-        * This is a special case used for ATTRIBUTE_TYPE.
-        * Big-/Little-endian conversion is done here.
-        * 
-        * @param this                          parser_t object
-        * @param rule_number           number of current rule
-        * @param[out] output_pos       pointer where to write the parsed result
-        * @return                                      
-        *                                                      - SUCCESS or
-        *                                                      - PARSE_ERROR when not successful
-        */
-       status_t (*parse_uint15) (private_parser_t *this, int rule_number, u_int16_t *output_pos);
-       
-       /**
-        * Parse a 16-Bit unsigned integer from the current parsing position.
-        * 
-        * Big-/Little-endian conversion is done here.
-        * 
-        * @param this                          parser_t object
-        * @param rule_number           number of current rule
-        * @param[out] output_pos       pointer where to write the parsed result
-        * @return                                      
-        *                                                      - SUCCESS or
-        *                                                      - PARSE_ERROR when not successful
-        */
-       status_t (*parse_uint16) (private_parser_t *this, int rule_number, u_int16_t *output_pos);
-       
-       /**
-        * Parse a 32-Bit unsigned integer from the current parsing position.
-        * 
-        * Big-/Little-endian conversion is done here.
-        * 
-        * @param this                          parser_t object
-        * @param rule_number           number of current rule
-        * @param[out] output_pos       pointer where to write the parsed result
-        * @return                                      
-        *                                                      - SUCCESS or
-        *                                                      - PARSE_ERROR when not successful
-        */
-       status_t (*parse_uint32) (private_parser_t *this, int rule_number, u_int32_t *output_pos);
-       
-       /**
-        * Parse a 64-Bit unsigned integer from the current parsing position.
-        * 
-        * @todo add support for big-endian machines.
-        * 
-        * @param this                          parser_t object
-        * @param rule_number           number of current rule
-        * @param[out] output_pos       pointer where to write the parsed result
-        * @return                                      
-        *                                                      - SUCCESS or
-        *                                                      - PARSE_ERROR when not successful
-        */
-       status_t (*parse_uint64) (private_parser_t *this, int rule_number, u_int64_t *output_pos);
-       
-       /**
-        * Parse a given amount of bytes and writes them to a specific location
-        * 
-        * @param this                          parser_t object
-        * @param rule_number           number of current rule
-        * @param[out] output_pos       pointer where to write the parsed result
-        * @param bytes                         number of bytes to parse
-        * @return                                      
-        *                                                      - SUCCESS or
-        *                                                      - PARSE_ERROR when not successful
-        */
-       status_t (*parse_bytes) (private_parser_t *this, int rule_number, u_int8_t *output_pos,size_t bytes);
-       
-       /**
-        * Parse a single Bit from the current parsing position
-        * 
-        * @param this                          parser_t object
-        * @param rule_number           number of current rule
-        * @param[out] output_pos       pointer where to write the parsed result
-        * @return                                      
-        *                                                      - SUCCESS or
-        *                                                      - PARSE_ERROR when not successful
-        */
-       status_t (*parse_bit)    (private_parser_t *this, int rule_number, bool *output_pos);
-       
-       /**
-        * Parse substructures in a list
-        * 
-        * This function calls the parser recursively to parse contained substructures
-        * in a linked_list_t. The list must already be created. Payload defines
-        * the type of the substructures. parsing is continued until the specified length
-        * is completely parsed.
-        * 
-        * @param this                          parser_t object
-        * @param rule_number           number of current rule
-        * @param[out] output_pos       pointer of a linked_list where substructures are added
-        * @param payload_type          type of the contained substructures to parse
-        * @param length                        number of bytes to parse in this list
-        * @return                                      
-        *                                                      - SUCCESS or
-        *                                                      - PARSE_ERROR when not successful
-        */
-       status_t (*parse_list)   (private_parser_t *this, int rule_number, linked_list_t **output_pos, payload_type_t payload_ype, size_t length);
-       
-       /**
-        * Parse data from current parsing position in a chunk.
-        * 
-        * This function clones length number of bytes to output_pos, without 
-        * modifiyng them. Space will be allocated and must be freed by caller.
-        * 
-        * @param this                          parser_t object
-        * @param rule_number           number of current rule
-        * @param[out] output_pos       pointer of a chunk which will point to the allocated data
-        * @param length                        number of bytes to clone
-        * @return                                      
-        *                                                      - SUCCESS or
-        *                                                      - PARSE_ERROR when not successful
-        */
-       status_t (*parse_chunk)  (private_parser_t *this, int rule_number, chunk_t *output_pos, size_t length);
 
        /**
         * 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.
         */
@@ -229,29 +86,52 @@ struct private_parser_t {
 };
 
 /**
- * Implementation of private_parser_t.parse_uint4.
+ * Forward declaration
+ */
+static status_t parse_payload(private_parser_t *this,
+                                                         payload_type_t payload_type, payload_t **payload);
+
+/**
+ * Log invalid length error
  */
-static status_t parse_uint4(private_parser_t *this, int rule_number, u_int8_t *output_pos)
+static bool short_input(private_parser_t *this, int number)
 {
-       if (this->byte_pos + sizeof(u_int8_t)  > this->input_roof)
+       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)
        {
-               DBG1(DBG_ENC, "  not enough input to parse rule %d %N",
-                        rule_number, encoding_type_names, this->rules[rule_number].type);
-               return PARSE_ERROR;
+               return short_input(this, rule_number);
        }
        switch (this->bit_pos)
        {
                case 0:
-                       /* caller interested in result ? */
-                       if (output_pos != NULL)
+                       if (output_pos)
                        {
                                *output_pos = *(this->byte_pos) >> 4;
                        }
                        this->bit_pos = 4;
                        break;
-               case 4: 
-                       /* caller interested in result ? */
-                       if (output_pos != NULL)
+               case 4:
+                       if (output_pos)
                        {
                                *output_pos = *(this->byte_pos) & 0x0F;
                        }
@@ -259,336 +139,265 @@ static status_t parse_uint4(private_parser_t *this, int rule_number, u_int8_t *o
                        this->byte_pos++;
                        break;
                default:
-                       DBG2(DBG_ENC, "  found rule %d %N on bitpos %d",
-                                rule_number, encoding_type_names,
-                                this->rules[rule_number].type, this->bit_pos);
-                       return PARSE_ERROR;
+                       return bad_bitpos(this, rule_number);
        }
-       
-       if (output_pos != NULL)
+       if (output_pos)
        {
                DBG3(DBG_ENC, "   => %d", *output_pos);
        }
-       
-       return SUCCESS;
+       return TRUE;
 }
 
 /**
- * Implementation of private_parser_t.parse_uint8.
+ * Parse a 8-Bit unsigned integer from the current parsing position.
  */
-static status_t parse_uint8(private_parser_t *this, int rule_number, u_int8_t *output_pos)
+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)
+       if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
        {
-               DBG1(DBG_ENC, "  not enough input to parse rule %d %N",
-                        rule_number, encoding_type_names, this->rules[rule_number].type);
-               return PARSE_ERROR;
+               return short_input(this, rule_number);
        }
        if (this->bit_pos)
        {
-               DBG1(DBG_ENC, "  found rule %d %N on bitpos %d",
-                        rule_number, encoding_type_names,
-                        this->rules[rule_number].type, this->bit_pos);
-               return PARSE_ERROR;
+               return bad_bitpos(this, rule_number);
        }
-
-       /* caller interested in result ? */
-       if (output_pos != NULL)
+       if (output_pos)
        {
                *output_pos = *(this->byte_pos);
                DBG3(DBG_ENC, "   => %d", *output_pos);
        }
        this->byte_pos++;
-       
-       return SUCCESS;
+       return TRUE;
 }
 
 /**
- * Implementation of private_parser_t.parse_uint15.
+ * Parse a 15-Bit unsigned integer from the current parsing position.
  */
-static status_t parse_uint15(private_parser_t *this, int rule_number, u_int16_t *output_pos)
+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)
        {
-               DBG1(DBG_ENC, "  not enough input to parse rule %d %N",
-                        rule_number, encoding_type_names, this->rules[rule_number].type);
-               return PARSE_ERROR;
+               return short_input(this, rule_number);
        }
        if (this->bit_pos != 1)
        {
-               DBG2(DBG_ENC, "  found rule %d %N on bitpos %d", rule_number,
-                        encoding_type_names, this->rules[rule_number].type, this->bit_pos);
-               return PARSE_ERROR;
+               return bad_bitpos(this, rule_number);
        }
-       /* caller interested in result ? */
-       if (output_pos != NULL)
+       if (output_pos)
        {
-               *output_pos = ntohs(*((u_int16_t*)this->byte_pos)) & ~0x8000;
+               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 += 2;
+       this->byte_pos += sizeof(u_int16_t);
        this->bit_pos = 0;
-       
-       return SUCCESS;
+       return TRUE;
 }
 
 /**
- * Implementation of private_parser_t.parse_uint16.
+ * Parse a 16-Bit unsigned integer from the current parsing position.
  */
-static status_t parse_uint16(private_parser_t *this, int rule_number, u_int16_t *output_pos)
+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)
        {
-               DBG1(DBG_ENC, "  not enough input to parse rule %d %N",
-                        rule_number, encoding_type_names, this->rules[rule_number].type);
-               return PARSE_ERROR;
+               return short_input(this, rule_number);
        }
        if (this->bit_pos)
        {
-               DBG1(DBG_ENC, "  found rule %d %N on bitpos %d", rule_number,
-                        encoding_type_names, this->rules[rule_number].type, this->bit_pos);
-               return PARSE_ERROR;
+               return bad_bitpos(this, rule_number);
        }
-       /* caller interested in result ? */
-       if (output_pos != NULL)
+       if (output_pos)
        {
-               *output_pos = ntohs(*((u_int16_t*)this->byte_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 += 2;
-       
-       return SUCCESS;
+       this->byte_pos += sizeof(u_int16_t);
+       return TRUE;
 }
 /**
- * Implementation of private_parser_t.parse_uint32.
+ * Parse a 32-Bit unsigned integer from the current parsing position.
  */
-static status_t parse_uint32(private_parser_t *this, int rule_number, u_int32_t *output_pos)
+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)
        {
-               DBG1(DBG_ENC, "  not enough input to parse rule %d %N",
-                        rule_number, encoding_type_names, this->rules[rule_number].type);
-               return PARSE_ERROR;
+               return short_input(this, rule_number);
        }
        if (this->bit_pos)
        {
-               DBG1(DBG_ENC, "  found rule %d %N on bitpos %d", rule_number,
-                        encoding_type_names, this->rules[rule_number].type, this->bit_pos);
-               return PARSE_ERROR;
+               return bad_bitpos(this, rule_number);
        }
-       /* caller interested in result ? */
-       if (output_pos != NULL)
+       if (output_pos)
        {
-               *output_pos = ntohl(*((u_int32_t*)this->byte_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 += 4;
-       
-       return SUCCESS;
-}
-
-/**
- * Implementation of private_parser_t.parse_uint64.
- */
-static status_t parse_uint64(private_parser_t *this, int rule_number, u_int64_t *output_pos)
-{
-       if (this->byte_pos + sizeof(u_int64_t) > this->input_roof)
-       {
-               DBG1(DBG_ENC, "  not enough input to parse rule %d %N",
-                        rule_number, encoding_type_names, this->rules[rule_number].type);
-               return PARSE_ERROR;
-       }
-       if (this->bit_pos)
-       {
-               DBG1(DBG_ENC, "  found rule %d %N on bitpos %d", rule_number,
-                        encoding_type_names, this->rules[rule_number].type, this->bit_pos);
-               return PARSE_ERROR;
-       }
-       /* caller interested in result ? */
-       if (output_pos != NULL)
-       {
-               /* assuming little endian host order */
-               *(output_pos + 1) = ntohl(*((u_int32_t*)this->byte_pos));
-               *output_pos = ntohl(*(((u_int32_t*)this->byte_pos) + 1));
-               
-               DBG3(DBG_ENC, "   => %b", (void*)output_pos, sizeof(u_int64_t));
-       }
-       this->byte_pos += 8;
-
-       return SUCCESS;
+       this->byte_pos += sizeof(u_int32_t);
+       return TRUE;
 }
 
 /**
- * Implementation of private_parser_t.parse_bytes.
+ * Parse a given amount of bytes and writes them to a specific location
  */
-static status_t parse_bytes (private_parser_t *this, int rule_number, u_int8_t *output_pos,size_t bytes)
+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)
        {
-               DBG1(DBG_ENC, "  not enough input to parse rule %d %N",
-                        rule_number, encoding_type_names, this->rules[rule_number].type);
-               return PARSE_ERROR;
+               return short_input(this, rule_number);
        }
        if (this->bit_pos)
        {
-               DBG1(DBG_ENC, "  found rule %d %N on bitpos %d", rule_number,
-                        encoding_type_names, this->rules[rule_number].type, this->bit_pos);
-               return PARSE_ERROR;
+               return bad_bitpos(this, rule_number);
        }
-
-       /* caller interested in result ? */
-       if (output_pos != NULL)
+       if (output_pos)
        {
-               memcpy(output_pos,this->byte_pos,bytes);
-               
-               DBG3(DBG_ENC, "   => %b", (void*)output_pos, bytes);
+               memcpy(output_pos, this->byte_pos, bytes);
+               DBG3(DBG_ENC, "   => %b", output_pos, bytes);
        }
        this->byte_pos += bytes;
-       
-       return SUCCESS;
+       return TRUE;
 }
 
 /**
- * Implementation of private_parser_t.parse_bit.
+ * Parse a single Bit from the current parsing position
  */
-static status_t parse_bit(private_parser_t *this, int rule_number, bool *output_pos)
+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)
        {
-               DBG1(DBG_ENC, "  not enough input to parse rule %d %N",
-                        rule_number, encoding_type_names, this->rules[rule_number].type);
-               return PARSE_ERROR;
+               return short_input(this, rule_number);
        }
-       /* caller interested in result ? */
-       if (output_pos != NULL)
-       {       
+       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 */
+               {       /* 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) 
+       if (this->bit_pos == 0)
        {
-               this->byte_pos++;       
+               this->byte_pos++;
        }
-       
-       return SUCCESS;
+       return TRUE;
 }
 
 /**
- * Implementation of private_parser_t.parse_list.
+ * Parse substructures in a list.
  */
-static status_t parse_list(private_parser_t *this, int rule_number, linked_list_t **output_pos, payload_type_t payload_type, size_t length)
+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;
-       
+       linked_list_t *list = *output_pos;
+
        if (length < 0)
        {
-               DBG1(DBG_ENC, "  invalid length for rule %d %N",
-                        rule_number, encoding_type_names, this->rules[rule_number].type);
-               return PARSE_ERROR;     
+               return short_input(this, rule_number);
        }
-       
        if (this->bit_pos)
        {
-               DBG1(DBG_ENC, "  found rule %d %N on bitpos %d", rule_number,
-                        encoding_type_names, this->rules[rule_number].type, this->bit_pos);
-               return PARSE_ERROR;
+               return bad_bitpos(this, rule_number);
        }
-       
        while (length > 0)
        {
                u_int8_t *pos_before = this->byte_pos;
                payload_t *payload;
-               status_t status;
+
                DBG2(DBG_ENC, "  %d bytes left, parsing recursively %N",
                         length, payload_type_names, payload_type);
-               status = this->public.parse_payload((parser_t*)this, payload_type, &payload);
-               if (status != SUCCESS)
+
+               if (parse_payload(this, payload_type, &payload) != SUCCESS)
                {
                        DBG1(DBG_ENC, "  parsing of a %N substructure failed",
                                 payload_type_names, payload_type);
-                       return status;
+                       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 SUCCESS; 
+       return TRUE;
 }
 
 /**
- * Implementation of private_parser_t.parse_chunk.
+ * Parse data from current parsing position in a chunk.
  */
-static status_t parse_chunk(private_parser_t *this, int rule_number, chunk_t *output_pos, size_t length)
+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)
        {
-               DBG1(DBG_ENC, "  not enough input (%d bytes) to parse rule %d %N",
-                        length, rule_number, encoding_type_names, this->rules[rule_number].type);
-               return PARSE_ERROR;
+               return short_input(this, rule_number);
        }
        if (this->bit_pos)
        {
-               DBG1(DBG_ENC, "  found rule %d %N on bitpos %d", rule_number,
-                        encoding_type_names, this->rules[rule_number].type, this->bit_pos);
-               return PARSE_ERROR;
+               return bad_bitpos(this, rule_number);
        }
-       if (output_pos != NULL)
+       if (output_pos)
        {
-               output_pos->len = length;
-               output_pos->ptr = malloc(length);
+               *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;
-       DBG3(DBG_ENC, "   => %b", (void*)output_pos->ptr, length);
-       
-       return SUCCESS;
+       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)
+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, payload_length = 0, spi_size = 0, attribute_length = 0;
+       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);
-       
+                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);
+       pld->get_encoding_rules(pld, &this->rules, &rule_count);
        for (rule_number = 0; rule_number < rule_count; rule_number++)
        {
                rule = &(this->rules[rule_number]);
@@ -598,7 +407,7 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                {
                        case U_INT_4:
                        {
-                               if (this->parse_uint4(this, rule_number, output + rule->offset) != SUCCESS) 
+                               if (!parse_uint4(this, rule_number, output + rule->offset))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -607,7 +416,7 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        }
                        case U_INT_8:
                        {
-                               if (this->parse_uint8(this, rule_number, output + rule->offset) != SUCCESS) 
+                               if (!parse_uint8(this, rule_number, output + rule->offset))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -616,7 +425,7 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        }
                        case U_INT_16:
                        {
-                               if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS) 
+                               if (!parse_uint16(this, rule_number, output + rule->offset))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -625,16 +434,7 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        }
                        case U_INT_32:
                        {
-                               if (this->parse_uint32(this, rule_number, output + rule->offset) != SUCCESS) 
-                               {
-                                       pld->destroy(pld);
-                                       return PARSE_ERROR;
-                               }
-                               break;
-                       }
-                       case U_INT_64:
-                       {
-                               if (this->parse_uint64(this, rule_number, output + rule->offset) != SUCCESS) 
+                               if (!parse_uint32(this, rule_number, output + rule->offset))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -643,7 +443,7 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        }
                        case IKE_SPI:
                        {
-                               if (this->parse_bytes(this, rule_number, output + rule->offset,8) != SUCCESS) 
+                               if (!parse_bytes(this, rule_number, output + rule->offset, 8))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -652,7 +452,7 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        }
                        case RESERVED_BIT:
                        {
-                               if (this->parse_bit(this, rule_number, NULL) != SUCCESS) 
+                               if (!parse_bit(this, rule_number, NULL))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -661,7 +461,7 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        }
                        case RESERVED_BYTE:
                        {
-                               if (this->parse_uint8(this, rule_number, NULL) != SUCCESS) 
+                               if (!parse_uint8(this, rule_number, NULL))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -670,7 +470,7 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        }
                        case FLAG:
                        {
-                               if (this->parse_bit(this, rule_number, output + rule->offset) != SUCCESS) 
+                               if (!parse_bit(this, rule_number, output + rule->offset))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -679,11 +479,12 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        }
                        case PAYLOAD_LENGTH:
                        {
-                               if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS) 
+                               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)
                                {
@@ -694,7 +495,7 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        }
                        case HEADER_LENGTH:
                        {
-                               if (this->parse_uint32(this, rule_number, output + rule->offset) != SUCCESS) 
+                               if (!parse_uint32(this, rule_number, output + rule->offset))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -703,7 +504,7 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        }
                        case SPI_SIZE:
                        {
-                               if (this->parse_uint8(this, rule_number, output + rule->offset) != SUCCESS) 
+                               if (!parse_uint8(this, rule_number, output + rule->offset))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -713,7 +514,8 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        }
                        case SPI:
                        {
-                               if (this->parse_chunk(this, rule_number, output + rule->offset, spi_size) != SUCCESS) 
+                               if (!parse_chunk(this, rule_number, output + rule->offset,
+                                                                spi_size))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -723,8 +525,9 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        case PROPOSALS:
                        {
                                if (payload_length < SA_PAYLOAD_HEADER_LENGTH ||
-                                       this->parse_list(this, rule_number, output + rule->offset, PROPOSAL_SUBSTRUCTURE,
-                                               payload_length - SA_PAYLOAD_HEADER_LENGTH) != SUCCESS)
+                                       !parse_list(this, rule_number, output + rule->offset,
+                                                               PROPOSAL_SUBSTRUCTURE,
+                                                               payload_length - SA_PAYLOAD_HEADER_LENGTH))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -733,9 +536,11 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        }
                        case TRANSFORMS:
                        {
-                               if (payload_length < spi_size + PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH ||
-                                       this->parse_list(this, rule_number, output + rule->offset, TRANSFORM_SUBSTRUCTURE,
-                                               payload_length - spi_size - PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH) != SUCCESS)
+                               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;
@@ -745,8 +550,9 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        case TRANSFORM_ATTRIBUTES:
                        {
                                if (payload_length < TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH ||
-                                       this->parse_list(this, rule_number, output + rule->offset, TRANSFORM_ATTRIBUTE,
-                                               payload_length - TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH) != SUCCESS)
+                                       !parse_list(this, rule_number, output + rule->offset,
+                                               TRANSFORM_ATTRIBUTE,
+                                               payload_length - TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -756,8 +562,9 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        case CONFIGURATION_ATTRIBUTES:
                        {
                                if (payload_length < CP_PAYLOAD_HEADER_LENGTH ||
-                                       this->parse_list(this, rule_number, output + rule->offset, CONFIGURATION_ATTRIBUTE,
-                                               payload_length - CP_PAYLOAD_HEADER_LENGTH) != SUCCESS)
+                                       !parse_list(this, rule_number, output + rule->offset,
+                                                               CONFIGURATION_ATTRIBUTE,
+                                                               payload_length - CP_PAYLOAD_HEADER_LENGTH))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -766,7 +573,7 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        }
                        case ATTRIBUTE_FORMAT:
                        {
-                               if (this->parse_bit(this, rule_number, output + rule->offset) != SUCCESS) 
+                               if (!parse_bit(this, rule_number, output + rule->offset))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -776,17 +583,16 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        }
                        case ATTRIBUTE_TYPE:
                        {
-                               if (this->parse_uint15(this, rule_number, output + rule->offset) != SUCCESS) 
+                               if (!parse_uint15(this, rule_number, output + rule->offset))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
                                }
-                               attribute_format = *(bool*)(output + rule->offset);
                                break;
                        }
                        case CONFIGURATION_ATTRIBUTE_LENGTH:
                        {
-                               if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS) 
+                               if (!parse_uint16(this, rule_number, output + rule->offset))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -795,8 +601,8 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                                break;
                        }
                        case ATTRIBUTE_LENGTH_OR_VALUE:
-                       {       
-                               if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS) 
+                       {
+                               if (!parse_uint16(this, rule_number, output + rule->offset))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -806,43 +612,42 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        }
                        case ATTRIBUTE_VALUE:
                        {
-                               if (attribute_format == FALSE)
+                               if (attribute_format == FALSE &&
+                                       !parse_chunk(this, rule_number, output + rule->offset,
+                                                                attribute_length))
                                {
-                                       if (this->parse_chunk(this, rule_number, output + rule->offset, attribute_length) != SUCCESS) 
-                                       {
-                                               pld->destroy(pld);
-                                               return PARSE_ERROR;
-                                       }
+                                       pld->destroy(pld);
+                                       return PARSE_ERROR;
                                }
                                break;
                        }
                        case NONCE_DATA:
                        {
                                if (payload_length < NONCE_PAYLOAD_HEADER_LENGTH ||
-                                       this->parse_chunk(this, rule_number, output + rule->offset, 
-                                               payload_length - NONCE_PAYLOAD_HEADER_LENGTH) != SUCCESS)
+                                       !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 ||
-                                       this->parse_chunk(this, rule_number, output + rule->offset,
-                                               payload_length - ID_PAYLOAD_HEADER_LENGTH) != SUCCESS)
+                                       !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 ||
-                                       this->parse_chunk(this, rule_number, output + rule->offset,
-                                               payload_length - AUTH_PAYLOAD_HEADER_LENGTH) != SUCCESS) 
+                                       !parse_chunk(this, rule_number, output + rule->offset,
+                                                                payload_length - AUTH_PAYLOAD_HEADER_LENGTH))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -852,8 +657,8 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        case CERT_DATA:
                        {
                                if (payload_length < CERT_PAYLOAD_HEADER_LENGTH ||
-                                       this->parse_chunk(this, rule_number, output + rule->offset, 
-                                               payload_length - CERT_PAYLOAD_HEADER_LENGTH) != SUCCESS) 
+                                       !parse_chunk(this, rule_number, output + rule->offset,
+                                                                payload_length - CERT_PAYLOAD_HEADER_LENGTH))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -863,8 +668,8 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        case CERTREQ_DATA:
                        {
                                if (payload_length < CERTREQ_PAYLOAD_HEADER_LENGTH ||
-                                       this->parse_chunk(this, rule_number, output + rule->offset, 
-                                               payload_length - CERTREQ_PAYLOAD_HEADER_LENGTH) != SUCCESS) 
+                                       !parse_chunk(this, rule_number, output + rule->offset,
+                                                                payload_length - CERTREQ_PAYLOAD_HEADER_LENGTH))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -874,8 +679,8 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        case EAP_DATA:
                        {
                                if (payload_length < EAP_PAYLOAD_HEADER_LENGTH ||
-                                       this->parse_chunk(this, rule_number, output + rule->offset, 
-                                               payload_length - EAP_PAYLOAD_HEADER_LENGTH) != SUCCESS) 
+                                       !parse_chunk(this, rule_number, output + rule->offset,
+                                                                payload_length - EAP_PAYLOAD_HEADER_LENGTH))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -885,109 +690,112 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                        case SPIS:
                        {
                                if (payload_length < DELETE_PAYLOAD_HEADER_LENGTH ||
-                                       this->parse_chunk(this, rule_number, output + rule->offset,
-                                               payload_length - DELETE_PAYLOAD_HEADER_LENGTH) != SUCCESS) 
+                                       !parse_chunk(this, rule_number, output + rule->offset,
+                                                                payload_length - DELETE_PAYLOAD_HEADER_LENGTH))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
-                               }               
-                               break;                  
+                               }
+                               break;
                        }
                        case VID_DATA:
                        {
                                if (payload_length < VENDOR_ID_PAYLOAD_HEADER_LENGTH ||
-                                       this->parse_chunk(this, rule_number, output + rule->offset,
-                                               payload_length - VENDOR_ID_PAYLOAD_HEADER_LENGTH) != SUCCESS) 
+                                       !parse_chunk(this, rule_number, output + rule->offset,
+                                                       payload_length - VENDOR_ID_PAYLOAD_HEADER_LENGTH))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
-                               }               
-                               break;                  
+                               }
+                               break;
                        }
                        case CONFIGURATION_ATTRIBUTE_VALUE:
                        {
-                               size_t data_length = attribute_length;
-                               if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) 
+                               if (!parse_chunk(this, rule_number, output + rule->offset,
+                                                                attribute_length))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
-                               }               
-                               break;                  
+                               }
+                               break;
                        }
                        case KEY_EXCHANGE_DATA:
                        {
                                if (payload_length < KE_PAYLOAD_HEADER_LENGTH ||
-                                       this->parse_chunk(this, rule_number, output + rule->offset,
-                                               payload_length - KE_PAYLOAD_HEADER_LENGTH) != SUCCESS) 
+                                       !parse_chunk(this, rule_number, output + rule->offset,
+                                                                payload_length - KE_PAYLOAD_HEADER_LENGTH))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
-                               }               
-                               break;                  
+                               }
+                               break;
                        }
                        case NOTIFICATION_DATA:
                        {
                                if (payload_length < NOTIFY_PAYLOAD_HEADER_LENGTH + spi_size ||
-                                       this->parse_chunk(this, rule_number, output + rule->offset, 
-                                               payload_length - NOTIFY_PAYLOAD_HEADER_LENGTH - spi_size) != SUCCESS) 
+                                       !parse_chunk(this, rule_number, output + rule->offset,
+                                               payload_length - NOTIFY_PAYLOAD_HEADER_LENGTH - spi_size))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
-                               }               
-                               break;                  
+                               }
+                               break;
                        }
                        case ENCRYPTED_DATA:
-                       {                               
+                       {
                                if (payload_length < ENCRYPTION_PAYLOAD_HEADER_LENGTH ||
-                                       this->parse_chunk(this, rule_number, output + rule->offset,
-                                               payload_length - ENCRYPTION_PAYLOAD_HEADER_LENGTH) != SUCCESS) 
+                                       !parse_chunk(this, rule_number, output + rule->offset,
+                                                       payload_length - ENCRYPTION_PAYLOAD_HEADER_LENGTH))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
-                               }               
-                               break;  
+                               }
+                               break;
                        }
                        case TS_TYPE:
                        {
-                               if (this->parse_uint8(this, rule_number, output + rule->offset) != SUCCESS) 
+                               if (!parse_uint8(this, rule_number, output + rule->offset))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
                                }
                                ts_type = *(u_int8_t*)(output + rule->offset);
-                               break;                                                  
+                               break;
                        }
                        case ADDRESS:
                        {
-                               size_t address_length = (ts_type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
-                               if (this->parse_chunk(this, rule_number, output + rule->offset,address_length) != SUCCESS) 
+                               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;                                                  
+                               break;
                        }
                        case TRAFFIC_SELECTORS:
                        {
                                if (payload_length < TS_PAYLOAD_HEADER_LENGTH ||
-                                       this->parse_list(this, rule_number, output + rule->offset, TRAFFIC_SELECTOR_SUBSTRUCTURE,
-                                               payload_length - TS_PAYLOAD_HEADER_LENGTH) != SUCCESS)
+                                       !parse_list(this, rule_number, output + rule->offset,
+                                                               TRAFFIC_SELECTOR_SUBSTRUCTURE,
+                                                               payload_length - TS_PAYLOAD_HEADER_LENGTH))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
                                }
-                               break;                                                  
+                               break;
                        }
                        case UNKNOWN_DATA:
                        {
                                if (payload_length < UNKNOWN_PAYLOAD_HEADER_LENGTH ||
-                                       this->parse_chunk(this, rule_number, output + rule->offset,
-                                               payload_length - UNKNOWN_PAYLOAD_HEADER_LENGTH) != SUCCESS)
+                                       !parse_chunk(this, rule_number, output + rule->offset,
+                                                               payload_length - UNKNOWN_PAYLOAD_HEADER_LENGTH))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
                                }
-                               break;                                                  
+                               break;
                        }
                        default:
                        {
@@ -1000,7 +808,7 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
                /* process next rulue */
                rule++;
        }
-       
+
        *payload = pld;
        DBG2(DBG_ENC, "parsing %N payload finished",
                 payload_type_names, payload_type);
@@ -1012,8 +820,7 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ
  */
 static int get_remaining_byte_count (private_parser_t *this)
 {
-       int count = (this->input_roof - this->byte_pos);
-       return count;
+       return this->input_roof - this->byte_pos;
 }
 
 /**
@@ -1030,7 +837,7 @@ static void reset_context (private_parser_t *this)
  */
 static void destroy(private_parser_t *this)
 {
-       free(this);     
+       free(this);
 }
 
 /*
@@ -1039,27 +846,17 @@ static void destroy(private_parser_t *this)
 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.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->parse_uint4 = parse_uint4;
-       this->parse_uint8 = parse_uint8;
-       this->parse_uint15 = parse_uint15;
-       this->parse_uint16 = parse_uint16;
-       this->parse_uint32 = parse_uint32;
-       this->parse_uint64 = parse_uint64;
-       this->parse_bytes = parse_bytes;
-       this->parse_bit = parse_bit;
-       this->parse_list = parse_list;
-       this->parse_chunk = parse_chunk;
-       
+
        this->input = data.ptr;
        this->byte_pos = data.ptr;
        this->bit_pos = 0;
        this->input_roof = data.ptr + data.len;
-       
-       return (parser_t*)this;
+
+       return &this->public;
 }
+