diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c
index 34ec3cb9e7e19ea4669d831a128d9a17f6c732e0..1891777caa21c9e688f930fb0726735128cc0814 100644
--- a/gtests/net/packetdrill/run_system_call.c
+++ b/gtests/net/packetdrill/run_system_call.c
@@ -283,7 +283,7 @@ static int check_type(struct expression *expression,
 }
 
 /* Sets the value from the expression argument, checking that it is a
- * valid size_t, and matches the expected type. Returns STATUS_OK on
+ * valid socklen_t, and matches the expected type. Returns STATUS_OK on
  * success; on failure returns STATUS_ERR and sets error message.
  */
 static int get_socklen_t(struct expression *expression,
@@ -576,6 +576,26 @@ static int off_t_bracketed_arg(struct expression_list *args,
 }
 #endif
 
+static int socklen_t_bracketed_arg(struct expression_list *args,
+				   int index, socklen_t *value, char **error)
+{
+	struct expression_list *list;
+	struct expression *expression;
+
+	expression = get_arg(args, index, error);
+	if (expression == NULL)
+		return STATUS_ERR;
+	if (check_type(expression, EXPR_LIST, error))
+		return STATUS_ERR;
+	list = expression->value.list;
+	if (expression_list_length(list) != 1) {
+		asprintf(error,
+			 "Expected [<integer>] but got multiple elements");
+		return STATUS_ERR;
+	}
+	return get_socklen_t(list->expression, value, error);
+}
+
 /* Return STATUS_OK iff the argument with the given index is an
  * ellipsis (...).
  */
@@ -3209,10 +3229,11 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 			      struct expression_list *args, char **error)
 {
 	int script_fd, live_fd, level, optname, live_result, result = STATUS_OK;
-	s32 script_optval, script_optlen, expected;
+	s32 script_optval, expected;
+	socklen_t script_optlen, live_optlen;
+	bool optlen_provided;
 	void *live_optval;
-	socklen_t live_optlen;
-	struct expression *val_expression;
+	struct expression *val_expression, *len_expression;
 
 	if (check_arg_count(args, 5, error))
 		return STATUS_ERR;
@@ -3224,8 +3245,16 @@ 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, 4, &script_optlen, error))
+	len_expression = get_arg(args, 4, error);
+	if (len_expression == NULL)
 		return STATUS_ERR;
+	if (len_expression->type == EXPR_ELLIPSIS) {
+		optlen_provided = false;
+	} else {
+		if (socklen_t_bracketed_arg(args, 4, &script_optlen, error))
+			return STATUS_ERR;
+		optlen_provided = true;
+	}
 	if (get_s32(syscall->result, &expected, error))
 		return STATUS_ERR;
 	val_expression = get_arg(args, 3, error);
@@ -3548,7 +3577,7 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 		return STATUS_ERR;
 	}
 
-	if (live_optlen != script_optlen) {
+	if (optlen_provided && live_optlen != script_optlen) {
 		asprintf(error, "optlen: expected: %d actual: %d",
 			 (int)script_optlen, (int)live_optlen);
 		free(live_optval);
@@ -3703,9 +3732,11 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			struct expression_list *args, char **error)
 {
-	int script_fd, live_fd, level, optname, optval_s32, optlen, result;
+	int script_fd, live_fd, level, optname, optval_s32, result;
+	socklen_t optlen;
+	bool optlen_provided;
 	void *optval = NULL;
-	struct expression *val_expression;
+	struct expression *val_expression, *len_expression;
 	struct linger linger;
 #ifdef SCTP_RTOINFO
 	struct sctp_rtoinfo rtoinfo;
@@ -3797,8 +3828,17 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 		return STATUS_ERR;
 	if (s32_arg(args, 2, &optname, error))
 		return STATUS_ERR;
-	if (s32_arg(args, 4, &optlen, error))
+
+	len_expression = get_arg(args, 4, error);
+	if (len_expression == NULL)
 		return STATUS_ERR;
+	if (len_expression->type == EXPR_ELLIPSIS) {
+		optlen_provided = false;
+	} else {
+		if (get_socklen_t(len_expression, &optlen, error))
+			return STATUS_ERR;
+		optlen_provided = true;
+	}
 
 	val_expression = get_arg(args, 3, error);
 	if (val_expression == NULL)
@@ -3810,14 +3850,23 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 		get_s32(val_expression->value.linger->l_linger,
 			&linger.l_linger, error);
 		optval = &linger;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct linger);
+		}
 		break;
 	case EXPR_STRING:
 		optval = val_expression->value.string;
