From 7448067dd3090dcc4224af881f7232f27037afd7 Mon Sep 17 00:00:00 2001
From: Hoelscher <jens.hoelscher@fh-muenster.de>
Date: Mon, 9 May 2016 10:36:00 +0200
Subject: [PATCH] add empty reconfig chunk

---
 gtests/net/packetdrill/lexer.l       |  1 +
 gtests/net/packetdrill/parser.y      | 38 +++++++++++++-
 gtests/net/packetdrill/sctp.h        |  7 +++
 gtests/net/packetdrill/sctp_packet.c | 78 ++++++++++++++++++++++------
 gtests/net/packetdrill/sctp_packet.h |  3 ++
 5 files changed, 109 insertions(+), 18 deletions(-)

diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l
index d08de406..5ad84697 100644
--- a/gtests/net/packetdrill/lexer.l
+++ b/gtests/net/packetdrill/lexer.l
@@ -572,6 +572,7 @@ SSN_TSN_RESET			return SSN_TSN_RESET;
 RECONFIG_RESPONSE		return RECONFIG_RESPONSE;
 ADD_OUTGOING_STREAMS		return ADD_OUTGOING_STREAMS;
 ADD_INCOMING_STREAMS		return ADD_INCOMING_STREAMS;
+RECONFIG_REQUEST_GENERIC	return RECONFIG_REQUEST_GENERIC;
 req_sn				return REQ_SN;
 resp_sn				return RESP_SN;
 last_tsn			return LAST_TSN;
diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index 6d3c7f6f..ecb74c63 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -528,7 +528,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %token <reserved> OUTGOING_SSN_RESET REQ_SN RESP_SN LAST_TSN SIDS INCOMING_SSN_RESET
 %token <reserved> RECONFIG_RESPONSE RESULT SENDER_NEXT_TSN RECEIVER_NEXT_TSN
 %token <reserved> SSN_TSN_RESET ADD_INCOMING_STREAMS NUMBER_OF_NEW_STREAMS
-%token <reserved> ADD_OUTGOING_STREAMS
+%token <reserved> ADD_OUTGOING_STREAMS RECONFIG_REQUEST_GENERIC
 %token <reserved> ADDR INCR TYPES PARAMS
 %token <reserved> IPV4_TYPE IPV6_TYPE HOSTNAME_TYPE
 %token <reserved> CAUSE
@@ -690,7 +690,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %type <parameter_list_item> sctp_adaptation_indication_parameter_spec
 %type <parameter_list_item> sctp_pad_parameter_spec sctp_reconfig_parameter_spec
 %type <parameter_list_item> outgoing_ssn_reset_request incoming_ssn_reset_request
-%type <parameter_list_item> reconfig_response ssn_tsn_reset_request
+%type <parameter_list_item> reconfig_response ssn_tsn_reset_request generic_reconfig_request
 %type <parameter_list_item> add_outgoing_streams_request add_incoming_streams_request
 %type <cause_list> opt_cause_list_spec sctp_cause_list_spec
 %type <cause_list_item> sctp_cause_spec
@@ -1752,6 +1752,7 @@ sctp_reconfig_parameter_spec
 | reconfig_response		{ $$ = $1; }
 | add_outgoing_streams_request  { $$ = $1; }
 | add_incoming_streams_request  { $$ = $1; }
+| generic_reconfig_request	{ $$ = $1; }
 ;
 
 opt_sender_next_tsn
@@ -1761,6 +1762,12 @@ opt_sender_next_tsn
 	}
 	$$ = $3;
 }
+| SENDER_NEXT_TSN '=' HEX_INTEGER { 
+	if (!is_valid_u32($3)) {
+		semantic_error("sender_next_tsn out of range");
+	}
+	$$ = $3;
+}
 | SENDER_NEXT_TSN '=' ELLIPSIS { $$ = -1; }
 ;
 
@@ -1771,6 +1778,12 @@ opt_receiver_next_tsn
 	}
 	$$ = $3;
 }
+| RECEIVER_NEXT_TSN '=' HEX_INTEGER { 
+	if (!is_valid_u32($3)) {
+		semantic_error("receiver_next_tsn out of range");
+	}
+	$$ = $3;
+}
 | RECEIVER_NEXT_TSN '=' ELLIPSIS { $$ = -1; }
 ;
 
@@ -1829,10 +1842,19 @@ add_incoming_streams_request
 }
 ;
 
+generic_reconfig_request
+: RECONFIG_REQUEST_GENERIC '[' opt_parameter_type ',' opt_len ',' opt_req_sn ',' opt_val ']' {
+	$$ = sctp_generic_reconfig_request_parameter_new($3, $5, $7, $9);
+}
+;
+
 sctp_reconfig_chunk_spec
 : RECONFIG '[' opt_flags ',' sctp_reconfig_parameter_list_spec ']' {
 	$$ = sctp_reconfig_chunk_new($3, $5);
 }
+| RECONFIG '[' opt_flags ']' {
+	$$ = sctp_reconfig_chunk_new($3, NULL);
+}
 ;
 
 opt_parameter_list_spec
@@ -5307,6 +5329,12 @@ assocreset_local_tsn
 	}
 	$$ = new_integer_expression($3, "%u");
 }
+| ASSOCRESET_LOCAL_TSN '=' HEX_INTEGER {
+	if (!is_valid_u32($3)) {
+		semantic_error("assocreset_local_tsn out of range");
+	}
+	$$ = new_integer_expression($3, "%u");
+}
 | ASSOCRESET_LOCAL_TSN '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
 ;
 
@@ -5317,6 +5345,12 @@ assocreset_remote_tsn
 	}
 	$$ = new_integer_expression($3, "%u");
 }
+| ASSOCRESET_REMOTE_TSN '=' HEX_INTEGER {
+	if (!is_valid_u32($3)) {
+		semantic_error("assocreset_remote_tsn out of range");
+	}
+	$$ = new_integer_expression($3, "%u");
+}
 | ASSOCRESET_REMOTE_TSN '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
 ;
 
diff --git a/gtests/net/packetdrill/sctp.h b/gtests/net/packetdrill/sctp.h
index badde342..0b95445b 100644
--- a/gtests/net/packetdrill/sctp.h
+++ b/gtests/net/packetdrill/sctp.h
@@ -387,6 +387,13 @@ struct sctp_add_incoming_streams_request_parameter {
 	__be16 reserved;
 } __packed;
 
+struct sctp_reconfig_generic_request_parameter {
+	__be16 type;
+	__be16 length;
+	__be32 reqsn;
+	__u8 value[];
+} __packed;
+
 #define SCTP_INVALID_STREAM_IDENTIFIER_CAUSE_CODE	0x0001
 #define SCTP_MISSING_MANDATORY_PARAMETER_CAUSE_CODE	0x0002
 #define SCTP_STALE_COOKIE_ERROR_CAUSE_CODE		0x0003
diff --git a/gtests/net/packetdrill/sctp_packet.c b/gtests/net/packetdrill/sctp_packet.c
index 6e61ad52..7936fc02 100644
--- a/gtests/net/packetdrill/sctp_packet.c
+++ b/gtests/net/packetdrill/sctp_packet.c
@@ -1313,22 +1313,23 @@ sctp_reconfig_chunk_new(s64 flgs, struct sctp_parameter_list *parameters)
 	chunk->length = htons(chunk_length);
 
 	offset = 0;
