From 0c5fde5437904e2a75bddf49e5c80e091e50524c Mon Sep 17 00:00:00 2001
From: Hoelscher <jens.hoelscher@fh-muenster.de>
Date: Mon, 14 Mar 2016 15:37:16 +0100
Subject: [PATCH] add support for incoming_ssn_reset_request_parameter for
 reconfig_chunk

---
 gtests/net/packetdrill/lexer.l                |  1 +
 gtests/net/packetdrill/parser.y               | 29 +++++++++----
 gtests/net/packetdrill/run_packet.c           | 16 ++++++-
 gtests/net/packetdrill/sctp.h                 |  8 ++++
 gtests/net/packetdrill/sctp_chunk_to_string.c | 30 +++++++++++++
 gtests/net/packetdrill/sctp_packet.c          | 42 +++++++++++++++++++
 gtests/net/packetdrill/sctp_packet.h          |  3 ++
 7 files changed, 118 insertions(+), 11 deletions(-)

diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l
index d258c19e..c889f1b0 100644
--- a/gtests/net/packetdrill/lexer.l
+++ b/gtests/net/packetdrill/lexer.l
@@ -567,6 +567,7 @@ gaps				return GAPS;
 dups				return DUPS;
 adaptation_code_point		return ADAPTATION_CODE_POINT;
 OUTGOING_SSN_RESET		return OUTGOING_SSN_RESET;
+INCOMING_SSN_RESET		return INCOMING_SSN_RESET;
 SSN_TSN_RESET			return SSN_TSN_RESET;
 RECONFIG_RESPONSE		return RECONFIG_RESPONSE;
 req_sn				return REQ_SN;
diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index a7af8e0d..f3befd60 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -525,7 +525,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %token <reserved> STATE_COOKIE UNRECOGNIZED_PARAMETER COOKIE_PRESERVATIVE
 %token <reserved> HOSTNAME_ADDRESS SUPPORTED_ADDRESS_TYPES ECN_CAPABLE
 %token <reserved> SUPPORTED_EXTENSIONS ADAPTATION_CODE_POINT ADAPTATION_INDICATION
-%token <reserved> OUTGOING_SSN_RESET REQ_SN RESP_SN LAST_TSN SIDS 
+%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
 %token <reserved> ADDR INCR TYPES PARAMS
@@ -688,7 +688,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %type <parameter_list_item> sctp_supported_extensions_parameter_spec
 %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 reconfig_response ssn_tsn_reset_request
+%type <parameter_list_item> outgoing_ssn_reset_request incoming_ssn_reset_request
+%type <parameter_list_item> reconfig_response ssn_tsn_reset_request
 %type <cause_list> opt_cause_list_spec sctp_cause_list_spec
 %type <cause_list_item> sctp_cause_spec
 %type <cause_list_item> sctp_generic_cause_spec
@@ -1743,9 +1744,10 @@ sctp_reconfig_parameter_list_spec
 ;
 
 sctp_reconfig_parameter_spec
-:outgoing_ssn_reset_request { $$ = $1; }
-|ssn_tsn_reset_request      { $$ = $1; }
-|reconfig_response          { $$ = $1; }
+: outgoing_ssn_reset_request	{ $$ = $1; }
+| incoming_ssn_reset_request	{ $$ = $1; }
+| ssn_tsn_reset_request		{ $$ = $1; }
+| reconfig_response		{ $$ = $1; }
 ;
  
 opt_sender_next_tsn
@@ -1769,7 +1771,7 @@ opt_receiver_next_tsn
 ;
 
 outgoing_ssn_reset_request
