Skip to content
Snippets Groups Projects
Commit 7c9072a1 authored by Michael Tüxen's avatar Michael Tüxen
Browse files

Merge branch 'master' of https://github.com/nplab/packetdrill

parents 516209bf 6b2fe3fa
No related branches found
No related tags found
No related merge requests found
......@@ -247,6 +247,14 @@ snd_flags return SND_FLAGS;
snd_ppid return SND_PPID;
snd_context return SND_CONTEXT;
ssb_adaptation_ind return SSB_ADAPTATION_IND;
sinfo_stream return SINFO_STREAM;
sinfo_ssn return SINFO_SSN;
sinfo_flags return SINFO_FLAGS;
sinfo_ppid return SINFO_PPID;
sinfo_context return SINFO_CONTEXT;
sinfo_timetolive return SINFO_TIMETOLIVE;
sinfo_tsn return SINFO_TSN;
sinfo_cumtsn return SINFO_CUMTSN;
CHUNK return CHUNK;
DATA return DATA;
INIT return INIT;
......@@ -319,6 +327,7 @@ staleness return STALENESS;
param return PARAM;
chk return CHK;
bad_crc32c return BAD_CRC32C;
NULL return NULL_;
--[a-zA-Z0-9_]+ yylval.string = option(yytext); return OPTION;
[-]?[0-9]*[.][0-9]+ yylval.floating = atof(yytext); return FLOAT;
[-]?[0-9]+ yylval.integer = atoll(yytext); return INTEGER;
......
......@@ -538,7 +538,9 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
%token <reserved> SASOC_ASOCMAXRXT SASOC_NUMBER_PEER_DESTINATIONS SASOC_PEER_RWND
%token <reserved> SASOC_LOCAL_RWND SASOC_COOKIE_LIFE SE_TYPE SE_ON
%token <reserved> SND_SID SND_FLAGS SND_PPID SND_CONTEXT SSB_ADAPTATION_IND
%token <reserved> BAD_CRC32C
%token <reserved> BAD_CRC32C NULL_
%token <reserved> SINFO_STREAM SINFO_SSN SINFO_FLAGS SINFO_PPID SINFO_CONTEXT
%token <reserved> SINFO_TIMETOLIVE SINFO_TSN SINFO_CUMTSN
%token <floating> FLOAT
%token <integer> INTEGER HEX_INTEGER
%token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR IPV6_ADDR
......@@ -588,7 +590,9 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
%type <expression> sasoc_asocmaxrxt sasoc_number_peer_destinations sasoc_peer_rwnd
%type <expression> sasoc_local_rwnd sasoc_cookie_life sctp_assocparams
%type <expression> sctp_sndinfo snd_sid snd_flags snd_ppid snd_context
%type <expression> sctp_event se_type se_on sctp_setadaptation
%type <expression> sctp_event se_type se_on sctp_setadaptation null
%type <expression> sctp_sndrcvinfo sinfo_stream sinfo_ssn sinfo_flags sinfo_ppid sinfo_context
%type <expression> sinfo_timetolive sinfo_tsn sinfo_cumtsn
%type <errno_info> opt_errno
%type <chunk_list> sctp_chunk_list_spec
%type <chunk_list_item> sctp_chunk_spec
......@@ -2434,6 +2438,12 @@ expression
| sctp_setadaptation{
$$ = $1;
}
| null {
$$ = $1;
}
| sctp_sndrcvinfo {
$$ = $1;
}
;
decimal_integer
......@@ -3095,17 +3105,14 @@ snd_context
sctp_sndinfo
: '{' snd_sid ',' snd_flags ',' snd_ppid ',' snd_context '}' {
#ifdef SCTP_DEFAULT_SNDINFO
$$ = new_expression(EXPR_SCTP_SNDINFO);
$$->value.sctp_sndinfo = calloc(1, sizeof(struct sctp_sndinfo));
$$->value.sctp_sndinfo = calloc(1, sizeof(struct sctp_sndinfo_expr));
$$->value.sctp_sndinfo->snd_sid = $2;
$$->value.sctp_sndinfo->snd_flags = $4;
$$->value.sctp_sndinfo->snd_ppid = $6;
$$->value.sctp_sndinfo->snd_context = $8;
#else
$$ = NULL;
#endif
}
;
sctp_setadaptation
: '{' SSB_ADAPTATION_IND '=' INTEGER '}' {
......@@ -3118,6 +3125,99 @@ sctp_setadaptation
}
;
sinfo_stream
: SINFO_STREAM '=' INTEGER {
if (!is_valid_u16($3)) {
semantic_error("sinfo_stream out of range");
}
$$ = new_integer_expression($3, "%u");
}
| SINFO_STREAM '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
;
sinfo_ssn
: SINFO_SSN '=' INTEGER {
if (!is_valid_u16($3)) {
semantic_error("sinfo_ssn out of range");
}
$$ = new_integer_expression($3, "%u");
}
| SINFO_SSN '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
;
sinfo_flags
: SINFO_FLAGS '=' INTEGER {
if (!is_valid_u16($3)) {
semantic_error("sinfo_flags out of range");
}
$$ = new_integer_expression($3, "%u");
}
| SINFO_FLAGS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
;
sinfo_ppid
: SINFO_PPID '=' INTEGER {
if (!is_valid_u32($3)) {
semantic_error("sinfo_ppid out of range");
}
$$ = new_integer_expression($3, "%u");
}
| SINFO_PPID '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
;
sinfo_context
: SINFO_CONTEXT '=' INTEGER {
if (!is_valid_u32($3)) {
semantic_error("sinfo_context out of range");
}
$$ = new_integer_expression($3, "%u");
}
| SINFO_CONTEXT '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
;
sinfo_timetolive
: SINFO_TIMETOLIVE '=' INTEGER {
if (!is_valid_u32($3)) {
semantic_error("snd_timetolive out of range");
}
$$ = new_integer_expression($3, "%u");
}
| SINFO_TIMETOLIVE '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
;
sinfo_tsn
: SINFO_TSN '=' INTEGER {
if (!is_valid_u32($3)) {
semantic_error("sinfo_tsn out of range");
}
$$ = new_integer_expression($3, "%u");
}
| SINFO_TSN '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
;
sinfo_cumtsn
: SINFO_CUMTSN '=' INTEGER {
if (!is_valid_u32($3)) {
semantic_error("sinfo_cumtsn out of range");
}
$$ = new_integer_expression($3, "%u");
}
| SINFO_CUMTSN '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
;
sctp_sndrcvinfo
: '{' sinfo_stream ',' sinfo_ssn ',' sinfo_flags ',' sinfo_ppid ',' sinfo_context ',' sinfo_timetolive ',' sinfo_tsn ',' sinfo_cumtsn '}' {
$$ = new_expression(EXPR_SCTP_SNDRCVINFO);
$$->value.sctp_sndrcvinfo = calloc(1, sizeof(struct sctp_sndrcvinfo));
$$->value.sctp_sndrcvinfo->sinfo_stream = $2;
$$->value.sctp_sndrcvinfo->sinfo_ssn = $4;
$$->value.sctp_sndrcvinfo->sinfo_flags = $6;
$$->value.sctp_sndrcvinfo->sinfo_ppid = $8;
$$->value.sctp_sndrcvinfo->sinfo_context = $10;
$$->value.sctp_sndrcvinfo->sinfo_timetolive = $12;
$$->value.sctp_sndrcvinfo->sinfo_tsn = $14;
$$->value.sctp_sndrcvinfo->sinfo_cumtsn = $16;
};
opt_errno
: { $$ = NULL; }
| WORD note {
......@@ -3157,3 +3257,8 @@ code_spec
}
;
null
: NULL_ {
$$ = new_expression(EXPR_NULL);
}
;
......@@ -2971,6 +2971,329 @@ error_out:
return status;
}
static int syscall_sctp_sendmsg(struct state *state, struct syscall_spec *syscall,
struct expression_list *args, char **error)
{
#if defined(__FreeBSD__) || defined(__Linux__) || defined(__NetBSD__) || defined(__OpenBSD__)
int result, script_fd, live_fd, len;
void *msg = NULL;
struct sockaddr_storage to;
struct sockaddr_storage *to_ptr = &to;
socklen_t tolen = 0;
u32 ppid, flags, timetolive, context;
u16 stream_no;
struct expression *sockaddr_expr, *tolen_expr, *ppid_expr, *flags_expr, *ttl_expr, *stream_no_expr, *context_expr;
if (check_arg_count(args, 10, error))
return STATUS_ERR;
if (s32_arg(args, 0, &script_fd, error))
return STATUS_ERR;
if (to_live_fd(state, script_fd, &live_fd, error))
return STATUS_ERR;
if (ellipsis_arg(args, 1, error))
return STATUS_ERR;
if (s32_arg(args, 2, &len, error))
return STATUS_ERR;
sockaddr_expr = get_arg(args, 3, error);
if (sockaddr_expr->type == EXPR_ELLIPSIS) {
socklen_t len = (socklen_t)sizeof(struct sockaddr_storage);
if (getpeername(live_fd, (struct sockaddr *)to_ptr, &len)) {
return STATUS_ERR;
}
tolen = len;
} else if (sockaddr_expr->type == EXPR_NULL) {
to_ptr = NULL;
tolen = 0;
} else {
if (sockaddr_expr->type == EXPR_SOCKET_ADDRESS_IPV4) {
memcpy(to_ptr, sockaddr_expr->value.socket_address_ipv4, sizeof(struct sockaddr_in));
tolen = sizeof(struct sockaddr_in);
} else if (sockaddr_expr->type == EXPR_SOCKET_ADDRESS_IPV6) {
memcpy(to_ptr, sockaddr_expr->value.socket_address_ipv6, sizeof(struct sockaddr_in6));
tolen = sizeof(struct sockaddr_in6);
} else {
asprintf(error, "Bad input for reciever in sctp_sentmsg");
return STATUS_ERR;
}
}
tolen_expr = get_arg(args, 4, error);
if (tolen_expr->type != EXPR_ELLIPSIS)
if (get_u32(tolen_expr, &tolen, error))
return STATUS_ERR;
ppid_expr = get_arg(args, 5, error);
if (get_u32(ppid_expr, &ppid, error))
return STATUS_ERR;
flags_expr = get_arg(args, 6, error);
if (get_u32(flags_expr, &flags, error))
return STATUS_ERR;
stream_no_expr =get_arg(args, 7, error);
if (get_u16(stream_no_expr, &stream_no, error))
return STATUS_ERR;
ttl_expr = get_arg(args, 8, error);
if (get_u32(ttl_expr, &timetolive, error))
return STATUS_ERR;
context_expr = get_arg(args, 9, error);
if (get_u32(context_expr, &context, error))
return STATUS_ERR;
msg = calloc(len, 1);
assert(msg != NULL);
begin_syscall(state, syscall);
result = sctp_sendmsg(live_fd, msg, (size_t)len, (struct sockaddr*) to_ptr,
tolen, ppid, flags, stream_no, timetolive, context);
if (end_syscall(state, syscall, CHECK_EXACT, result, error)) {
free(msg);
return STATUS_ERR;
}
free(msg);
return STATUS_OK;
#else
asprintf(error, "sctp_sendmsg is not supported");
return STATUS_ERR;
#endif
}
#if defined(__FreeBSD__) || defined(__Linux__) || defined(__NetBSD__) || defined(__OpenBSD__)
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 (expr->sinfo_ppid->type != EXPR_ELLIPSIS) {
u32 sinfo_ppid;
if (get_u32(expr->sinfo_ppid, &sinfo_ppid, error)) {
return STATUS_ERR;
}
if (sctp_sndrcvinfo->sinfo_ppid != sinfo_ppid) {
asprintf(error, "sctp_sndrcvinfo.sinfo_ppid: expected: %u actual: %u",
sinfo_ppid, sctp_sndrcvinfo->sinfo_ppid);
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 (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;
}
#endif
static int syscall_sctp_recvmsg(struct state *state, struct syscall_spec *syscall,
struct expression_list *args,
char **error)
{
#if defined(__FreeBSD__) || defined(__Linux__) || defined(__NetBSD__) || defined(__OpenBSD__)
int script_fd, live_fd, live_msg_flags, result;
void *msg;
u32 len;
struct sockaddr live_from;
socklen_t live_fromlen;
struct sctp_sndrcvinfo live_sinfo;
struct expression *len_expr, *script_sinfo_expr, *script_msg_flags_expr;
struct expression *script_fromlen_expr, *script_from_expr;
if (check_arg_count(args, 7, error))
return STATUS_ERR;
if (s32_arg(args, 0, &script_fd, error))
return STATUS_ERR;
if (to_live_fd(state, script_fd, &live_fd, error))
return STATUS_ERR;
if (ellipsis_arg(args, 1, error))
return STATUS_ERR;
len_expr = get_arg(args, 2, error);
if (get_u32(len_expr, &len, error))
return STATUS_ERR;
msg = calloc(len, 1);
assert(msg != NULL);
begin_syscall(state, syscall);
result = sctp_recvmsg(live_fd, msg, len, (struct sockaddr*) &live_from,
&live_fromlen, &live_sinfo, &live_msg_flags);
free(msg);
if (end_syscall(state, syscall, CHECK_EXACT, result, error)) {
return STATUS_ERR;
}
script_from_expr = get_arg(args, 3, error);
if (script_from_expr->type != EXPR_ELLIPSIS) {
struct sockaddr *script_addr;
if (script_from_expr->type == EXPR_SOCKET_ADDRESS_IPV4) {
script_addr = (struct sockaddr*)script_from_expr->value.socket_address_ipv4;
} else if( script_from_expr->type == EXPR_SOCKET_ADDRESS_IPV6) {
script_addr = (struct sockaddr*)script_from_expr->value.socket_address_ipv6;
} else {
asprintf(error, "sctp_recvmsg fromlen: can't check sctp_recvmsg from");
return STATUS_ERR;
}
if (script_addr->sa_family != live_from.sa_family) {
asprintf(error, "sctp_recvmsg from.sa_family: expected: %d actual: %d",
script_addr->sa_family, live_from.sa_family);
return STATUS_ERR;
}
switch(script_addr->sa_family) {
case AF_INET:
{
struct sockaddr_in *script_sockaddr = (struct sockaddr_in*)script_addr;
struct sockaddr_in *live_sockaddr = (struct sockaddr_in*)&live_from;
if (live_sockaddr->sin_port != script_sockaddr->sin_port) {
asprintf(error, "sctp_recvmsg from.sinport. expected: %d actual %d",
ntohs(script_sockaddr->sin_port), ntohs(live_sockaddr->sin_port));
return STATUS_ERR;
}
if (live_sockaddr->sin_addr.s_addr != script_sockaddr->sin_addr.s_addr) {
int len = strnlen(inet_ntoa(script_sockaddr->sin_addr), 16);
char *expected_addr = malloc(sizeof(char) * len);
memcpy(expected_addr, inet_ntoa(script_sockaddr->sin_addr), len);
asprintf(error, "sctp_recvmsg from.sin_addr. expected: %s actual %s",
expected_addr, inet_ntoa(live_sockaddr->sin_addr));
free(expected_addr);
return STATUS_ERR;
}
}
break;
case AF_INET6:
{
struct sockaddr_in6 *script_sockaddr = (struct sockaddr_in6*)script_addr;
struct sockaddr_in6 *live_sockaddr = (struct sockaddr_in6*)&live_from;
if (live_sockaddr->sin6_port != script_sockaddr->sin6_port) {
asprintf(error, "sctp_recvmsg from.sinport. expected: %d actual %d",
ntohs(script_sockaddr->sin6_port), ntohs(live_sockaddr->sin6_port));
return STATUS_ERR;
}
if (live_sockaddr->sin6_addr.s6_addr != script_sockaddr->sin6_addr.s6_addr) {
char expected_addr[INET6_ADDRSTRLEN];
char live_addr[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &script_sockaddr->sin6_addr, expected_addr, INET6_ADDRSTRLEN);
inet_ntop(AF_INET6, &live_sockaddr->sin6_addr, live_addr, INET6_ADDRSTRLEN);
asprintf(error, "sctp_recvmsg from.sin6_addr. expected: %s actual %s",
expected_addr, live_addr);
return STATUS_ERR;
}
}
break;
}
}
script_fromlen_expr = get_arg(args, 4, error);
if (script_fromlen_expr->type != EXPR_ELLIPSIS) {
int script_fromlen;
if (get_s32(script_fromlen_expr, &script_fromlen, error))
return STATUS_ERR;
if (script_fromlen != live_fromlen) {
asprintf(error, "sctp_recvmsg fromlen: expected: %d actual: %d",
script_fromlen, live_fromlen);
return STATUS_ERR;
}
}
script_sinfo_expr = get_arg(args, 5, error);
if (script_sinfo_expr->type != EXPR_ELLIPSIS) {
if (check_sctp_sndrcvinfo(script_sinfo_expr->value.sctp_sndrcvinfo, &live_sinfo, error)) {
return STATUS_ERR;
}
}
script_msg_flags_expr = get_arg(args, 6, error);
if (script_msg_flags_expr->type != EXPR_ELLIPSIS) {
int script_msg_flags;
if (get_s32(script_msg_flags_expr, &script_msg_flags, error))
return STATUS_ERR;
if (script_msg_flags != live_msg_flags) {
asprintf(error, "sctp_recvmsg msg_flags: expected: %d actual: %d",
script_msg_flags, live_msg_flags);
return STATUS_ERR;
}
}
return STATUS_OK;
#else
asprintf(error, "sctp_sendmsg is not supported");
return STATUS_ERR;
#endif
}
/* A dispatch table with all the system calls that we support... */
struct system_call_entry {
const char *name;
......@@ -3002,6 +3325,8 @@ struct system_call_entry system_call_table[] = {
{"getsockopt", syscall_getsockopt},
{"setsockopt", syscall_setsockopt},
{"poll", syscall_poll},
{"sctp_sendmsg", syscall_sctp_sendmsg},
{"sctp_recvmsg", syscall_sctp_recvmsg},
};
/* Evaluate the system call arguments and invoke the system call. */
......
......@@ -53,6 +53,7 @@ struct expression_type_entry {
};
struct expression_type_entry expression_type_table[] = {
{ EXPR_NONE, "none" },
{ EXPR_NULL, "null" },
{ EXPR_ELLIPSIS, "ellipsis" },
{ EXPR_INTEGER, "integer" },
{ EXPR_WORD, "word" },
......@@ -77,6 +78,7 @@ struct expression_type_entry expression_type_table[] = {
{ EXPR_SCTP_EVENT, "sctp_event" },
{ EXPR_SCTP_SNDINFO, "sctp_sndinfo" },
{ EXPR_SCTP_SETADAPTATION, "sctp_setadaptation"},
{ EXPR_SCTP_SNDRCVINFO, "sctp_sndrcvinfo" },
{ NUM_EXPR_TYPES, NULL}
};
......@@ -280,6 +282,7 @@ void free_expression(struct expression *expression)
(expression->type >= NUM_EXPR_TYPES))
assert(!"bad expression type");
switch (expression->type) {
case EXPR_NULL:
case EXPR_ELLIPSIS:
case EXPR_INTEGER:
break;
......@@ -365,6 +368,16 @@ void free_expression(struct expression *expression)
case EXPR_SCTP_SETADAPTATION:
free_expression(expression->value.sctp_setadaptation->ssb_adaptation_ind);
break;
case EXPR_SCTP_SNDRCVINFO:
free_expression(expression->value.sctp_sndrcvinfo->sinfo_stream);
free_expression(expression->value.sctp_sndrcvinfo->sinfo_ssn);
free_expression(expression->value.sctp_sndrcvinfo->sinfo_flags);
free_expression(expression->value.sctp_sndrcvinfo->sinfo_ppid);
free_expression(expression->value.sctp_sndrcvinfo->sinfo_context);
free_expression(expression->value.sctp_sndrcvinfo->sinfo_timetolive);
free_expression(expression->value.sctp_sndrcvinfo->sinfo_tsn);
free_expression(expression->value.sctp_sndrcvinfo->sinfo_cumtsn);
break;
case EXPR_WORD:
assert(expression->value.string);
free(expression->value.string);
......@@ -966,6 +979,58 @@ static int evaluate_sctp_setadaptation_expression(struct expression *in,
return STATUS_OK;
}
static int evaluate_sctp_sndrcvinfo_expression(struct expression *in,
struct expression *out,
char **error)
{
struct sctp_sndrcvinfo_expr *in_info;
struct sctp_sndrcvinfo_expr *out_info;
assert(in->type == EXPR_SCTP_SNDRCVINFO);
assert(in->value.sctp_sndrcvinfo);
assert(out->type == EXPR_SCTP_SNDRCVINFO);
out->value.sctp_sndrcvinfo = calloc(1, sizeof(struct sctp_sndrcvinfo_expr));
in_info = in->value.sctp_sndrcvinfo;
out_info = out->value.sctp_sndrcvinfo;
if (evaluate(in_info->sinfo_stream,
&out_info->sinfo_stream,
error))
return STATUS_ERR;
if (evaluate(in_info->sinfo_ssn,
&out_info->sinfo_ssn,
error))
return STATUS_ERR;
if (evaluate(in_info->sinfo_flags,
&out_info->sinfo_flags,
error))
return STATUS_ERR;
if (evaluate(in_info->sinfo_ppid,
&out_info->sinfo_ppid,
error))
return STATUS_ERR;
if (evaluate(in_info->sinfo_context,
&out_info->sinfo_context,
error))
return STATUS_ERR;
if (evaluate(in_info->sinfo_timetolive,
&out_info->sinfo_timetolive,
error))
return STATUS_ERR;
if (evaluate(in_info->sinfo_tsn,
&out_info->sinfo_tsn,
error))
return STATUS_ERR;
if (evaluate(in_info->sinfo_cumtsn,
&out_info->sinfo_cumtsn,
error))
return STATUS_ERR;
return STATUS_OK;
}
static int evaluate(struct expression *in,
struct expression **out_ptr, char **error)
{
......@@ -980,6 +1045,8 @@ static int evaluate(struct expression *in,
return STATUS_ERR;
}
switch (in->type) {
case EXPR_NULL:
break;
case EXPR_ELLIPSIS:
break;
case EXPR_INTEGER: /* copy as-is */
......@@ -1025,6 +1092,9 @@ static int evaluate(struct expression *in,
case EXPR_SCTP_SETADAPTATION:
result = evaluate_sctp_setadaptation_expression(in, out, error);
break;
case EXPR_SCTP_SNDRCVINFO:
result = evaluate_sctp_sndrcvinfo_expression(in, out, error);
break;
case EXPR_WORD:
out->type = EXPR_INTEGER;
if (symbol_to_int(in->value.string,
......
......@@ -33,6 +33,7 @@
/* The types of expressions in a script */
enum expression_t {
EXPR_NONE,
EXPR_NULL, /* Expression to handle NULL */
EXPR_ELLIPSIS, /* ... but no value */
EXPR_INTEGER, /* integer in 'num' */
EXPR_LINGER, /* struct linger for SO_LINGER */
......@@ -56,7 +57,8 @@ enum expression_t {
EXPR_SCTP_ASSOCPARAMS, /* struct sctp_assocparams for SCTP_ASSOCINFO */
EXPR_SCTP_EVENT, /* struct sctp_event for SCTP_EVENT */
EXPR_SCTP_SNDINFO, /* struct sctp_sndinfo for SCTP_DEFAULT_SNDINFO */
EXPR_SCTP_SETADAPTATION, /* struct sctp_setadaptation for SCTP_ADATTATION_LAYER */
EXPR_SCTP_SETADAPTATION, /* struct sctp_setadaptation for SCTP_ADATTATION_LAYER */
EXPR_SCTP_SNDRCVINFO, /* struct sctp_sndrcvinfo for syscall sctp_recvmsg */
NUM_EXPR_TYPES,
};
/* Convert an expression type to a human-readable string */
......@@ -88,6 +90,7 @@ struct expression {
struct sctp_event_expr *sctp_event;
struct sctp_sndinfo_expr *sctp_sndinfo;
struct sctp_setadaptation_expr *sctp_setadaptation;
struct sctp_sndrcvinfo_expr *sctp_sndrcvinfo;
} value;
const char *format; /* the printf format for printing the value */
};
......@@ -227,6 +230,18 @@ struct sctp_setadaptation_expr {
struct expression *ssb_adaptation_ind;
};
/* Parse tree for sctp_sndrcvinfo in sctp_recvmsg syscall. */
struct sctp_sndrcvinfo_expr {
struct expression *sinfo_stream;
struct expression *sinfo_ssn;
struct expression *sinfo_flags;
struct expression *sinfo_ppid;
struct expression *sinfo_context;
struct expression *sinfo_timetolive;
struct expression *sinfo_tsn;
struct expression *sinfo_cumtsn;
};
/* The errno-related info from strace to summarize a system call error */
struct errno_spec {
const char *errno_macro; /* errno symbol (C macro name) */
......
+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
//sctp_recvmsg(int sd, void * msg, size_t len, struct sockaddr * from, socklen_t * fromlen, struct sctp_sndrcvinfo* sinfo, int * msg_flags);
+0.0 < sctp: DATA[flgs=BE, len=1016, tsn=1, sid=0, ssn=0, ppid=0]
* > sctp: SACK[flgs=0, cum_tsn=1, a_rwnd=..., gaps=[], dups=[]]
+0.0 sctp_recvmsg(3, ..., 1000, ..., ..., ..., 8) = 1000
+0.0 < sctp: DATA[flgs=BE, len=1016, tsn=2, sid=0, ssn=1, ppid=0]
* > sctp: SACK[flgs=0, cum_tsn=2, a_rwnd=..., gaps=[], dups=[]]
+0.0 sctp_recvmsg(3, ..., 1000, ..., ..., {sinfo_stream=0, sinfo_ssn=1, sinfo_flags=0,
sinfo_ppid=0, sinfo_context=0, sinfo_timetolive=0, sinfo_tsn=2, sinfo_cumtsn=2}, 8) = 1000
+0.0 < sctp: DATA[flgs=BE, len=1016, tsn=3, sid=0, ssn=2, ppid=0]
* > sctp: SACK[flgs=0, cum_tsn=3, a_rwnd=..., gaps=[], dups=[]]
+0.0 sctp_recvmsg(3, ..., 1000, {sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")}, 16,
{sinfo_stream=0, sinfo_ssn=2, sinfo_flags=0, sinfo_ppid=0, sinfo_context=0, sinfo_timetolive=0, sinfo_tsn=3, sinfo_cumtsn=3}, 8) = 1000
+0.0 close(3) = 0
+0.0 > sctp: SHUTDOWN[flgs=0, cum_tsn=3]
+0.1 < sctp: SHUTDOWN_ACK[flgs=0]
+0.0 > sctp: SHUTDOWN_COMPLETE[flgs=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
//sctp_sendmsg(int sd, const void * msg, size_t len, struct sockaddr *to, socklen_t tolen,
// uint32_t ppid, uint32_t flags, uint16_t stream_no, uint32_t timetolive, uint32_t context);
+0.0 sctp_sendmsg(3, ..., 1000, ..., ..., 0, 0, 0, 0, 0) = 1000
+0.0 > 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=[]]
+0.0 sctp_sendmsg(3, ..., 1000, {sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")}, 16, 0, 0, 0, 0, 0) = 1000
+0.0 > sctp: DATA[flgs=BE, len=1016, tsn=2, sid=0, ssn=1, ppid=0]
+0.0 < sctp: SACK[flgs=0, cum_tsn=2, a_rwnd=1500, gaps=[], dups=[]]
+0.0 sctp_sendmsg(3, ..., 1000, NULL, 0, 0, 0, 0, 0, 0) = 1000
+0.0 > sctp: DATA[flgs=BE, len=1016, tsn=3, sid=0, ssn=2, ppid=0]
+0.0 < sctp: SACK[flgs=0, cum_tsn=3, a_rwnd=1500, gaps=[], dups=[]]
+0.0 close(3) = 0
+0.0 > sctp: SHUTDOWN[flgs=0, cum_tsn=0]
+0.1 < sctp: SHUTDOWN_ACK[flgs=0]
+0.0 > sctp: SHUTDOWN_COMPLETE[flgs=0]
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