Skip to content
Snippets Groups Projects
Commit 11853c2e authored by hoelscher's avatar hoelscher
Browse files

add support for sctp_remote_error event

parent f45a4fe7
No related branches found
No related tags found
No related merge requests found
......@@ -306,6 +306,12 @@ sac_outbound_streams return SAC_OUTBOUND_STREAMS;
sac_inbound_streams return SAC_INBOUND_STREAMS;
sac_assoc_id return SAC_ASSOC_ID;
sac_info return SAC_INFO;
sre_type return SRE_TYPE;
sre_flags return SRE_FLAGS;
sre_length return SRE_LENGTH;
sre_error return SRE_ERROR;
sre_assoc_id return SRE_ASSOC_ID;
sre_data return SRE_DATA;
auth_type return AUTH_TYPE;
auth_flags return AUTH_FLAGS;
auth_length return AUTH_LENGTH;
......
......@@ -557,6 +557,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
%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 <reserved> AUTH_TYPE AUTH_FLAGS AUTH_LENGTH AUTH_INDICATION AUTH_ASSOC_ID
%token <reserved> SRE_TYPE SRE_FLAGS SRE_LENGTH SRE_ERROR SRE_ASSOC_ID SRE_DATA
%token <floating> FLOAT
%token <integer> INTEGER HEX_INTEGER
%token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR IPV6_ADDR
......@@ -619,6 +620,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
%type <expression> sac_inbound_streams sac_assoc_id sac_info
%type <expression> sctp_send_failed_event ssfe_type ssfe_flags ssfe_length ssfe_error ssfe_assoc_id
%type <expression> sctp_authkey_event auth_type auth_flags auth_length auth_keynumber auth_indication auth_assoc_id
%type <expression> sctp_remote_error sre_type sre_flags sre_length sre_error sre_assoc_id sre_data
%type <errno_info> opt_errno
%type <chunk_list> sctp_chunk_list_spec
%type <chunk_list_item> sctp_chunk_spec
......@@ -2594,6 +2596,7 @@ sockaddr
data
: ELLIPSIS { new_expression(EXPR_ELLIPSIS); }
| sctp_assoc_change { $$ = $1; }
| sctp_remote_error { $$ = $1; }
| sctp_shutdown_event { $$ = $1; }
| sctp_sender_dry_event { $$ = $1; }
| sctp_send_failed_event { $$ = $1; }
......@@ -3899,6 +3902,78 @@ sac_inbound_streams ',' sac_assoc_id ',' sac_info '}' {
}
;
sre_type
: SRE_TYPE '=' INTEGER {
if (!is_valid_u16($3)) {
semantic_error("sre_type out of range");
}
$$ = new_integer_expression($3, "%hu");
}
| SRE_TYPE '=' WORD {
$$ = new_expression(EXPR_WORD);
$$->value.string = $3;
}
| SRE_TYPE '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
;
sre_flags
: SRE_FLAGS '=' INTEGER {
if (!is_valid_u16($3)) {
semantic_error("sre_flags out of range");
}
$$ = new_integer_expression($3, "%hu");
}
| SRE_FLAGS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
;
sre_length
: SRE_LENGTH '=' INTEGER {
if (!is_valid_u32($3)) {
semantic_error("sre_length out of range");
}
$$ = new_integer_expression($3, "%u");
}
| SRE_LENGTH '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
;
sre_error
: SRE_ERROR '=' INTEGER {
if (!is_valid_u16($3)) {
semantic_error("sre_error out of range");
}
$$ = new_integer_expression($3, "%hu");
}
| SRE_ERROR '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
;
sre_assoc_id
: SRE_ASSOC_ID '=' INTEGER {
if (!is_valid_u32($3)) {
semantic_error("sre_assoc_id out of range");
}
$$ = new_integer_expression($3, "%u");
}
| SRE_ASSOC_ID '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
;
sre_data
: SRE_DATA '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
| SRE_DATA '=' array { $$ = $3; }
;
sctp_remote_error
: '{' sre_type ',' sre_flags ',' sre_length ',' sre_error ',' sre_assoc_id ',' sre_data '}' {
$$ = new_expression(EXPR_SCTP_REMOTE_ERROR);
$$->value.sctp_remote_error = calloc(1, sizeof(struct sctp_remote_error_expr));
$$->value.sctp_remote_error->sre_type = $2;
$$->value.sctp_remote_error->sre_flags = $4;
$$->value.sctp_remote_error->sre_length = $6;
$$->value.sctp_remote_error->sre_error = $8;
$$->value.sctp_remote_error->sre_assoc_id = $10;
$$->value.sctp_remote_error->sre_data = $12;
}
;
opt_errno
: { $$ = NULL; }
| WORD note {
......
......@@ -527,6 +527,7 @@ static int iovec_new(struct expression *expression,
assert(iov_expr->iov_base->type == EXPR_ELLIPSIS ||
iov_expr->iov_base->type == EXPR_SCTP_ASSOC_CHANGE ||
iov_expr->iov_base->type == EXPR_SCTP_REMOTE_ERROR ||
iov_expr->iov_base->type == EXPR_SCTP_SHUTDOWN_EVENT ||
iov_expr->iov_base->type == EXPR_SCTP_AUTHKEY_EVENT ||
iov_expr->iov_base->type == EXPR_SCTP_SENDER_DRY_EVENT ||
......@@ -3339,6 +3340,46 @@ static int check_sctp_nxtinfo(struct sctp_nxtinfo_expr *expr,
}
#endif
static int check_u8array_expr(struct expression *expr_list, u8 *data, size_t data_len, char *val_name, char **error) {
if ( expr_list->type != EXPR_ELLIPSIS) {
struct expression *expr = NULL;
unsigned int i;
switch(expr_list->type) {
case EXPR_LIST:
if (data_len != expression_list_length(expr_list->value.list)) {
asprintf(error, "%s length: expected: %u actual %zu",
val_name, expression_list_length(expr_list->value.list), data_len);
return STATUS_ERR;
}
for (i = 0; i < data_len; i++) {
expr = get_arg(expr_list->value.list, i, error);
if (expr->type != EXPR_ELLIPSIS) {
u8 script_val;
if (get_u8(expr, &script_val, error)) {
return STATUS_ERR;
}
if (script_val != data[i]) {
asprintf(error, "%s[%d]: expected: %hhu actual: %hhu",
val_name, i, script_val, data[i]);
return STATUS_ERR;
}
}
}
break;
case EXPR_NULL:
if (data != NULL)
return STATUS_ERR;
break;
default: asprintf(error, "Bad expressiontype for sac_info");
return STATUS_ERR;
break;
}
}
return STATUS_OK;
}
#if defined(__FreeBSD__) || defined(linux)
static int check_sctp_assoc_change(struct sctp_assoc_change_expr *expr,
struct sctp_assoc_change *sctp_event,
......@@ -3367,40 +3408,36 @@ static int check_sctp_assoc_change(struct sctp_assoc_change_expr *expr,
if (check_u32_expr(expr->sac_assoc_id, sctp_event->sac_assoc_id,
"sctp_assoc_change.sac_assoc_id", error))
return STATUS_ERR;
if ( expr->sac_info->type != EXPR_ELLIPSIS) {
size_t infolen;
struct expression *info_expr = NULL;
unsigned int i;
infolen = sctp_event->sac_length - sizeof(struct sctp_assoc_change);
switch(expr->sac_info->type) {
case EXPR_LIST:
if (infolen != expression_list_length(expr->sac_info->value.list)) {
asprintf(error, "sctp_assoc_change.sac_info length: expected: %u actual %zu",
expression_list_length(expr->sac_info->value.list), infolen);
return STATUS_ERR;
}
for (i = 0; i < infolen; i++) {
info_expr = get_arg(expr->sac_info->value.list, i, error);
if (info_expr->type != EXPR_ELLIPSIS) {
u8 script_val;
if (check_u8array_expr(expr->sac_info, sctp_event->sac_info, sctp_event->sac_length - sizeof(struct sctp_assoc_change),
"sctp_assoc_change.sac_info", error))
return STATUS_ERR;
return STATUS_OK;
}
#endif
if (get_u8(info_expr, &script_val, error)) {
return STATUS_ERR;
}
if (script_val != sctp_event->sac_info[i]) {
asprintf(error, "sctp_assoc_change.sac_info[%d]: expected: %hhu actual: %hhu",
i, script_val, sctp_event->sac_info[i]);
return STATUS_ERR;
}
}
}
break;
default: asprintf(error, "Bad expressiontype for sac_info");
#if defined(__FreeBSD__) || defined(linux)
static int check_sctp_remote_error(struct sctp_remote_error_expr *expr,
struct sctp_remote_error *sctp_event,
char **error) {
if (check_u16_expr(expr->sre_type, sctp_event->sre_type,
"sctp_remote_error.sre_type", error))
return STATUS_ERR;
if (check_u16_expr(expr->sre_flags, sctp_event->sre_flags,
"sctp_remote_error.sre_flags", error))
return STATUS_ERR;
if (check_u32_expr(expr->sre_length, sctp_event->sre_length,
"sctp_remote_error.sre_length", error))
return STATUS_ERR;
if (check_u16_expr(expr->sre_error, sctp_event->sre_error,
"sctp_remote_error.sre_error", error))
return STATUS_ERR;
if (check_u32_expr(expr->sre_assoc_id, sctp_event->sre_assoc_id,
"sctp_remote_error.sre_assoc_id", error))
return STATUS_ERR;
if (check_u8array_expr(expr->sre_data, sctp_event->sre_data, sctp_event->sre_length - sizeof(struct sctp_remote_error),
"sctp_remote_error.sre_data", error))
return STATUS_ERR;
break;
}
}
return STATUS_OK;
}
#endif
......@@ -3526,6 +3563,12 @@ static int check_sctp_notification(struct iovec *iov,
error))
return STATUS_ERR;
break;
case EXPR_SCTP_REMOTE_ERROR:
if (check_sctp_remote_error(script_iov_base->value.sctp_remote_error,
(struct sctp_remote_error *) 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,
......
......@@ -87,6 +87,7 @@ struct expression_type_entry expression_type_table[] = {
{ EXPR_SCTP_NXTINFO, "sctp_nxtinfo" },
{ EXPR_SCTP_RECVV_RN, "sctp_recvv_rn " },
{ EXPR_SCTP_ASSOC_CHANGE, "sctp_assoc_change"},
{ EXPR_SCTP_REMOTE_ERROR, "sctp_remote_error"},
{ EXPR_SCTP_SHUTDOWN_EVENT, "sctp_shutdown_event"},
{ EXPR_SCTP_AUTHKEY_EVENT, "sctp_authkey_event"},
{ EXPR_SCTP_SENDER_DRY_EVENT,"sctp_sender_dry_event"},
......@@ -445,6 +446,14 @@ void free_expression(struct expression *expression)
free_expression(expression->value.sctp_assoc_change->sac_assoc_id);
free_expression(expression->value.sctp_assoc_change->sac_info);
break;
case EXPR_SCTP_REMOTE_ERROR:
free_expression(expression->value.sctp_remote_error->sre_type);
free_expression(expression->value.sctp_remote_error->sre_flags);
free_expression(expression->value.sctp_remote_error->sre_length);
free_expression(expression->value.sctp_remote_error->sre_error);
free_expression(expression->value.sctp_remote_error->sre_assoc_id);
free_expression(expression->value.sctp_remote_error->sre_data);
break;
case EXPR_SCTP_SHUTDOWN_EVENT:
free_expression(expression->value.sctp_shutdown_event->sse_type);
free_expression(expression->value.sctp_shutdown_event->sse_flags);
......@@ -1384,8 +1393,8 @@ static int evaluate_sctp_recvv_rn_expression(struct expression *in,
}
static int evaluate_sctp_assoc_change_expression(struct expression *in,
struct expression *out,
char **error)
struct expression *out,
char **error)
{
struct sctp_assoc_change_expr *in_event;
struct sctp_assoc_change_expr *out_event;
......@@ -1439,6 +1448,50 @@ static int evaluate_sctp_assoc_change_expression(struct expression *in,
return STATUS_OK;
}
static int evaluate_sctp_remote_error_expression(struct expression *in,
struct expression *out,
char **error)
{
struct sctp_remote_error_expr *in_event;
struct sctp_remote_error_expr *out_event;
assert(in->type == EXPR_SCTP_REMOTE_ERROR);
assert(in->value.sctp_remote_error);
assert(out->type == EXPR_SCTP_REMOTE_ERROR);
out->value.sctp_remote_error = calloc(1, sizeof(struct sctp_remote_error_expr));
in_event = in->value.sctp_remote_error;
out_event = out->value.sctp_remote_error;
if (evaluate(in_event->sre_type,
&out_event->sre_type,
error))
return STATUS_ERR;
if (evaluate(in_event->sre_flags,
&out_event->sre_flags,
error))
return STATUS_ERR;
if (evaluate(in_event->sre_length,
&out_event->sre_length,
error))
return STATUS_ERR;
if (evaluate(in_event->sre_error,
&out_event->sre_error,
error))
return STATUS_ERR;
if (evaluate(in_event->sre_assoc_id,
&out_event->sre_assoc_id,
error))
return STATUS_ERR;
if (evaluate(in_event->sre_data,
&out_event->sre_data,
error))
return STATUS_ERR;
return STATUS_OK;
}
static int evaluate_sctp_shutdown_event_expression(struct expression *in,
struct expression *out,
char **error)
......@@ -1687,6 +1740,9 @@ static int evaluate(struct expression *in,
case EXPR_SCTP_ASSOC_CHANGE:
result = evaluate_sctp_assoc_change_expression(in, out, error);
break;
case EXPR_SCTP_REMOTE_ERROR:
result = evaluate_sctp_remote_error_expression(in, out, error);
break;
case EXPR_SCTP_SHUTDOWN_EVENT:
result = evaluate_sctp_shutdown_event_expression(in, out, error);
break;
......
......@@ -67,6 +67,7 @@ enum expression_t {
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, /* expression tree for sctp_assoc_change_event */
EXPR_SCTP_REMOTE_ERROR, /* expression tree for sctp_remote_error_event */
EXPR_SCTP_SHUTDOWN_EVENT, /* expression tree for sctp_shutdown_event */
EXPR_SCTP_AUTHKEY_EVENT, /* expression tree for sctp_authentication_event */
EXPR_SCTP_SENDER_DRY_EVENT, /* expression tree for sctp_sender_dry_event */
......@@ -111,6 +112,7 @@ struct expression {
struct sctp_nxtinfo_expr *sctp_nxtinfo;
struct sctp_recvv_rn_expr *sctp_recvv_rn;
struct sctp_assoc_change_expr *sctp_assoc_change;
struct sctp_remote_error_expr *sctp_remote_error;
struct sctp_shutdown_event_expr *sctp_shutdown_event;
struct sctp_authkey_event_expr *sctp_authkey_event;
struct sctp_sender_dry_event_expr *sctp_sender_dry_event;
......@@ -338,6 +340,15 @@ struct sctp_assoc_change_expr {
struct expression *sac_info;
};
/* Parse tree for sctp_assoc_change for notifications. */
struct sctp_remote_error_expr {
struct expression *sre_type;
struct expression *sre_flags;
struct expression *sre_length;
struct expression *sre_error;
struct expression *sre_assoc_id;
struct expression *sre_data;
};
/* Parse tree for sctp_shutdown_event for notifications. */
struct sctp_shutdown_event_expr {
struct expression *sse_type;
......
......@@ -168,7 +168,6 @@ 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" },
......@@ -177,7 +176,6 @@ struct int_symbol platform_symbols_table[] = {
{ SCTP_PARTIAL_DELIVERY_EVENT, "SCTP_PARTIAL_DELIVERY_EVENT" },
{ SCTP_AUTHENTICATION_EVENT, "SCTP_AUTHENTICATION_EVENT" },
{ SCTP_STREAM_RESET_EVENT, "SCTP_STREAM_RESET_EVENT" },
{ SCTP_SENDER_DRY_EVENT, "SCTP_SENDER_DRY_EVENT" },
{ SCTP_NOTIFICATIONS_STOPPED_EVENT, "SCTP_NOTIFICATIONS_STOPPED_EVENT"},
{ SCTP_ASSOC_RESET_EVENT, "SCTP_ASSOC_RESET_EVENT" },
{ SCTP_STREAM_CHANGE_EVENT, "SCTP_STREAM_CHANGE_EVENT" },
......
+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 setsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_REMOTE_ERROR, se_on=1}, 8) = 0
+0.0 getsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_REMOTE_ERROR, se_on=1}, [8]) = 0
+0.0 > sctp: INIT[flgs=0, tag=1, a_rwnd=..., os=..., is=..., tsn=1, ...]
+0.1 < sctp: INIT_ACK[flgs=0, tag=2, a_rwnd=1500, os=1, is=1, tsn=1, STATE_COOKIE[len=4, val=...]]
+0.0 > sctp: COOKIE_ECHO[flgs=0, len=4, val=...]
+0.1 < sctp: COOKIE_ACK[flgs=0]
+0.0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
+0.0 < sctp: ERROR[flgs=0, INVALID_STREAM_IDENTIFIER[sid=1]]
+0.0 sctp_recvv(3, [{iov_base={sre_type=SCTP_REMOTE_ERROR, sre_flags=0, sre_length=32, sre_error=1,
sre_assoc_id=..., sre_data=[0x09, 0x00, 0x00 , 0x0C, 0x00, 0x01, 0x00 , 0x08, 0x00, 0x01, 0x00 , 0x00]}, iov_len=1000}], 1, ..., 20, NULL, [0], [SCTP_RECVV_NOINFO],
[MSG_NOTIFICATION|MSG_EOR]) = 32
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment