diff --git a/SCTP_SocketAPI_Status.md b/SCTP_SocketAPI_Status.md
index a6aeec4be05404b347a6d54b3fe638320f789784..b3b01fbe176eb847affc39de7d6175940c9b57b3 100644
--- a/SCTP_SocketAPI_Status.md
+++ b/SCTP_SocketAPI_Status.md
@@ -27,9 +27,9 @@ For Linux the following tables are based on [sctp.h](https://github.com/sctp/lks
 |`SCTP_ADAPTATION_INDICATION`       | [RFC6458](https://tools.ietf.org/html/rfc6458#section-6.1.6)  | [RFC5061](https://tools.ietf.org/html/rfc5061) | unsupported | supported   | supported   |
 |`SCTP_PARTIAL_DELIVERY_EVENT`      | [RFC6458](https://tools.ietf.org/html/rfc6458#section-6.1.7)  | [RFC3758](https://tools.ietf.org/html/rfc3758) | unsupported | supported   | supported   |
 |`SCTP_AUTHENTICATION_EVENT`        | [RFC6458](https://tools.ietf.org/html/rfc6458#section-6.1.8)  | [RFC4895](https://tools.ietf.org/html/rfc4895) | unsupported | supported   | supported   |
-|`SCTP_SENDER_DRY_EVENT`            | [RFC6458](https://tools.ietf.org/html/rfc6458#section-6.1.9)  | [RFC4960](https://tools.ietf.org/html/rfc4960) | unsupported | supported   | supported   |
+|`SCTP_SENDER_DRY_EVENT`            | [RFC6458](https://tools.ietf.org/html/rfc6458#section-6.1.9)  | [RFC4960](https://tools.ietf.org/html/rfc4960) | supported   | supported   | supported   |
 |`SCTP_NOTIFICATIONS_STOPPED_EVENT` | [RFC6458](https://tools.ietf.org/html/rfc6458#section-6.1.10) | [RFC4960](https://tools.ietf.org/html/rfc4960) | unsupported | unsupported | unsupported |
-|`SCTP_SEND_FAILED_EVENT`           | [RFC6458](https://tools.ietf.org/html/rfc6458#section-6.1.10) | [RFC4960](https://tools.ietf.org/html/rfc4960) | unsupported | unsupported | supported   |
+|`SCTP_SEND_FAILED_EVENT`           | [RFC6458](https://tools.ietf.org/html/rfc6458#section-6.1.10) | [RFC4960](https://tools.ietf.org/html/rfc4960) | supported   | unsupported | supported   |
 
 ## SCTP Socket Options
 |Name                          | API Spec                                                      | Protocol Spec                                  | packetdrill | Linux               | FreeBSD   |
@@ -85,8 +85,8 @@ For Linux the following tables are based on [sctp.h](https://github.com/sctp/lks
 |`sctp_freepaddrs()` | [RFC6458](https://tools.ietf.org/html/rfc6458#section-9.4)  | [RFC4960](https://tools.ietf.org/html/rfc4960) | unsupported | supported   | supported |
 |`sctp_getladdrs()`  | [RFC6458](https://tools.ietf.org/html/rfc6458#section-9.5)  | [RFC4960](https://tools.ietf.org/html/rfc4960) | unsupported | supported   | supported |
 |`sctp_freeladdrs()` | [RFC6458](https://tools.ietf.org/html/rfc6458#section-9.6)  | [RFC4960](https://tools.ietf.org/html/rfc4960) | unsupported | supported   | supported |
-|`sctp_sendmsg()`    | [RFC6458](https://tools.ietf.org/html/rfc6458#section-9.7)  | [RFC5061](https://tools.ietf.org/html/rfc5061) | unsupported | supported   | supported |
-|`sctp_recvmsg()`    | [RFC6458](https://tools.ietf.org/html/rfc6458#section-9.8)  | [RFC4960](https://tools.ietf.org/html/rfc4960) | unsupported | supported   | supported |
+|`sctp_sendmsg()`    | [RFC6458](https://tools.ietf.org/html/rfc6458#section-9.7)  | [RFC5061](https://tools.ietf.org/html/rfc5061) | supported   | supported   | supported |
+|`sctp_recvmsg()`    | [RFC6458](https://tools.ietf.org/html/rfc6458#section-9.8)  | [RFC4960](https://tools.ietf.org/html/rfc4960) | supported   | supported   | supported |
 |`sctp_connectx()`   | [RFC6458](https://tools.ietf.org/html/rfc6458#section-9.9)  | [RFC4960](https://tools.ietf.org/html/rfc4960) | unsupported | supported   | supported |
 |`sctp_send()`       | [RFC6458](https://tools.ietf.org/html/rfc6458#section-9.10) | [RFC4960](https://tools.ietf.org/html/rfc4960) | unsupported | supported   | supported |
 |`sctp_sendx()`      | [RFC6458](https://tools.ietf.org/html/rfc6458#section-9.11) | [RFC4960](https://tools.ietf.org/html/rfc4960) | unsupported | supported   | supported |
diff --git a/gtests/net/packetdrill/Makefile.Linux b/gtests/net/packetdrill/Makefile.Linux
index 371e5ff32653f75317e8d818e0436a0487e53cd8..964c8e7640f6217f49db1e62c4fa3cc6ec383a01 100644
--- a/gtests/net/packetdrill/Makefile.Linux
+++ b/gtests/net/packetdrill/Makefile.Linux
@@ -1,2 +1,2 @@
-packetdrill-ext-libs := -lpthread -lrt
+packetdrill-ext-libs := -lpthread -lrt -lsctp
 include Makefile.common
diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l
index 61af210e8a20b634a729ac250b0cea29b7a93e14..647f775b17c4192112df7b9fb20dfeab5f0acaf1 100644
--- a/gtests/net/packetdrill/lexer.l
+++ b/gtests/net/packetdrill/lexer.l
@@ -275,6 +275,13 @@ sendv_flags			return SENDV_FLAGS;
 sendv_sndinfo			return SENDV_SNDINFO;
 sendv_prinfo			return SENDV_PRINFO;
 sendv_authinfo			return SENDV_AUTHINFO;
+ssfe_type                       return SSFE_TYPE;
+ssfe_flags                      return SSFE_FLAGS;
+ssfe_length                     return SSFE_LENGTH;
+ssfe_error                      return SSFE_ERROR;
+ssfe_info                       return SSFE_INFO;
+ssfe_assoc_id                   return SSFE_ASSOC_ID;
+ssfe_data                       return SSFE_DATA;
 rcv_sid                         return RCV_SID;
 rcv_ssn                         return RCV_SSN;
 rcv_flags                       return RCV_FLAGS;
diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index a8e49b87bdeea6603ce9ae65ef3a0c13d9756a89..8855fb81224c901c5ee496bdb0ca58d95f8b2cd2 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -555,6 +555,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %token <reserved> _SCTP_AUTHENTICATION_EVENT_ _SCTP_SENDER_DRY_EVENT_
 %token <reserved> SAC_TYPE SAC_FLAGS SAC_LENGTH SAC_STATE SAC_ERROR SAC_OUTBOUND_STREAMS
 %token <reserved> SAC_INBOUND_STREAMS SAC_ASSOC_ID SAC_INFO
+%token <reserved> SSFE_TYPE SSFE_FLAGS SSFE_LENGTH SSFE_ERROR SSFE_INFO SSFE_ASSOC_ID SSFE_DATA
 %token <floating> FLOAT
 %token <integer> INTEGER HEX_INTEGER
 %token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR IPV6_ADDR
@@ -613,8 +614,9 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %type <expression> sctp_shutdown_event sse_type sse_flags sse_length
 %type <expression> sctp_sender_dry_event sender_dry_type sender_dry_flags sender_dry_length sender_dry_assoc_id
 %type <expression> sctp_event_subscribe
-%type <expression> sctp_assoc_change_event sac_type sac_flags sac_length sac_state sac_error sac_outbound_streams
+%type <expression> sctp_assoc_change sac_type sac_flags sac_length sac_state sac_error sac_outbound_streams
 %type <expression> sac_inbound_streams sac_assoc_id
+%type <expression> sctp_send_failed_event ssfe_type ssfe_flags ssfe_length ssfe_error ssfe_assoc_id
 %type <errno_info> opt_errno
 %type <chunk_list> sctp_chunk_list_spec
 %type <chunk_list_item> sctp_chunk_spec
@@ -2589,9 +2591,10 @@ sockaddr
 
 data
 : ELLIPSIS { new_expression(EXPR_ELLIPSIS); }
-| sctp_assoc_change_event { $$ = $1; }
-| sctp_shutdown_event { $$ = $1; }
-| sctp_sender_dry_event { $$ = $1; }
+| sctp_assoc_change         { $$ = $1; }
+| sctp_shutdown_event       { $$ = $1; }
+| sctp_sender_dry_event     { $$ = $1; }
+| sctp_send_failed_event    { $$ = $1; }
 ;
 
 msghdr
@@ -3631,6 +3634,76 @@ sctp_sender_dry_event
 	$$->value.sctp_sender_dry_event->sender_dry_assoc_id = $8;
 }
 ;
+ssfe_type
+: SSFE_TYPE '=' INTEGER {
+	if (!is_valid_u16($3)) {
+		semantic_error("ssfe_type out of range");
+	}
+	$$ = new_integer_expression($3, "%hu");
+}
+| SSFE_TYPE '=' WORD {
+	$$ = new_expression(EXPR_WORD);
+	$$->value.string = $3;
+}
+| SSFE_TYPE '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+ssfe_flags
+: SSFE_FLAGS '=' INTEGER {
+	if (!is_valid_u16($3)) {
+		semantic_error("ssfe_flags out of range");
+	}
+	$$ = new_integer_expression($3, "%hu");
+}
+| SSFE_FLAGS '=' WORD {
+	$$ = new_expression(EXPR_WORD);
+	$$->value.string = $3;
+}
+| SSFE_FLAGS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+ssfe_length
+: SSFE_LENGTH '=' INTEGER {
+	if (!is_valid_u32($3)) {
+		semantic_error("ssfe_length out of range");
+	}
+	$$ = new_integer_expression($3, "%u");
+}
+| SSFE_LENGTH '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+ssfe_error
+: SSFE_ERROR '=' INTEGER {
+	if (!is_valid_u32($3)) {
+		semantic_error("ssfe_error out of range");
+	}
+	$$ = new_integer_expression($3, "%u");
+}
+| SSFE_ERROR '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+ssfe_assoc_id
+: SSFE_ASSOC_ID '=' INTEGER {
+	if (!is_valid_u32($3)) {
+		semantic_error("ssfe_assoc_id out of range");
+	}
+	$$ = new_integer_expression($3, "%u");
+}
+| SSFE_ASSOC_ID '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sctp_send_failed_event
+: '{' ssfe_type ',' ssfe_flags ',' ssfe_length ',' ssfe_error ',' SSFE_INFO '=' sctp_sndinfo ',' ssfe_assoc_id ',' SSFE_DATA '=' ELLIPSIS '}' {
+	$$ = new_expression(EXPR_SCTP_SEND_FAILED_EVENT);
+	$$->value.sctp_send_failed_event = calloc(1, sizeof(struct sctp_send_failed_event_expr));
+	$$->value.sctp_send_failed_event->ssfe_type = $2;
+	$$->value.sctp_send_failed_event->ssfe_flags = $4;
+	$$->value.sctp_send_failed_event->ssfe_length = $6;
+	$$->value.sctp_send_failed_event->ssfe_error = $8;
+	$$->value.sctp_send_failed_event->ssfe_info = $12;
+	$$->value.sctp_send_failed_event->ssfe_assoc_id = $14;
+	$$->value.sctp_send_failed_event->ssfe_data = new_expression(EXPR_ELLIPSIS);
+};
 
 sac_type
 : SAC_TYPE '=' INTEGER {
@@ -3720,20 +3793,20 @@ sac_assoc_id
 | SAC_ASSOC_ID '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
 ;
 
-sctp_assoc_change_event
+sctp_assoc_change
 : '{' sac_type ',' sac_flags ',' sac_length ',' sac_state ',' sac_error ',' sac_outbound_streams ','
 sac_inbound_streams ',' sac_assoc_id ',' SAC_INFO '=' ELLIPSIS '}' {
-	$$ = new_expression(EXPR_SCTP_ASSOC_CHANGE_EVENT);
-	$$->value.sctp_assoc_change_event = calloc(1, sizeof(struct sctp_assoc_change_event_expr));
-	$$->value.sctp_assoc_change_event->sac_type = $2;
-	$$->value.sctp_assoc_change_event->sac_flags = $4;
-	$$->value.sctp_assoc_change_event->sac_length = $6;
-	$$->value.sctp_assoc_change_event->sac_state = $8;
-	$$->value.sctp_assoc_change_event->sac_error = $10;
-	$$->value.sctp_assoc_change_event->sac_outbound_streams = $12;
-	$$->value.sctp_assoc_change_event->sac_inbound_streams = $14;
-	$$->value.sctp_assoc_change_event->sac_assoc_id = $16;
-	$$->value.sctp_assoc_change_event->sac_info = new_expression(EXPR_ELLIPSIS);
+	$$ = new_expression(EXPR_SCTP_ASSOC_CHANGE);
+	$$->value.sctp_assoc_change = calloc(1, sizeof(struct sctp_assoc_change_expr));
+	$$->value.sctp_assoc_change->sac_type = $2;
+	$$->value.sctp_assoc_change->sac_flags = $4;
+	$$->value.sctp_assoc_change->sac_length = $6;
+	$$->value.sctp_assoc_change->sac_state = $8;
+	$$->value.sctp_assoc_change->sac_error = $10;
+	$$->value.sctp_assoc_change->sac_outbound_streams = $12;
+	$$->value.sctp_assoc_change->sac_inbound_streams = $14;
+	$$->value.sctp_assoc_change->sac_assoc_id = $16;
+	$$->value.sctp_assoc_change->sac_info = new_expression(EXPR_ELLIPSIS);
 }
 ;
 
diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c
index 80087b9b337878d6d20020c1b2cf881ba366ab37..664d0a8af11c7249f3933b62a1eb4d5e0fe1d621 100644
--- a/gtests/net/packetdrill/run_system_call.c
+++ b/gtests/net/packetdrill/run_system_call.c
@@ -414,6 +414,72 @@ static int get_sockstorage_arg(struct expression *arg, struct sockaddr_storage *
 }
 #endif
 
+#if defined(__FreeBSD__) || defined(linux)
+int check_u8_expr(struct expression *expr, u8 value, char *val_name, char **error) {
+	if (expr->type != EXPR_ELLIPSIS) {
+		u8 script_val;
+		 
+		if (get_u8(expr, &script_val, error)) {
+			return STATUS_ERR;
+		}
+		if (script_val != value) {
+			asprintf(error, "%s: expected: %hhu actual: %hhu", val_name, script_val, value);
+			return STATUS_ERR;
+		}
+	}
+	return STATUS_OK;
+}
+#endif
+
+#if defined(__FreeBSD__) || defined(linux)
+int check_u16_expr(struct expression *expr, u16 value, char *val_name, char **error) {
+	if (expr->type != EXPR_ELLIPSIS) {
+		u16 script_val;
+		 
+		if (get_u16(expr, &script_val, error)) {
+			return STATUS_ERR;
+		}
+		if (script_val != value) {
+			asprintf(error, "%s: expected: %hu actual: %hu", val_name, script_val, value);
+			return STATUS_ERR;
+		}
+	}
+	return STATUS_OK;
+}
+#endif
+
+int check_s32_expr(struct expression *expr, s16 value, char *val_name, char **error) {
+	if (expr->type != EXPR_ELLIPSIS) {
+		s32 script_val;
+		 
+		if (get_s32(expr, &script_val, error)) {
+			return STATUS_ERR;
+		}
+		if (script_val != value) {
+			asprintf(error, "%s: expected: %d actual: %d", val_name, script_val, value);
+			return STATUS_ERR;
+		}
+	}
+	return STATUS_OK;
+}
+
+#if defined(__FreeBSD__) || defined(linux)
+int check_u32_expr(struct expression *expr, u16 value, char *val_name, char **error) {
+	if (expr->type != EXPR_ELLIPSIS) {
+		u32 script_val;
+		 
+		if (get_u32(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
+
 /* Free all the space used by the given iovec. */
 static void iovec_free(struct iovec *iov, size_t iov_len)
 {
@@ -460,8 +526,10 @@ static int iovec_new(struct expression *expression,
 		iov_expr = list->expression->value.iovec;
 
 		assert(iov_expr->iov_base->type == EXPR_ELLIPSIS ||
+		       iov_expr->iov_base->type == EXPR_SCTP_ASSOC_CHANGE ||
 		       iov_expr->iov_base->type == EXPR_SCTP_SHUTDOWN_EVENT ||
-		       iov_expr->iov_base->type == EXPR_SCTP_SENDER_DRY_EVENT);
+		       iov_expr->iov_base->type == EXPR_SCTP_SENDER_DRY_EVENT ||
+		       iov_expr->iov_base->type == EXPR_SCTP_SEND_FAILED_EVENT);
 		assert(iov_expr->iov_len->type == EXPR_INTEGER);
 
 		len = iov_expr->iov_len->value.num;
@@ -1743,30 +1811,13 @@ static int syscall_shutdown(struct state *state, struct syscall_spec *syscall,
 static int check_linger(struct linger_expr *expr,
 			struct linger *linger, char **error)
 {
-	if (expr->l_onoff->type != EXPR_ELLIPSIS) {
-		int l_onoff;
-
-		if (get_s32(expr->l_onoff, &l_onoff, error)) {
-			return STATUS_ERR;
-		}
-		if (linger->l_onoff != l_onoff) {
-			asprintf(error, "linger.l_onoff: expected: %d actual: %d",
-				 l_onoff, linger->l_onoff);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->l_linger->type != EXPR_ELLIPSIS) {
-		int l_linger;
+	if (check_s32_expr(expr->l_onoff, linger->l_onoff,
+			   "linger.l_onoff", error))
+		return STATUS_ERR;
+	if (check_s32_expr(expr->l_linger, linger->l_linger,
+			   "linger.l_linger", error))
+		return STATUS_ERR;
 
-		if (get_s32(expr->l_linger, &l_linger, error)) {
-			return STATUS_ERR;
-		}
-		if (linger->l_linger != l_linger) {
-			asprintf(error, "linger.l_linger: expected: %d actual: %d",
-				 l_linger, linger->l_linger);
-			return STATUS_ERR;
-		}
-	}
 	return STATUS_OK;
 }
 
@@ -1774,42 +1825,16 @@ 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 (expr->srto_initial->type != EXPR_ELLIPSIS) {
-		u32 srto_initial;
-
-		if (get_u32(expr->srto_initial, &srto_initial, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_rtoinfo->srto_initial != srto_initial) {
-			asprintf(error, "sctp_rtoinfo.srto_initial: expected: %u actual: %u",
-				 srto_initial, sctp_rtoinfo->srto_initial);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->srto_max->type != EXPR_ELLIPSIS) {
-		u32 srto_max;
-
-		if (get_u32(expr->srto_max, &srto_max, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_rtoinfo->srto_max != srto_max) {
-			asprintf(error, "sctp_rtoinfo.srto_max: expected: %u actual: %u",
-				 srto_max, sctp_rtoinfo->srto_max);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->srto_min->type != EXPR_ELLIPSIS) {
-		u32 srto_min;
+	if (check_u32_expr(expr->srto_initial, sctp_rtoinfo->srto_initial,
+			   "sctp_rtoinfo.srto_initial", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->srto_max, sctp_rtoinfo->srto_max,
+			   "sctp_rtoinfo.srto_max", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->srto_min, sctp_rtoinfo->srto_min,
+			   "sctp_rtoinfo.srto_min", error))
+		return STATUS_ERR;
 
-		if (get_u32(expr->srto_min, &srto_min, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_rtoinfo->srto_min != srto_min) {
-			asprintf(error, "sctp_rtoinfo.srto_min: expected: %u actual: %u",
-				srto_min, sctp_rtoinfo->srto_min);
-			return STATUS_ERR;
-		}
-	}
 	return STATUS_OK;
 }
 #endif
@@ -1818,54 +1843,19 @@ static int check_sctp_rtoinfo(struct sctp_rtoinfo_expr *expr,
 static int check_sctp_initmsg(struct sctp_initmsg_expr *expr,
 			      struct sctp_initmsg *sctp_initmsg, char **error)
 {
-	if (expr->sinit_num_ostreams->type != EXPR_ELLIPSIS) {
-		u16 sinit_num_ostreams;
-
-		if (get_u16(expr->sinit_num_ostreams, &sinit_num_ostreams, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_initmsg->sinit_num_ostreams != sinit_num_ostreams) {
-			asprintf(error, "sctp_initmsg.sinit_num_ostreams: expected: %hu actual: %hu",
-				 sinit_num_ostreams, sctp_initmsg->sinit_num_ostreams);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sinit_max_instreams->type != EXPR_ELLIPSIS) {
-		u16 sinit_max_instreams;
-
-		if (get_u16(expr->sinit_max_instreams, &sinit_max_instreams, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_initmsg->sinit_max_instreams != sinit_max_instreams) {
-			asprintf(error, "sctp_initmsg.sinit_max_instreams: expected: %hu actual: %hu",
-				 sinit_max_instreams, sctp_initmsg->sinit_max_instreams);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sinit_max_attempts->type != EXPR_ELLIPSIS) {
-		u16 sinit_max_attempts;
-
-		if (get_u16(expr->sinit_max_attempts, &sinit_max_attempts, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_initmsg->sinit_max_attempts != sinit_max_attempts) {
-			asprintf(error, "sctp_initmsg.sinit_max_attempts: expected: %hu actual: %hu",
-				 sinit_max_attempts, sctp_initmsg->sinit_max_attempts);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sinit_max_init_timeo->type != EXPR_ELLIPSIS) {
-		u16 sinit_max_init_timeo;
+	if (check_u16_expr(expr->sinit_num_ostreams, sctp_initmsg->sinit_num_ostreams,
+			   "sctp_initmsg.sinit_num_ostreams", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->sinit_max_instreams, sctp_initmsg->sinit_max_instreams,
+			   "sctp_initmsg.sinit_max_instreams", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->sinit_max_attempts, sctp_initmsg->sinit_max_attempts,
+			   "sctp_initmsg.sinit_max_attempts", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->sinit_max_init_timeo, sctp_initmsg->sinit_max_init_timeo,
+			   "sctp_initmsg.sinit_max_init_timeo", error))
+		return STATUS_ERR;
 
-		if (get_u16(expr->sinit_max_init_timeo, &sinit_max_init_timeo, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_initmsg->sinit_max_init_timeo != sinit_max_init_timeo) {
-			asprintf(error, "sctp_initmsg.sinit_max_init_timeo: expected: %hu actual: %hu",
-				 sinit_max_init_timeo, sctp_initmsg->sinit_max_init_timeo);
-			return STATUS_ERR;
-		}
-	}
 	return STATUS_OK;
 }
 #endif
@@ -1875,30 +1865,13 @@ static int check_sctp_sack_info(struct sctp_sack_info_expr *expr,
 				struct sctp_sack_info *sctp_sack_info,
 				char **error)
 {
-	if (expr->sack_delay->type != EXPR_ELLIPSIS) {
-		u32 sack_delay;
-
-		if (get_u32(expr->sack_delay, &sack_delay, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_sack_info->sack_delay != sack_delay) {
-			asprintf(error, "sctp_sack_info.sack_delay: expected: %u actual: %u",
-				 sack_delay, sctp_sack_info->sack_delay);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sack_freq->type != EXPR_ELLIPSIS) {
-		u32 sack_freq;
+	if (check_u32_expr(expr->sack_delay, sctp_sack_info->sack_delay,
+			   "sctp_sack_info.sack_delay", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->sack_freq, sctp_sack_info->sack_freq,
+			   "sctp_sack_info.sack_freq", error))
+		return STATUS_ERR;
 
-		if (get_u32(expr->sack_freq, &sack_freq, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_sack_info->sack_freq != sack_freq) {
-			asprintf(error, "sctp_sack_info.sack_freq: expected: %u actual: %u",
-				 sack_freq, sctp_sack_info->sack_freq);
-			return STATUS_ERR;
-		}
-	}
 	return STATUS_OK;
 }
 #endif
@@ -1908,66 +1881,22 @@ static int check_sctp_paddrinfo(struct sctp_paddrinfo_expr *expr,
 				struct sctp_paddrinfo *sctp_paddrinfo,
 				char **error)
 {
-	if (expr->spinfo_state->type != EXPR_ELLIPSIS) {
-		s32 spinfo_state;
-
-		if (get_s32(expr->spinfo_state, &spinfo_state, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_paddrinfo->spinfo_state != spinfo_state) {
-			asprintf(error, "sctp_paddrinfo.spinfo_state: expected: %u actual: %u",
-				spinfo_state, sctp_paddrinfo->spinfo_state);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->spinfo_cwnd->type != EXPR_ELLIPSIS) {
-		u32 spinfo_cwnd;
-
-		if (get_u32(expr->spinfo_cwnd, &spinfo_cwnd, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_paddrinfo->spinfo_cwnd != spinfo_cwnd) {
-			asprintf(error, "sctp_paddrinfo.spinfo_cwnd: expected: %u actual: %u",
-				 spinfo_cwnd, sctp_paddrinfo->spinfo_cwnd);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->spinfo_srtt->type != EXPR_ELLIPSIS) {
-		u32 spinfo_srtt;
-
-		if (get_u32(expr->spinfo_srtt, &spinfo_srtt, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_paddrinfo->spinfo_srtt != spinfo_srtt) {
-			asprintf(error, "sctp_paddrinfo.spinfo_srtt: expected: %u actual: %u",
-				 spinfo_srtt, sctp_paddrinfo->spinfo_srtt);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->spinfo_rto->type != EXPR_ELLIPSIS) {
-		u32 spinfo_rto;
-
-		if (get_u32(expr->spinfo_rto, &spinfo_rto, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_paddrinfo->spinfo_rto != spinfo_rto) {
-			asprintf(error, "sctp_paddrinfo.spinfo_rto: expected: %u actual: %u",
-				 spinfo_rto, sctp_paddrinfo->spinfo_rto);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->spinfo_mtu->type != EXPR_ELLIPSIS) {
-		u32 spinfo_mtu;
+	if (check_s32_expr(expr->spinfo_state, sctp_paddrinfo->spinfo_state,
+			   "sctp_paddrinfo.spinfo_state", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->spinfo_cwnd, sctp_paddrinfo->spinfo_cwnd,
+			   "sctp_paddrinfo.spinfo_cwnd", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->spinfo_srtt, sctp_paddrinfo->spinfo_srtt,
+			   "sctp_paddrinfo.spinfo_srtt", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->spinfo_rto, sctp_paddrinfo->spinfo_rto,
+			   "sctp_paddrinfo.spinfo_rto", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->spinfo_mtu, sctp_paddrinfo->spinfo_mtu,
+			   "sctp_paddrinfo.spinfo_mtu", error))
+		return STATUS_ERR;
 
-		if (get_u32(expr->spinfo_mtu, &spinfo_mtu, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_paddrinfo->spinfo_mtu != spinfo_mtu) {
-			asprintf(error, "sctp_paddrinfo.spinfo_mtu: expected: %u actual: %u",
-				 spinfo_mtu, sctp_paddrinfo->spinfo_mtu);
-			return STATUS_ERR;
-		}
-	}
 	return STATUS_OK;
 }
 #endif
@@ -1977,90 +1906,27 @@ static int check_sctp_status(struct sctp_status_expr *expr,
 			     struct sctp_status *sctp_status,
 			     char **error)
 {
-	if (expr->sstat_state->type != EXPR_ELLIPSIS) {
-		s32 sstat_state;
-
-		if (get_s32(expr->sstat_state, &sstat_state, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_status->sstat_state != sstat_state) {
-			asprintf(error, "sctp_status.sstat_state: expected: %d actual: %d",
-				 sstat_state, sctp_status->sstat_state);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sstat_rwnd->type != EXPR_ELLIPSIS) {
-		u32 sstat_rwnd;
-
-		if (get_u32(expr->sstat_rwnd, &sstat_rwnd, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_status->sstat_rwnd != sstat_rwnd) {
-			asprintf(error, "sctp_status.sstat_rwnd: expected: %u actual: %u",
-				 sstat_rwnd, sctp_status->sstat_rwnd);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sstat_unackdata->type != EXPR_ELLIPSIS) {
-		u16 sstat_unackdata;
-
-		if (get_u16(expr->sstat_unackdata, &sstat_unackdata, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_status->sstat_unackdata != sstat_unackdata) {
-			asprintf(error, "sctp_status.sstat_unackdata: expected: %hu actual: %hu",
-				 sstat_unackdata, sctp_status->sstat_unackdata);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sstat_penddata->type != EXPR_ELLIPSIS) {
-		u16 sstat_penddata;
-
-		if (get_u16(expr->sstat_penddata, &sstat_penddata, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_status->sstat_penddata != sstat_penddata) {
-			asprintf(error, "sctp_status.sstat_penddata: expected: %hu actual: %hu",
-				 sstat_penddata, sctp_status->sstat_penddata);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sstat_instrms->type != EXPR_ELLIPSIS) {
-		u16 sstat_instrms;
-
-		if (get_u16(expr->sstat_instrms, &sstat_instrms, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_status->sstat_instrms != sstat_instrms) {
-			asprintf(error, "sctp_status.sstat_instrms: expected: %hu actual: %hu",
-				 sstat_instrms, sctp_status->sstat_instrms);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sstat_outstrms->type != EXPR_ELLIPSIS) {
-		u16 sstat_outstrms;
-
-		if (get_u16(expr->sstat_outstrms, &sstat_outstrms, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_status->sstat_outstrms != sstat_outstrms) {
-			asprintf(error, "sctp_status.sstat_outstrms: expected: %hu actual: %hu",
-				 sstat_outstrms, sctp_status->sstat_outstrms);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sstat_fragmentation_point->type != EXPR_ELLIPSIS) {
-		u32 sstat_fragmentation_point;
-
-		if (get_u32(expr->sstat_fragmentation_point, &sstat_fragmentation_point, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_status->sstat_fragmentation_point != sstat_fragmentation_point) {
-			asprintf(error, "sctp_status.sstat_fragmentation_point: expected: %u actual: %u",
-				sstat_fragmentation_point, sctp_status->sstat_fragmentation_point);
-			return STATUS_ERR;
-		}
-	}
+	if (check_s32_expr(expr->sstat_state, sctp_status->sstat_state,
+			   "sctp_status.sstat_state", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->sstat_rwnd, sctp_status->sstat_rwnd,
+			   "sctp_status.sstat_rwnd", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->sstat_unackdata, sctp_status->sstat_unackdata,
+			   "sctp_status.sstat_unackdata", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->sstat_penddata, sctp_status->sstat_penddata,
+			   "sctp_status.sstat_penddata", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->sstat_instrms, sctp_status->sstat_instrms,
+			   "sctp_status.sstat_instrms", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->sstat_outstrms, sctp_status->sstat_outstrms,
+			   "sctp_status.sstat_outstrms", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->sstat_fragmentation_point, sctp_status->sstat_fragmentation_point,
+			   "sctp_status.sstat_fragmentation_point", error))
+		return STATUS_ERR;
 	if (expr->sstat_primary->type != EXPR_ELLIPSIS) {
 		if (check_sctp_paddrinfo(expr->sstat_primary->value.sctp_paddrinfo,
 					 &sctp_status->sstat_primary, error)) {
@@ -2076,69 +1942,27 @@ static int check_sctp_paddrparams(struct sctp_paddrparams_expr *expr,
 				  struct sctp_paddrparams *sctp_paddrparams,
 				  char **error)
 {
-	if (expr->spp_hbinterval->type != EXPR_ELLIPSIS) {
-		u32 spp_hbinterval;
-
-		if (get_u32(expr->spp_hbinterval, &spp_hbinterval, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_paddrparams->spp_hbinterval != spp_hbinterval) {
-			asprintf(error, "sctp_paddrparams.spp_hbinterval: expected: %u actual: %u",
-				 spp_hbinterval, sctp_paddrparams->spp_hbinterval);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->spp_pathmaxrxt->type != EXPR_ELLIPSIS) {
-		u16 spp_pathmaxrxt;
-
-		if (get_u16(expr->spp_pathmaxrxt, &spp_pathmaxrxt, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_paddrparams->spp_pathmaxrxt != spp_pathmaxrxt) {
-			asprintf(error, "sctp_paddrparams.spp_pathmaxrxt: expected: %hu actual: %hu",
-				 spp_pathmaxrxt, sctp_paddrparams->spp_pathmaxrxt);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->spp_pathmtu->type != EXPR_ELLIPSIS) {
-		u32 spp_pathmtu;
-
-		if (get_u32(expr->spp_pathmtu, &spp_pathmtu, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_paddrparams->spp_pathmtu != spp_pathmtu) {
-			asprintf(error, "sctp_paddrparams.spp_pathmtu: expected: %u actual: %u",
-				 spp_pathmtu, sctp_paddrparams->spp_pathmtu);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->spp_flags->type != EXPR_ELLIPSIS) {
-		u32 spp_flags;
+	if (check_u32_expr(expr->spp_hbinterval, sctp_paddrparams->spp_hbinterval,
+			   "sctp_paddrparams.spp_hbinterval", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->spp_pathmaxrxt, sctp_paddrparams->spp_pathmaxrxt,
+			   "sctp_paddrparams.spp_pathmaxrxt", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->spp_pathmtu, sctp_paddrparams->spp_pathmtu,
+			   "sctp_paddrparams.spp_pathmtu", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->spp_flags, sctp_paddrparams->spp_flags,
+			   "sctp_paddrparams.spp_flags", error))
+		return STATUS_ERR;
 
-		if (get_u32(expr->spp_flags, &spp_flags, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_paddrparams->spp_flags != spp_flags) {
-			asprintf(error, "sctp_paddrparams.spp_flags: expected: 0x%08x actual: 0x%08x",
-				 spp_flags, sctp_paddrparams->spp_flags);
-			return STATUS_ERR;
-		}
-	}
 	if (expr->spp_ipv6_flowlabel->type != EXPR_ELLIPSIS) {
 #ifdef linux
 		asprintf(error, "linux doesn't support sctp_paddrparams.spp_ipv6_flowlabel");
 		return STATUS_ERR;
 #else
-		u32 spp_ipv6_flowlabel;
-
-		if (get_u32(expr->spp_ipv6_flowlabel, &spp_ipv6_flowlabel, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_paddrparams->spp_ipv6_flowlabel != spp_ipv6_flowlabel) {
-			asprintf(error, "sctp_paddrparams.spp_ipv6_flowlabel: expected: %u actual: %u",
-				 spp_ipv6_flowlabel, sctp_paddrparams->spp_ipv6_flowlabel);
+		if (check_u32_expr(expr->spp_ipv6_flowlabel, sctp_paddrparams->spp_ipv6_flowlabel,
+				   "sctp_paddrparams.spp_ipv6_flowlabel", error))
 			return STATUS_ERR;
-		}
 #endif
 	}
 	if (expr->spp_dscp->type != EXPR_ELLIPSIS) {
@@ -2146,16 +1970,9 @@ static int check_sctp_paddrparams(struct sctp_paddrparams_expr *expr,
 		asprintf(error, "linux doesn't support sctp_paddrparams.spp_dscp");
 		return STATUS_ERR;
 #else
-		u8 spp_dscp;
-
-		if (get_u8(expr->spp_dscp, &spp_dscp, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_paddrparams->spp_dscp != spp_dscp) {
-			asprintf(error, "sctp_paddrparams.spp_dscp: expected: %hhu actual: %hhu",
-				 spp_dscp, sctp_paddrparams->spp_dscp);
+		if (check_u8_expr(expr->spp_dscp, sctp_paddrparams->spp_dscp,
+				   "sctp_paddrparams.spp_dscp", error))
 			return STATUS_ERR;
-		}
 #endif
 	}
 	return STATUS_OK;
@@ -2167,18 +1984,10 @@ static int check_sctp_assoc_value(struct sctp_assoc_value_expr *expr,
 				  struct sctp_assoc_value *sctp_assoc_value,
 				  char **error)
 {
-	if (expr->assoc_value->type != EXPR_ELLIPSIS) {
-		u32 assoc_value;
+	if (check_u16_expr(expr->assoc_value, sctp_assoc_value->assoc_value,
+			   "sctp_assoc_value.stream_id", error))
+		return STATUS_ERR;
 
-		if (get_u32(expr->assoc_value, &assoc_value, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_assoc_value->assoc_value != assoc_value) {
-			asprintf(error, "sctp_assoc_value.assoc_value: expected: %u actual: %u",
-				 assoc_value, sctp_assoc_value->assoc_value);
-			return STATUS_ERR;
-		}
-	}
 	return STATUS_OK;
 }
 #endif
@@ -2188,30 +1997,13 @@ static int check_sctp_stream_value(struct sctp_stream_value_expr *expr,
 				   struct sctp_stream_value *sctp_stream_value,
 				   char **error)
 {
-	if (expr->stream_id->type != EXPR_ELLIPSIS) {
-		u16 stream_id;
-
-		if (get_u16(expr->stream_id, &stream_id, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_stream_value->stream_id != stream_id) {
-			asprintf(error, "sctp_stream_value.stream_id: expected: %u actual: %u",
-				 stream_id, sctp_stream_value->stream_id);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->stream_value->type != EXPR_ELLIPSIS) {
-		u16 stream_value;
+	if (check_u16_expr(expr->stream_id, sctp_stream_value->stream_id,
+			   "sctp_stream_value.stream_id", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->stream_value, sctp_stream_value->stream_value,
+			   "sctp_stream_value.stream_value", error))
+		return STATUS_ERR;
 
-		if (get_u16(expr->stream_value, &stream_value, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_stream_value->stream_value != stream_value) {
-			asprintf(error, "sctp_stream_value.stream_value: expected: %u actual: %u",
-				 stream_value, sctp_stream_value->stream_value);
-			return STATUS_ERR;
-		}
-	}
 	return STATUS_OK;
 }
 #endif
@@ -2221,66 +2013,21 @@ static int check_sctp_assocparams(struct sctp_assocparams_expr *expr,
 			     struct sctp_assocparams *sctp_assocparams,
 			     char **error)
 {
-	if (expr->sasoc_asocmaxrxt->type != EXPR_ELLIPSIS) {
-		u16 sasoc_asocmaxrxt;
-
-		if (get_u16(expr->sasoc_asocmaxrxt, &sasoc_asocmaxrxt, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_assocparams->sasoc_asocmaxrxt != sasoc_asocmaxrxt) {
-			asprintf(error, "sctp_assocparams.sasoc_asocmaxrxt: expected: %hu actual: %hu",
-				 sasoc_asocmaxrxt, sctp_assocparams->sasoc_asocmaxrxt);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sasoc_number_peer_destinations->type != EXPR_ELLIPSIS) {
-		u16 sasoc_number_peer_destinations;
-
-		if (get_u16(expr->sasoc_number_peer_destinations, &sasoc_number_peer_destinations, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_assocparams->sasoc_number_peer_destinations != sasoc_number_peer_destinations) {
-			asprintf(error, "sctp_assocparams.sasoc_number_peer_destinations: expected: %hu actual: %hu",
-					 sasoc_number_peer_destinations, sctp_assocparams->sasoc_number_peer_destinations);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sasoc_peer_rwnd->type != EXPR_ELLIPSIS) {
-		u32 sasoc_peer_rwnd;
-
-		if (get_u32(expr->sasoc_peer_rwnd, &sasoc_peer_rwnd, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_assocparams->sasoc_peer_rwnd != sasoc_peer_rwnd) {
-			asprintf(error, "sctp_assocparams.sasoc_peer_rwnd: expected: %u actual: %u",
-				 sasoc_peer_rwnd, sctp_assocparams->sasoc_peer_rwnd);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sasoc_local_rwnd->type != EXPR_ELLIPSIS) {
-		u32 sasoc_local_rwnd;
-
-		if (get_u32(expr->sasoc_local_rwnd, &sasoc_local_rwnd, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_assocparams->sasoc_local_rwnd != sasoc_local_rwnd) {
-			asprintf(error, "sctp_assocparams.sasoc_local_rwnd: expected: %u actual: %u",
-				 sasoc_local_rwnd, sctp_assocparams->sasoc_local_rwnd);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sasoc_cookie_life->type != EXPR_ELLIPSIS) {
-		u32 sasoc_cookie_life;
-
-		if (get_u32(expr->sasoc_cookie_life, &sasoc_cookie_life, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_assocparams->sasoc_cookie_life != sasoc_cookie_life) {
-			asprintf(error, "sctp_assocparams.sasoc_cookie_life: expected: %u actual: %u",
-				 sasoc_cookie_life, sctp_assocparams->sasoc_cookie_life);
-			return STATUS_ERR;
-		}
-	}
+	if (check_u16_expr(expr->sasoc_asocmaxrxt, sctp_assocparams->sasoc_asocmaxrxt,
+			   "sctp_assocparams.sasoc_asocmaxrxt", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->sasoc_number_peer_destinations, sctp_assocparams->sasoc_number_peer_destinations,
+			   "sctp_assocparams.sasoc_number_peer_destinations", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->sasoc_peer_rwnd, sctp_assocparams->sasoc_peer_rwnd,
+			   "sctp_assocparams.sasoc_peer_rwnd", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->sasoc_local_rwnd, sctp_assocparams->sasoc_local_rwnd,
+			   "sctp_assocparams.sasoc_local_rwnd", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->sasoc_cookie_life, sctp_assocparams->sasoc_cookie_life,
+			   "sctp_assocparams.sasoc_cookie_life", error))
+		return STATUS_ERR;
 
 	return STATUS_OK;
 }
@@ -2291,30 +2038,13 @@ static int check_sctp_event(struct sctp_event_expr *expr,
 			    struct sctp_event *sctp_event,
 			    char **error)
 {
-	if (expr->se_type->type != EXPR_ELLIPSIS) {
-		u16 se_type;
-
-		if (get_u16(expr->se_type, &se_type, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_event->se_type != se_type) {
-			asprintf(error, "sctp_event.se_type: expected: %hu actual: %hu",
-				 se_type, sctp_event->se_type);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->se_on->type != EXPR_ELLIPSIS) {
-		u8 se_on;
+	if (check_u16_expr(expr->se_type, sctp_event->se_type,
+			   "sctp_event.se_type", error))
+		return STATUS_ERR;
+	if (check_u8_expr(expr->se_on, sctp_event->se_on,
+			   "sctp_event.se_on", error))
+		return STATUS_ERR;
 
-		if (get_u8(expr->se_on, &se_on, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_event->se_on != se_on) {
-			asprintf(error, "sctp_event.se_on: expected: %hhu actual: %hhu",
-				 se_on, sctp_event->se_on);
-			return STATUS_ERR;
-		}
-	}
 	return STATUS_OK;
 }
 #endif
@@ -2324,126 +2054,36 @@ static int check_sctp_event_subscribe(struct sctp_event_subscribe_expr *expr,
 				      struct sctp_event_subscribe *sctp_events,
 				      char **error)
 {
-	if (expr->sctp_data_io_event->type != EXPR_ELLIPSIS) {
-		u8 sctp_data_io_event;
-
-		if (get_u8(expr->sctp_data_io_event, &sctp_data_io_event, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_events->sctp_data_io_event != sctp_data_io_event) {
-			asprintf(error, "sctp_event_subscribe.sctp_data_io_event: expected: %hhu actual: %hhu",
-				 sctp_data_io_event, sctp_events->sctp_data_io_event);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sctp_association_event->type != EXPR_ELLIPSIS) {
-		u8 sctp_association_event;
-
-		if (get_u8(expr->sctp_association_event, &sctp_association_event, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_events->sctp_association_event != sctp_association_event) {
-			asprintf(error, "sctp_event_subscribe.sctp_association_event: expected: %hhu actual: %hhu",
-				 sctp_association_event, sctp_events->sctp_association_event);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sctp_address_event->type != EXPR_ELLIPSIS) {
-		u8 sctp_address_event;
-
-		if (get_u8(expr->sctp_address_event, &sctp_address_event, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_events->sctp_address_event != sctp_address_event) {
-			asprintf(error, "sctp_event_subscribe.sctp_address_event: expected: %hhu actual: %hhu",
-				 sctp_address_event, sctp_events->sctp_address_event);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sctp_send_failure_event->type != EXPR_ELLIPSIS) {
-		u8 sctp_send_failure_event;
-
-		if (get_u8(expr->sctp_send_failure_event, &sctp_send_failure_event, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_events->sctp_send_failure_event != sctp_send_failure_event) {
-			asprintf(error, "sctp_event_subscribe.sctp_send_failure_event: expected: %hhu actual: %hhu",
-				 sctp_send_failure_event, sctp_events->sctp_send_failure_event);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sctp_peer_error_event->type != EXPR_ELLIPSIS) {
-		u8 sctp_peer_error_event;
-
-		if (get_u8(expr->sctp_peer_error_event, &sctp_peer_error_event, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_events->sctp_peer_error_event != sctp_peer_error_event) {
-			asprintf(error, "sctp_event_subscribe.sctp_peer_error_event: expected: %hhu actual: %hhu",
-				 sctp_peer_error_event, sctp_events->sctp_peer_error_event);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sctp_shutdown_event->type != EXPR_ELLIPSIS) {
-		u8 sctp_shutdown_event;
-
-		if (get_u8(expr->sctp_shutdown_event, &sctp_shutdown_event, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_events->sctp_shutdown_event != sctp_shutdown_event) {
-			asprintf(error, "sctp_event_subscribe.sctp_shutdown_event: expected: %hhu actual: %hhu",
-				 sctp_shutdown_event, sctp_events->sctp_shutdown_event);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sctp_partial_delivery_event->type != EXPR_ELLIPSIS) {
-		u8 sctp_partial_delivery_event;
-
-		if (get_u8(expr->sctp_partial_delivery_event, &sctp_partial_delivery_event, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_events->sctp_partial_delivery_event != sctp_partial_delivery_event) {
-			asprintf(error, "sctp_event_subscribe.sctp_partial_delivery_event: expected: %hhu actual: %hhu",
-				 sctp_partial_delivery_event, sctp_events->sctp_partial_delivery_event);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sctp_adaptation_layer_event->type != EXPR_ELLIPSIS) {
-		u8 sctp_adaptation_layer_event;
-
-		if (get_u8(expr->sctp_adaptation_layer_event, &sctp_adaptation_layer_event, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_events->sctp_adaptation_layer_event != sctp_adaptation_layer_event) {
-			asprintf(error, "sctp_event_subscribe.sctp_adaptation_layer_event: expected: %hhu actual: %hhu",
-				 sctp_adaptation_layer_event, sctp_events->sctp_adaptation_layer_event);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sctp_authentication_event->type != EXPR_ELLIPSIS) {
-		u8 sctp_authentication_event;
-
-		if (get_u8(expr->sctp_authentication_event, &sctp_authentication_event, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_events->sctp_authentication_event != sctp_authentication_event) {
-			asprintf(error, "sctp_event_subscribe.sctp_authentication_event: expected: %hhu actual: %hhu",
-				 sctp_authentication_event, sctp_events->sctp_authentication_event);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sctp_sender_dry_event->type != EXPR_ELLIPSIS) {
-		u8 sctp_sender_dry_event;
-
-		if (get_u8(expr->sctp_sender_dry_event, &sctp_sender_dry_event, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_events->sctp_sender_dry_event != sctp_sender_dry_event) {
-			asprintf(error, "sctp_event_subscribe.sctp_sender_dry_event: expected: %hhu actual: %hhu",
-				 sctp_sender_dry_event, sctp_events->sctp_sender_dry_event);
-			return STATUS_ERR;
-		}
-	}
+	if (check_u8_expr(expr->sctp_data_io_event, sctp_events->sctp_data_io_event,
+			   "sctp_event_subscribe.sctp_data_io_event", error))
+		return STATUS_ERR;
+	if (check_u8_expr(expr->sctp_association_event, sctp_events->sctp_association_event,
+			   "sctp_event_subscribe.sctp_association_event", error))
+		return STATUS_ERR;
+	if (check_u8_expr(expr->sctp_address_event, sctp_events->sctp_address_event,
+			   "sctp_event_subscribe.sctp_address_event", error))
+		return STATUS_ERR;
+	if (check_u8_expr(expr->sctp_send_failure_event, sctp_events->sctp_send_failure_event,
+			   "sctp_event_subscribe.sctp_send_failure_event", error))
+		return STATUS_ERR;
+	if (check_u8_expr(expr->sctp_peer_error_event, sctp_events->sctp_peer_error_event,
+			   "sctp_event_subscribe.sctp_peer_error_event", error))
+		return STATUS_ERR;
+	if (check_u8_expr(expr->sctp_shutdown_event, sctp_events->sctp_shutdown_event,
+			   "sctp_event_subscribe.sctp_shutdown_event", error))
+		return STATUS_ERR;
+	if (check_u8_expr(expr->sctp_partial_delivery_event, sctp_events->sctp_partial_delivery_event,
+			   "sctp_event_subscribe.sctp_partial_delivery_event", error))
+		return STATUS_ERR;
+	if (check_u8_expr(expr->sctp_adaptation_layer_event, sctp_events->sctp_adaptation_layer_event,
+			   "sctp_event_subscribe.sctp_adaptation_layer_event", error))
+		return STATUS_ERR;
+	if (check_u8_expr(expr->sctp_authentication_event, sctp_events->sctp_authentication_event,
+			   "sctp_event_subscribe.sctp_authentication_event", error))
+		return STATUS_ERR;
+	if (check_u8_expr(expr->sctp_sender_dry_event, sctp_events->sctp_sender_dry_event,
+			   "sctp_event_subscribe.sctp_sender_dry_event", error))
+		return STATUS_ERR;
 
 	return STATUS_OK;
 }
@@ -2453,30 +2093,12 @@ static int check_sctp_sndinfo(struct sctp_sndinfo_expr *expr,
 			      struct sctp_sndinfo *sctp_sndinfo,
 			      char **error)
 {
-	if (expr->snd_sid->type != EXPR_ELLIPSIS) {
-		u16 snd_sid;
-
-		if (get_u16(expr->snd_sid, &snd_sid, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_sndinfo->snd_sid != snd_sid) {
-			asprintf(error, "sctp_sndinfo.snd_sid: expected: %hu actual: %hu",
-				 snd_sid, sctp_sndinfo->snd_sid);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->snd_flags->type != EXPR_ELLIPSIS) {
-		u16 snd_flags;
-
-		if (get_u16(expr->snd_flags, &snd_flags, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_sndinfo->snd_flags != snd_flags) {
-			asprintf(error, "sctp_sndinfo.snd_flags: expected: %hu actual: %hu",
-				 snd_flags, sctp_sndinfo->snd_flags);
-			return STATUS_ERR;
-		}
-	}
+	if (check_u16_expr(expr->snd_sid, sctp_sndinfo->snd_sid,
+			   "sctp_sndinfo.snd_sid", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->snd_flags, sctp_sndinfo->snd_flags,
+			   "sctp_sndinfo.snd_flags", error))
+		return STATUS_ERR;
 	if (expr->snd_ppid->type != EXPR_ELLIPSIS) {
 		u32 snd_ppid;
 
@@ -2489,18 +2111,10 @@ static int check_sctp_sndinfo(struct sctp_sndinfo_expr *expr,
 			return STATUS_ERR;
 		}
 	}
-	if (expr->snd_context->type != EXPR_ELLIPSIS) {
-		u32 snd_context;
+	if (check_u32_expr(expr->snd_context, sctp_sndinfo->snd_context,
+			   "sctp_sndinfo.snd_context", error))
+		return STATUS_ERR;
 
-		if (get_u32(expr->snd_context, &snd_context, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_sndinfo->snd_context != snd_context) {
-			asprintf(error, "sctp_sndinfo.snd_context: expected: %u actual: %u",
-				 snd_context, sctp_sndinfo->snd_context);
-			return STATUS_ERR;
-		}
-	}
 	return STATUS_OK;
 }
 #endif
@@ -2510,18 +2124,10 @@ static int check_sctp_setadaptation(struct sctp_setadaptation_expr *expr,
 				    struct sctp_setadaptation *sctp_setadaptation,
 				    char **error)
 {
-	if (expr->ssb_adaptation_ind->type != EXPR_ELLIPSIS) {
-		u32 ssb_adaptation_ind;
+	if (check_u32_expr(expr->ssb_adaptation_ind, sctp_setadaptation->ssb_adaptation_ind,
+			   "sctp_setadptation.ssb_adaptation_ind", error))
+		return STATUS_ERR;
 
-		if (get_u32(expr->ssb_adaptation_ind, &ssb_adaptation_ind, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_setadaptation->ssb_adaptation_ind != ssb_adaptation_ind) {
-			asprintf(error, "sctp_setadaptation.ssb_adaptation_ind: expected: %u actual: %u",
-				 ssb_adaptation_ind, sctp_setadaptation->ssb_adaptation_ind);
-			return STATUS_ERR;
-		}
-	}
 	return STATUS_OK;
 }
 #endif
@@ -3199,7 +2805,7 @@ error_out:
 static int syscall_sctp_sendmsg(struct state *state, struct syscall_spec *syscall,
 			struct expression_list *args, char **error)
 {
-#if defined(__FreeBSD__) || defined(__Linux__)
+#if defined(__FreeBSD__) || defined(linux)
 	int result, script_fd, live_fd, len;
 	void *msg = NULL;
 	struct sockaddr_storage to;
@@ -3279,46 +2885,19 @@ static int syscall_sctp_sendmsg(struct state *state, struct syscall_spec *syscal
 #endif
 }
 
-#if defined(__FreeBSD__) || defined(__Linux__)
+#if defined(__FreeBSD__) || defined(linux)
 static int check_sctp_sndrcvinfo(struct sctp_sndrcvinfo_expr *expr,
 				 struct sctp_sndrcvinfo *sctp_sndrcvinfo,
 				 char** error) {
-	if (expr->sinfo_stream->type != EXPR_ELLIPSIS) {
-		u16 sinfo_stream;
-
-		if (get_u16(expr->sinfo_stream, &sinfo_stream, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_sndrcvinfo->sinfo_stream != sinfo_stream) {
-			asprintf(error, "sctp_sndrcvinfo.sinfo_stream: expected: %hu actual: %hu",
-				 sinfo_stream, sctp_sndrcvinfo->sinfo_stream);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sinfo_ssn->type != EXPR_ELLIPSIS) {
-		u16 sinfo_ssn;
-
-		if (get_u16(expr->sinfo_ssn, &sinfo_ssn, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_sndrcvinfo->sinfo_ssn != sinfo_ssn) {
-			asprintf(error, "sctp_sndrcvinfo.sinfo_ssn: expected: %hu actual: %hu",
-				 sinfo_ssn, sctp_sndrcvinfo->sinfo_ssn);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sinfo_flags->type != EXPR_ELLIPSIS) {
-		u16 sinfo_flags;
-
-		if (get_u16(expr->sinfo_flags, &sinfo_flags, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_sndrcvinfo->sinfo_flags != sinfo_flags) {
-			asprintf(error, "sctp_sndrcvinfo.sinfo_flags: expected: %hu actual: %hu",
-				 sinfo_flags, sctp_sndrcvinfo->sinfo_flags);
-			return STATUS_ERR;
-		}
-	}
+	if (check_u16_expr(expr->sinfo_stream, sctp_sndrcvinfo->sinfo_stream,
+			   "sctp_sndrcvinfo.sinfo_stream", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->sinfo_ssn, sctp_sndrcvinfo->sinfo_ssn,
+			   "sctp_sndrcvinfo.sinfo_ssn", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->sinfo_flags, sctp_sndrcvinfo->sinfo_flags,
+			   "sctp_sndrcvinfo.sinfo_flags", error))
+		return STATUS_ERR;
 	if (expr->sinfo_ppid->type != EXPR_ELLIPSIS) {
 		u32 sinfo_ppid;
 
@@ -3331,54 +2910,19 @@ static int check_sctp_sndrcvinfo(struct sctp_sndrcvinfo_expr *expr,
 			return STATUS_ERR;
 		}
 	}
-	if (expr->sinfo_context->type != EXPR_ELLIPSIS) {
-		u32 sinfo_context;
-
-		if (get_u32(expr->sinfo_context, &sinfo_context, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_sndrcvinfo->sinfo_context != sinfo_context) {
-			asprintf(error, "sctp_sndrcvinfo.sinfo_context: expected: %u actual: %u",
-				 sinfo_context, sctp_sndrcvinfo->sinfo_context);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sinfo_timetolive->type != EXPR_ELLIPSIS) {
-		u32 sinfo_timetolive;
-
-		if (get_u32(expr->sinfo_timetolive, &sinfo_timetolive, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_sndrcvinfo->sinfo_timetolive != sinfo_timetolive) {
-			asprintf(error, "sctp_sndrcvinfo.sinfo_timetolive: expected: %u actual: %u",
-				 sinfo_timetolive, sctp_sndrcvinfo->sinfo_timetolive);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sinfo_tsn->type != EXPR_ELLIPSIS) {
-		u32 sinfo_tsn;
-
-		if (get_u32(expr->sinfo_tsn, &sinfo_tsn, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_sndrcvinfo->sinfo_tsn != sinfo_tsn) {
-			asprintf(error, "sctp_sndrcvinfo.sinfo_tsn: expected: %u actual: %u",
-				 sinfo_tsn, sctp_sndrcvinfo->sinfo_tsn);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sinfo_cumtsn->type != EXPR_ELLIPSIS) {
-		u32 sinfo_cumtsn;
+	if (check_u32_expr(expr->sinfo_context, sctp_sndrcvinfo->sinfo_context,
+			   "sctp_sndrcvinfo.sinfo_context", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->sinfo_timetolive, sctp_sndrcvinfo->sinfo_timetolive,
+			   "sctp_sndrcvinfo.sinfo_timetolive", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->sinfo_tsn, sctp_sndrcvinfo->sinfo_tsn,
+			   "sctp_sndrcvinfo.sinfo_tsn", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->sinfo_cumtsn, sctp_sndrcvinfo->sinfo_cumtsn,
+			   "sctp_sndrcvinfo.sinfo_cumtsn", error))
+		return STATUS_ERR;
 
-		if (get_u32(expr->sinfo_cumtsn, &sinfo_cumtsn, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_sndrcvinfo->sinfo_cumtsn != sinfo_cumtsn) {
-			asprintf(error, "sctp_sndrcvinfo.sinfo_cumtsn: expected: %u actual: %u",
-				 sinfo_cumtsn, sctp_sndrcvinfo->sinfo_cumtsn);
-			return STATUS_ERR;
-		}
-	}
 	return STATUS_OK;
 }
 
@@ -3450,7 +2994,7 @@ static int syscall_sctp_recvmsg(struct state *state, struct syscall_spec *syscal
 				struct expression_list *args,
 				char **error)
 {
-#if defined(__FreeBSD__) || defined(__Linux__)
+#if defined(__FreeBSD__) || defined(linux)
 	int script_fd, live_fd, live_msg_flags, result;
 	void *msg;
 	u32 len;
@@ -3734,42 +3278,12 @@ static int check_sctp_rcvinfo(struct sctp_rcvinfo_expr *expr,
 			      struct sctp_rcvinfo *sctp_rcvinfo,
 			      char **error)
 {
-	if (expr->rcv_sid->type != EXPR_ELLIPSIS) {
-		u16 rcv_sid;
-
-		if (get_u16(expr->rcv_sid, &rcv_sid, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_rcvinfo->rcv_sid != rcv_sid) {
-			asprintf(error, "sctp_rcvinfo.rcv_sid: expected: %hu actual: %hu",
-				 rcv_sid, sctp_rcvinfo->rcv_sid);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->rcv_ssn->type != EXPR_ELLIPSIS) {
-		u16 rcv_ssn;
-
-		if (get_u16(expr->rcv_ssn, &rcv_ssn, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_rcvinfo->rcv_ssn != rcv_ssn) {
-			asprintf(error, "sctp_rcvinfo.rcv_ssn: expected: %hu actual: %hu",
-				 rcv_ssn, sctp_rcvinfo->rcv_ssn);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->rcv_flags->type != EXPR_ELLIPSIS) {
-		u16 rcv_flags;
-
-		if (get_u16(expr->rcv_flags, &rcv_flags, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_rcvinfo->rcv_flags != rcv_flags) {
-			asprintf(error, "sctp_rcvinfo.rcv_flags: expected: %hu actual: %hu",
-				 rcv_flags, sctp_rcvinfo->rcv_flags);
-			return STATUS_ERR;
-		}
-	}
+	if (check_u16_expr(expr->rcv_sid, sctp_rcvinfo->rcv_sid, "sctp_rcvinfo.rcv_sid", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->rcv_ssn, sctp_rcvinfo->rcv_ssn, "sctp_rcvinfo.rcv_ssn", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->rcv_flags, sctp_rcvinfo->rcv_flags, "sctp_rcvinfo.rcv_flags", error))
+		return STATUS_ERR;
 	if (expr->rcv_ppid->type != EXPR_ELLIPSIS) {
 		u32 rcv_ppid;
 
@@ -3782,42 +3296,16 @@ static int check_sctp_rcvinfo(struct sctp_rcvinfo_expr *expr,
 			return STATUS_ERR;
 		}
 	}
-	if (expr->rcv_tsn->type != EXPR_ELLIPSIS) {
-		u32 rcv_tsn;
-
-		if (get_u32(expr->rcv_tsn, &rcv_tsn, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_rcvinfo->rcv_tsn != rcv_tsn) {
-			asprintf(error, "sctp_rcvinfo.rcv_tsn: expected: %u actual: %u",
-				 rcv_tsn, sctp_rcvinfo->rcv_tsn);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->rcv_cumtsn->type != EXPR_ELLIPSIS) {
-		u32 rcv_cumtsn;
-
-		if (get_u32(expr->rcv_cumtsn, &rcv_cumtsn, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_rcvinfo->rcv_cumtsn != rcv_cumtsn) {
-			asprintf(error, "sctp_rcvinfo.rcv_cumtsn: expected: %u actual: %u",
-				 rcv_cumtsn, sctp_rcvinfo->rcv_cumtsn);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->rcv_context->type != EXPR_ELLIPSIS) {
-		u32 rcv_context;
+	if (check_u32_expr(expr->rcv_tsn, sctp_rcvinfo->rcv_tsn,
+			   "sctp_rcvinfo.rcv_tsn", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->rcv_cumtsn, sctp_rcvinfo->rcv_cumtsn,
+			   "sctp_rcvinfo.rcv_cumtsn", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->rcv_context, sctp_rcvinfo->rcv_context,
+			   "sctp_rcvinfo.rcv_context", error))
+		return STATUS_ERR;
 
-		if (get_u32(expr->rcv_context, &rcv_context, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_rcvinfo->rcv_context != rcv_context) {
-			asprintf(error, "sctp_rcvinfo.rcv_context: expected: %u actual: %u",
-				 rcv_context, sctp_rcvinfo->rcv_context);
-			return STATUS_ERR;
-		}
-	}
 	return STATUS_OK;
 }
 #endif
@@ -3827,30 +3315,10 @@ static int check_sctp_nxtinfo(struct sctp_nxtinfo_expr *expr,
 			      struct sctp_nxtinfo *sctp_nxtinfo,
 			      char **error)
 {
-	if (expr->nxt_sid->type != EXPR_ELLIPSIS) {
-		u16 nxt_sid;
-
-		if (get_u16(expr->nxt_sid, &nxt_sid, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_nxtinfo->nxt_sid != nxt_sid) {
-			asprintf(error, "sctp_nxtinfo.nxt_sid: expected: %hu actual: %hu",
-				 nxt_sid, sctp_nxtinfo->nxt_sid);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->nxt_flags->type != EXPR_ELLIPSIS) {
-		u16 nxt_flags;
-
-		if (get_u16(expr->nxt_flags, &nxt_flags, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_nxtinfo->nxt_flags != nxt_flags) {
-			asprintf(error, "sctp_nxtinfo.nxt_flags: expected: %hu actual: %hu",
-				 nxt_flags, sctp_nxtinfo->nxt_flags);
-			return STATUS_ERR;
-		}
-	}
+	if (check_u16_expr(expr->nxt_sid, sctp_nxtinfo->nxt_sid, "sctp_nxtinfo.nxt_sid", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->nxt_flags, sctp_nxtinfo->nxt_flags, "sctp_nxtinfo.nxt_flags", error))
+		return STATUS_ERR;
 	if (expr->nxt_ppid->type != EXPR_ELLIPSIS) {
 		u32 nxt_ppid;
 
@@ -3863,18 +3331,43 @@ static int check_sctp_nxtinfo(struct sctp_nxtinfo_expr *expr,
 			return STATUS_ERR;
 		}
 	}
-	if (expr->nxt_length->type != EXPR_ELLIPSIS) {
-		u32 nxt_length;
+	if (check_u32_expr(expr->nxt_length, sctp_nxtinfo->nxt_length, "sctp_nxtinfo.nxt_length", error))
+		return STATUS_ERR;
+
+	return STATUS_OK;
+}
+#endif
+
+#if defined(__FreeBSD__) || defined(linux)
+static int check_sctp_assoc_change(struct sctp_assoc_change_expr *expr,
+				   struct sctp_assoc_change *sctp_event,
+				   char **error) {
+
+	if (check_u16_expr(expr->sac_type, sctp_event->sac_type,
+			   "sctp_assoc_change.sac_type", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->sac_flags, sctp_event->sac_flags,
+			   "sctp_assoc_change.sac_flags", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->sac_length, sctp_event->sac_length,
+			   "sctp_assoc_change.sac_length", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->sac_state, sctp_event->sac_state,
+			   "sctp_assoc_change.sac_state", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->sac_error, sctp_event->sac_error,
+			   "sctp_assoc_change.sac_error", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->sac_outbound_streams, sctp_event->sac_outbound_streams,
+			   "sctp_assoc_change.sac_outbound_streams", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->sac_inbound_streams, sctp_event->sac_inbound_streams,
+			   "sctp_assoc_change.sac_inbound_streams", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->sac_assoc_id, sctp_event->sac_assoc_id,
+			   "sctp_assoc_change.sac_assoc_id", error))
+		return STATUS_ERR;
 
-		if (get_u32(expr->nxt_length, &nxt_length, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_nxtinfo->nxt_length != nxt_length) {
-			asprintf(error, "sctp_nxtinfo.nxt_length: expected: %u actual: %u",
-				 nxt_length, sctp_nxtinfo->nxt_length);
-			return STATUS_ERR;
-		}
-	}
 	return STATUS_OK;
 }
 #endif
@@ -3883,96 +3376,66 @@ static int check_sctp_nxtinfo(struct sctp_nxtinfo_expr *expr,
 static int check_sctp_shutdown_event(struct sctp_shutdown_event_expr *expr,
 				     struct sctp_shutdown_event *sctp_event,
 				     char **error) {
-	if (expr->sse_type->type != EXPR_ELLIPSIS) {
-		u16 sse_type;
 
-		if (get_u16(expr->sse_type, &sse_type, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_event->sse_type != sse_type) {
-			asprintf(error, "sctp_shutdown_event.sse_type: expected: %hu actual: %hu",
-				 sse_type, sctp_event->sse_type);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sse_flags->type != EXPR_ELLIPSIS) {
-		u16 sse_flags;
-
-		if (get_u16(expr->sse_flags, &sse_flags, error)) {
-			return STATUS_ERR;		}
-		if (sctp_event->sse_flags != sse_flags) {
-			asprintf(error, "sctp_shutdown_event.sse_flags: expected: %hu actual: %hu",
-				 sse_flags, sctp_event->sse_flags);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sse_length->type != EXPR_ELLIPSIS) {
-		u32 sse_length;
+	if (check_u16_expr(expr->sse_type, sctp_event->sse_type,
+			   "sctp_shutdown_event.sse_type", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->sse_flags, sctp_event->sse_flags,
+			   "sctp_shutdown_event.sse_flags", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->sse_length, sctp_event->sse_length,
+			   "sctp_shutdown_event.sse_length", error))
+		return STATUS_ERR;
 
-		if (get_u32(expr->sse_length, &sse_length, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_event->sse_length != sse_length) {
-			asprintf(error, "sctp_shutdown_event.sse_length: expected: %u actual: %u",
-				 sse_length, sctp_event->sse_length);
-			return STATUS_ERR;
-		}
-	}
 	return STATUS_OK;
 }
 #endif
+
 #if defined(__FreeBSD__) || defined(linux)
 static int check_sctp_sender_dry_event(struct sctp_sender_dry_event_expr *expr,
 				       struct sctp_sender_dry_event *sctp_event,
 				       char **error) {
-	if (expr->sender_dry_type->type != EXPR_ELLIPSIS) {
-		u16 sender_dry_type;
-
-		if (get_u16(expr->sender_dry_type, &sender_dry_type, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_event->sender_dry_type != sender_dry_type) {
-			asprintf(error, "sctp_sender_dry_event.sender_dry_type: expected: %hu actual: %hu",
-				 sender_dry_type, sctp_event->sender_dry_type);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sender_dry_flags->type != EXPR_ELLIPSIS) {
-		u16 sender_dry_flags;
 
-		if (get_u16(expr->sender_dry_flags, &sender_dry_flags, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_event->sender_dry_flags != sender_dry_flags) {
-			asprintf(error, "sctp_sender_dry_event.sender_dry_flags: expected: %hu actual: %hu",
-				 sender_dry_flags, sctp_event->sender_dry_flags);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sender_dry_type->type != EXPR_ELLIPSIS) {
-		u32 sender_dry_length;
+	if (check_u16_expr(expr->sender_dry_type, sctp_event->sender_dry_type,
+			   "sctp_sender_dry.sender_dry_type", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->sender_dry_flags, sctp_event->sender_dry_flags,
+			   "sctp_sender_dry.sender_dry_flags", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->sender_dry_length, sctp_event->sender_dry_length,
+			   "sctp_sender_dry.sender_dry_length", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->sender_dry_assoc_id, sctp_event->sender_dry_assoc_id,
+			   "sctp_sender_dry.sender_dry_assoc_id", error))
+		return STATUS_ERR;
 
-		if (get_u32(expr->sender_dry_length, &sender_dry_length, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_event->sender_dry_length != sender_dry_length) {
-			asprintf(error, "sctp_sender_dry_event.sender_dry_length: expected: %u actual: %u",
-				 sender_dry_length, sctp_event->sender_dry_length);
-			return STATUS_ERR;
-		}
-	}
-	if (expr->sender_dry_assoc_id->type != EXPR_ELLIPSIS) {
-		u32 sender_dry_assoc_id;
+	return STATUS_OK;
+}
+#endif
 
-		if (get_u32(expr->sender_dry_assoc_id, &sender_dry_assoc_id, error)) {
-			return STATUS_ERR;
-		}
-		if (sctp_event->sender_dry_assoc_id != sender_dry_assoc_id) {
-			asprintf(error, "sctp_sender_dry_event.sender_dry_assoc_id: expected: %u actual: %u",
-				 sender_dry_assoc_id, sctp_event->sender_dry_assoc_id);
+#if defined(__FreeBSD__)
+static int check_sctp_send_failed_event(struct sctp_send_failed_event_expr *expr,
+				       struct sctp_send_failed_event *sctp_event,
+				       char **error) {
+	if (check_u16_expr(expr->ssfe_type, sctp_event->ssfe_type,
+			   "sctp_send_failed.ssfe_type", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->ssfe_flags, sctp_event->ssfe_flags,
+			   "sctp_send_failed.ssfe_flags", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->ssfe_length, sctp_event->ssfe_length,
+			   "sctp_send_failed.ssfe_length", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->ssfe_error, sctp_event->ssfe_error,
+			   "sctp_send_failed.ssfe_error", error))
+		return STATUS_ERR;
+	if (expr->ssfe_info->type != EXPR_ELLIPSIS) {
+		if (check_sctp_sndinfo(expr->ssfe_info->value.sctp_sndinfo, &sctp_event->ssfe_info, error))
 			return STATUS_ERR;
-		}
 	}
+	if (check_u32_expr(expr->ssfe_assoc_id, sctp_event->ssfe_assoc_id,
+			   "sctp_send_failed.ssfe_assoc_id", error))
+		return STATUS_ERR;
 
 	return STATUS_OK;
 }
@@ -3996,6 +3459,12 @@ static int check_sctp_notification(struct iovec *iov,
 			return STATUS_ERR;
 		script_iov_base = script_iov->value.iovec->iov_base;
 		switch (script_iov_base->type) {
+		case EXPR_SCTP_ASSOC_CHANGE:
+			if (check_sctp_assoc_change(script_iov_base->value.sctp_assoc_change,
+						    (struct sctp_assoc_change *) iov->iov_base,
+						    error))
+				return STATUS_ERR;
+			break;
 		case EXPR_SCTP_SHUTDOWN_EVENT:
 			if (check_sctp_shutdown_event(script_iov_base->value.sctp_shutdown_event,
 						      (struct sctp_shutdown_event *) iov->iov_base,
@@ -4008,6 +3477,14 @@ static int check_sctp_notification(struct iovec *iov,
 						       error))
 				return STATUS_ERR;
 			break;
+#if defined(__FreeBSD__)
+		case EXPR_SCTP_SEND_FAILED_EVENT:
+			if (check_sctp_send_failed_event(script_iov_base->value.sctp_send_failed_event,
+						        (struct sctp_send_failed_event *) iov->iov_base,
+						        error))
+				return STATUS_ERR;
+			break;
+#endif
 		case EXPR_ELLIPSIS:
 			break;
 		default:
diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c
index 121d47ede6545ded9cb3c76baaa0d508b5ac713b..5ceb9c6d00475a120085b825197acaa434a0a46b 100644
--- a/gtests/net/packetdrill/script.c
+++ b/gtests/net/packetdrill/script.c
@@ -86,9 +86,10 @@ struct expression_type_entry expression_type_table[] = {
 	{ EXPR_SCTP_RCVINFO,         "sctp_rcvinfo"    },
 	{ EXPR_SCTP_NXTINFO,         "sctp_nxtinfo"    },
 	{ EXPR_SCTP_RECVV_RN,        "sctp_recvv_rn "  },
-	{ EXPR_SCTP_ASSOC_CHANGE_EVENT,"sctp_assoc_change_event"},
+	{ EXPR_SCTP_ASSOC_CHANGE,    "sctp_assoc_change"},
 	{ EXPR_SCTP_SHUTDOWN_EVENT,  "sctp_shutdown_event"},
 	{ EXPR_SCTP_SENDER_DRY_EVENT,"sctp_sender_dry_event"},
+	{ EXPR_SCTP_SEND_FAILED_EVENT,"sctp_send_failed_event"},
 	{ NUM_EXPR_TYPES,            NULL}
 };
 
@@ -432,16 +433,16 @@ void free_expression(struct expression *expression)
 		free_expression(expression->value.sctp_recvv_rn->recvv_rcvinfo);
 		free_expression(expression->value.sctp_recvv_rn->recvv_nxtinfo);
 		break;
-	case EXPR_SCTP_ASSOC_CHANGE_EVENT:
-		free_expression(expression->value.sctp_assoc_change_event->sac_type);
-		free_expression(expression->value.sctp_assoc_change_event->sac_flags);
-		free_expression(expression->value.sctp_assoc_change_event->sac_length);
-		free_expression(expression->value.sctp_assoc_change_event->sac_state);
-		free_expression(expression->value.sctp_assoc_change_event->sac_error);
-		free_expression(expression->value.sctp_assoc_change_event->sac_outbound_streams);
-		free_expression(expression->value.sctp_assoc_change_event->sac_inbound_streams);
-		free_expression(expression->value.sctp_assoc_change_event->sac_assoc_id);
-		free_expression(expression->value.sctp_assoc_change_event->sac_info);
+	case EXPR_SCTP_ASSOC_CHANGE:
+		free_expression(expression->value.sctp_assoc_change->sac_type);
+		free_expression(expression->value.sctp_assoc_change->sac_flags);
+		free_expression(expression->value.sctp_assoc_change->sac_length);
+		free_expression(expression->value.sctp_assoc_change->sac_state);
+		free_expression(expression->value.sctp_assoc_change->sac_error);
+		free_expression(expression->value.sctp_assoc_change->sac_outbound_streams);
+		free_expression(expression->value.sctp_assoc_change->sac_inbound_streams);
+		free_expression(expression->value.sctp_assoc_change->sac_assoc_id);
+		free_expression(expression->value.sctp_assoc_change->sac_info);
 		break;
 	case EXPR_SCTP_SHUTDOWN_EVENT:
 		free_expression(expression->value.sctp_shutdown_event->sse_type);
@@ -454,6 +455,15 @@ void free_expression(struct expression *expression)
 		free_expression(expression->value.sctp_sender_dry_event->sender_dry_length);
 		free_expression(expression->value.sctp_sender_dry_event->sender_dry_assoc_id);
 		break;
+	case EXPR_SCTP_SEND_FAILED_EVENT:
+		free_expression(expression->value.sctp_send_failed_event->ssfe_type);
+		free_expression(expression->value.sctp_send_failed_event->ssfe_flags);
+		free_expression(expression->value.sctp_send_failed_event->ssfe_length);
+		free_expression(expression->value.sctp_send_failed_event->ssfe_error);
+		free_expression(expression->value.sctp_send_failed_event->ssfe_info);
+		free_expression(expression->value.sctp_send_failed_event->ssfe_assoc_id);
+		free_expression(expression->value.sctp_send_failed_event->ssfe_data);
+		break;
 	case EXPR_WORD:
 		assert(expression->value.string);
 		free(expression->value.string);
@@ -576,7 +586,6 @@ static int evaluate_iovec_expression(struct expression *in,
 
 	in_iov = in->value.iovec;
 	out_iov = out->value.iovec;
-
 	if (evaluate(in_iov->iov_base,		&out_iov->iov_base,	error))
 		return STATUS_ERR;
 	if (evaluate(in_iov->iov_len,		&out_iov->iov_len,	error))
@@ -1365,21 +1374,21 @@ static int evaluate_sctp_recvv_rn_expression(struct expression *in,
 	return STATUS_OK;
 }
 
-static int evaluate_sctp_assoc_change_event_expression(struct expression *in,
+static int evaluate_sctp_assoc_change_expression(struct expression *in,
 						       struct expression *out,
 						       char **error)
 {
-	struct sctp_assoc_change_event_expr *in_event;
-	struct sctp_assoc_change_event_expr *out_event;
+	struct sctp_assoc_change_expr *in_event;
+	struct sctp_assoc_change_expr *out_event;
 
-	assert(in->type == EXPR_SCTP_ASSOC_CHANGE_EVENT);
-	assert(in->value.sctp_assoc_change_event);
-	assert(out->type == EXPR_SCTP_ASSOC_CHANGE_EVENT);
+	assert(in->type == EXPR_SCTP_ASSOC_CHANGE);
+	assert(in->value.sctp_assoc_change);
+	assert(out->type == EXPR_SCTP_ASSOC_CHANGE);
 
-	out->value.sctp_assoc_change_event = calloc(1, sizeof(struct sctp_assoc_change_event_expr));
+	out->value.sctp_assoc_change = calloc(1, sizeof(struct sctp_assoc_change_expr));
 
-	in_event = in->value.sctp_assoc_change_event;
-	out_event = out->value.sctp_assoc_change_event;
+	in_event = in->value.sctp_assoc_change;
+	out_event = out->value.sctp_assoc_change;
 
 	if (evaluate(in_event->sac_type,
 		     &out_event->sac_type,
@@ -1489,6 +1498,54 @@ static int evaluate_sctp_sender_dry_event_expression(struct expression *in,
 	return STATUS_OK;
 }
 
+static int evaluate_sctp_send_failed_event_expression(struct expression *in,
+						      struct expression *out,
+						      char **error)
+{
+	struct sctp_send_failed_event_expr *in_event;
+	struct sctp_send_failed_event_expr *out_event;
+
+	assert(in->type == EXPR_SCTP_SEND_FAILED_EVENT);
+	assert(in->value.sctp_send_failed_event);
+	assert(out->type == EXPR_SCTP_SEND_FAILED_EVENT);
+
+	out->value.sctp_send_failed_event = calloc(1, sizeof(struct sctp_send_failed_event_expr));
+
+	in_event = in->value.sctp_send_failed_event;
+	out_event = out->value.sctp_send_failed_event;
+
+	if (evaluate(in_event->ssfe_type,
+		     &out_event->ssfe_type,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_event->ssfe_flags,
+		     &out_event->ssfe_flags,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_event->ssfe_length,
+		     &out_event->ssfe_length,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_event->ssfe_error,
+		     &out_event->ssfe_error,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_event->ssfe_info,
+		     &out_event->ssfe_info,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_event->ssfe_assoc_id,
+		     &out_event->ssfe_assoc_id,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_event->ssfe_data,
+		     &out_event->ssfe_data,
+		     error))
+		return STATUS_ERR;
+
+	return STATUS_OK;
+}
+
 static int evaluate(struct expression *in,
 		    struct expression **out_ptr, char **error)
 {
@@ -1574,8 +1631,8 @@ static int evaluate(struct expression *in,
 	case EXPR_SCTP_RECVV_RN:
 		result = evaluate_sctp_recvv_rn_expression(in, out, error);
 		break;
-	case EXPR_SCTP_ASSOC_CHANGE_EVENT:
-		result = evaluate_sctp_assoc_change_event_expression(in, out, error);
+	case EXPR_SCTP_ASSOC_CHANGE:
+		result = evaluate_sctp_assoc_change_expression(in, out, error);
 		break;
 	case EXPR_SCTP_SHUTDOWN_EVENT:
 		result = evaluate_sctp_shutdown_event_expression(in, out, error);
@@ -1583,6 +1640,9 @@ static int evaluate(struct expression *in,
 	case EXPR_SCTP_SENDER_DRY_EVENT:
 		result = evaluate_sctp_sender_dry_event_expression(in, out, error);
 		break;
+	case EXPR_SCTP_SEND_FAILED_EVENT:
+		result = evaluate_sctp_send_failed_event_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 40a96b42dfd7763bbee3ffec425ac9aba13f0dbd..fe4463278ac4f5c7abd38274f148f0acc058b70d 100644
--- a/gtests/net/packetdrill/script.h
+++ b/gtests/net/packetdrill/script.h
@@ -66,9 +66,10 @@ enum expression_t {
 	EXPR_SCTP_RCVINFO,        /* struct sctp_rcvinfo for syscall sctp_recvv */
 	EXPR_SCTP_NXTINFO,        /* struct sctp_nxtinfo for syscall sctp_recvv */
 	EXPR_SCTP_RECVV_RN,       /* struct sctp_recvv_rn for syscall sctp_recvv */
-	EXPR_SCTP_ASSOC_CHANGE_EVENT, /* expression tree for sctp_assoc_change_event */
+	EXPR_SCTP_ASSOC_CHANGE,   /* expression tree for sctp_assoc_change_event */
 	EXPR_SCTP_SHUTDOWN_EVENT, /* expression tree for sctp_shutdown_event */
 	EXPR_SCTP_SENDER_DRY_EVENT, /* expression tree for sctp_sender_dry_event */
+	EXPR_SCTP_SEND_FAILED_EVENT, /* expression tree for sctp_send_failed_event */
 	NUM_EXPR_TYPES,
 };
 /* Convert an expression type to a human-readable string */
@@ -108,9 +109,10 @@ struct expression {
 		struct sctp_rcvinfo_expr *sctp_rcvinfo;
 		struct sctp_nxtinfo_expr *sctp_nxtinfo;
 		struct sctp_recvv_rn_expr *sctp_recvv_rn;
-		struct sctp_assoc_change_event_expr *sctp_assoc_change_event;
+		struct sctp_assoc_change_expr *sctp_assoc_change;
 		struct sctp_shutdown_event_expr *sctp_shutdown_event;
 		struct sctp_sender_dry_event_expr *sctp_sender_dry_event;
+		struct sctp_send_failed_event_expr *sctp_send_failed_event;
 	} value;
 	const char *format;	/* the printf format for printing the value */
 };
@@ -321,8 +323,8 @@ struct sctp_recvv_rn_expr {
 	struct expression *recvv_nxtinfo;
 };
 
-/* Parse tree for sctp_assoc_change_event for notifications. */
-struct sctp_assoc_change_event_expr {
+/* Parse tree for sctp_assoc_change for notifications. */
+struct sctp_assoc_change_expr {
 	struct expression *sac_type;
 	struct expression *sac_flags;
 	struct expression *sac_length;
@@ -341,7 +343,7 @@ struct sctp_shutdown_event_expr {
 	struct expression *sse_length;
 };
 
-/* Parse tree for sctp_shutdown_event for notifications. */
+/* Parse tree for sctp_sender_dry_event for notifications. */
 struct sctp_sender_dry_event_expr {
 	struct expression *sender_dry_type;
 	struct expression *sender_dry_flags;
@@ -349,6 +351,17 @@ struct sctp_sender_dry_event_expr {
 	struct expression *sender_dry_assoc_id;
 };
 
+/* Parse tree for sctp_send_failed_event for notifications. */
+struct sctp_send_failed_event_expr {
+	struct expression *ssfe_type;
+	struct expression *ssfe_flags;
+	struct expression *ssfe_length;
+	struct expression *ssfe_error;
+	struct expression *ssfe_info;
+	struct expression *ssfe_assoc_id;
+	struct expression *ssfe_data;
+};
+
 /* 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 63c501f5939789880e159c2c3960aac22e2550f6..798a5675b5c4b5225565f303f2f3634de9077197 100644
--- a/gtests/net/packetdrill/symbols_freebsd.c
+++ b/gtests/net/packetdrill/symbols_freebsd.c
@@ -168,8 +168,10 @@ struct int_symbol platform_symbols_table[] = {
 	{ SCTP_PEER_ADDR_CHANGE,            "SCTP_PEER_ADDR_CHANGE"           },
 	{ SCTP_REMOTE_ERROR,                "SCTP_REMOTE_ERROR"               },
 	{ SCTP_SEND_FAILED,                 "SCTP_SEND_FAILED"                },
+	{ SCTP_ASSOC_CHANGE,                "SCTP_ASSOC_CHANGE"               },
 	{ SCTP_SHUTDOWN_EVENT,              "SCTP_SHUTDOWN_EVENT"             },
 	{ SCTP_SENDER_DRY_EVENT,            "SCTP_SENDER_DRY_EVENT"           },
+	{ SCTP_SEND_FAILED_EVENT,           "SCTP_SEND_FAILED_EVENT"          },
 	{ SCTP_ADAPTATION_INDICATION,       "SCTP_ADAPTATION_INDICATION"      }, 
 	{ SCTP_ADAPTION_INDICATION,         "SCTP_ADAPTION_INDICATION"        },
 	{ SCTP_PARTIAL_DELIVERY_EVENT,      "SCTP_PARTIAL_DELIVERY_EVENT"     },
@@ -203,6 +205,13 @@ struct int_symbol platform_symbols_table[] = {
 	{ SCTP_RECVV_RN,                    "SCTP_RECVV_RN"                   },
 	{ SCTP_RECVRCVINFO,                 "SCTP_RECVRCVINFO"                },
 	{ SCTP_RECVNXTINFO,                 "SCTP_RECVNXTINFO"                },
+	{ SCTP_DATA_SENT,                   "SCTP_DATA_SENT"                  },
+	{ SCTP_DATA_UNSENT,                 "SCTP_DATA_UNSENT"                },
+	{ SCTP_COMM_UP,                     "SCTP_COMM_UP"                    },
+	{ SCTP_COMM_LOST,                   "SCTP_COMM_LOST"                  },
+	{ SCTP_RESTART,                     "SCTP_RESTART"                    },
+	{ SCTP_SHUTDOWN_COMP,               "SCTP_SHUTDOWN_COMP"              },
+	{ SCTP_CANT_STR_ASSOC,              "SCTP_CANT_STR_ASSOC"             },
 	/* /usr/include/netinet/tcp.h */
 	{ TCP_NODELAY,                      "TCP_NODELAY"                     },
 	{ TCP_MAXSEG,                       "TCP_MAXSEG"                      },
diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp.pkt
index a4a590a3c238841b3fd5ee2f39d24e0feb3e0bae..de271ad5d098cc165a4ebab2a0dd9db7c5b872c9 100644
--- a/gtests/net/packetdrill/tests/bsd/sctp/sctp.pkt
+++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp.pkt
@@ -9,21 +9,21 @@
 +0.0 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR)
 +0.0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
 +0.1 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress)
-+0.0 > sctp: INIT[tag=1 tsn=0]
-+0.0 < sctp: INIT_ACK[tag=2 a_rwnd=1500 os=1 is =1 tsn=3] // faked
-+0.0 > sctp: COOKIE_ECHO[] // syntax not clear
-+0.0 < sctp: COOKIE_ACK[]
++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
 +1.0 write(3, ..., 1000) = 1000
-+0.0 > sctp: DATA[tsn=0 sid=0 ssn=0 ppid=0]
-+0.0 < sctp: SACK[tsn=0 a_rwnd=1500]
-+1.0 < sctp: DATA[tsn=3 sid=0 ssn=0 ppid=0] // How to handle
-+0.0 > sctp: SACK[tsn=3]
++0.0 > sctp: DATA[flgs=BE, len=1016, tsn=2, sid=0, ssn=0, ppid=0]
++0.0 < sctp: SACK[flgs=0, cum_tsn=2, a_rwnd=1500, gaps=[], dups=[]]
++1.0 < sctp: DATA[flgs=BE, len=1016, tsn=3, sid=0, ssn=0, ppid=0] // How to handle
++0.0 > sctp: SACK[flgs=0, cum_tsn=3, a_rwnd=1500, gaps=[], dups=[]]
 +0.0 read(3, ..., 2000) = 1000
-+1.0 < sctp: DATA[tsn=4 sid=0 ssn=1 ppid=0]
++1.0 < sctp: DATA[flgs=BE, len=1016, tsn=4, sid=0, ssn=0, ppid=0]
 +0.0 read(3, ..., 2000) = 1000
-+0.2 > sctp: SACK[tsn=4]
++0.2 > sctp: SACK[flgs=0, cum_tsn=4, a_rwnd=1500, gaps=[], dups=[]]
 +0.0 close(3) = 0
-+0.0 > sctp: SHUTDOWN[tsn=4]
-+0.0 < sctp: SHUTDOWN_ACK[]
-+0.0 > sctp: SHUTDOWN_COMPLETE[]
++0.0 > sctp: SHUTDOWN[flgs=0, cum_tsn=4]
++0.0 < sctp: SHUTDOWN_ACK[flgs=0]
++0.0 > sctp: SHUTDOWN_COMPLETE[flgs=0]
diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_notifications.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_notifications.pkt
deleted file mode 100644
index df4d613cf608fd9e3fff382cd06609dc75d907b5..0000000000000000000000000000000000000000
--- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_notifications.pkt
+++ /dev/null
@@ -1,41 +0,0 @@
-+0.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
-//enable shutdown events
-+0.0 setsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_SHUTDOWN_EVENT, se_on=1}, 8) = 0
-+0.0 getsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_SHUTDOWN_EVENT, se_on=1}, [8]) = 0
-+0.0 setsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_SHUTDOWN_EVENT, se_on=0}, 8) = 0
-+0.0 getsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_SHUTDOWN_EVENT, se_on=0}, [8]) = 0
-
-+0.0 setsockopt(3, IPPROTO_SCTP, SCTP_EVENTS, {sctp_data_io_event=1, sctp_association_event=1, sctp_address_event=0, sctp_send_failure_event=1,
-sctp_peer_error_event=0, sctp_shutdown_event=1, sctp_partial_delivery_event=0, sctp_adaptation_layer_event=0, sctp_authentication_event=0,
-sctp_sender_dry_event=0}, 11) = 0
-+0.0 getsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_SHUTDOWN_EVENT, se_on=1}, [8]) = 0
-+0.0 setsockopt(3, IPPROTO_SCTP, SCTP_EVENTS, {sctp_data_io_event=1, sctp_association_event=1, sctp_address_event=0, sctp_send_failure_event=1,
-sctp_peer_error_event=0, sctp_shutdown_event=0, sctp_partial_delivery_event=0, sctp_adaptation_layer_event=0, sctp_authentication_event=0,
-sctp_sender_dry_event=0}, 11) = 0
-
-+0.0 setsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_SENDER_DRY_EVENT, se_on=1}, 8) = 0
-+0.0 sctp_recvv(3, [{iov_base={sender_dry_type=SCTP_SENDER_DRY_EVENT, sender_dry_flags=0, sender_dry_length=12, sender_dry_assoc_id=3}, iov_len=1000}], 1,
-..., 20, NULL, [0], [SCTP_RECVV_NOINFO], [MSG_NOTIFICATION|MSG_EOR]) = 12
-
-
-
-+0.0 getsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_SHUTDOWN_EVENT, se_on=0}, [8]) = 0
-+0.0 setsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_SHUTDOWN_EVENT, se_on=1}, 8) = 0
-// Tear down the association
-+0.0 < sctp: SHUTDOWN[flgs=0, cum_tsn=0]
-*    > sctp: SHUTDOWN_ACK[flgs=0]
-+0.0 < sctp: SHUTDOWN_COMPLETE[flgs=0]
-+0.0 recvmsg(3, {msg_name(...)=..., 
-		 msg_iov(1)=[{iov_base={sse_type=SCTP_SHUTDOWN_EVENT, sse_flags=0, sse_length=12}, iov_len=1000}],
-		 msg_flags=MSG_NOTIFICATION|MSG_EOR}, 0) = 12
-//+0.0 sctp_recvv(3, [{iov_base={sse_type=SCTP_SHUTDOWN_EVENT, sse_flags=1, sse_length=12}, iov_len=1000}], 1,
-//..., 20, NULL, [0], [SCTP_RECVV_NOINFO], [MSG_NOTIFICATION|MSG_EOR]) = 12
diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_sendv.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_sendv.pkt
index 29d2f27969af1a2255bff0570e43e42e42c13e40..114a476808ae46fa799c0b32ea28b879eb416d27 100644
--- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_sendv.pkt
+++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_sendv.pkt
@@ -14,7 +14,7 @@
 //sctp_sendv(int sd, const struct iovec *iov, int iovcnt, struct sockaddr *addrs, int addrcnt, void *info, socklen_t infolen, unsigned int infotype, int flags);
 
 //test with sctp_sendv_authinfo
-+1.0 sctp_sendv(3, [{iov_base=..., iov_len=500}, {iov_base=..., iov_len=500}], 2, ..., 1, {auth_keynumber=123}, 2, SCTP_SENDV_AUTHINFO, 0) = 1000
++1.0 sctp_sendv(3, [{iov_base=..., iov_len=500}, {iov_base=..., iov_len=500}], 2, NULL, 0, {auth_keynumber=123}, 2, SCTP_SENDV_AUTHINFO, 0) = 1000
 *    > sctp: DATA[flgs=BE, len=1016, tsn=1, sid=0, ssn=0, ppid=0]
 +0.0 < sctp: SACK[flgs=0, cum_tsn=1, a_rwnd=1500, gaps=[], dups=[]]