diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index a8aa42363c5ab2ca6a32c6a55ecf3b73a1d177e7..8f353410b201060a80ebbcd1c7cfa2262974a2f4 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -564,9 +564,10 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %type <expression_list> expression_list function_arguments
 %type <expression> expression binary_expression array
 %type <expression> decimal_integer hex_integer
-%type <expression> inaddr sockaddr msghdr iovec pollfd opt_revents linger
-%type <expression> sctp_rtoinfo sctp_initmsg sctp_assocval sctp_sackinfo
-%type <expression> sctp_status
+%type <expression> inaddr sockaddr msghdr iovec pollfd opt_revents 
+%type <expression> linger l_onoff l_linger
+%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
@@ -2280,30 +2281,74 @@ opt_revents
 | ',' REVENTS '=' expression     { $$ = $4; }
 ;
 
+l_onoff
+: ONOFF '=' INTEGER { 
+	if (!is_valid_s32($3)) {
+		semantic_error("linger onoff out of range");
+	} else {
+		$$ = new_integer_expression($3, "%ld"); 
+	}	
+}
+| ONOFF '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+l_linger
+: LINGER '=' INTEGER { 
+	if (!is_valid_s32($3)) {
+		semantic_error("linger out of range");
+	}
+	$$ = new_integer_expression($3, "%ld");
+}
+| LINGER '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
 linger
