From c56350a6a70d6a10b40695555b511160b3084cbf Mon Sep 17 00:00:00 2001
From: Michael Tuexen <tuexen@fh-muenster.de>
Date: Mon, 12 Oct 2015 00:28:52 +0200
Subject: [PATCH] Add some infrastructure to support explicit vtags.

This is not working yet.
---
 gtests/net/packetdrill/packet.h      |  1 +
 gtests/net/packetdrill/parser.y      | 40 ++++++++++++++++++++++++++--
 gtests/net/packetdrill/run_packet.c  |  2 +-
 gtests/net/packetdrill/sctp_packet.c |  6 ++++-
 gtests/net/packetdrill/sctp_packet.h |  1 +
 5 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/gtests/net/packetdrill/packet.h b/gtests/net/packetdrill/packet.h
index 832f6125..8e931ec2 100644
--- a/gtests/net/packetdrill/packet.h
+++ b/gtests/net/packetdrill/packet.h
@@ -109,6 +109,7 @@ struct packet {
 #define FLAG_WIN_NOCHECK	0x1  /* don't check TCP receive window */
 #define FLAG_OPTIONS_NOCHECK	0x2  /* don't check TCP options */
 #define FLAGS_SCTP_BAD_CRC32C   0x4  /* compute bad CRC32C for SCTP packets */
+#define FLAGS_SCTP_EXPLICIT_TAG 0x8  /* verification tag specified */
 
 	enum ip_ecn_t ecn;	/* IPv4/IPv6 ECN treatment for packet */
 
diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index bb2fb56b..7df5a638 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -821,7 +821,7 @@ sctp_packet_spec
 	enum direction_t direction = outer->direction;
 
 	inner = new_sctp_packet(in_config->wire_protocol, direction, $2,
-	                        false, $5, &error);
+	                        -1, false, $5, &error);
 	if (inner == NULL) {
 		assert(error != NULL);
 		semantic_error(error);
@@ -836,7 +836,43 @@ sctp_packet_spec
 	enum direction_t direction = outer->direction;
 
 	inner = new_sctp_packet(in_config->wire_protocol, direction, $2,
-	                        true, $8, &error);
+	                        -1, true, $8, &error);
+	if (inner == NULL) {
+		assert(error != NULL);
+		semantic_error(error);
+		free(error);
+	}
+
+	$$ = packet_encapsulate_and_free(outer, inner);
+}
+| packet_prefix opt_ip_info SCTP '(' TAG '=' INTEGER ')' ':' sctp_chunk_list_spec {
+	char *error = NULL;
+	struct packet *outer = $1, *inner = NULL;
+	enum direction_t direction = outer->direction;
+
+	if (!is_valid_u32($7)) {
+		semantic_error("tag value out of range");
+	}
+	inner = new_sctp_packet(in_config->wire_protocol, direction, $2,
+	                        $7, false, $10, &error);
+	if (inner == NULL) {
+		assert(error != NULL);
+		semantic_error(error);
+		free(error);
+	}
+
+	$$ = packet_encapsulate_and_free(outer, inner);
+}
+| packet_prefix opt_ip_info SCTP '(' BAD_CRC32C ',' TAG '=' INTEGER ')' ':' sctp_chunk_list_spec {
+	char *error = NULL;
+	struct packet *outer = $1, *inner = NULL;
+	enum direction_t direction = outer->direction;
+
+	if (!is_valid_u32($9)) {
+		semantic_error("tag value out of range");
+	}
+	inner = new_sctp_packet(in_config->wire_protocol, direction, $2,
+	                        $9, true, $12, &error);
 	if (inner == NULL) {
 		assert(error != NULL);
 		semantic_error(error);
diff --git a/gtests/net/packetdrill/run_packet.c b/gtests/net/packetdrill/run_packet.c
index 45d44a1c..7dc504fd 100644
--- a/gtests/net/packetdrill/run_packet.c
+++ b/gtests/net/packetdrill/run_packet.c
@@ -2695,7 +2695,7 @@ int abort_association(struct state *state, struct socket *socket)
 	chunk_list = sctp_chunk_list_new();
 	sctp_chunk_list_append(chunk_list, sctp_abort_chunk_new(flgs, cause_list));
 	packet = new_sctp_packet(socket->address_family,
-				 DIRECTION_INBOUND, ECN_NONE, false,
+				 DIRECTION_INBOUND, ECN_NONE, -1, false,
 				 chunk_list, &error);
 	if (packet == NULL)
 		die("%s", error);
diff --git a/gtests/net/packetdrill/sctp_packet.c b/gtests/net/packetdrill/sctp_packet.c
index 2658b47d..48416d3b 100644
--- a/gtests/net/packetdrill/sctp_packet.c
+++ b/gtests/net/packetdrill/sctp_packet.c
@@ -2242,6 +2242,7 @@ struct packet *
 new_sctp_packet(int address_family,
                 enum direction_t direction,
                 enum ip_ecn_t ecn,
+                s64 tag,
                 bool bad_crc32c,
                 struct sctp_chunk_list *list,
                 char **error)
@@ -2512,6 +2513,9 @@ new_sctp_packet(int address_family,
 	if (bad_crc32c) {
 		packet->flags |= FLAGS_SCTP_BAD_CRC32C;
 	}
+	if (tag != -1) {
+		packet->flags |= FLAGS_SCTP_EXPLICIT_TAG;
+	}
 	packet->ecn = ecn;
 
 	/* Set IP header fields */
@@ -2528,7 +2532,7 @@ new_sctp_packet(int address_family,
 	/* Set SCTP header fields */
 	packet->sctp->src_port = htons(0);
 	packet->sctp->dst_port = htons(0);
-	packet->sctp->v_tag = htonl(0);
+	packet->sctp->v_tag = htonl((u32)tag);
 	packet->sctp->crc32c = htonl(0);
 
 	for (chunk_item = list->first;
diff --git a/gtests/net/packetdrill/sctp_packet.h b/gtests/net/packetdrill/sctp_packet.h
index ca0256b1..c32e8d9d 100644
--- a/gtests/net/packetdrill/sctp_packet.h
+++ b/gtests/net/packetdrill/sctp_packet.h
@@ -423,6 +423,7 @@ sctp_cause_list_free(struct sctp_cause_list *list);
 extern struct packet *new_sctp_packet(int address_family,
 				      enum direction_t direction,
 				      enum ip_ecn_t ecn,
+				      s64 tag,
 				      bool bad_crc32c,
 				      struct sctp_chunk_list *chunk_list,
 				      char **error);
-- 
GitLab