From 8e39ad2daa47eb378a4907abc5e3079453bf2a22 Mon Sep 17 00:00:00 2001
From: hoelscher <jens.hoelscher@fh-muenster.de>
Date: Sat, 28 Nov 2015 01:11:13 +0100
Subject: [PATCH] add support for socketoption SCTP_SET_PEER_PRIMARY_ADDR, test
 does not work

---
 gtests/net/packetdrill/lexer.l                |  2 ++
 gtests/net/packetdrill/parser.y               | 20 ++++++++++-
 gtests/net/packetdrill/run_system_call.c      | 18 +++++++++-
 gtests/net/packetdrill/script.c               | 35 +++++++++++++++++++
 gtests/net/packetdrill/script.h               |  8 +++++
 gtests/net/packetdrill/symbols_freebsd.c      |  1 +
 .../getsockopt/sctp_set_peer_primary_addr.pkt |  9 +++--
 7 files changed, 89 insertions(+), 4 deletions(-)

diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l
index 9f07914d..5ab6e90f 100644
--- a/gtests/net/packetdrill/lexer.l
+++ b/gtests/net/packetdrill/lexer.l
@@ -387,6 +387,8 @@ gaids_assoc_id			return GAIDS_ASSOC_ID;
 gauth_assoc_id			return GAUTH_ASSOC_ID;
 gauth_number_of_chunks		return GAUTH_NUMBER_OF_CHUNKS;
 gauth_chunks			return GAUTH_CHUNKS;
+sspp_assoc_id			return SSPP_ASSOC_ID;
+sspp_addr			return SSPP_ADDR;
 CHUNK				return CHUNK;
 DATA				return DATA;
 INIT				return INIT;
diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index 6a6f2deb..c4fc0704 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -564,7 +564,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %token <reserved> SPC_TYPE SPC_FLAGS SPC_LENGTH SPC_AADDR SPC_STATE SPC_ERROR SPC_ASSOC_ID
 %token <reserved> SSF_TYPE SSF_LENGTH SSF_FLAGS SSF_ERROR SSF_INFO SSF_ASSOC_ID SSF_DATA
 %token <reserved> SAI_TYPE SAI_FLAGS SAI_LENGTH SAI_ADAPTATION_IND SAI_ASSOC_ID
-%token <reserved> GAIDS_NUMBER_OF_IDS GAIDS_ASSOC_ID
+%token <reserved> GAIDS_NUMBER_OF_IDS GAIDS_ASSOC_ID SSPP_ASSOC_ID SSPP_ADDR
 %token <reserved> SN_TYPE SN_FLAGS SN_LENGTH
 %token <floating> FLOAT
 %token <integer> INTEGER HEX_INTEGER
@@ -638,6 +638,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %type <expression> sctp_send_failed ssf_type ssf_length ssf_flags ssf_error ssf_info ssf_data
 %type <expression> sctp_adaptation_event sai_type sai_flags sai_length sai_adaptation_ind
 %type <expression> sctp_tlv sn_type sn_flags sn_length sctp_assoc_ids gaids_number_of_ids
+%type <expression> sctp_setpeerprim 
 %type <errno_info> opt_errno
 %type <chunk_list> sctp_chunk_list_spec
 %type <chunk_list_item> sctp_chunk_spec
@@ -2555,6 +2556,9 @@ expression
 | sctp_authchunks   {
 	$$ = $1;
 }
+| sctp_setpeerprim  {
+	$$ = $1;
+}
 | null              {
 	$$ = $1;
 }
@@ -4815,6 +4819,20 @@ sctp_authchunks
 	$$->value.sctp_authchunks->gauth_chunks = $6;
 };
 
+sctp_setpeerprim
+: '{' SSPP_ASSOC_ID '=' sctp_assoc_id ',' SSPP_ADDR '=' sockaddr '}' {
+	$$ = new_expression(EXPR_SCTP_SETPEERPRIM);
+	$$->value.sctp_setpeerprim = calloc(1, sizeof(struct sctp_setpeerprim_expr));
+	$$->value.sctp_setpeerprim->sspp_assoc_id = $4;
+	$$->value.sctp_setpeerprim->sspp_addr = $8;
+}
+| '{' SSPP_ADDR '=' sockaddr '}' {
+	$$ = new_expression(EXPR_SCTP_SETPEERPRIM);
+	$$->value.sctp_setpeerprim = calloc(1, sizeof(struct sctp_setpeerprim_expr));
+	$$->value.sctp_setpeerprim->sspp_assoc_id = new_expression(EXPR_ELLIPSIS);
+	$$->value.sctp_setpeerprim->sspp_addr = $4;
+};
+
 opt_errno
 :                   { $$ = NULL; }
 | WORD note         {
diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c
index 780c4155..954b0c5b 100644
--- a/gtests/net/packetdrill/run_system_call.c
+++ b/gtests/net/packetdrill/run_system_call.c
@@ -495,7 +495,7 @@ static int ellipsis_arg(struct expression_list *args, int index, char **error)
 	return STATUS_OK;
 }
 