-: '{' ONOFF '=' INTEGER ',' LINGER '=' INTEGER '}' {
+: '{' l_onoff ',' l_linger '}' {
 	$$ = new_expression(EXPR_LINGER);
-	$$->value.linger.l_onoff  = $4;
-	$$->value.linger.l_linger = $8;
+	$$->value.linger = (struct linger_expr*) calloc(1, sizeof(struct linger_expr));
+	$$->value.linger->l_onoff  = $2;
+	$$->value.linger->l_linger = $4;
 }
 ;
 
-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 aef5ef0e5f85824c00e4eb30c433190985d3b45c..339459ec2f72cf8f373d509b764e68245d8f132a 100644
--- a/gtests/net/packetdrill/run_system_call.c
+++ b/gtests/net/packetdrill/run_system_call.c
@@ -1560,8 +1560,10 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 			      struct expression_list *args, char **error)
 {
 	int script_fd, live_fd, level, optname, result;
-	s32 script_optval, live_optval, script_optlen;
-	socklen_t live_optlen = sizeof(live_optval);
+	s32 script_optval, script_optlen, expected;
+	void *live_optval;
+	socklen_t live_optlen;
+	struct expression *val_expression;
 	if (check_arg_count(args, 5, error))
 		return STATUS_ERR;
 	if (s32_arg(args, 0, &script_fd, error))
@@ -1572,37 +1574,170 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 		return STATUS_ERR;
 	if (s32_arg(args, 2, &optname, error))
 		return STATUS_ERR;
-	if (s32_bracketed_arg(args, 3, &script_optval, error))
-		return STATUS_ERR;
 	if (s32_bracketed_arg(args, 4, &script_optlen, error))
 		return STATUS_ERR;
-	if (script_optlen != 4) {
-		asprintf(error, "Unsupported getsockopt optlen: %d",
-			 (int)script_optlen);
+	if (get_s32(syscall->result, &expected, error))
 		return STATUS_ERR;
+	val_expression = get_arg(args, 3, error);
+	if (val_expression == NULL) {
+		return STATUS_ERR;
+	} else if (val_expression->type == EXPR_LINGER) {
+		live_optval = malloc(sizeof(struct linger));
+		live_optlen = (socklen_t)sizeof(struct linger);
+#ifdef SCTP_RTOINFO
+	} else if (val_expression->type == EXPR_SCTP_RTOINFO) {
+		live_optval = malloc(sizeof(struct sctp_rtoinfo));
+		live_optlen = (socklen_t)sizeof(struct sctp_rtoinfo);
+		((struct sctp_rtoinfo*)live_optval)->srto_assoc_id = 0;
+#endif
+#ifdef SCTP_STATUS
+	} else if (val_expression->type == EXPR_SCTP_STATUS) {
+		live_optval = malloc(sizeof(val_expression->value.sctp_status));
+		live_optlen = (socklen_t)sizeof(val_expression->value.sctp_status);
+		((struct sctp_status*) live_optval)->sstat_assoc_id = val_expression->value.sctp_status.sstat_assoc_id;
+#endif
+	} else {
+		s32_bracketed_arg(args, 3, &script_optval, error);
+		live_optval = malloc(sizeof(int));
+		live_optlen = (socklen_t)sizeof(int);
 	}
 
 	begin_syscall(state, syscall);
 
-	result = getsockopt(live_fd, level, optname,
-			    &live_optval, &live_optlen);
-
-	if (end_syscall(state, syscall, CHECK_EXACT, result, error))
-		return STATUS_ERR;
-
-	if ((int)live_optlen != script_optlen) {
-		asprintf(error,
-			 "Bad getsockopt optlen: expected: %d actual: %d",
-			 (int)script_optlen, (int)live_optlen);
+	result = getsockopt(live_fd, level, optname, live_optval, &live_optlen);
+	if (end_syscall(state, syscall, CHECK_NON_NEGATIVE, result, error)) {
 		return STATUS_ERR;
 	}
-	if (live_optval != script_optval) {
-		asprintf(error,
-			 "Bad getsockopt optval: expected: %d actual: %d",
-			 (int)script_optval, (int)live_optval);
+
+	if (live_optlen != script_optlen) {
+		asprintf(error, "Bad getsockopt optlen: expected: %d actual: %d",
+		         (int)script_optlen, (int)live_optlen);
+		free(live_optval);
 		return STATUS_ERR;
 	}
+	if (val_expression->type == EXPR_LINGER) {
+		struct expression *l_onoff = val_expression->value.linger->l_onoff;
+		struct expression *l_linger = val_expression->value.linger->l_linger;
+		struct linger *ling = live_optval;
+		int val_onoff = 0; 
+		if (l_onoff->type == EXPR_INTEGER) {
+			if (get_s32(l_onoff, &val_onoff, error)) {
+				free(live_optval);
+				return STATUS_ERR;
+			}
+			if (val_onoff != ling->l_onoff) {
+				asprintf(error, "Bad getsockopt Linger onoff: expected: %d actual: %d",
+			         	(int) val_onoff, ling->l_onoff);
+				free(live_optval);
+				return STATUS_ERR;
+			}
+		}
+		int val_linger = 0;
+		if (l_linger->type == EXPR_INTEGER) {
+			if (get_s32(l_linger, &val_linger, error)) {
+				free(live_optval);
+				return STATUS_ERR;
+			}
+			if (ling->l_linger != val_linger) {
+				asprintf(error, "Bad getsockopt Linger Value: expected: %d actual: %d",
+			        	 val_linger, ling->l_linger);
+				free(live_optval);
+				return STATUS_ERR;
+			}
+		}
 
+#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;
+		int initial=0, max=0, min=0;
+		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
+	} else if (val_expression->type == EXPR_SCTP_STATUS) {
+		struct sctp_status *live_val = live_optval;
+		struct sctp_status *expected_val = &(val_expression->value.sctp_status);
+		if (live_val->sstat_state != expected_val->sstat_state) {
+			asprintf(error, "Bad getsockopt SCTP_STATUS state: expected: %d actual: %d ",
+			         expected_val->sstat_state, live_val->sstat_state);
+			free(live_optval);
+			return STATUS_ERR;
+		} else if (live_val->sstat_rwnd != expected_val->sstat_rwnd) {
+			asprintf(error, "Bad getsockopt SCTP_STATUS rwnd: expected: %u actual: %u ",
+			         expected_val->sstat_rwnd, live_val->sstat_rwnd);
+			free(live_optval);
+			return STATUS_ERR;
+		} else if (live_val->sstat_unackdata != expected_val->sstat_unackdata) {
+			asprintf(error, "Bad getsockopt SCTP_STATUS unackdata: expected: %u actual: %u",
+			         expected_val->sstat_unackdata, live_val->sstat_unackdata);
+			free(live_optval);
+			return STATUS_ERR;
+		} else if (live_val->sstat_penddata != expected_val->sstat_penddata) {
+			asprintf(error, "Bad getsockopt SCTP_STATUS penddata: expected: %u actual: %u",
+			         expected_val->sstat_penddata, live_val->sstat_penddata);
+			free(live_optval);
+			return STATUS_ERR;
+		} else if (live_val->sstat_instrms != expected_val->sstat_instrms) {
+			asprintf(error, "Bad getsockopt SCTP_STATUS instreams: expected: %u actual: %u",
+			         expected_val->sstat_instrms, live_val->sstat_instrms);
+			free(live_optval);
+			return STATUS_ERR;
+		} else if (live_val->sstat_outstrms != expected_val->sstat_outstrms) {
+			asprintf(error, "Bad getsockopt SCTP_STATUS outstreams: expected: %u actual: %u",
+			         expected_val->sstat_outstrms, live_val->sstat_outstrms);
+			free(live_optval);
+			return STATUS_ERR;
+		} else if (live_val->sstat_fragmentation_point != expected_val->sstat_fragmentation_point){
+			asprintf(error, "Bad getsockopt SCTP_STATUS fragmentation point: expected: %u actual: %u",
+			         expected_val->sstat_fragmentation_point, live_val->sstat_fragmentation_point);
+			free(live_optval);
+			return STATUS_ERR;
+		}
+#endif
+	} else {
+		if (*(int*)live_optval != script_optval) {
+			asprintf(error, "Bad getsockopt optval: expected: %d actual: %d",
+			         (int)script_optval, *(int*)live_optval);
+			free(live_optval);
+			return STATUS_ERR;
+		}
+	}
+	free(live_optval);
 	return STATUS_OK;
 }
 
@@ -1630,7 +1765,11 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 	if (val_expression == NULL)
 		return STATUS_ERR;
 	if (val_expression->type == EXPR_LINGER) {
-		optval = &val_expression->value.linger;
+		optval = malloc(sizeof(struct linger));
+		get_s32(val_expression->value.linger->l_onoff, 
+			&(((struct linger*) optval)->l_onoff), error);
+		get_s32(val_expression->value.linger->l_linger,
+                        &(((struct linger*) optval)->l_linger), error);
 	} else if (val_expression->type == EXPR_STRING) {
 		optval = val_expression->value.string;
 	} else if (val_expression->type == EXPR_LIST) {
@@ -1639,7 +1778,20 @@ 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) {
-		optval = &val_expression->value.sctp_rtoinfo;
+		struct sctp_rtoinfo *rtoinfo;
+		struct sctp_rtoinfo_expr *expr_rtoinfo  = val_expression->value.sctp_rtoinfo;
+		if (expr_rtoinfo->srto_initial->type != EXPR_INTEGER ||
+			expr_rtoinfo->srto_max->type != EXPR_INTEGER ||
+			expr_rtoinfo->srto_min->type != EXPR_INTEGER) { 
+			asprintf(error, "Bad setsockopt, bad inputtype for rtoinfo");
+			return STATUS_ERR;
+		}
+		rtoinfo = malloc(sizeof(struct sctp_rtoinfo));
+		rtoinfo->srto_initial = expr_rtoinfo->srto_initial->value.num;
+		rtoinfo->srto_max = expr_rtoinfo->srto_max->value.num;
+		rtoinfo->srto_min = expr_rtoinfo->srto_min->value.num;
+		rtoinfo->srto_assoc_id = 0;
+		optval = rtoinfo;
 #endif
 #ifdef SCTP_INITMSG
 	} else if (val_expression->type == EXPR_SCTP_INITMSG) {
@@ -1669,6 +1821,7 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 	result = setsockopt(live_fd, level, optname, optval, optlen);
 
 	return end_syscall(state, syscall, CHECK_EXACT, result, error);
+	free(optval);
 }
 
 static int syscall_poll(struct state *state, struct syscall_spec *syscall,
diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c
index c4fdb4b2aedff29ebc5592f6bb95651b6cdd9b35..7b7d656577e63322f865f600d38a354e1280bd73 100644
--- a/gtests/net/packetdrill/script.c
+++ b/gtests/net/packetdrill/script.c
@@ -285,9 +285,17 @@ void free_expression(struct expression *expression)
 	switch (expression->type) {
 	case EXPR_ELLIPSIS:
 	case EXPR_INTEGER:
+		break;
 	case EXPR_LINGER:
+		free(expression->value.linger->l_onoff);
+		free(expression->value.linger->l_linger);
+		break;
 #ifdef SCTP_RTOINFO
 	case EXPR_SCTP_RTOINFO:
+		free(expression->value.sctp_rtoinfo->srto_initial);
+		free(expression->value.sctp_rtoinfo->srto_max);
+		free(expression->value.sctp_rtoinfo->srto_min);
+		break;
 #endif
 #ifdef SCTP_INITMSG
 	case EXPR_SCTP_INITMSG:
diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h
index a2b2e46b118718d717504bb56fc35586d0c9e21b..cba02337b50e441dd038f2b8a4e5f6fcc50a81cc 100644
--- a/gtests/net/packetdrill/script.h
+++ b/gtests/net/packetdrill/script.h
@@ -72,7 +72,7 @@ struct expression {
 	union {
 		s64 num;
 		char *string;
-		struct linger linger;
+		struct linger_expr *linger;
 		struct sockaddr_in *socket_address_ipv4;
 		struct sockaddr_in6 *socket_address_ipv6;
 		struct binary_expression *binary;
@@ -81,7 +81,7 @@ struct expression {
 		struct msghdr_expr *msghdr;
 		struct pollfd_expr *pollfd;
 #ifdef SCTP_RTOINFO
-		struct sctp_rtoinfo sctp_rtoinfo;
+		struct sctp_rtoinfo_expr *sctp_rtoinfo;
 #endif
 #ifdef SCTP_INITMSG
 		struct sctp_initmsg sctp_initmsg;
@@ -136,6 +136,20 @@ struct pollfd_expr {
 	struct expression *revents;	/* returned events */
 };
 
+/* Handle values for socketoption SO_Linger with inputtypes and values*/
+struct linger_expr {
+	struct expression *l_onoff;
+	struct expression *l_linger;
+};
+/* Parse tree for syscall get/setsockopt for sctp_rtoinfo*/
+#ifdef SCTP_RTOINFO
+struct sctp_rtoinfo_expr {
+	struct expression *srto_initial;
+	struct expression *srto_max;
+	struct expression *srto_min;
+};
+#endif
+
 /* 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/sctp_packet.c b/gtests/net/packetdrill/sctp_packet.c
index 40b44dba9bac9d862e7995a027806920068c6d2e..ac26f2082a8d57ecdf84a538dfe0c32c52c8b2f1 100644
--- a/gtests/net/packetdrill/sctp_packet.c
+++ b/gtests/net/packetdrill/sctp_packet.c
@@ -421,10 +421,10 @@ sctp_data_chunk_new(s64 flgs, s64 len, s64 tsn, s64 sid, s64 ssn, s64 ppid)
 		chunk->ssn = htons((u16)ssn);
 	}
 	if (ppid == -1) {
-		chunk->ppid = htons(0);
+		chunk->ppid = htonl(0);
 		flags |= FLAG_DATA_CHUNK_PPID_NOCHECK;
 	} else {
-		chunk->ppid = htons((u32)ppid);
+		chunk->ppid = htonl((u32)ppid);
 	}
 	memset(chunk->data, 0,
 	       length + padding_length - sizeof(struct sctp_data_chunk));
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
new file mode 100644
index 0000000000000000000000000000000000000000..8374c2c9fb78140ccaaeeeefef61792e53cb6ef0
--- /dev/null
+++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt
@@ -0,0 +1,29 @@
+0 socket(..., SOCK_STREAM, IPPROTO_SCTP) = 3
++0.0 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR)
++0.0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+// Check the handshake with an empty(!) cookie
++0.1 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress)
++0.0 > sctp: INIT[flgs=0, tag=1, a_rwnd=..., os=..., is=..., tsn=1, ...]
++0.1 < sctp: INIT_ACK[flgs=0, tag=2, a_rwnd=1500, os=1, is=1, tsn=1, STATE_COOKIE[len=4, val=...]]
++0.0 > sctp: COOKIE_ECHO[flgs=0, len=4, val=...]
++0.1 < sctp: COOKIE_ACK[flgs=0]
+
++0.0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
+
++0 getsockopt(3, IPPROTO_SCTP, SCTP_STATUS, {sstat_state=8, sstat_rwnd=1500, sstat_unackdata=0, sstat_penddata=0, sstat_instrms=1, sstat_outstrms=1, 
+ 		sstat_fragmentation_point=1452, sstat_primary=...}, [176])= 0
+
++0 setsockopt(3, SOL_SOCKET, SO_LINGER, {onoff=1, linger=30}, 8) = 0
++0 getsockopt(3, SOL_SOCKET, SO_LINGER, {onoff=128, linger=30}, [8]) = 0
++0 getsockopt(3, SOL_SOCKET, SO_LINGER, {onoff=128, linger=...}, [8]) = 0
++0 getsockopt(3, SOL_SOCKET, SO_LINGER, {onoff=..., linger=30}, [8]) = 0
++0 getsockopt(3, SOL_SOCKET, SO_LINGER, {onoff=..., linger=...}, [8]) = 0
+
++0 setsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=100, srto_max=200, srto_min=50}, 16) = 0
++0 getsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=100, srto_max=200, srto_min=50}, [16]) = 0
++0 getsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=..., srto_max=200, srto_min=50}, [16]) = 0
++0 getsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=100, srto_max=..., srto_min=50}, [16]) = 0
++0 getsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=100, srto_max=200, srto_min=...}, [16]) = 0
+
++0 close(3) = 0
+