From f17c825697226ef6ab7b93b0c1f9ec5c1e2f14e4 Mon Sep 17 00:00:00 2001 From: Michael Tuexen <tuexen@fh-muenster.de> Date: Sat, 11 Jul 2015 23:02:48 +0200 Subject: [PATCH] Add support for a generic parameter. This fixes https://github.com/nplab/packetdrill/issues/19 --- gtests/net/packetdrill/lexer.l | 1 + gtests/net/packetdrill/parser.y | 60 ++++++++++++++++++++++------ gtests/net/packetdrill/sctp_packet.c | 52 +++++++++++++++++++++--- gtests/net/packetdrill/sctp_packet.h | 3 ++ 4 files changed, 98 insertions(+), 18 deletions(-) diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l index ecf60c4d..f24e7292 100644 --- a/gtests/net/packetdrill/lexer.l +++ b/gtests/net/packetdrill/lexer.l @@ -243,6 +243,7 @@ ppid return PPID; cum_tsn return CUM_TSN; gaps return GAPS; dups return DUPS; +PARAMETER return PARAMETER; HEARTBEAT_INFORMATION return HEARTBEAT_INFORMATION; IPV4_ADDRESS return IPV4_ADDRESS; IPV6_ADDRESS return IPV6_ADDRESS; diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index f11d5410..d70fa720 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -508,9 +508,9 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %token <reserved> SHUTDOWN_COMPLETE PAD %token <reserved> TYPE FLAGS LEN %token <reserved> TAG A_RWND OS IS TSN SID SSN PPID CUM_TSN GAPS DUPS -%token <reserved> HEARTBEAT_INFORMATION IPV4_ADDRESS IPV6_ADDRESS STATE_COOKIE -%token <reserved> UNRECOGNIZED_PARAMETER COOKIE_PRESERVATIVE HOSTNAME_ADDRESS -%token <reserved> SUPPORTED_ADDRESS_TYPES ECN_CAPABLE +%token <reserved> PARAMETER HEARTBEAT_INFORMATION IPV4_ADDRESS IPV6_ADDRESS +%token <reserved> STATE_COOKIE UNRECOGNIZED_PARAMETER COOKIE_PRESERVATIVE +%token <reserved> HOSTNAME_ADDRESS SUPPORTED_ADDRESS_TYPES ECN_CAPABLE %token <reserved> ADDR INCR TYPES PARAMS %token <reserved> IPV4_TYPE IPV6_TYPE HOSTNAME_TYPE %token <floating> FLOAT @@ -568,6 +568,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <chunk_list_item> sctp_pad_chunk_spec %type <parameter_list> opt_parameter_list_spec sctp_parameter_list_spec %type <parameter_list_item> sctp_parameter_spec +%type <parameter_list_item> sctp_generic_parameter_spec %type <parameter_list_item> sctp_heartbeat_information_parameter_spec %type <parameter_list_item> sctp_ipv4_address_parameter_spec %type <parameter_list_item> sctp_ipv6_address_parameter_spec @@ -578,8 +579,9 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <parameter_list_item> sctp_supported_address_types_parameter_spec %type <parameter_list_item> sctp_ecn_capable_parameter_spec %type <parameter_list_item> sctp_pad_parameter_spec -%type <integer> opt_chunk_type opt_flags opt_data_flags opt_abort_flags -%type <integer> opt_shutdown_complete_flags opt_chunk_len +%type <integer> opt_chunk_type opt_parameter_type +%type <integer> opt_flags opt_data_flags opt_abort_flags +%type <integer> opt_shutdown_complete_flags opt_len %type <integer> opt_tag opt_a_rwnd opt_os opt_is opt_tsn opt_sid opt_ssn %type <integer> opt_cum_tsn opt_ppid %type <byte_list> opt_val byte_list @@ -830,13 +832,13 @@ opt_flags } ; -opt_chunk_len +opt_len : LEN '=' ELLIPSIS { $$ = -1; } | LEN '=' INTEGER { if (!is_valid_u16($3)) { semantic_error("length value out of range"); - } - $$ = $3; + } + $$ = $3; } ; @@ -1141,7 +1143,7 @@ dup ; sctp_generic_chunk_spec -: CHUNK '[' opt_chunk_type ',' opt_flags ',' opt_chunk_len ',' opt_val ']' { +: CHUNK '[' opt_chunk_type ',' opt_flags ',' opt_len ',' opt_val ']' { if (($7 != -1) && ($7 < sizeof(struct sctp_chunk))) { semantic_error("length value out of range"); } @@ -1156,7 +1158,7 @@ sctp_generic_chunk_spec } sctp_data_chunk_spec -: DATA '[' opt_data_flags ',' opt_chunk_len ',' opt_tsn ',' opt_sid ',' opt_ssn ',' opt_ppid ']' { +: DATA '[' opt_data_flags ',' opt_len ',' opt_tsn ',' opt_sid ',' opt_ssn ',' opt_ppid ']' { if (($5 != -1) && ($5 < sizeof(struct sctp_data_chunk))) { semantic_error("length value out of range"); } @@ -1215,7 +1217,7 @@ sctp_error_chunk_spec } sctp_cookie_echo_chunk_spec -: COOKIE_ECHO '[' opt_flags ',' opt_chunk_len ',' VAL '=' ELLIPSIS ']' { +: COOKIE_ECHO '[' opt_flags ',' opt_len ',' VAL '=' ELLIPSIS ']' { $$ = sctp_cookie_echo_chunk_new($3, $5, NULL); } @@ -1240,7 +1242,7 @@ sctp_shutdown_complete_chunk_spec } sctp_pad_chunk_spec -: PAD '[' opt_flags ',' opt_chunk_len ',' VAL '=' ELLIPSIS ']' { +: PAD '[' opt_flags ',' opt_len ',' VAL '=' ELLIPSIS ']' { $$ = sctp_pad_chunk_new($3, $5, NULL); } @@ -1258,7 +1260,8 @@ sctp_parameter_list_spec ; sctp_parameter_spec -: sctp_heartbeat_information_parameter_spec { $$ = $1; } +: sctp_generic_parameter_spec { $$ = $1; } +| sctp_heartbeat_information_parameter_spec { $$ = $1; } | sctp_ipv4_address_parameter_spec { $$ = $1; } | sctp_ipv6_address_parameter_spec { $$ = $1; } | sctp_state_cookie_parameter_spec { $$ = $1; } @@ -1270,6 +1273,37 @@ sctp_parameter_spec | sctp_pad_parameter_spec { $$ = $1; } ; +opt_parameter_type +: TYPE '=' ELLIPSIS { $$ = -1; } +| TYPE '=' HEX_INTEGER { + if (!is_valid_u16($3)) { + semantic_error("type value out of range"); + } + $$ = $3; +} +| TYPE '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("type value out of range"); + } + $$ = $3; +} +; + +sctp_generic_parameter_spec +: PARAMETER '[' opt_parameter_type ',' opt_len ',' opt_val ']' { + if (($5 != -1) && ($5 < sizeof(struct sctp_parameter))) { + semantic_error("length value out of range"); + } + if (($5 != -1) && ($7 != NULL) && + ($5 != sizeof(struct sctp_parameter) + $7->nr_entries)) { + semantic_error("length value incompatible with val"); + } + if (($5 == -1) && ($7 != NULL)) { + semantic_error("length needs to be specified"); + } + $$ = sctp_generic_parameter_new($3, $5, $7); +} + sctp_heartbeat_information_parameter_spec : HEARTBEAT_INFORMATION '[' ELLIPSIS ']' { $$ = sctp_heartbeat_information_parameter_new(-1, NULL); diff --git a/gtests/net/packetdrill/sctp_packet.c b/gtests/net/packetdrill/sctp_packet.c index 4ca10243..1571702f 100644 --- a/gtests/net/packetdrill/sctp_packet.c +++ b/gtests/net/packetdrill/sctp_packet.c @@ -261,10 +261,10 @@ sctp_generic_chunk_new(s64 type, s64 flgs, s64 len, flags = 0; if (bytes == NULL) { - flags |= FLAG_CHUNK_LENGTH_NOCHECK; flags |= FLAG_CHUNK_VALUE_NOCHECK; } if (len == -1) { + flags |= FLAG_CHUNK_LENGTH_NOCHECK; length = (u16)sizeof(struct sctp_chunk); } else { length = (u16)len; @@ -288,10 +288,6 @@ sctp_generic_chunk_new(s64 type, s64 flgs, s64 len, chunk->flags = (u8)flgs; } chunk->length = htons(length); - if (len == -1) { - flags |= FLAG_CHUNK_LENGTH_NOCHECK; - flags |= FLAG_CHUNK_VALUE_NOCHECK; - } if (bytes != NULL) { for (i = 0, item = bytes->first; item != NULL; @@ -1055,6 +1051,52 @@ sctp_parameter_list_item_new(struct sctp_parameter *parameter, u32 length, u32 f return item; } +struct sctp_parameter_list_item * +sctp_generic_parameter_new(s64 type, s64 len, struct sctp_byte_list *bytes) +{ + struct sctp_parameter *parameter; + struct sctp_byte_list_item *item; + u32 flags; + u16 parameter_length, value_length, padding_length, i; + + flags = 0; + if (bytes == NULL) { + flags |= FLAG_CHUNK_VALUE_NOCHECK; + } + if (len == -1) { + parameter_length = (u16)sizeof(struct sctp_chunk); + flags |= FLAG_CHUNK_LENGTH_NOCHECK; + } else { + parameter_length = (u16)len; + } + value_length = parameter_length - sizeof(struct sctp_parameter); + padding_length = parameter_length % 4; + if (padding_length > 0) { + padding_length = 4 - padding_length; + } + parameter = malloc(parameter_length + padding_length); + assert(parameter != NULL); + if (type == -1) { + parameter->type = 0; + flags |= FLAG_CHUNK_TYPE_NOCHECK; + } else { + parameter->type = htons((u16)type); + } + parameter->length = htons(parameter_length); + if (bytes != NULL) { + for (i = 0, item = bytes->first; + item != NULL; + i++, item = item->next) { + parameter->value[i] = item->byte; + } + } else { + memset(parameter->value, 0, value_length); + } + /* Clear the padding */ + memset(parameter->value + value_length, 0, padding_length); + return sctp_parameter_list_item_new(parameter, parameter_length, flags); +} + struct sctp_parameter_list_item * sctp_heartbeat_information_parameter_new(s64 len, u8 *information) { diff --git a/gtests/net/packetdrill/sctp_packet.h b/gtests/net/packetdrill/sctp_packet.h index b8cc7ef1..85a3ea62 100644 --- a/gtests/net/packetdrill/sctp_packet.h +++ b/gtests/net/packetdrill/sctp_packet.h @@ -250,6 +250,9 @@ struct sctp_parameter_list_item * sctp_parameter_list_item_new(struct sctp_parameter *parameter, u32 length, u32 flags); +struct sctp_parameter_list_item * +sctp_generic_parameter_new(s64 type, s64 len, struct sctp_byte_list *bytes); + struct sctp_parameter_list_item * sctp_heartbeat_information_parameter_new(s64 len, u8 *information); -- GitLab