-#if defined(SCTP_GET_PEER_ADDR_INFO) || defined(SCTP_PEER_ADDR_PARAMS)
+#if defined(SCTP_GET_PEER_ADDR_INFO) || defined(SCTP_PEER_ADDR_PARAMS) || defined(SCTP_SET_PEER_PRIMARY_ADDR)
 /* Return STATUS_OK if the argument in from type sockaddr_in or
  * sockaddr_in6
  */
@@ -3513,6 +3513,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 #ifdef SCTP_ADAPTATION_LAYER
 	struct sctp_setadaptation setadaptation;
 #endif
+#ifdef SCTP_SET_PEER_PRIMARY_ADDR
+	struct sctp_setpeerprim setpeerprim;
+#endif
 #ifdef SCTP_PEER_ADDR_PARAMS
 	struct sctp_paddrparams paddrparams;
 #ifdef linux
@@ -3863,6 +3866,19 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 		optval = &setadaptation;
 		break;
 #endif
+#ifdef SCTP_SET_PEER_PRIMARY_ADDR
+	case EXPR_SCTP_SETPEERPRIM:
+		if (get_sctp_assoc_t(val_expression->value.sctp_setpeerprim->sspp_assoc_id,
+				     &setpeerprim.sspp_assoc_id, error)) {
+			return STATUS_ERR;
+		}
+		if (get_sockstorage_arg(val_expression->value.sctp_setpeerprim->sspp_addr,
+		    		&setpeerprim.sspp_addr, live_fd)) {
+			return STATUS_ERR;
+		}
+		optval = &setpeerprim;
+		break;
+#endif
 #ifdef SCTP_PEER_ADDR_PARAMS
 	case EXPR_SCTP_PEER_ADDR_PARAMS:
 		if (get_sctp_assoc_t(val_expression->value.sctp_paddrparams->spp_assoc_id,
diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c
index 41744e15..ee105cb9 100644
--- a/gtests/net/packetdrill/script.c
+++ b/gtests/net/packetdrill/script.c
@@ -105,6 +105,7 @@ struct expression_type_entry expression_type_table[] = {
 	{ EXPR_SCTP_EXTRCVINFO,      "sctp_extrcvinfo" },
 	{ EXPR_SCTP_ASSOC_IDS,       "sctp_assoc_ids"  },
 	{ EXPR_SCTP_AUTHCHUNKS,      "sctp_authchunks" },
+	{ EXPR_SCTP_SETPEERPRIM,     "sctp_setpeerprim"},
 	{ NUM_EXPR_TYPES,            NULL}
 };
 
@@ -591,6 +592,10 @@ void free_expression(struct expression *expression)
 		free_expression(expression->value.sctp_authchunks->gauth_number_of_chunks);
 		free_expression(expression->value.sctp_authchunks->gauth_chunks);
 		break;
+	case EXPR_SCTP_SETPEERPRIM:
+		free_expression(expression->value.sctp_setpeerprim->sspp_assoc_id);
+		free_expression(expression->value.sctp_setpeerprim->sspp_addr);
+		break;
 	case EXPR_WORD:
 		assert(expression->value.string);
 		free(expression->value.string);
@@ -2316,6 +2321,33 @@ static int evaluate_sctp_authchunks_expression(struct expression *in,
 	return STATUS_OK;
 }
 
+static int evaluate_sctp_setpeerprim_expression(struct expression *in,
+					        struct expression *out,
+					        char **error)
+{
+	struct sctp_setpeerprim_expr *in_sspp;
+	struct sctp_setpeerprim_expr *out_sspp;
+
+	assert(in->type == EXPR_SCTP_SETPEERPRIM);
+	assert(in->value.sctp_setpeerprim);
+	assert(out->type == EXPR_SCTP_SETPEERPRIM);
+
+	out->value.sctp_setpeerprim = calloc(1, sizeof(struct sctp_setpeerprim_expr));
+
+	in_sspp = in->value.sctp_setpeerprim;
+	out_sspp = out->value.sctp_setpeerprim;
+
+	if (evaluate(in_sspp->sspp_assoc_id,
+		     &out_sspp->sspp_assoc_id,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_sspp->sspp_addr,
+		     &out_sspp->sspp_addr,
+		     error))
+		return STATUS_ERR;
+	return STATUS_OK;
+}
+
 static int evaluate(struct expression *in,
 		    struct expression **out_ptr, char **error)
 {
@@ -2455,6 +2487,9 @@ static int evaluate(struct expression *in,
 	case EXPR_SCTP_AUTHCHUNKS:
 		result = evaluate_sctp_authchunks_expression(in, out, error);
 		break;
+	case EXPR_SCTP_SETPEERPRIM:
+		result = evaluate_sctp_setpeerprim_expression(in, out, error);
+		break;
 	case EXPR_WORD:
 		out->type = EXPR_INTEGER;
 		if (symbol_to_int(in->value.string,
diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h
index 1913bef6..36a70bfd 100644
--- a/gtests/net/packetdrill/script.h
+++ b/gtests/net/packetdrill/script.h
@@ -85,6 +85,7 @@ enum expression_t {
 	EXPR_SCTP_EXTRCVINFO,     /* expression tree for sctp_extrcvinfo struct in cmsghdr */
 	EXPR_SCTP_ASSOC_IDS,      /* expression tree for sctp_assoc_ids struct for [gs]etsockopt */
 	EXPR_SCTP_AUTHCHUNKS,     /* expression tree for sctp_authchunks struct for [gs]etsockopt */
+	EXPR_SCTP_SETPEERPRIM,    /* expression tree for sctp_setpeerprim struct for [gs]etsockopt */
 	NUM_EXPR_TYPES,
 };
 /* Convert an expression type to a human-readable string */
@@ -143,6 +144,7 @@ struct expression {
 		struct sctp_extrcvinfo_expr *sctp_extrcvinfo;
 		struct sctp_assoc_ids_expr *sctp_assoc_ids;
 		struct sctp_authchunks_expr *sctp_authchunks;
+		struct sctp_setpeerprim_expr *sctp_setpeerprim;
 	} value;
 	const char *format;	/* the printf format for printing the value */
 };
@@ -540,6 +542,12 @@ struct sctp_authchunks_expr {
 	struct expression *gauth_chunks;
 };
 
+/* Parse tree for sctp_setpeerprim struct for [gs]etsockopt. */
+struct sctp_setpeerprim_expr {
+	struct expression *sspp_assoc_id;
+	struct expression *sspp_addr;
+};
+
 /* The errno-related info from strace to summarize a system call error */
 struct errno_spec {
 	const char *errno_macro;	/* errno symbol (C macro name) */
diff --git a/gtests/net/packetdrill/symbols_freebsd.c b/gtests/net/packetdrill/symbols_freebsd.c
index de6b5e95..367564b2 100644
--- a/gtests/net/packetdrill/symbols_freebsd.c
+++ b/gtests/net/packetdrill/symbols_freebsd.c
@@ -111,6 +111,7 @@ struct int_symbol platform_symbols_table[] = {
 	{ SCTP_LOCAL_AUTH_CHUNKS,           "SCTP_LOCAL_AUTH_CHUNKS"          },
 	{ SCTP_GET_ASSOC_NUMBER,            "SCTP_GET_ASSOC_NUMBER"           },
 	{ SCTP_GET_ASSOC_ID_LIST,           "SCTP_GET_ASSOC_ID_LIST"          },
+	{ SCTP_SET_PEER_PRIMARY_ADDR,       "SCTP_SET_PEER_PRIMARY_ADDR"      },
 	{ SCTP_AUTH_CHUNK,                  "SCTP_AUTH_CHUNK"                 },
 	{ SCTP_AUTH_KEY,                    "SCTP_AUTH_KEY"                   },
 	{ SCTP_AUTH_DEACTIVATE_KEY,         "SCTP_AUTH_DEACTIVATE_KEY"        },
diff --git a/gtests/net/packetdrill/tests/bsd/sctp/api_tests/getsockopt/sctp_set_peer_primary_addr.pkt b/gtests/net/packetdrill/tests/bsd/sctp/api_tests/getsockopt/sctp_set_peer_primary_addr.pkt
index 71340f99..4a3e7b88 100644
--- a/gtests/net/packetdrill/tests/bsd/sctp/api_tests/getsockopt/sctp_set_peer_primary_addr.pkt
+++ b/gtests/net/packetdrill/tests/bsd/sctp/api_tests/getsockopt/sctp_set_peer_primary_addr.pkt
@@ -10,7 +10,12 @@
 
 +0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
 
-+0 setsockopt(3, IPPROTO_SCTP, SCTP_SET_PEER_PRIMARY_ADDR, {sspp_assoc_id=..., sspp={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")},}, 20) = 0
-+0 setsockopt(3, IPPROTO_SCTP, SCTP_SET_PEER_PRIMARY_ADDR, {sspp={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")},}, 20) = 0
++0 setsockopt(3, IPPROTO_SCTP, SCTP_SET_PEER_PRIMARY_ADDR, {sspp_addr={sa_family=AF_INET,
+								       sin_port=htons(8080),
+								       sin_addr=inet_addr("192.0.2.1")}}, 136) = 0
++0 setsockopt(3, IPPROTO_SCTP, SCTP_SET_PEER_PRIMARY_ADDR, {sspp_assoc_id=...,
+							    sspp_addr={sa_family=AF_INET,
+								       sin_port=htons(8080),
+								       sin_addr=inet_addr("192.0.2.1")}}, 136) = 0
 
 +0 close(3) = 0
-- 
GitLab