From e7595f2d19565586deb788a8390c1780b9ac0172 Mon Sep 17 00:00:00 2001
From: hoelscher <jens.hoelscher@fh-muenster.de>
Date: Fri, 27 Nov 2015 16:35:14 +0100
Subject: [PATCH] add support for socketoption sctp_auth_active_key

---
 gtests/net/packetdrill/lexer.l                |  2 +
 gtests/net/packetdrill/parser.y               | 29 ++++++++++-
 gtests/net/packetdrill/run_system_call.c      | 49 +++++++++++++++++++
 gtests/net/packetdrill/script.c               | 36 ++++++++++++++
 gtests/net/packetdrill/script.h               |  8 +++
 gtests/net/packetdrill/symbols_freebsd.c      |  1 +
 .../getsockopt/sctp_auth_active_key.pkt       |  9 ++--
 .../getsockopt/sctp_fragment_interleave.pkt   |  2 +-
 .../tests/bsd/sctp/api_tests/run-all-tests    |  1 +
 9 files changed, 130 insertions(+), 7 deletions(-)

diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l
index 41035ebd..63e848bf 100644
--- a/gtests/net/packetdrill/lexer.l
+++ b/gtests/net/packetdrill/lexer.l
@@ -214,6 +214,8 @@ assoc_id			return ASSOC_ID;
 assoc_value			return ASSOC_VALUE;
 stream_id			return STREAM_ID;
 stream_value			return STREAM_VALUE;
+scact_assoc_id			return SCACT_ASSOC_ID;
+scact_keynumber			return SCACT_KEYNUMBER;
 sack_assoc_id			return SACK_ASSOC_ID;
 sack_delay			return SACK_DELAY;
 sack_freq			return SACK_FREQ;
diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index 569c9be5..932fbf70 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -508,7 +508,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %token <reserved> SINIT_MAX_INIT_TIMEO
 %token <reserved> ASSOC_ID ASSOC_VALUE
 %token <reserved> STREAM_ID STREAM_VALUE
-%token <reserved> SACK_ASSOC_ID SACK_DELAY SACK_FREQ
+%token <reserved> SCACT_ASSOC_ID SCACT_KEYNUMBER SACK_ASSOC_ID SACK_DELAY SACK_FREQ
 %token <reserved> SSTAT_ASSOC_ID SSTAT_STATE SSTAT_RWND SSTAT_UNACKDATA SSTAT_PENDDATA
 %token <reserved> SSTAT_INSTRMS SSTAT_OUTSTRMS SSTAT_FRAGMENTATION_POINT
 %token <reserved> SSTAT_PRIMARY
@@ -607,7 +607,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %type <expression> sstat_instrms sstat_outstrms sstat_fragmentation_point sstat_primary
 %type <expression> sctp_initmsg sinit_num_ostreams sinit_max_instreams sinit_max_attempts
 %type <expression> sinit_max_init_timeo sctp_assoc_value sctp_stream_value
-%type <expression> sctp_sackinfo sack_delay sack_freq
+%type <expression> sctp_authkeyid scact_keynumber sctp_sackinfo sack_delay sack_freq
 %type <expression> sctp_rtoinfo srto_initial srto_max srto_min sctp_paddrinfo
 %type <expression> sctp_paddrparams spp_address spp_hbinterval spp_pathmtu spp_pathmaxrxt
 %type <expression> spp_flags spp_ipv6_flowlabel spp_dscp ssp_addr
@@ -2486,6 +2486,9 @@ expression
 | sctp_stream_value  {
 	$$ = $1;
 }
+| sctp_authkeyid    {
+	$$ = $1;
+}
 | sctp_sackinfo     {
 	$$ = $1;
 }
@@ -2911,6 +2914,28 @@ sctp_assoc_value
 	$$->value.sctp_assoc_value->assoc_value = $4;
 }
 ;