+		if (!optlen_provided) {
+			optlen = (socklen_t)strlen(val_expression->value.string);
+		}
 		break;
 	case EXPR_LIST:
 		if (s32_bracketed_arg(args, 3, &optval_s32, error))
 			return STATUS_ERR;
 		optval = &optval_s32;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(s32);
+		}
 		break;
 #ifdef SCTP_RTOINFO
 	case EXPR_SCTP_RTOINFO:
@@ -3838,6 +3887,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			return STATUS_ERR;
 		}
 		optval = &rtoinfo;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_rtoinfo);
+		}
 		break;
 #endif
 #ifdef SCTP_ASSOCINFO
@@ -3867,6 +3919,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			return STATUS_ERR;
 		}
 		optval = &assocparams;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_assocparams);
+		}
 		break;
 #endif
 #ifdef SCTP_INITMSG
@@ -3875,6 +3930,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			return STATUS_ERR;
 		}
 		optval = &initmsg;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_initmsg);
+		}
 		break;
 #endif
 #if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED) || defined(SCTP_ENABLE_STREAM_RESET)
@@ -3888,19 +3946,24 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			return STATUS_ERR;
 		}
 		optval = &assoc_value;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_assoc_value);
+		}
 		break;
 #endif
 #ifdef SCTP_HMAC_IDENT
 	case EXPR_SCTP_HMACALGO: {
-		int len, i;
 		struct expression_list *list;
+		size_t size;
+		unsigned int len, i;
 
 		if (check_type(val_expression->value.sctp_hmacalgo->shmac_idents, EXPR_LIST, error)) {
 			return STATUS_ERR;
 		}
 		list = val_expression->value.sctp_hmacalgo->shmac_idents->value.list;
 		len = expression_list_length(list);
-		hmacalgo = malloc(sizeof(u32) + (sizeof(u16) * len));
+		size = sizeof(struct sctp_hmacalgo) + len * sizeof(u16);
+		hmacalgo = malloc(size);
 
 		if (get_u32(val_expression->value.sctp_hmacalgo->shmac_number_of_idents,
 			    &hmacalgo->shmac_number_of_idents, error)) {
@@ -3913,8 +3976,11 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			get_u16(expr, &(hmacalgo->shmac_idents[i]), error);
 		}
 		optval = &hmacalgo;
-		break;
+		if (!optlen_provided) {
+			optlen = (socklen_t)size;
 		}
+		break;
+	}
 #endif
 #ifdef SCTP_SS_VALUE
 	case EXPR_SCTP_STREAM_VALUE:
@@ -3928,6 +3994,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			return STATUS_ERR;
 		}
 		optval = &stream_value;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_stream_value);
+		}
 		break;
 #endif
 #if defined(SCTP_AUTH_ACTIVE_KEY) || defined(SCTP_AUTH_DEACTIVATE_KEY) || defined(SCTP_AUTH_DELETE_KEY)
@@ -3941,6 +4010,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			return STATUS_ERR;
 		}
 		optval = &authkeyid;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_authkeyid);
+		}
 		break;
 #endif
 #ifdef SCTP_DELAYED_SACK
@@ -3958,6 +4030,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			return STATUS_ERR;
 		}
 		optval = &sack_info;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_sack_info);
+		}
 		break;
 #endif
 #ifdef SCTP_STATUS
@@ -3967,6 +4042,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			return STATUS_ERR;
 		}
 		optval = &status;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_status);
+		}
 		break;
 #endif
 #ifdef SCTP_GET_PEER_ADDR_INFO
@@ -3981,6 +4059,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			return STATUS_ERR;
 		}
 		optval = &paddrinfo;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_paddrinfo);
+		}
 		break;
 #endif
 #ifdef SCTP_EVENT
@@ -3998,6 +4079,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			return STATUS_ERR;
 		}
 		optval = &event;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_event);
+		}
 		break;
 #endif
 #ifdef SCTP_EVENTS
@@ -4043,6 +4127,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			return STATUS_ERR;
 		}
 		optval = &event_subscribe;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_event_subscribe);
+		}
 		break;
 #endif
 #ifdef SCTP_DEFAULT_SEND_PARAM
@@ -4051,6 +4138,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			return STATUS_ERR;
 		}
 		optval = &sndrcvinfo;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_sndrcvinfo);
+		}
 		break;
 #endif
 #ifdef SCTP_DEFAULT_SNDINFO
@@ -4076,6 +4166,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			return STATUS_ERR;
 		}
 		optval = &sndinfo;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_sndinfo);
+		}
 		break;
 #endif
 #ifdef SCTP_DEFAULT_PRINFO
@@ -4090,6 +4183,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 		}
 		default_prinfo.pr_assoc_id = 0;
 		optval = &default_prinfo;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_default_prinfo);
