]> git.ipfire.org Git - thirdparty/strongswan.git/blobdiff - src/libcharon/encoding/parser.c
Spelling fixes
[thirdparty/strongswan.git] / src / libcharon / encoding / parser.c
index 09b52168f9a0f630bd6a80f453aed77873a20f93..de66ad467748e25aca83759510f32e6bc5ffb8e9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2005-2009 Martin Willi
  * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
+ * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
  */
 
 #include <stdlib.h>
-#include <arpa/inet.h>
 #include <string.h>
 
 #include "parser.h"
 
 #include <library.h>
 #include <daemon.h>
-#include <utils/linked_list.h>
+#include <collections/linked_list.h>
 #include <encoding/payloads/encodings.h>
 #include <encoding/payloads/payload.h>
 #include <encoding/payloads/sa_payload.h>
@@ -33,7 +32,7 @@
 #include <encoding/payloads/nonce_payload.h>
 #include <encoding/payloads/id_payload.h>
 #include <encoding/payloads/notify_payload.h>
-#include <encoding/payloads/encryption_payload.h>
+#include <encoding/payloads/encrypted_payload.h>
 #include <encoding/payloads/auth_payload.h>
 #include <encoding/payloads/cert_payload.h>
 #include <encoding/payloads/certreq_payload.h>