+scact_keynumber
+: SCACT_KEYNUMBER '=' INTEGER {
+	if (!is_valid_u16($3)) {
+		semantic_error("scact_keynumber out of range");
+	}
+	$$ = new_integer_expression($3, "%hu");
+}
+| SCACT_KEYNUMBER '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+
+sctp_authkeyid
+: '{' SCACT_ASSOC_ID '=' sctp_assoc_id ',' scact_keynumber '}' {
+	$$ = new_expression(EXPR_SCTP_AUTHKEYID);
+	$$->value.sctp_authkeyid = calloc(1, sizeof(struct sctp_authkeyid_expr));
+	$$->value.sctp_authkeyid->scact_assoc_id = $4;
+	$$->value.sctp_authkeyid->scact_keynumber = $6;
+}
+| '{' scact_keynumber '}'{ 
+	$$ = new_expression(EXPR_SCTP_AUTHKEYID);
+	$$->value.sctp_authkeyid = calloc(1, sizeof(struct sctp_authkeyid_expr));
+	$$->value.sctp_authkeyid->scact_assoc_id = new_expression(EXPR_ELLIPSIS);
+	$$->value.sctp_authkeyid->scact_keynumber = $2;
+}
 
 sack_delay
 : SACK_DELAY '=' INTEGER {
diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c
index 011dd62c..724ea1a5 100644
--- a/gtests/net/packetdrill/run_system_call.c
+++ b/gtests/net/packetdrill/run_system_call.c
@@ -2568,6 +2568,22 @@ static int check_sctp_initmsg(struct sctp_initmsg_expr *expr,
 }
 #endif
 
+#ifdef SCTP_AUTH_ACTIVE_KEY
+static int check_sctp_authkeyid(struct sctp_authkeyid_expr *expr,
+				struct sctp_authkeyid *sctp_authkeyid,
+				char **error)
+{
+	if (check_sctp_assoc_t_expr(expr->scact_assoc_id, sctp_authkeyid->scact_assoc_id,
+			 	    "sctp_authkeyid.scact_assoc_id", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->scact_keynumber, sctp_authkeyid->scact_keynumber,
+			   "sctp_authkeyid.scact_keynumber", error))
+		return STATUS_ERR;
+
+	return STATUS_OK;
+}
+#endif
+
 #ifdef SCTP_DELAYED_SACK
 static int check_sctp_sack_info(struct sctp_sack_info_expr *expr,
 				struct sctp_sack_info *sctp_sack_info,
@@ -2969,6 +2985,18 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 		live_optlen = (socklen_t)sizeof(struct sctp_initmsg);
 		break;
 #endif
+#ifdef SCTP_AUTH_ACTIVE_KEY
+	case EXPR_SCTP_AUTHKEYID:
+		live_optval = malloc(sizeof(struct sctp_authkeyid));
+		live_optlen = (socklen_t)sizeof(struct sctp_authkeyid);
+		if (get_sctp_assoc_t(val_expression->value.sctp_authkeyid->scact_assoc_id,
+				    &((struct sctp_authkeyid*) live_optval)->scact_assoc_id,
+				    error)) {
+			free(live_optval);
+			return STATUS_ERR;
+		}
+		break;
+#endif
 #ifdef SCTP_DELAYED_SACK
 	case EXPR_SCTP_SACKINFO:
 		live_optval = malloc(sizeof(struct sctp_sack_info));
@@ -3174,6 +3202,11 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 		result = check_sctp_initmsg(val_expression->value.sctp_initmsg, live_optval, error);
 		break;
 #endif
+#ifdef SCTP_AUTH_ACTIVE_KEY
+	case EXPR_SCTP_AUTHKEYID:
+		result = check_sctp_authkeyid(val_expression->value.sctp_authkeyid, live_optval, error);
+		break;
+#endif
 #ifdef SCTP_DELAYED_SACK
 	case EXPR_SCTP_SACKINFO:
 		result = check_sctp_sack_info(val_expression->value.sctp_sack_info, live_optval, error);
@@ -3269,6 +3302,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 #if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED)
 	struct sctp_assoc_value assoc_value;
 #endif
+#ifdef SCTP_AUTH_ACTIVE_KEY
+	struct sctp_authkeyid authkeyid;
+#endif
 #ifdef SCTP_DELAYED_SACK
 	struct sctp_sack_info sack_info;
 #endif
@@ -3423,6 +3459,19 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 		optval = &stream_value;
 		break;
 #endif
+#ifdef SCTP_AUTH_ACTIVE_KEY
+	case EXPR_SCTP_AUTHKEYID:
+		if (get_sctp_assoc_t(val_expression->value.sctp_authkeyid->scact_assoc_id,
+				    &authkeyid.scact_assoc_id, error)) {
+			return STATUS_ERR;
+		}
+		if (get_u16(val_expression->value.sctp_authkeyid->scact_keynumber,
+			    &authkeyid.scact_keynumber, error)) {
+			return STATUS_ERR;
+		}
+		optval = &authkeyid;
+		break;
+#endif
 #ifdef SCTP_DELAYED_SACK
 	case EXPR_SCTP_SACKINFO:
 		if (get_sctp_assoc_t(val_expression->value.sctp_sack_info->sack_assoc_id,
diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c
index e51c89f6..30a5d678 100644
--- a/gtests/net/packetdrill/script.c
+++ b/gtests/net/packetdrill/script.c
@@ -70,6 +70,7 @@ struct expression_type_entry expression_type_table[] = {
 	{ EXPR_SCTP_RTOINFO,         "sctp_rtoinfo"},
 	{ EXPR_SCTP_INITMSG,         "sctp_initmsg"},
 	{ EXPR_SCTP_ASSOC_VALUE,     "sctp_assoc_value"},
+	{ EXPR_SCTP_AUTHKEYID,       "sctp_authkeyid"},
 	{ EXPR_SCTP_SACKINFO,        "sctp_sackinfo"},
 	{ EXPR_SCTP_STATUS,          "sctp_status"},
 	{ EXPR_SCTP_PADDRINFO,	     "sctp_paddrinfo"},
@@ -332,6 +333,11 @@ void free_expression(struct expression *expression)
 		free_expression(expression->value.sctp_initmsg->sinit_max_attempts);
 		free_expression(expression->value.sctp_initmsg->sinit_max_init_timeo);
 		break;
+	case EXPR_SCTP_AUTHKEYID:
+		assert(expression->value.sctp_authkeyid);
+		free_expression(expression->value.sctp_authkeyid->scact_assoc_id);
+		free_expression(expression->value.sctp_authkeyid->scact_keynumber);
+		break;
 	case EXPR_SCTP_SACKINFO:
 		assert(expression->value.sctp_sack_info);
 		free_expression(expression->value.sctp_sack_info->sack_assoc_id);
@@ -890,6 +896,33 @@ static int evaluate_sctp_assoc_value_expression(struct expression *in,
 	return STATUS_OK;
 }
 
+static int evaluate_sctp_authkeyid_expression(struct expression *in,
+					      struct expression *out,
+					      char **error)
+{
+	struct sctp_authkeyid_expr *in_authkeyid;
+	struct sctp_authkeyid_expr *out_authkeyid;
+
+	assert(in->type == EXPR_SCTP_AUTHKEYID);
+	assert(in->value.sctp_authkeyid);
+	assert(out->type == EXPR_SCTP_AUTHKEYID);
+
+	out->value.sctp_authkeyid = calloc(1, sizeof(struct sctp_authkeyid_expr));
+
+	in_authkeyid = in->value.sctp_authkeyid;
+	out_authkeyid = out->value.sctp_authkeyid;
+
+	if (evaluate(in_authkeyid->scact_assoc_id,
+		     &out_authkeyid->scact_assoc_id,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_authkeyid->scact_keynumber,
+		     &out_authkeyid->scact_keynumber,
+		     error))
+		return STATUS_ERR;
+	return STATUS_OK;
+}
+
 static int evaluate_sctp_sack_info_expression(struct expression *in,
 					    struct expression *out,
 					    char **error)
@@ -2217,6 +2250,9 @@ static int evaluate(struct expression *in,
 	case EXPR_SCTP_ASSOC_VALUE:
 		result = evaluate_sctp_assoc_value_expression(in, out, error);
 		break;
+	case EXPR_SCTP_AUTHKEYID:
+		result = evaluate_sctp_authkeyid_expression(in, out, error);	
+		break;
 	case EXPR_SCTP_SACKINFO:
 		result = evaluate_sctp_sack_info_expression(in, out, error);	
 		break;
diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h
index df4e1d76..c38efbeb 100644
--- a/gtests/net/packetdrill/script.h
+++ b/gtests/net/packetdrill/script.h
@@ -50,6 +50,7 @@ enum expression_t {
 	EXPR_SCTP_RTOINFO,	  /* struct sctp_rtoinfo for SCTP_RTOINFO */
 	EXPR_SCTP_INITMSG,	  /* struct sctp_initmsg for SCTP_INITMSG */
 	EXPR_SCTP_ASSOC_VALUE,	  /* struct sctp_assoc_value */
+	EXPR_SCTP_AUTHKEYID,      /* expression tree for sctp_authkeyid struct for [gs]etsockopt */
 	EXPR_SCTP_SACKINFO,	  /* struct sctp_sack_info_expr for */
 	EXPR_SCTP_STATUS,	  /* struct sctp_status for SCTP_STATUS */
 	EXPR_SCTP_PADDRINFO,
@@ -104,6 +105,7 @@ struct expression {
 		struct sctp_rtoinfo_expr *sctp_rtoinfo;
 		struct sctp_initmsg_expr *sctp_initmsg;
 		struct sctp_assoc_value_expr *sctp_assoc_value;
+		struct sctp_authkeyid_expr *sctp_authkeyid;
 		struct sctp_sack_info_expr *sctp_sack_info;
 		struct sctp_status_expr *sctp_status;
 		struct sctp_paddrinfo_expr *sctp_paddrinfo;
@@ -220,6 +222,12 @@ struct sctp_stream_value_expr {
 	struct expression *stream_value;
 };
 
+/* Parse tree for a sctp_authkey struct in a [gs]etsockopt syscall. */
+struct sctp_authkeyid_expr {
+	struct expression *scact_assoc_id;
+	struct expression *scact_keynumber;
+};
+
 /* Parse tree for a sctp_sack_info struct in a [gs]etsockopt syscall. */
 struct sctp_sack_info_expr {
 	struct expression *sack_assoc_id;
diff --git a/gtests/net/packetdrill/symbols_freebsd.c b/gtests/net/packetdrill/symbols_freebsd.c
index 4f4f2c17..98eb97b5 100644
--- a/gtests/net/packetdrill/symbols_freebsd.c
+++ b/gtests/net/packetdrill/symbols_freebsd.c
@@ -87,6 +87,7 @@ struct int_symbol platform_symbols_table[] = {
 	{ SCTP_PRIMARY_ADDR,                "SCTP_PRIMARY_ADDR"               },
 	{ SCTP_ADAPTATION_LAYER,            "SCTP_ADAPTATION_LAYER"           },
 	{ SCTP_MAXSEG,                      "SCTP_MAXSEG"                     },
+	{ SCTP_AUTH_ACTIVE_KEY,             "SCTP_AUTH_ACTIVE_KEY"            },
 	{ SCTP_DELAYED_SACK,                "SCTP_DELAYED_SACK"               },
 	{ SCTP_MAX_BURST,                   "SCTP_MAX_BURST"                  },
 	{ SCTP_PEER_ADDR_PARAMS,            "SCTP_PEER_ADDR_PARAMS"           },
diff --git a/gtests/net/packetdrill/tests/bsd/sctp/api_tests/getsockopt/sctp_auth_active_key.pkt b/gtests/net/packetdrill/tests/bsd/sctp/api_tests/getsockopt/sctp_auth_active_key.pkt
index e9647e1c..9974a36f 100644
--- a/gtests/net/packetdrill/tests/bsd/sctp/api_tests/getsockopt/sctp_auth_active_key.pkt
+++ b/gtests/net/packetdrill/tests/bsd/sctp/api_tests/getsockopt/sctp_auth_active_key.pkt
@@ -10,10 +10,11 @@
 
 +0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
 
-+0 setsockopt(3, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, {scact_assoc_id=0, scact_keynumber=123}, 6) = 0
-+0 getsockopt(3, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, {scact_assoc_id=0, scact_keynumber=123}, [6]) = 0
++0 getsockopt(3, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, {scact_assoc_id=0, scact_keynumber=0}, [8]) = 0
++0 setsockopt(3, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, {scact_assoc_id=0, scact_keynumber=0}, 8) = 0
++0 getsockopt(3, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, {scact_assoc_id=0, scact_keynumber=0}, [8]) = 0
 
-+0 setsockopt(3, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, {scact_keynumber=123}, 6) = 0
-+0 getsockopt(3, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, {scact_keynumber=123}, [6]) = 0
++0 setsockopt(3, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, {scact_keynumber=1}, 8) = 0
++0 getsockopt(3, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, {scact_keynumber=1}, [8]) = 0
 
 +0 close(3) = 0
diff --git a/gtests/net/packetdrill/tests/bsd/sctp/api_tests/getsockopt/sctp_fragment_interleave.pkt b/gtests/net/packetdrill/tests/bsd/sctp/api_tests/getsockopt/sctp_fragment_interleave.pkt
index 9dcafc62..f8a8f2da 100644
--- a/gtests/net/packetdrill/tests/bsd/sctp/api_tests/getsockopt/sctp_fragment_interleave.pkt
+++ b/gtests/net/packetdrill/tests/bsd/sctp/api_tests/getsockopt/sctp_fragment_interleave.pkt
@@ -10,7 +10,7 @@
 
 +0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
 
-+0 getsockopt(3, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, [0], [4]) = 0
++0 getsockopt(3, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, [1], [4]) = 0
 +0 setsockopt(3, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, [2], 4) = 0
 +0 getsockopt(3, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, [2], [4]) = 0
 
diff --git a/gtests/net/packetdrill/tests/bsd/sctp/api_tests/run-all-tests b/gtests/net/packetdrill/tests/bsd/sctp/api_tests/run-all-tests
index c5374c08..c2290936 100755
--- a/gtests/net/packetdrill/tests/bsd/sctp/api_tests/run-all-tests
+++ b/gtests/net/packetdrill/tests/bsd/sctp/api_tests/run-all-tests
@@ -127,6 +127,7 @@ set testcases = (setsockopt/sctp_rtoinfo_1 \
 		 sctp_recvmsg/sctp_recvmsg_1 \
 		 sctp_recvmsg/sctp_recvmsg_2 \
 		 sctp_recvmsg/sctp_recvmsg_3 \
+		 sctp_connectx/sctp_connectx \
 		 sctp_recvv/sctp_recvv_1 \
 		 sctp_recvv/sctp_recvv_2 \
 		 sctp_recvv/sctp_recvv_3 \
-- 
GitLab