From c4d639700c95d5048b95a37c6e9bb9c4c3f420fc Mon Sep 17 00:00:00 2001
From: hoelscher <jens.hoelscher@fh-muenster.de>
Date: Thu, 26 Nov 2015 23:36:15 +0100
Subject: [PATCH] add sctp_default_prinfo for [gs]etsockopt syscall

---
 gtests/net/packetdrill/lexer.l                |  1 +
 gtests/net/packetdrill/parser.y               | 22 +++++-
 gtests/net/packetdrill/run_system_call.c      | 78 ++++++++++++++++++-
 gtests/net/packetdrill/script.c               | 41 ++++++++++
 gtests/net/packetdrill/script.h               |  9 +++
 gtests/net/packetdrill/symbols_freebsd.c      |  1 +
 .../bsd/sctp/sctp_get_socket_options.pkt      |  3 +
 7 files changed, 149 insertions(+), 6 deletions(-)

diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l
index 2476987f..9d0f8866 100644
--- a/gtests/net/packetdrill/lexer.l
+++ b/gtests/net/packetdrill/lexer.l
@@ -291,6 +291,7 @@ serinfo_next_length             return SERINFO_NEXT_LENGTH;
 serinfo_next_ppid		return SERINFO_NEXT_PPID;
 pr_policy			return PR_POLICY;
 pr_value			return PR_VALUE;
+pr_assoc_id                     return PR_ASSOC_ID;
 sendv_flags			return SENDV_FLAGS;
 sendv_sndinfo			return SENDV_SNDINFO;
 sendv_prinfo			return SENDV_PRINFO;
diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index 89cbf3c7..db0fd2cd 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -544,7 +544,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %token <reserved> SINFO_STREAM SINFO_SSN SINFO_FLAGS SINFO_PPID SINFO_CONTEXT SINFO_ASSOC_ID
 %token <reserved> SINFO_TIMETOLIVE SINFO_TSN SINFO_CUMTSN SINFO_PR_VALUE SERINFO_NEXT_FLAGS
 %token <reserved> SERINFO_NEXT_STREAM SERINFO_NEXT_AID SERINFO_NEXT_LENGTH SERINFO_NEXT_PPID
-%token <reserved> PR_POLICY PR_VALUE AUTH_KEYNUMBER SENDV_FLAGS SENDV_SNDINFO
+%token <reserved> PR_POLICY PR_VALUE PR_ASSOC_ID AUTH_KEYNUMBER SENDV_FLAGS SENDV_SNDINFO
 %token <reserved> SENDV_PRINFO SENDV_AUTHINFO
 %token <reserved> RCV_SID RCV_SSN RCV_FLAGS RCV_PPID RCV_TSN RCV_CUMTSN RCV_CONTEXT RCV_ASSOC_ID
 %token <reserved> NXT_SID NXT_FLAGS NXT_PPID NXT_LENGTH NXT_ASSOC_ID
@@ -619,7 +619,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %type <expression> sctp_sndrcvinfo sinfo_stream sinfo_ssn sinfo_flags sinfo_ppid sinfo_context
 %type <expression> sinfo_timetolive sinfo_tsn sinfo_cumtsn sinfo_assoc_id sinfo_pr_value serinfo_next_flags
 %type <expression> serinfo_next_stream serinfo_next_aid serinfo_next_length serinfo_next_ppid sctp_extrcvinfo
-%type <expression> sctp_prinfo sctp_authinfo pr_policy sctp_sendv_spa
+%type <expression> sctp_prinfo sctp_authinfo pr_policy sctp_sendv_spa sctp_default_prinfo
 %type <expression> sctp_rcvinfo rcv_sid rcv_ssn rcv_flags rcv_ppid rcv_tsn rcv_cumtsn rcv_context rcv_assoc_id
 %type <expression> sctp_nxtinfo nxt_sid nxt_flags nxt_ppid nxt_length nxt_assoc_id sctp_recvv_rn
 %type <expression> sctp_shutdown_event sse_type sse_flags sse_length sse_assoc_id
@@ -2522,6 +2522,9 @@ expression
 | sctp_prinfo       {
 	$$ = $1;
 }
+|sctp_default_prinfo{
+	$$ = $1;
+}
 | sctp_authinfo     {
 	$$ = $1;
 }
@@ -3697,8 +3700,21 @@ pr_policy
 	$$ = new_integer_expression($3, "%hu");
 };
 
+sctp_default_prinfo
+: '{' pr_policy ',' PR_VALUE '=' INTEGER ',' PR_ASSOC_ID '=' expression'}' {
+	$$ = new_expression(EXPR_SCTP_DEFAULT_PRINFO);
+	$$->value.sctp_default_prinfo = calloc(1, sizeof(struct sctp_default_prinfo_expr));
+	$$->value.sctp_default_prinfo->pr_policy = $2;
+	if (!is_valid_u32($6)) {
+		semantic_error("pr_value out of range");
+	}
+	$$->value.sctp_default_prinfo->pr_value = new_integer_expression($6, "%u");
+	$$->value.sctp_default_prinfo->pr_assoc_id = $10;
+}
+;
+
 sctp_prinfo
-: '{' pr_policy ',' PR_VALUE '=' INTEGER'}' {
+: '{' pr_policy ',' PR_VALUE '=' INTEGER '}' {
 	$$ = new_expression(EXPR_SCTP_PRINFO);
 	$$->value.sctp_prinfo = calloc(1, sizeof(struct sctp_prinfo_expr));
 	$$->value.sctp_prinfo->pr_policy = $2;
diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c
index d5ce3c0d..40c26cb4 100644
--- a/gtests/net/packetdrill/run_system_call.c
+++ b/gtests/net/packetdrill/run_system_call.c
@@ -660,6 +660,23 @@ int check_u32_expr(struct expression *expr, u32 value, char *val_name, char **er
 	return STATUS_OK;
 }
 
+#if defined(__FreeBSD__) || defined(linux)
+int check_sctp_assoc_t_expr(struct expression *expr, sctp_assoc_t value, char *val_name, char **error) {
+	if (expr->type != EXPR_ELLIPSIS) {
+		sctp_assoc_t script_val;
+
+		if (get_sctp_assoc_t(expr, &script_val, error)) {
+			return STATUS_ERR;
+		}
+		if (script_val != value) {
+			asprintf(error, "%s: expected: %u actual: %u", val_name, script_val, value);
+			return STATUS_ERR;
+		}
+	}
+	return STATUS_OK;
+}
+#endif
+
 int check_socklen_t_expr(struct expression *expr, socklen_t value, char *val_name, char **error) {
 	if (expr->type != EXPR_ELLIPSIS) {
 		socklen_t script_val;
@@ -2509,8 +2526,8 @@ static int check_linger(struct linger_expr *expr,
 static int check_sctp_rtoinfo(struct sctp_rtoinfo_expr *expr,
 			      struct sctp_rtoinfo *sctp_rtoinfo, char **error)
 {
-	if (check_u32_expr(expr->srto_assoc_id, sctp_rtoinfo->srto_assoc_id,
-			   "sctp_rtoinfo.srto_assoc_id", error))
+	if (check_sctp_assoc_t_expr(expr->srto_assoc_id, sctp_rtoinfo->srto_assoc_id,
+				    "sctp_rtoinfo.srto_assoc_id", error))
 		return STATUS_ERR;
 	if (check_u32_expr(expr->srto_initial, sctp_rtoinfo->srto_initial,
 			   "sctp_rtoinfo.srto_initial", error))
@@ -2821,13 +2838,31 @@ static int check_sctp_sndinfo(struct sctp_sndinfo_expr *expr,
 	return STATUS_OK;
 }
 #endif
+#ifdef SCTP_DEFAULT_PRINFO
+static int check_sctp_default_prinfo(struct sctp_default_prinfo_expr *expr,
+				     struct sctp_default_prinfo *info,
+				     char **error)
+{
+	if (check_sctp_assoc_t_expr(expr->pr_assoc_id, info->pr_assoc_id,
+				   "sctp_default_prinfo.pr_assoc_id", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->pr_policy, info->pr_policy,
+			   "sctp_default_prinfo.pr_policy", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->pr_value, info->pr_value,
+			   "sctp_default_prinfo.pr_value", error))
+		return STATUS_ERR;
+
+	return STATUS_OK;
+}
+#endif
 
 #ifdef SCTP_PRIMARY_ADDR
 static int check_sctp_setprim(struct sctp_setprim_expr *expr,
 			      struct sctp_setprim *sctp_setprim,
 			      char **error)
 {
-	if (check_u32_expr(expr->ssp_assoc_id, sctp_setprim->ssp_assoc_id,
+	if (check_sctp_assoc_t_expr(expr->ssp_assoc_id, sctp_setprim->ssp_assoc_id,
 			   "sctp_setprim.ssp_assoc_id", error))
 		return STATUS_ERR;
 	if (check_sockaddr(expr->ssp_addr, (struct sockaddr *)&sctp_setprim->ssp_addr, error))
@@ -3027,6 +3062,18 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 		}
 		break;
 #endif
+#ifdef SCTP_DEFAULT_PRINFO
+	case EXPR_SCTP_DEFAULT_PRINFO:
+		live_optval = malloc(sizeof(struct sctp_default_prinfo));
+		live_optlen = sizeof(struct sctp_default_prinfo);
+		if (get_sctp_assoc_t(val_expression->value.sctp_default_prinfo->pr_assoc_id,
+				     &((struct sctp_default_prinfo *)live_optval)->pr_assoc_id,
+				     error)) {
+			free(live_optval);
+			return STATUS_ERR;
+		}
+		break;
+#endif
 #ifdef SCTP_PRIMARY_ADDR
 	case EXPR_SCTP_SETPRIM:
 		live_optval = malloc(sizeof(struct sctp_setprim));
@@ -3136,6 +3183,11 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 		result = check_sctp_sndinfo(val_expression->value.sctp_sndinfo, live_optval, error);
 		break;
 #endif
+#ifdef SCTP_DEFAULT_PRINFO
+	case EXPR_SCTP_DEFAULT_PRINFO:
+		result = check_sctp_default_prinfo(val_expression->value.sctp_default_prinfo, live_optval, error);
+		break;
+#endif
 #ifdef SCTP_PRIMARY_ADDR
 	case EXPR_SCTP_SETPRIM:
 		result = check_sctp_setprim(val_expression->value.sctp_setprim, live_optval, error);
@@ -3202,6 +3254,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 #ifdef SCTP_DEFAULT_SNDINFO
 	struct sctp_sndinfo sndinfo;
 #endif
+#ifdef SCTP_DEFAULT_PRINFO
+	struct sctp_default_prinfo default_prinfo;
+#endif
 #ifdef SCTP_PRIMARY_ADDR
 	struct sctp_setprim setprim;
 #endif
@@ -3458,6 +3513,23 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 		optval = &sndinfo;
 		break;
 #endif
+#ifdef SCTP_DEFAULT_PRINFO
+	case EXPR_SCTP_DEFAULT_PRINFO:
+		if (get_u16(val_expression->value.sctp_default_prinfo->pr_policy,
+			    &default_prinfo.pr_policy, error)) {
+			return STATUS_ERR;
+		}
+		if (get_u32(val_expression->value.sctp_default_prinfo->pr_value,
+			    &default_prinfo.pr_value, error)) {
+			return STATUS_ERR;
+		}
+		if (get_sctp_assoc_t(val_expression->value.sctp_default_prinfo->pr_assoc_id,
+				    &default_prinfo.pr_assoc_id, error)) {
+			return STATUS_ERR;
+		}
+		optval = &default_prinfo;		
+		break;		
+#endif
 #ifdef SCTP_PRIMARY_ADDR
 	case EXPR_SCTP_SETPRIM:
 		if (get_sctp_assoc_t(val_expression->value.sctp_setprim->ssp_assoc_id,
diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c
index ec2f92d6..887b1a0b 100644
--- a/gtests/net/packetdrill/script.c
+++ b/gtests/net/packetdrill/script.c
@@ -83,6 +83,7 @@ struct expression_type_entry expression_type_table[] = {
 	{ EXPR_SCTP_SETADAPTATION,   "sctp_setadaptation"},
 	{ EXPR_SCTP_SNDRCVINFO,      "sctp_sndrcvinfo" },
 	{ EXPR_SCTP_PRINFO,          "sctp_prinfo"     },
+	{ EXPR_SCTP_DEFAULT_PRINFO,  "sctp_default_prinfo"},
 	{ EXPR_SCTP_AUTHINFO,        "sctp_authinfo"   },
 	{ EXPR_SCTP_SENDV_SPA,       "sctp_sendv_spa"  },
 	{ EXPR_SCTP_RCVINFO,         "sctp_rcvinfo"    },
@@ -427,6 +428,11 @@ void free_expression(struct expression *expression)
 		free_expression(expression->value.sctp_prinfo->pr_policy);
 		free_expression(expression->value.sctp_prinfo->pr_value);
 		break;		
+	case EXPR_SCTP_DEFAULT_PRINFO:
+		free_expression(expression->value.sctp_default_prinfo->pr_policy);
+		free_expression(expression->value.sctp_default_prinfo->pr_value);
+		free_expression(expression->value.sctp_default_prinfo->pr_assoc_id);
+		break;		
 	case EXPR_SCTP_AUTHINFO:
 		free_expression(expression->value.sctp_authinfo->auth_keynumber);
 		break;
@@ -1399,6 +1405,38 @@ static int evaluate_sctp_prinfo_expression(struct expression *in,
 	return STATUS_OK;	
 }
 
+static int evaluate_sctp_default_prinfo_expression(struct expression *in,
+						   struct expression *out,
+						   char **error)
+{
+        struct sctp_default_prinfo_expr *in_info;
+        struct sctp_default_prinfo_expr *out_info;
+
+        assert(in->type == EXPR_SCTP_DEFAULT_PRINFO);
+        assert(in->value.sctp_default_prinfo);
+        assert(out->type == EXPR_SCTP_DEFAULT_PRINFO);
+
+        out->value.sctp_default_prinfo = calloc(1, sizeof(struct sctp_default_prinfo_expr));
+                     
+        in_info = in->value.sctp_default_prinfo;
+        out_info = out->value.sctp_default_prinfo;
+                     
+        if (evaluate(in_info->pr_policy,
+		     &out_info->pr_policy,
+		     error))
+		return STATUS_ERR;
+        if (evaluate(in_info->pr_value,
+		     &out_info->pr_value,
+		     error))
+		return STATUS_ERR;
+        if (evaluate(in_info->pr_assoc_id,
+		     &out_info->pr_assoc_id,
+		     error))
+		return STATUS_ERR;
+
+	return STATUS_OK;	
+}
+
 static int evaluate_sctp_authinfo_expression(struct expression *in,
 					     struct expression *out,
 					     char **error)
@@ -2205,6 +2243,9 @@ static int evaluate(struct expression *in,
 	case EXPR_SCTP_PRINFO:
 		result = evaluate_sctp_prinfo_expression(in, out, error);
 		break;
+	case EXPR_SCTP_DEFAULT_PRINFO:
+		result = evaluate_sctp_default_prinfo_expression(in, out, error);
+		break;
 	case EXPR_SCTP_AUTHINFO:
 		result = evaluate_sctp_authinfo_expression(in, out, error);
 		break;
diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h
index 740e7485..b2b15803 100644
--- a/gtests/net/packetdrill/script.h
+++ b/gtests/net/packetdrill/script.h
@@ -63,6 +63,7 @@ enum expression_t {
 	EXPR_SCTP_SETADAPTATION,  /* struct sctp_setadaptation for SCTP_ADATTATION_LAYER */
 	EXPR_SCTP_SNDRCVINFO,     /* struct sctp_sndrcvinfo for syscall sctp_recvmsg */
 	EXPR_SCTP_PRINFO,	  /* struct sctp_prinfo for syscall sctp_sendv */
+	EXPR_SCTP_DEFAULT_PRINFO, /* expression tree for struct sctp_default_prinfo for syscall [gs]etsockopt */
 	EXPR_SCTP_AUTHINFO,	  /* struct sctp_authinfo for syscall sctp_sendv */
 	EXPR_SCTP_SENDV_SPA,	  /* struct sctp_sendv_spa for syscall sctp_sendv */
 	EXPR_SCTP_RCVINFO,        /* struct sctp_rcvinfo for syscall sctp_recvv */
@@ -116,6 +117,7 @@ struct expression {
 		struct sctp_setadaptation_expr *sctp_setadaptation;
 		struct sctp_sndrcvinfo_expr *sctp_sndrcvinfo;
 		struct sctp_prinfo_expr *sctp_prinfo;
+		struct sctp_default_prinfo_expr *sctp_default_prinfo;
 		struct sctp_authinfo_expr *sctp_authinfo;
 		struct sctp_sendv_spa_expr *sctp_sendv_spa;
 		struct sctp_rcvinfo_expr *sctp_rcvinfo;
@@ -329,6 +331,13 @@ struct sctp_prinfo_expr {
 	struct expression *pr_value;
 };
 
+/* Parse tree for sctp_default_prinfo in [gs]etsockopt syscall. */
+struct sctp_default_prinfo_expr {
+	struct expression *pr_policy;
+	struct expression *pr_value;
+	struct expression *pr_assoc_id;
+};
+
 /* Parse tree for sctp_authinfo in sctp_sendv syscall. */
 struct sctp_authinfo_expr {
 	struct expression *auth_keynumber;
diff --git a/gtests/net/packetdrill/symbols_freebsd.c b/gtests/net/packetdrill/symbols_freebsd.c
index ae52fa39..4f4f2c17 100644
--- a/gtests/net/packetdrill/symbols_freebsd.c
+++ b/gtests/net/packetdrill/symbols_freebsd.c
@@ -93,6 +93,7 @@ struct int_symbol platform_symbols_table[] = {
 	{ SCTP_EVENT,                       "SCTP_EVENT"                      },
 	{ SCTP_EVENTS,                      "SCTP_EVENTS"                     },
 	{ SCTP_DEFAULT_SNDINFO,             "SCTP_DEFAULT_SNDINFO"            },
+	{ SCTP_DEFAULT_PRINFO,              "SCTP_DEFAULT_PRINFO"             },
 	{ SCTP_STATUS,                      "SCTP_STATUS"                     },
 	{ SCTP_GET_PEER_ADDR_INFO,          "SCTP_GET_PEER_ADDR_INFO"         },
 	{ SCTP_FRAGMENT_INTERLEAVE,         "SCTP_FRAGMENT_INTERLEAVE"        },
diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt
index 637209b2..d11d2c32 100644
--- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt
+++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt
@@ -13,6 +13,9 @@
 +0 setsockopt(3, IPPROTO_SCTP, SCTP_PRIMARY_ADDR, {ssp_assoc_id=0, ssp_addr={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")}}, 136) = 0
 +0 getsockopt(3, IPPROTO_SCTP, SCTP_PRIMARY_ADDR, {ssp_assoc_id=0, ssp_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_DEFAULT_PRINFO, {pr_policy=SCTP_PR_SCTP_TTL, pr_value=5, pr_assoc_id=3}, 12) = 0
++0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_PRINFO, {pr_policy=SCTP_PR_SCTP_TTL, pr_value=5, pr_assoc_id=3}, [12]) = 0
+
 +0 setsockopt(3, IPPROTO_SCTP, SCTP_STATUS, {sstat_state=..., sstat_rwnd=..., sstat_unackdata=..., sstat_penddata=...,
 sstat_instrms=..., sstat_outstrms=..., sstat_fragmentation_point=..., sstat_primary=...}, 176) = -1
 
-- 
GitLab