@@ -59,25 +58,30 @@ struct private_parser_t {
         */
        parser_t public;
 
+       /**
+        * major IKE version
+        */
+       uint8_t major_version;
+
        /**
         * Current bit for reading in input data.
         */
-       u_int8_t bit_pos;
+       uint8_t bit_pos;
 
        /**
         * Current byte for reading in input data.
         */
-       u_int8_t *byte_pos;
+       uint8_t *byte_pos;
 
        /**
         * Input data to parse.
         */
-       u_int8_t *input;
+       uint8_t *input;
 
        /**
         * Roof of input, used for length-checking.
         */
-       u_int8_t *input_roof;
+       uint8_t *input_roof;
 
        /**
         * Set of encoding rules for this parsing session.
@@ -109,9 +113,9 @@ static bool bad_bitpos(private_parser_t *this, int number)
  * 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)
+                                               uint8_t *output_pos)
 {
-       if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
+       if (this->byte_pos + sizeof(uint8_t) > this->input_roof)
        {
                return short_input(this, rule_number);
        }
@@ -137,7 +141,7 @@ static bool parse_uint4(private_parser_t *this, int rule_number,
        }
        if (output_pos)
        {
-               DBG3(DBG_ENC, "   => %d", *output_pos);
+               DBG3(DBG_ENC, "   => %hhu", *output_pos);
        }
        return TRUE;
 }
@@ -146,9 +150,9 @@ static bool parse_uint4(private_parser_t *this, int rule_number,
  * Parse a 8-Bit unsigned integer from the current parsing position.
  */
 static bool parse_uint8(private_parser_t *this, int rule_number,
-                                               u_int8_t *output_pos)
+                                               uint8_t *output_pos)
 {
-       if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
+       if (this->byte_pos + sizeof(uint8_t) > this->input_roof)
        {
                return short_input(this, rule_number);
        }
@@ -159,7 +163,7 @@ static bool parse_uint8(private_parser_t *this, int rule_number,
        if (output_pos)
        {
                *output_pos = *(this->byte_pos);
-               DBG3(DBG_ENC, "   => %d", *output_pos);
+               DBG3(DBG_ENC, "   => %hhu", *output_pos);
        }
        this->byte_pos++;
        return TRUE;
@@ -169,9 +173,9 @@ static bool parse_uint8(private_parser_t *this, int rule_number,
  * Parse a 15-Bit unsigned integer from the current parsing position.
  */
 static bool parse_uint15(private_parser_t *this, int rule_number,
-                                                u_int16_t *output_pos)
+                                                uint16_t *output_pos)
 {
-       if (this->byte_pos + sizeof(u_int16_t) > this->input_roof)
+       if (this->byte_pos + sizeof(uint16_t) > this->input_roof)
        {
                return short_input(this, rule_number);
        }
@@ -181,11 +185,11 @@ static bool parse_uint15(private_parser_t *this, int rule_number,
        }
        if (output_pos)
        {
-               memcpy(output_pos, this->byte_pos, sizeof(u_int16_t));
+               memcpy(output_pos, this->byte_pos, sizeof(uint16_t));
                *output_pos = ntohs(*output_pos) & ~0x8000;
-               DBG3(DBG_ENC, "   => %d", *output_pos);
+               DBG3(DBG_ENC, "   => %hu", *output_pos);
        }
-       this->byte_pos += sizeof(u_int16_t);
+       this->byte_pos += sizeof(uint16_t);
        this->bit_pos = 0;
        return TRUE;
 }
@@ -194,9 +198,9 @@ static bool parse_uint15(private_parser_t *this, int rule_number,
  * Parse a 16-Bit unsigned integer from the current parsing position.
  */
 static bool parse_uint16(private_parser_t *this, int rule_number,
-                                                u_int16_t *output_pos)
+                                                uint16_t *output_pos)
 {
-       if (this->byte_pos + sizeof(u_int16_t) > this->input_roof)
+       if (this->byte_pos + sizeof(uint16_t) > this->input_roof)
        {
                return short_input(this, rule_number);
        }
@@ -206,20 +210,20 @@ static bool parse_uint16(private_parser_t *this, int rule_number,
        }
        if (output_pos)
        {
-               memcpy(output_pos, this->byte_pos, sizeof(u_int16_t));
+               memcpy(output_pos, this->byte_pos, sizeof(uint16_t));
                *output_pos = ntohs(*output_pos);
-               DBG3(DBG_ENC, "   => %d", *output_pos);
+               DBG3(DBG_ENC, "   => %hu", *output_pos);
        }
-       this->byte_pos += sizeof(u_int16_t);
+       this->byte_pos += sizeof(uint16_t);
        return TRUE;
 }
 /**
  * Parse a 32-Bit unsigned integer from the current parsing position.
  */
 static bool parse_uint32(private_parser_t *this, int rule_number,
-                                                u_int32_t *output_pos)
+                                                uint32_t *output_pos)
 {
-       if (this->byte_pos + sizeof(u_int32_t) > this->input_roof)
+       if (this->byte_pos + sizeof(uint32_t) > this->input_roof)
        {
                return short_input(this, rule_number);
        }
@@ -229,11 +233,11 @@ static bool parse_uint32(private_parser_t *this, int rule_number,
        }
        if (output_pos)
        {
-               memcpy(output_pos, this->byte_pos, sizeof(u_int32_t));
+               memcpy(output_pos, this->byte_pos, sizeof(uint32_t));
                *output_pos = ntohl(*output_pos);
-               DBG3(DBG_ENC, "   => %d", *output_pos);
+               DBG3(DBG_ENC, "   => %u", *output_pos);
        }
-       this->byte_pos += sizeof(u_int32_t);
+       this->byte_pos += sizeof(uint32_t);
        return TRUE;
 }
 
@@ -241,7 +245,7 @@ static bool parse_uint32(private_parser_t *this, int rule_number,
  * Parse a given amount of bytes and writes them to a specific location
  */
 static bool parse_bytes(private_parser_t *this, int rule_number,
-                                               u_int8_t *output_pos, int bytes)
+                                               uint8_t *output_pos, int bytes)
 {
        if (this->byte_pos + bytes > this->input_roof)
        {
@@ -254,7 +258,7 @@ static bool parse_bytes(private_parser_t *this, int rule_number,
        if (output_pos)
        {
                memcpy(output_pos, this->byte_pos, bytes);
-               DBG3(DBG_ENC, "   => %b", output_pos, bytes);
+               DBG3(DBG_ENC, "   %b", output_pos, bytes);
        }
        this->byte_pos += bytes;
        return TRUE;
@@ -266,13 +270,13 @@ static bool parse_bytes(private_parser_t *this, int rule_number,
 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)
+       if (this->byte_pos + sizeof(uint8_t) > this->input_roof)
        {
                return short_input(this, rule_number);
        }
        if (output_pos)
        {
-               u_int8_t mask;
+               uint8_t mask;
                mask = 0x01 << (7 - this->bit_pos);
                *output_pos = *this->byte_pos & mask;
 
@@ -308,7 +312,7 @@ static bool parse_list(private_parser_t *this, int rule_number,
        }
        while (length > 0)
        {
-               u_int8_t *pos_before = this->byte_pos;
+               uint8_t *pos_before = this->byte_pos;
                payload_t *payload;
 
                DBG2(DBG_ENC, "  %d bytes left, parsing recursively %N",
@@ -352,7 +356,7 @@ static bool parse_chunk(private_parser_t *this, int rule_number,
        {
                *output_pos = chunk_alloc(length);
                memcpy(output_pos->ptr, this->byte_pos, length);
-               DBG3(DBG_ENC, "   => %b", output_pos->ptr, length);
+               DBG3(DBG_ENC, "   %b", output_pos->ptr, length);
        }
        this->byte_pos += length;
        return TRUE;
@@ -363,33 +367,41 @@ METHOD(parser_t, parse_payload, status_t,
 {
        payload_t *pld;
        void *output;
-       size_t rule_count;
-       int payload_length = 0, spi_size = 0, attribute_length = 0;
-       u_int16_t ts_type = 0;
+       int payload_length = 0, spi_size = 0, attribute_length = 0, header_length;
+       uint16_t ts_type = 0;
        bool attribute_format = FALSE;
-       int rule_number;
+       int rule_number, rule_count;
        encoding_rule_t *rule;
 
        /* create instance of the payload to parse */
-       pld = payload_create(payload_type);
+       if (payload_is_known(payload_type, this->major_version))
+       {
+               pld = payload_create(payload_type);
+       }
+       else
+       {
+               pld = (payload_t*)unknown_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, (u_int)(this->input_roof - this->byte_pos));
 
        /* 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);
+       /* parse the payload with its own rules */
+       rule_count = pld->get_encoding_rules(pld, &this->rules);
        for (rule_number = 0; rule_number < rule_count; rule_number++)
        {
+               /* update header length for each rule, as it is dynamic (SPIs) */
+               header_length = pld->get_header_length(pld);
+
                rule = &(this->rules[rule_number]);
                DBG2(DBG_ENC, "  parsing rule %d %N",
                         rule_number, encoding_type_names, rule->type);
-               switch (rule->type)
+               switch ((int)rule->type)
                {
                        case U_INT_4:
                        {
@@ -456,8 +468,9 @@ METHOD(parser_t, parse_payload, status_t,
                                        return PARSE_ERROR;
                                }
                                /* parsed u_int16 should be aligned */
-                               payload_length = *(u_int16_t*)(output + rule->offset);
-                               if (payload_length < UNKNOWN_PAYLOAD_HEADER_LENGTH)
+                               payload_length = *(uint16_t*)(output + rule->offset);
+                               /* all payloads must have at least 4 bytes header */
+                               if (payload_length < 4)
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -471,7 +484,7 @@ METHOD(parser_t, parse_payload, status_t,
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
                                }
-                               spi_size = *(u_int8_t*)(output + rule->offset);
+                               spi_size = *(uint8_t*)(output + rule->offset);
                                break;
                        }
                        case SPI:
@@ -484,61 +497,41 @@ METHOD(parser_t, parse_payload, status_t,
                                }
                                break;
                        }
-                       case PROPOSALS:
-                       {
-                               if (payload_length < SA_PAYLOAD_HEADER_LENGTH ||
-                                       !parse_list(this, rule_number, output + rule->offset,
-                                                               PROPOSAL_SUBSTRUCTURE,
-                                                               payload_length - SA_PAYLOAD_HEADER_LENGTH))
-                               {
-                                       pld->destroy(pld);
-                                       return PARSE_ERROR;
-                               }
-                               break;
-                       }
-                       case PROPOSALS_V1:
+                       case PAYLOAD_LIST + PLV2_PROPOSAL_SUBSTRUCTURE:
+                       case PAYLOAD_LIST + PLV1_PROPOSAL_SUBSTRUCTURE:
+                       case PAYLOAD_LIST + PLV2_TRANSFORM_SUBSTRUCTURE:
+                       case PAYLOAD_LIST + PLV1_TRANSFORM_SUBSTRUCTURE:
+                       case PAYLOAD_LIST + PLV2_TRANSFORM_ATTRIBUTE:
+                       case PAYLOAD_LIST + PLV1_TRANSFORM_ATTRIBUTE:
+                       case PAYLOAD_LIST + PLV2_CONFIGURATION_ATTRIBUTE:
+                       case PAYLOAD_LIST + PLV1_CONFIGURATION_ATTRIBUTE:
+                       case PAYLOAD_LIST + PLV2_TRAFFIC_SELECTOR_SUBSTRUCTURE:
                        {
-                               if (payload_length < SA_PAYLOAD_V1_HEADER_LENGTH ||
+                               if (payload_length < header_length ||
                                        !parse_list(this, rule_number, output + rule->offset,
-                                                               PROPOSAL_SUBSTRUCTURE_V1,
-                                                               payload_length - SA_PAYLOAD_V1_HEADER_LENGTH))
+                                                               rule->type - PAYLOAD_LIST,
+                                                               payload_length - header_length))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
                                }
                                break;
                        }
-                       case TRANSFORMS:
+                       case CHUNK_DATA:
                        {
-                               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;
-                               }
-                               break;
-                       }
-                       case TRANSFORM_ATTRIBUTES:
-                       {
-                               if (payload_length < TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH ||
-                                       !parse_list(this, rule_number, output + rule->offset,
-                                               TRANSFORM_ATTRIBUTE,
-                                               payload_length - TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH))
+                               if (payload_length < header_length ||
+                                       !parse_chunk(this, rule_number, output + rule->offset,
+                                                                payload_length - header_length))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
                                }
                                break;
                        }
-                       case CONFIGURATION_ATTRIBUTES:
+                       case ENCRYPTED_DATA:
                        {
-                               if (payload_length < CP_PAYLOAD_HEADER_LENGTH ||
-                                       !parse_list(this, rule_number, output + rule->offset,
-                                                               CONFIGURATION_ATTRIBUTE,
-                                                               payload_length - CP_PAYLOAD_HEADER_LENGTH))
+                               if (!parse_chunk(this, rule_number, output + rule->offset,
+                                                                this->input_roof - this->byte_pos))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
@@ -564,14 +557,14 @@ METHOD(parser_t, parse_payload, status_t,
                                }
                                break;
                        }
-                       case CONFIGURATION_ATTRIBUTE_LENGTH:
+                       case ATTRIBUTE_LENGTH:
                        {
                                if (!parse_uint16(this, rule_number, output + rule->offset))
                                {
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
                                }
-                               attribute_length = *(u_int16_t*)(output + rule->offset);
+                               attribute_length = *(uint16_t*)(output + rule->offset);
                                break;
                        }
                        case ATTRIBUTE_LENGTH_OR_VALUE:
@@ -581,7 +574,7 @@ METHOD(parser_t, parse_payload, status_t,
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
                                }
-                               attribute_length = *(u_int16_t*)(output + rule->offset);
+                               attribute_length = *(uint16_t*)(output + rule->offset);
                                break;
                        }
                        case ATTRIBUTE_VALUE:
@@ -595,137 +588,6 @@ METHOD(parser_t, parse_payload, status_t,
                                }
                                break;
                        }
-                       case NONCE_DATA:
-                       {
-                               if (payload_length < NONCE_PAYLOAD_HEADER_LENGTH ||
-                                       !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 ||
-                                       !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 ||
-                                       !parse_chunk(this, rule_number, output + rule->offset,
-                                                                payload_length - AUTH_PAYLOAD_HEADER_LENGTH))
-                               {
-                                       pld->destroy(pld);
-                                       return PARSE_ERROR;
-                               }
-                               break;
-                       }
-                       case CERT_DATA:
-                       {
-                               if (payload_length < CERT_PAYLOAD_HEADER_LENGTH ||
-                                       !parse_chunk(this, rule_number, output + rule->offset,
-                                                                payload_length - CERT_PAYLOAD_HEADER_LENGTH))
-                               {
-                                       pld->destroy(pld);
-                                       return PARSE_ERROR;
-                               }
-                               break;
-                       }
-                       case CERTREQ_DATA:
-                       {
-                               if (payload_length < CERTREQ_PAYLOAD_HEADER_LENGTH ||
-                                       !parse_chunk(this, rule_number, output + rule->offset,
-                                                                payload_length - CERTREQ_PAYLOAD_HEADER_LENGTH))
-                               {
-                                       pld->destroy(pld);
-                                       return PARSE_ERROR;
-                               }
-                               break;
-                       }
-                       case EAP_DATA:
-                       {
-                               if (payload_length < EAP_PAYLOAD_HEADER_LENGTH ||
-                                       !parse_chunk(this, rule_number, output + rule->offset,
-                                                                payload_length - EAP_PAYLOAD_HEADER_LENGTH))
-                               {
-                                       pld->destroy(pld);
-                                       return PARSE_ERROR;
-                               }
-                               break;
-                       }
-                       case SPIS:
-                       {
-                               if (payload_length < DELETE_PAYLOAD_HEADER_LENGTH ||
-                                       !parse_chunk(this, rule_number, output + rule->offset,
-                                                                payload_length - DELETE_PAYLOAD_HEADER_LENGTH))
-                               {
-                                       pld->destroy(pld);
-                                       return PARSE_ERROR;
-                               }
-                               break;
-                       }
-                       case VID_DATA:
-                       {
-                               if (payload_length < VENDOR_ID_PAYLOAD_HEADER_LENGTH ||
-                                       !parse_chunk(this, rule_number, output + rule->offset,
-                                                       payload_length - VENDOR_ID_PAYLOAD_HEADER_LENGTH))
-                               {
-                                       pld->destroy(pld);
-                                       return PARSE_ERROR;
-                               }
-                               break;
-                       }
-                       case CONFIGURATION_ATTRIBUTE_VALUE:
-                       {
-                               if (!parse_chunk(this, rule_number, output + rule->offset,
-                                                                attribute_length))
-                               {
-                                       pld->destroy(pld);
-                                       return PARSE_ERROR;
-                               }
-                               break;
-                       }
-                       case KEY_EXCHANGE_DATA:
-                       {
-                               if (payload_length < KE_PAYLOAD_HEADER_LENGTH ||
-                                       !parse_chunk(this, rule_number, output + rule->offset,
-                                                                payload_length - KE_PAYLOAD_HEADER_LENGTH))
-                               {
-                                       pld->destroy(pld);
-                                       return PARSE_ERROR;
-                               }
-                               break;
-                       }
-                       case NOTIFICATION_DATA:
-                       {
-                               if (payload_length < NOTIFY_PAYLOAD_HEADER_LENGTH + spi_size ||
-                                       !parse_chunk(this, rule_number, output + rule->offset,
-                                               payload_length - NOTIFY_PAYLOAD_HEADER_LENGTH - spi_size))
-                               {
-                                       pld->destroy(pld);
-                                       return PARSE_ERROR;
-                               }
-                               break;
-                       }
-                       case ENCRYPTED_DATA:
-                       {
-                               if (payload_length < ENCRYPTION_PAYLOAD_HEADER_LENGTH ||
-                                       !parse_chunk(this, rule_number, output + rule->offset,
-                                                       payload_length - ENCRYPTION_PAYLOAD_HEADER_LENGTH))
-                               {
-                                       pld->destroy(pld);
-                                       return PARSE_ERROR;
-                               }
-                               break;
-                       }
                        case TS_TYPE:
                        {
                                if (!parse_uint8(this, rule_number, output + rule->offset))
@@ -733,7 +595,7 @@ METHOD(parser_t, parse_payload, status_t,
                                        pld->destroy(pld);
                                        return PARSE_ERROR;
                                }
-                               ts_type = *(u_int8_t*)(output + rule->offset);
+                               ts_type = *(uint8_t*)(output + rule->offset);
                                break;
                        }
                        case ADDRESS:
@@ -748,29 +610,6 @@ METHOD(parser_t, parse_payload, status_t,
                                }
                                break;
                        }
-                       case TRAFFIC_SELECTORS:
-                       {
-                               if (payload_length < TS_PAYLOAD_HEADER_LENGTH ||
-                                       !parse_list(this, rule_number, output + rule->offset,
-                                                               TRAFFIC_SELECTOR_SUBSTRUCTURE,
-                                                               payload_length - TS_PAYLOAD_HEADER_LENGTH))
-                               {
-                                       pld->destroy(pld);
-                                       return PARSE_ERROR;
-                               }
-                               break;
-                       }
-                       case UNKNOWN_DATA:
-                       {
-                               if (payload_length < UNKNOWN_PAYLOAD_HEADER_LENGTH ||
-                                       !parse_chunk(this, rule_number, output + rule->offset,
-                                                               payload_length - UNKNOWN_PAYLOAD_HEADER_LENGTH))
-                               {
-                                       pld->destroy(pld);
-                                       return PARSE_ERROR;
-                               }
-                               break;
-                       }
                        default:
                        {
                                DBG1(DBG_ENC, "  no rule to parse rule %d %N",
@@ -779,7 +618,7 @@ METHOD(parser_t, parse_payload, status_t,
                                return PARSE_ERROR;
                        }
                }
-               /* process next rulue */
+               /* process next rule */
                rule++;
        }
 
@@ -802,6 +641,12 @@ METHOD(parser_t, reset_context, void,
        this->bit_pos = 0;
 }
 
+METHOD(parser_t, set_major_version, void,
+       private_parser_t *this, uint8_t major_version)
+{
+       this->major_version = major_version;
+}
+
 METHOD(parser_t, destroy, void,
        private_parser_t *this)
 {
@@ -819,6 +664,7 @@ parser_t *parser_create(chunk_t data)
                .public = {
                        .parse_payload = _parse_payload,
                        .reset_context = _reset_context,
+                       .set_major_version = _set_major_version,
                        .get_remaining_byte_count = _get_remaining_byte_count,
                        .destroy = _destroy,
                },