-	for (item = parameters->first; item != NULL; item = item->next) {
-		parameter_padding_length = item->length % 4;
-		if (parameter_padding_length > 0) {
-			parameter_padding_length = 4 - parameter_padding_length;
-		}
-		memcpy(chunk->parameter + offset,
-		       item->parameter,
-		       item->length + parameter_padding_length);
-		free(item->parameter);
-		item->parameter = (struct sctp_parameter *)(chunk->parameter + offset);
-		if (item->flags & FLAG_PARAMETER_LENGTH_NOCHECK) {
-			flags |= FLAG_CHUNK_LENGTH_NOCHECK;
+	if (parameters != NULL) {
+		for (item = parameters->first; item != NULL; item = item->next) {
+			parameter_padding_length = item->length % 4;
+			if (parameter_padding_length > 0) {
+				parameter_padding_length = 4 - parameter_padding_length;
+			}
+			memcpy(chunk->parameter + offset,
+			       item->parameter,
+			       item->length + parameter_padding_length);
+			free(item->parameter);
+			item->parameter = (struct sctp_parameter *)(chunk->parameter + offset);
+			if (item->flags & FLAG_PARAMETER_LENGTH_NOCHECK) {
+				flags |= FLAG_CHUNK_LENGTH_NOCHECK;
+			}
+			offset += item->length + parameter_padding_length;
 		}
-		offset += item->length + parameter_padding_length;
 	}
-
 	return sctp_chunk_list_item_new((struct sctp_chunk *)chunk,
 					chunk_length + padding_length,
 					flags, parameters,
@@ -1921,6 +1922,7 @@ sctp_reconfig_response_parameter_new(s64 respsn, s64 result, s64 sender_next_tsn
 			parameter->receiver_next_tsn = htonl((u32)receiver_next_tsn);
 		}
 	}
+
 	return sctp_parameter_list_item_new((struct sctp_parameter *)parameter,
 					    parameter_length, flags);
 }
@@ -1973,7 +1975,7 @@ sctp_add_outgoing_streams_request_parameter_new(s64 reqsn, s32 number_of_new_str
 	} else {
 		parameter->reqsn = htonl((u32)reqsn);
 	}
-	if (reqsn == -1) {
+	if (number_of_new_streams == -1) {
 		flags |= FLAG_RECONFIG_NUMBER_OF_NEW_STREAMS_NOCHECK;
 		parameter->number_of_new_streams = 0;
 	} else {
@@ -2006,7 +2008,7 @@ sctp_add_incoming_streams_request_parameter_new(s64 reqsn, s32 number_of_new_str
 	} else {
 		parameter->reqsn = htonl((u32)reqsn);
 	}
-	if (reqsn == -1) {
+	if (number_of_new_streams == -1) {
 		flags |= FLAG_RECONFIG_NUMBER_OF_NEW_STREAMS_NOCHECK;
 		parameter->number_of_new_streams = 0;
 	} else {
@@ -2017,6 +2019,50 @@ sctp_add_incoming_streams_request_parameter_new(s64 reqsn, s32 number_of_new_str
 					    parameter_length, flags);
 }
 
+struct sctp_parameter_list_item *
+sctp_generic_reconfig_request_parameter_new(s32 type, s32 len, s64 reqsn, struct sctp_byte_list *payload)
+{
+	struct sctp_reconfig_generic_request_parameter *parameter;
+	struct sctp_byte_list_item *item;
+	u32 flags = 0;
+	u16 parameter_length;
+	u16 payload_len=0;
+
+	if (payload != NULL) {
+		payload_len = payload->nr_entries;
+	}
+	parameter_length = sizeof(struct sctp_reconfig_generic_request_parameter) + payload_len;
+
+	parameter = malloc(parameter_length);
+	assert(parameter != NULL);
+
+	if (type == -1) {
+		parameter->type = 0;
+	} else {
+		parameter->type = htons((u16)type);
+	}
+	if (len == -1) {
+		parameter->length = 0;
+	} else {
+		parameter->length = htons((u16)len);
+	}
+	if (reqsn == -1) {
+		flags |= FLAG_RECONFIG_REQ_SN_NOCHECK;
+		parameter->reqsn = 0;
+	} else {
+		parameter->reqsn = htonl((u32)reqsn);
+	}
+	if (payload != NULL) {
+		int i = 0;
+		for (i = 0, item = payload->first; item != NULL; i++, item = item->next) {
+			parameter->value[i] = item->byte;
+		}
+	}
+
+	return sctp_parameter_list_item_new((struct sctp_parameter *)parameter,
+					     parameter_length, flags);
+}
+
 struct sctp_parameter_list_item *
 sctp_ecn_capable_parameter_new(void)
 {
diff --git a/gtests/net/packetdrill/sctp_packet.h b/gtests/net/packetdrill/sctp_packet.h
index 8a1a4bec..7581f207 100644
--- a/gtests/net/packetdrill/sctp_packet.h
+++ b/gtests/net/packetdrill/sctp_packet.h
@@ -405,6 +405,9 @@ sctp_add_outgoing_streams_request_parameter_new(s64 reqsn, s32 number_of_new_str
 struct sctp_parameter_list_item *
 sctp_add_incoming_streams_request_parameter_new(s64 reqsn, s32 number_of_new_streams);
 
+struct sctp_parameter_list_item *
+sctp_generic_reconfig_request_parameter_new(s32 type, s32 len, s64 reqsn, struct sctp_byte_list *payload);
+
 struct sctp_parameter_list *
 sctp_parameter_list_new(void);
 
-- 
GitLab