diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index 21ea1f0b73ff8473221dfcb83d8d9b57a2df74fb..7fc2b6c6360dcdde3c83eba45ddc2615c41e8b30 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -566,8 +566,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %type <expression> decimal_integer hex_integer
 %type <expression> inaddr sockaddr msghdr iovec pollfd opt_revents 
 %type <expression> linger l_onoff l_linger
-%type <expression> sctp_rtoinfo sctp_initmsg sctp_assocval sctp_sackinfo
-%type <expression> sctp_status
+%type <expression> sctp_status sctp_initmsg sctp_assocval sctp_sackinfo
+%type <expression> sctp_rtoinfo srto_initial srto_max srto_min
 %type <errno_info> opt_errno
 %type <chunk_list> sctp_chunk_list_spec
 %type <chunk_list_item> sctp_chunk_spec
@@ -2282,8 +2282,8 @@ opt_revents
 ;
 
 l_onoff
-: ONOFF '=' INTEGER  { 
-	if (!is_valid_u32($3)){
+: ONOFF '=' INTEGER { 
+	if (!is_valid_s32($3)){
 		semantic_error("linger onoff out of range");
 	} else {
 		$$ = new_integer_expression( $3, "%ld" ); 
@@ -2293,8 +2293,8 @@ l_onoff
 ;
 
 l_linger
-: LINGER '=' INTEGER  { 
-	if (!is_valid_u32($3)){
+: LINGER '=' INTEGER { 
+	if (!is_valid_s32($3)){
 		semantic_error("linger out of range");
 	}
 	$$ = new_integer_expression( $3, "%ld");
@@ -2311,22 +2311,44 @@ linger
 }
 ;
 
-sctp_rtoinfo
-: '{' SRTO_INITIAL '=' INTEGER ',' SRTO_MAX '=' INTEGER ',' SRTO_MIN '=' INTEGER '}' {
-#ifdef SCTP_RTOINFO
-	$$ = new_expression(EXPR_SCTP_RTOINFO);
-	if (!is_valid_u32($4)) {
+srto_initial
+: SRTO_INITIAL '=' INTEGER {
+	if (!is_valid_u32($3)){
 		semantic_error("srto_initial out of range");
 	}
-	$$->value.sctp_rtoinfo.srto_initial = $4;
-	if (!is_valid_u32($8)) {
+        $$ = new_integer_expression( $3, "%u");
+}
+| SRTO_INITIAL '=' ELLIPSIS { $$ = new_expression( EXPR_ELLIPSIS ); }
+;
+
+srto_max
+: SRTO_MAX '=' INTEGER {
+	if (!is_valid_u32($3)) {
 		semantic_error("srto_max out of range");
 	}
-	$$->value.sctp_rtoinfo.srto_max = $8;
-	if (!is_valid_u32($12)) {
+	$$ = new_integer_expression( $3, "%u");
+}
+| SRTO_MAX '=' ELLIPSIS { $$ = new_expression( EXPR_ELLIPSIS ); }
+;
+
+srto_min
+: SRTO_MIN '=' INTEGER {
+	if (!is_valid_u32($3)) {
 		semantic_error("srto_min out of range");
 	}
-	$$->value.sctp_rtoinfo.srto_min = $12;
+	$$ = new_integer_expression( $3, "%u");
+}
+| SRTO_MIN '=' ELLIPSIS { $$ = new_expression( EXPR_ELLIPSIS ); }
+;
+
+sctp_rtoinfo
+: '{' srto_initial ',' srto_max ',' srto_min '}' {
+#ifdef SCTP_RTOINFO
+	$$ = new_expression(EXPR_SCTP_RTOINFO);
+	$$->value.sctp_rtoinfo = (struct sctp_rtoinfo_expr*) calloc(1, sizeof(struct sctp_rtoinfo_expr));
+	$$->value.sctp_rtoinfo->srto_initial = $2;
+	$$->value.sctp_rtoinfo->srto_max = $4;
+	$$->value.sctp_rtoinfo->srto_min = $6;
 #else
 	$$ = NULL;
 #endif
diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c
index 81579a5f80be897b498b53c2bf11fee8cd4a5e7d..8e0be86ea4716f1f7a3b8512bcdcb1d8b034ef65 100644
--- a/gtests/net/packetdrill/run_system_call.c
+++ b/gtests/net/packetdrill/run_system_call.c
@@ -1586,8 +1586,8 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 		live_optlen = (socklen_t)sizeof(struct linger);
 #ifdef SCTP_RTOINFO
 	} else if (val_expression->type == EXPR_SCTP_RTOINFO) {
-		live_optval = malloc(sizeof(val_expression->value.sctp_rtoinfo));
-		live_optlen = (socklen_t)sizeof(val_expression->value.sctp_rtoinfo);
+		live_optval = malloc(sizeof(struct sctp_rtoinfo));
+		live_optlen = (socklen_t)sizeof(struct sctp_rtoinfo);
 #endif
 #ifdef SCTP_STATUS
 	} else if (val_expression->type == EXPR_SCTP_STATUS) {
@@ -1647,22 +1647,44 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 
 #ifdef SCTP_RTOINFO
 	} else if (val_expression->type == EXPR_SCTP_RTOINFO) {
+		struct expression *srto_initial = val_expression->value.sctp_rtoinfo->srto_initial;
+		struct expression *srto_max = val_expression->value.sctp_rtoinfo->srto_max;
+		struct expression *srto_min = val_expression->value.sctp_rtoinfo->srto_min;
 		struct sctp_rtoinfo *rtoinfo = live_optval;
-		if (rtoinfo->srto_initial != val_expression->value.sctp_rtoinfo.srto_initial){
-			asprintf(error, "Bad getsockopt SCTP_RTOINFO initial: expected: %u actual: %u",
-			         val_expression->value.sctp_rtoinfo.srto_initial, rtoinfo->srto_initial);
-			free(live_optval);
-			return STATUS_ERR;
-		} else if (rtoinfo->srto_max != val_expression->value.sctp_rtoinfo.srto_max){
-		 	asprintf(error, "Bad getsockopt SCTP_RTOINFO SRTO_MAX: expected: %u actual: %u",
-		 	         val_expression->value.sctp_rtoinfo.srto_max, rtoinfo->srto_max);
-			free(live_optval);
-			return STATUS_ERR;
-		} else if (rtoinfo->srto_min != val_expression->value.sctp_rtoinfo.srto_min){
-		 	asprintf(error, "Bad getsockopt SCTP_RTOINFO SRTO_MIN: expected: %u actual: %u",
-		 	         val_expression->value.sctp_rtoinfo.srto_min, rtoinfo->srto_min);
-			free(live_optval);
-			return STATUS_ERR;
+		int initial, max, min;
+		if (srto_initial->type == EXPR_INTEGER) {
+			if (get_s32(srto_initial, &initial, error)) {
+				free(live_optval);
+				return STATUS_ERR;
+			}
+			if (rtoinfo->srto_initial != initial){
+				asprintf(error, "Bad getsockopt SCTP_RTOINFO initial: expected: %u actual: %u",
+					initial, rtoinfo->srto_initial);
+				free(live_optval);
+				return STATUS_ERR;
+			}
+		} else if (srto_max->type == EXPR_INTEGER) {
+			if (get_s32(srto_max, &max, error)) {
+				free(live_optval);
+				return STATUS_ERR;
+			}
+			if (rtoinfo->srto_max != max){
+				asprintf(error, "Bad getsockopt SCTP_RTOINFO SRTO_MAX: expected: %u actual: %u",
+					max, rtoinfo->srto_max);
+				free(live_optval);
+				return STATUS_ERR;
+			}
+		} else if (srto_min->type == EXPR_INTEGER) {
+			if (get_s32(srto_min, &min, error)) {
+				free(live_optval);
+				return STATUS_ERR;
+			}
+			if (rtoinfo->srto_min != min){
+				asprintf(error, "Bad getsockopt SCTP_RTOINFO SRTO_MIN: expected: %u actual: %u",
+					min, rtoinfo->srto_min);
+				free(live_optval);
+				return STATUS_ERR;
+			}
 		}
 #endif
 #ifdef SCTP_STATUS
@@ -1754,6 +1776,15 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 		optval = &optval_s32;
 #ifdef SCTP_RTOINFO
 	} else if (val_expression->type == EXPR_SCTP_RTOINFO) {
+		if(val_expression->value.sctp_rtoinfo->srto_initial->type != EXPR_INTEGER ||
+			val_expression->value.sctp_rtoinfo->srto_max->type != EXPR_INTEGER ||
+			val_expression->value.sctp_rtoinfo->srto_min->type != EXPR_INTEGER) { 
+			return STATUS_ERR;
+		}
+		optval = malloc(sizeof(struct sctp_rtoinfo));
+		((struct sctp_rtoinfo*) optval)->srto_initial = val_expression->value.sctp_rtoinfo->srto_initial->value.num;
+		((struct sctp_rtoinfo*) optval)->srto_max = val_expression->value.sctp_rtoinfo->srto_initial->value.num;
+		((struct sctp_rtoinfo*) optval)->srto_min = val_expression->value.sctp_rtoinfo->srto_initial->value.num;
 		optval = &val_expression->value.sctp_rtoinfo;
 #endif
 #ifdef SCTP_INITMSG
diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h
index 32cdc368c93f1e9decff90659f422c1eeb5f8d4b..cba02337b50e441dd038f2b8a4e5f6fcc50a81cc 100644
--- a/gtests/net/packetdrill/script.h
+++ b/gtests/net/packetdrill/script.h
@@ -81,7 +81,7 @@ struct expression {
 		struct msghdr_expr *msghdr;
 		struct pollfd_expr *pollfd;
 #ifdef SCTP_RTOINFO
-		struct sctp_rtoinfo_expr sctp_rtoinfo;
+		struct sctp_rtoinfo_expr *sctp_rtoinfo;
 #endif
 #ifdef SCTP_INITMSG
 		struct sctp_initmsg sctp_initmsg;