-:OUTGOING_SSN_RESET '[' opt_req_sn ',' opt_resp_sn ',' opt_last_tsn ']' {
+: OUTGOING_SSN_RESET '[' opt_req_sn ',' opt_resp_sn ',' opt_last_tsn ']' {
 	$$ = sctp_outgoing_ssn_reset_request_parameter_new($3, $5, $7, NULL);
 }
 | OUTGOING_SSN_RESET '[' opt_req_sn ',' opt_resp_sn ',' opt_last_tsn ',' SIDS '=' '[' u16_list ']' ']' {
@@ -1777,17 +1779,26 @@ outgoing_ssn_reset_request
 }
 ;
 
+incoming_ssn_reset_request
+: INCOMING_SSN_RESET '[' opt_req_sn ']' {
+	$$ = sctp_incoming_ssn_reset_request_parameter_new($3, NULL);
+}
+| INCOMING_SSN_RESET '[' opt_req_sn ',' SIDS '=' '[' u16_list ']' ']' {
+	$$ = sctp_incoming_ssn_reset_request_parameter_new($3, $8);
+}
+;
+
 ssn_tsn_reset_request
-:SSN_TSN_RESET '[' opt_req_sn ']' {
+: SSN_TSN_RESET '[' opt_req_sn ']' {
 	$$ = sctp_ssn_tsn_reset_request_parameter_new($3);
 }
 ;
 
 reconfig_response
-:RECONFIG_RESPONSE '[' opt_resp_sn ',' opt_result ']' {
+: RECONFIG_RESPONSE '[' opt_resp_sn ',' opt_result ']' {
 	$$ = sctp_reconfig_response_parameter_new($3, $5, -2, -2);
 }
-|RECONFIG_RESPONSE '[' opt_resp_sn ',' opt_result ',' opt_sender_next_tsn ',' opt_receiver_next_tsn']' {
+| RECONFIG_RESPONSE '[' opt_resp_sn ',' opt_result ',' opt_sender_next_tsn ',' opt_receiver_next_tsn']' {
 	$$ = sctp_reconfig_response_parameter_new($3, $5, $7, $9);
 }
 ;
diff --git a/gtests/net/packetdrill/run_packet.c b/gtests/net/packetdrill/run_packet.c
index 1ff35223..6b48611d 100644
--- a/gtests/net/packetdrill/run_packet.c
+++ b/gtests/net/packetdrill/run_packet.c
@@ -758,10 +758,16 @@ static int map_inbound_sctp_packet(
 						reset->last_tsn = htonl(ntohl(reset->last_tsn) + remote_diff);
 						break;
 					}
+					case SCTP_INCOMING_SSN_RESET_REQUEST_PARAMETER_TYPE: {
+						struct sctp_incoming_ssn_reset_request_parameter *reset;
+						reset = (struct sctp_incoming_ssn_reset_request_parameter *)parameter;
+						reset->reqsn = htonl(ntohl(reset->reqsn) + remote_diff);
+						break;
+					}
 					case SCTP_SSN_TSN_RESET_REQUEST_PARAMETER_TYPE: {
 						struct sctp_ssn_tsn_reset_request_parameter *reset;
 						reset = (struct sctp_ssn_tsn_reset_request_parameter *)parameter;
-						reset->reqsn = htonl(ntohl(reset->reqsn) + remote_diff);						
+						reset->reqsn = htonl(ntohl(reset->reqsn) + remote_diff);
 						break;
 					}
 					case SCTP_RECONFIG_RESPONSE_PARAMETER_TYPE: {
@@ -995,10 +1001,16 @@ static int map_outbound_live_sctp_packet(
 						reset->last_tsn = htonl(ntohl(reset->last_tsn) + local_diff);
 						break;
 					}
+					case SCTP_INCOMING_SSN_RESET_REQUEST_PARAMETER_TYPE: {
+						struct sctp_incoming_ssn_reset_request_parameter *reset;
+						reset = (struct sctp_incoming_ssn_reset_request_parameter *)parameter;
+						reset->reqsn = htonl(ntohl(reset->reqsn) + local_diff);
+						break;
+					}
 					case SCTP_SSN_TSN_RESET_REQUEST_PARAMETER_TYPE: {
 						struct sctp_ssn_tsn_reset_request_parameter *reset;
 						reset = (struct sctp_ssn_tsn_reset_request_parameter *)parameter;
-						reset->reqsn = htonl(ntohl(reset->reqsn) + local_diff);						
+						reset->reqsn = htonl(ntohl(reset->reqsn) + local_diff);				
 						break;
 					}
 					case SCTP_RECONFIG_RESPONSE_PARAMETER_TYPE: {
diff --git a/gtests/net/packetdrill/sctp.h b/gtests/net/packetdrill/sctp.h
index a9a5730d..58a9f252 100644
--- a/gtests/net/packetdrill/sctp.h
+++ b/gtests/net/packetdrill/sctp.h
@@ -249,6 +249,7 @@ struct sctp_reconfig_chunk {
 #define SCTP_HOSTNAME_ADDRESS_PARAMETER_TYPE		0x000b
 #define SCTP_SUPPORTED_ADDRESS_TYPES_PARAMETER_TYPE	0x000c
 #define SCTP_OUTGOING_SSN_RESET_REQUEST_PARAMETER_TYPE  0x000d
+#define SCTP_INCOMING_SSN_RESET_REQUEST_PARAMETER_TYPE  0x000e
 #define SCTP_SSN_TSN_RESET_REQUEST_PARAMETER_TYPE       0x000f
 #define SCTP_RECONFIG_RESPONSE_PARAMETER_TYPE           0x0010
 #define SCTP_ECN_CAPABLE_PARAMETER_TYPE			0x8000
@@ -344,6 +345,13 @@ struct sctp_outgoing_ssn_reset_request_parameter {
 	__be16 sids[];
 } __packed;
 
+struct sctp_incoming_ssn_reset_request_parameter {
+	__be16 type;
+	__be16 length;
+	__be32 reqsn;
+	__be16 sids[];
+} __packed;
+
 struct sctp_ssn_tsn_reset_request_parameter {
 	__be16 type;
 	__be16 length;
diff --git a/gtests/net/packetdrill/sctp_chunk_to_string.c b/gtests/net/packetdrill/sctp_chunk_to_string.c
index 51bb4ca2..0f73312a 100644
--- a/gtests/net/packetdrill/sctp_chunk_to_string.c
+++ b/gtests/net/packetdrill/sctp_chunk_to_string.c
@@ -348,6 +348,32 @@ static int sctp_outgoing_ssn_reset_request_parameter_to_string(
 	return STATUS_OK;
 }
 
+static int sctp_incoming_ssn_reset_request_parameter_to_string(
+	FILE *s,
+	struct sctp_incoming_ssn_reset_request_parameter *parameter,
+	char **error)
+{
+	u16 length;
+	u32 reqsn;
+	int len;
+
+	length = ntohs(parameter->length);
+	reqsn = ntohl(parameter->reqsn);
+	fputs("INCOMING_SSN_RESET[", s);
+	fprintf(s, "len=%hu, ", length);
+	fprintf(s, "req_sn=%u ,", reqsn);
+	fputs("sids=[", s);
+	for(len = 0; len < ((length-8)/sizeof(u16)); len++) {
+		u16 sid;
+		sid = ntohs(parameter->sids[len]);
+		if (len > 0)
+			fprintf(s, ", ");
+		fprintf(s, "%hu", sid);	
+	}
+	fputs("]", s);
+	return STATUS_OK;
+}
+
 static int sctp_ssn_tsn_reset_request_parameter_to_string(
 	FILE *s,
 	struct sctp_ssn_tsn_reset_request_parameter *parameter,
@@ -505,6 +531,10 @@ static int sctp_parameter_to_string(FILE *s,
 		result = sctp_outgoing_ssn_reset_request_parameter_to_string(s,
 			(struct sctp_outgoing_ssn_reset_request_parameter *)parameter, error);
 		break;
+	case SCTP_INCOMING_SSN_RESET_REQUEST_PARAMETER_TYPE:
+		result = sctp_incoming_ssn_reset_request_parameter_to_string(s,
+			(struct sctp_incoming_ssn_reset_request_parameter *)parameter, error);
+		break;
 	case SCTP_SSN_TSN_RESET_REQUEST_PARAMETER_TYPE:
 		result = sctp_ssn_tsn_reset_request_parameter_to_string(s,
 			(struct sctp_ssn_tsn_reset_request_parameter *)parameter, error);
diff --git a/gtests/net/packetdrill/sctp_packet.c b/gtests/net/packetdrill/sctp_packet.c
index 27893aa5..fd49921e 100644
--- a/gtests/net/packetdrill/sctp_packet.c
+++ b/gtests/net/packetdrill/sctp_packet.c
@@ -1842,6 +1842,41 @@ sctp_outgoing_ssn_reset_request_parameter_new(s64 reqsn, s64 respsn, s64 last_ts
 					    parameter_length, flags);
 }
 
+struct sctp_parameter_list_item *
+sctp_incoming_ssn_reset_request_parameter_new(s64 reqsn, struct sctp_u16_list *sids)
+{
+	struct sctp_incoming_ssn_reset_request_parameter *parameter;
+	u32 flags = 0;
+	u16 parameter_length;
+	int i = 0, sid_len = 0;
+
+	if (sids != NULL) {
+		sid_len = sids->nr_entries;
+	}
+	
+	parameter_length = sizeof(struct sctp_incoming_ssn_reset_request_parameter) + (sizeof(u16) * sid_len);
+
+	parameter = malloc(parameter_length);
+	assert(parameter != NULL);
+
+	parameter->type = htons(SCTP_INCOMING_SSN_RESET_REQUEST_PARAMETER_TYPE);
+	parameter->length = htons(parameter_length);
+	if (reqsn == -1) {
+		flags |= FLAG_RECONFIG_REQ_SN_NOCHECK;
+		parameter->reqsn = 0;
+	} else {
+		parameter->reqsn = htonl((u32)reqsn);
+	}
+	if (sids != NULL) {
+		struct sctp_u16_list_item *item;
+		for (item = sids->first; item != NULL; item = item->next) {
+			parameter->sids[i] = item->value;
+		}
+	}
+	return sctp_parameter_list_item_new((struct sctp_parameter *)parameter,
+					    parameter_length, flags);
+}
+
 struct sctp_parameter_list_item *
 sctp_reconfig_response_parameter_new(s64 respsn, s64 result, s64 sender_next_tsn, s64 receiver_next_tsn)
 {
@@ -2570,6 +2605,13 @@ new_sctp_packet(int address_family,
 						return NULL;
 					}
 					break;
+				case SCTP_INCOMING_SSN_RESET_REQUEST_PARAMETER_TYPE:
+					if (parameter_item->flags & FLAG_RECONFIG_REQ_SN_NOCHECK) {
+						asprintf(error,
+							 "reqsn value must be specified for inbound packets");
+						return NULL;
+					}
+					break;
 				case SCTP_SSN_TSN_RESET_REQUEST_PARAMETER_TYPE:
 					if (parameter_item->flags & FLAG_RECONFIG_REQ_SN_NOCHECK) {
 						asprintf(error,
diff --git a/gtests/net/packetdrill/sctp_packet.h b/gtests/net/packetdrill/sctp_packet.h
index d8d29b24..515901b0 100644
--- a/gtests/net/packetdrill/sctp_packet.h
+++ b/gtests/net/packetdrill/sctp_packet.h
@@ -383,6 +383,9 @@ sctp_pad_parameter_new(s64 len, u8 *padding);
 struct sctp_parameter_list_item *
 sctp_outgoing_ssn_reset_request_parameter_new(s64 reqsn, s64 respsn, s64 last_tsn, struct sctp_u16_list *sids);
 
+struct sctp_parameter_list_item *
+sctp_incoming_ssn_reset_request_parameter_new(s64 reqsn, struct sctp_u16_list *sids);
+
 struct sctp_parameter_list_item *
 sctp_ssn_tsn_reset_request_parameter_new(s64 reqsn);
 
-- 
GitLab