+		}
 		break;
 	case EXPR_SCTP_DEFAULT_PRINFO:
 		if (get_u16(val_expression->value.sctp_default_prinfo->pr_policy,
@@ -4105,6 +4201,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			return STATUS_ERR;
 		}
 		optval = &default_prinfo;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_default_prinfo);
+		}
 		break;
 #endif
 #ifdef SCTP_PRIMARY_ADDR
@@ -4118,6 +4217,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			return STATUS_ERR;
 		}
 		optval = &setprim;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_setprim);
+		}
 		break;
 #endif
 #ifdef SCTP_ADAPTATION_LAYER
@@ -4127,6 +4229,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			return STATUS_ERR;
 		}
 		optval = &setadaptation;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_setadaptation);
+		}
 		break;
 #endif
 #ifdef SCTP_SET_PEER_PRIMARY_ADDR
@@ -4140,6 +4245,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			return STATUS_ERR;
 		}
 		optval = &setpeerprim;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_setpeerprim);
+		}
 		break;
 #endif
 #ifdef SCTP_AUTH_CHUNK
@@ -4149,20 +4257,25 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			return STATUS_ERR;
 		}
 		optval = &authchunk;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_authchunk);
+		}
 		break;
 #endif
 #ifdef SCTP_AUTH_KEY
 	case EXPR_SCTP_AUTHKEY: {
-		int i = 0, len = 0;
 		struct expression *key_expr;
 		struct expression_list *list;
+		size_t size;
+		unsigned int i, len;
 
 		if (check_type(val_expression->value.sctp_authkey->sca_key, EXPR_LIST, error)) {
 			return STATUS_ERR;
 		}
 		list = val_expression->value.sctp_authkey->sca_key->value.list;
 		len = expression_list_length(list);
-		key = malloc(sizeof(sctp_assoc_t) + sizeof(u16) + sizeof(u16) + (sizeof(u8) * len));
+		size = sizeof(struct sctp_authkey) + len * sizeof(u8);
+		key = malloc(size);
 
 		if (get_sctp_assoc_t(val_expression->value.sctp_authkey->sca_assoc_id,
 				     &key->sca_assoc_id, error)) {
@@ -4186,8 +4299,10 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 				return STATUS_ERR;
 			}
 		}
-		key->sca_keylength = len;
 		optval = key;
+		if (!optlen_provided) {
+			optlen = (socklen_t)size;
+		}
 		break;
 	}
 #endif
@@ -4246,19 +4361,24 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 		paddrparams.spp_sackdelay = 0;
 #endif
 		optval = &paddrparams;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_paddrparams);
+		}
 		break;
 #endif
 #ifdef SCTP_RESET_STREAMS
 	case EXPR_SCTP_RESET_STREAMS: {
 		struct expression_list *list;
-		int len = 0, i = 0;
+		size_t size;
+		unsigned int len, i;
 
 		if (check_type(val_expression->value.sctp_reset_streams->srs_stream_list, EXPR_LIST, error)) {
 			return STATUS_ERR;
 		}
 		list = val_expression->value.sctp_reset_streams->srs_stream_list->value.list;
 		len = expression_list_length(list);
-		reset_streams = malloc(sizeof(u32) + sizeof(u16) + sizeof(u16) + (sizeof(u16) * len));
+		size = sizeof(struct sctp_reset_streams) + len * sizeof(u16);
+		reset_streams = malloc(size);
 
 		if (get_sctp_assoc_t(val_expression->value.sctp_reset_streams->srs_assoc_id,
 				     &reset_streams->srs_assoc_id, error)) {
@@ -4280,6 +4400,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			get_u16(expr, &(reset_streams->srs_stream_list[i]), error);
 		}
 		optval = reset_streams;
+		if (!optlen_provided) {
+			optlen = (socklen_t)size;
+		}
 		break;
 	}
 #endif
@@ -4298,6 +4421,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			return STATUS_ERR;
 		}
 		optval = &add_streams;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_add_streams);
+		}
 		break;
 #endif
 #ifdef SCTP_REMOTE_UDP_ENCAPS_PORT
@@ -4316,6 +4442,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			return STATUS_ERR;
 		}
 		optval = &udpencaps;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct sctp_udpencaps);
+		}
 		break;
 #endif
 #ifdef TCP_FUNCTION_BLK
@@ -4331,6 +4460,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 			return STATUS_ERR;
 		}
 		optval = &tcp_function_set;
+		if (!optlen_provided) {
+			optlen = (socklen_t)sizeof(struct tcp_function_set);
+		}
 		break;
 #endif
 	default: