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

Add support for the SCTP_SS_VALUE socket option.

parent 9fdcdd5d
No related branches found
No related tags found
No related merge requests found
...@@ -203,6 +203,8 @@ noecn return NO_ECN; ...@@ -203,6 +203,8 @@ noecn return NO_ECN;
ce return CE; ce return CE;
[.][.][.] return ELLIPSIS; [.][.][.] return ELLIPSIS;
assoc_value return ASSOC_VALUE; assoc_value return ASSOC_VALUE;
stream_id return STREAM_ID;
stream_value return STREAM_VALUE;
sack_delay return SACK_DELAY; sack_delay return SACK_DELAY;
sack_freq return SACK_FREQ; sack_freq return SACK_FREQ;
srto_initial return SRTO_INITIAL; srto_initial return SRTO_INITIAL;
......
...@@ -506,6 +506,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, ...@@ -506,6 +506,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
%token <reserved> SINIT_NUM_OSTREAMS SINIT_MAX_INSTREAMS SINIT_MAX_ATTEMPTS %token <reserved> SINIT_NUM_OSTREAMS SINIT_MAX_INSTREAMS SINIT_MAX_ATTEMPTS
%token <reserved> SINIT_MAX_INIT_TIMEO %token <reserved> SINIT_MAX_INIT_TIMEO
%token <reserved> ASSOC_VALUE %token <reserved> ASSOC_VALUE
%token <reserved> STREAM_ID STREAM_VALUE
%token <reserved> SACK_DELAY SACK_FREQ %token <reserved> SACK_DELAY SACK_FREQ
%token <reserved> SSTAT_STATE SSTAT_RWND SSTAT_UNACKDATA SSTAT_PENDDATA %token <reserved> SSTAT_STATE SSTAT_RWND SSTAT_UNACKDATA SSTAT_PENDDATA
%token <reserved> SSTAT_INSTRMS SSTAT_OUTSTRMS SSTAT_FRAGMENTATION_POINT %token <reserved> SSTAT_INSTRMS SSTAT_OUTSTRMS SSTAT_FRAGMENTATION_POINT
...@@ -569,6 +570,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, ...@@ -569,6 +570,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
%type <expression> linger l_onoff l_linger %type <expression> linger l_onoff l_linger
%type <expression> sctp_status sctp_initmsg sctp_sackinfo %type <expression> sctp_status sctp_initmsg sctp_sackinfo
%type <expression> sctp_assoc_value %type <expression> sctp_assoc_value
%type <expression> sctp_stream_value
%type <expression> sctp_rtoinfo srto_initial srto_max srto_min %type <expression> sctp_rtoinfo srto_initial srto_max srto_min
%type <errno_info> opt_errno %type <errno_info> opt_errno
%type <chunk_list> sctp_chunk_list_spec %type <chunk_list> sctp_chunk_list_spec
...@@ -2337,6 +2339,9 @@ expression ...@@ -2337,6 +2339,9 @@ expression
| sctp_assoc_value { | sctp_assoc_value {
$$ = $1; $$ = $1;
} }
| sctp_stream_value {
$$ = $1;
}
| sctp_sackinfo { | sctp_sackinfo {
$$ = $1; $$ = $1;
} }
...@@ -2561,6 +2566,19 @@ sctp_initmsg ...@@ -2561,6 +2566,19 @@ sctp_initmsg
} }
; ;
sctp_stream_value
: '{' STREAM_ID '=' expression ',' STREAM_VALUE '=' expression '}' {
#if defined(SCTP_SS_VALUE)
$$ = new_expression(EXPR_SCTP_STREAM_VALUE);
$$->value.sctp_stream_value = calloc(1, sizeof(struct sctp_stream_value_expr));
$$->value.sctp_stream_value->stream_id = $4;
$$->value.sctp_stream_value->stream_value = $8;
#else
$$ = NULL;
#endif
}
;
sctp_assoc_value sctp_assoc_value
: '{' ASSOC_VALUE '=' expression '}' { : '{' ASSOC_VALUE '=' expression '}' {
#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED) #if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED)
......
...@@ -180,6 +180,26 @@ static int check_type(struct expression *expression, ...@@ -180,6 +180,26 @@ static int check_type(struct expression *expression,
} }
} }
/* Sets the value from the expression argument, checking that it is a
* valid u16, and matches the expected type. Returns STATUS_OK on
* success; on failure returns STATUS_ERR and sets error message.
*/
static int get_u16(struct expression *expression,
u16 *value, char **error)
{
if (check_type(expression, EXPR_INTEGER, error))
return STATUS_ERR;
if ((expression->value.num > UINT16_MAX) ||
(expression->value.num < 0)) {
asprintf(error,
"Value out of range for 16-bit unsigned integer: %lld",
expression->value.num);
return STATUS_ERR;
}
*value = expression->value.num;
return STATUS_OK;
}
/* Sets the value from the expression argument, checking that it is a /* Sets the value from the expression argument, checking that it is a
* valid u32, and matches the expected type. Returns STATUS_OK on * valid u32, and matches the expected type. Returns STATUS_OK on
* success; on failure returns STATUS_ERR and sets error message. * success; on failure returns STATUS_ERR and sets error message.
...@@ -1636,6 +1656,18 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, ...@@ -1636,6 +1656,18 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
live_optval = malloc(sizeof(struct sctp_assoc_value)); live_optval = malloc(sizeof(struct sctp_assoc_value));
live_optlen = (socklen_t)sizeof(struct sctp_assoc_value); live_optlen = (socklen_t)sizeof(struct sctp_assoc_value);
((struct sctp_assoc_value *) live_optval)->assoc_id = 0; ((struct sctp_assoc_value *) live_optval)->assoc_id = 0;
#endif
#ifdef SCTP_SS_VALUE
} else if (val_expression->type == EXPR_SCTP_STREAM_VALUE) {
live_optval = malloc(sizeof(struct sctp_stream_value));
live_optlen = (socklen_t)sizeof(struct sctp_stream_value);
((struct sctp_stream_value *) live_optval)->assoc_id = 0;
if (get_u16(val_expression->value.sctp_stream_value->stream_id,
&((struct sctp_stream_value *) live_optval)->stream_id,
error)) {
free(live_optval);
return STATUS_ERR;
}
#endif #endif
} else { } else {
s32_bracketed_arg(args, 3, &script_optval, error); s32_bracketed_arg(args, 3, &script_optval, error);
...@@ -1788,6 +1820,38 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, ...@@ -1788,6 +1820,38 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
return STATUS_ERR; return STATUS_ERR;
} }
} }
#endif
#ifdef SCTP_SS_VALUE
} else if (val_expression->type == EXPR_SCTP_STREAM_VALUE) {
struct expression *stream_id = val_expression->value.sctp_stream_value->stream_id;
struct expression *stream_value = val_expression->value.sctp_stream_value->stream_value;
struct sctp_stream_value *sctp_stream_value = live_optval;
u16 value;
if (stream_id->type != EXPR_ELLIPSIS) {
if (get_u16(stream_id, &value, error)) {
free(live_optval);
return STATUS_ERR;
}
if (sctp_stream_value->stream_id != value) {
asprintf(error, "Bad getsockopt sctp_stream_value.stream_id: expected: %u actual: %u",
value, sctp_stream_value->stream_id);
free(live_optval);
return STATUS_ERR;
}
}
if (stream_value->type != EXPR_ELLIPSIS) {
if (get_u16(stream_value, &value, error)) {
free(live_optval);
return STATUS_ERR;
}
if (sctp_stream_value->stream_value != value) {
asprintf(error, "Bad getsockopt sctp_stream_value.stream_value: expected: %u actual: %u",
value, sctp_stream_value->stream_value);
free(live_optval);
return STATUS_ERR;
}
}
#endif #endif
} else { } else {
if (*(int*)live_optval != script_optval) { if (*(int*)live_optval != script_optval) {
...@@ -1807,7 +1871,12 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, ...@@ -1807,7 +1871,12 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
int script_fd, live_fd, level, optname, optval_s32, optlen, result; int script_fd, live_fd, level, optname, optval_s32, optlen, result;
void *optval = NULL; void *optval = NULL;
struct expression *val_expression; struct expression *val_expression;
#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED)
struct sctp_assoc_value assoc_value; struct sctp_assoc_value assoc_value;
#endif
#if defined(SCTP_SS_VALUE)
struct sctp_stream_value stream_value;
#endif
if (check_arg_count(args, 5, error)) if (check_arg_count(args, 5, error))
return STATUS_ERR; return STATUS_ERR;
...@@ -1867,6 +1936,19 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, ...@@ -1867,6 +1936,19 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
} }
optval = &assoc_value; optval = &assoc_value;
#endif #endif
#ifdef SCTP_SS_VALUE
} else if (val_expression->type == EXPR_SCTP_STREAM_VALUE) {
stream_value.assoc_id = 0;
if (get_u16(val_expression->value.sctp_stream_value->stream_id,
&stream_value.stream_id, error)) {
return STATUS_ERR;
}
if (get_u16(val_expression->value.sctp_stream_value->stream_value,
&stream_value.stream_value, error)) {
return STATUS_ERR;
}
optval = &stream_value;
#endif
#ifdef SCTP_DELAYED_SACK #ifdef SCTP_DELAYED_SACK
} else if (val_expression->type == EXPR_SCTP_SACKINFO) { } else if (val_expression->type == EXPR_SCTP_SACKINFO) {
optval = &val_expression->value.sctp_sack_info; optval = &val_expression->value.sctp_sack_info;
......
...@@ -79,6 +79,9 @@ struct expression_type_entry expression_type_table[] = { ...@@ -79,6 +79,9 @@ struct expression_type_entry expression_type_table[] = {
#endif #endif
#ifdef SCTP_STATUS #ifdef SCTP_STATUS
{ EXPR_SCTP_STATUS, "sctp_status"}, { EXPR_SCTP_STATUS, "sctp_status"},
#endif
#ifdef SCTP_SS_VALUE
{ EXPR_SCTP_STREAM_VALUE, "sctp_stream_value"},
#endif #endif
{ NUM_EXPR_TYPES, NULL} { NUM_EXPR_TYPES, NULL}
}; };
...@@ -312,6 +315,12 @@ void free_expression(struct expression *expression) ...@@ -312,6 +315,12 @@ void free_expression(struct expression *expression)
case EXPR_SCTP_STATUS: case EXPR_SCTP_STATUS:
#endif #endif
break; break;
#ifdef SCTP_SS_VALUE
case EXPR_SCTP_STREAM_VALUE:
free(expression->value.sctp_stream_value->stream_id);
free(expression->value.sctp_stream_value->stream_value);
break;
#endif
case EXPR_WORD: case EXPR_WORD:
assert(expression->value.string); assert(expression->value.string);
free(expression->value.string); free(expression->value.string);
...@@ -521,6 +530,32 @@ static int evaluate_sctp_assoc_value_expression(struct expression *in, ...@@ -521,6 +530,32 @@ static int evaluate_sctp_assoc_value_expression(struct expression *in,
} }
#endif #endif
#ifdef SCTP_SS_VALUE
static int evaluate_sctp_stream_value_expression(struct expression *in,
struct expression *out,
char **error)
{
struct sctp_stream_value_expr *in_value;
struct sctp_stream_value_expr *out_value;
assert(in->type == EXPR_SCTP_STREAM_VALUE);
assert(in->value.sctp_stream_value);
assert(out->type == EXPR_SCTP_STREAM_VALUE);
out->value.sctp_stream_value = calloc(1, sizeof(struct sctp_stream_value_expr));
in_value = in->value.sctp_stream_value;
out_value = out->value.sctp_stream_value;
if (evaluate(in_value->stream_id, &out_value->stream_id, error))
return STATUS_ERR;
if (evaluate(in_value->stream_value, &out_value->stream_value, error))
return STATUS_ERR;
return STATUS_OK;
}
#endif
static int evaluate(struct expression *in, static int evaluate(struct expression *in,
struct expression **out_ptr, char **error) struct expression **out_ptr, char **error)
{ {
...@@ -572,6 +607,11 @@ static int evaluate(struct expression *in, ...@@ -572,6 +607,11 @@ static int evaluate(struct expression *in,
memcpy(&out->value.sctp_status, &in->value.sctp_status, memcpy(&out->value.sctp_status, &in->value.sctp_status,
sizeof(in->value.sctp_status)); sizeof(in->value.sctp_status));
break; break;
#endif
#ifdef SCTP_SS_VALUE
case EXPR_SCTP_STREAM_VALUE:
evaluate_sctp_stream_value_expression(in, out, error);
break;
#endif #endif
case EXPR_WORD: case EXPR_WORD:
out->type = EXPR_INTEGER; out->type = EXPR_INTEGER;
......
...@@ -60,6 +60,9 @@ enum expression_t { ...@@ -60,6 +60,9 @@ enum expression_t {
#endif #endif
#ifdef SCTP_STATUS #ifdef SCTP_STATUS
EXPR_SCTP_STATUS, /* struct sctp_status for SCTP_STATUS */ EXPR_SCTP_STATUS, /* struct sctp_status for SCTP_STATUS */
#endif
#ifdef SCTP_SS_VALUE
EXPR_SCTP_STREAM_VALUE, /* struct sctp_stream_value for SCTP_SS_VALUE */
#endif #endif
NUM_EXPR_TYPES, NUM_EXPR_TYPES,
}; };
...@@ -94,6 +97,9 @@ struct expression { ...@@ -94,6 +97,9 @@ struct expression {
#endif #endif
#ifdef SCTP_STATUS #ifdef SCTP_STATUS
struct sctp_status sctp_status; struct sctp_status sctp_status;
#endif
#ifdef SCTP_SS_VALUE
struct sctp_stream_value_expr *sctp_stream_value;
#endif #endif
} value; } value;
const char *format; /* the printf format for printing the value */ const char *format; /* the printf format for printing the value */
...@@ -157,6 +163,14 @@ struct sctp_assoc_value_expr { ...@@ -157,6 +163,14 @@ struct sctp_assoc_value_expr {
}; };
#endif #endif
#ifdef SCTP_SS_VALUE
/* Parse tree for a sctp_stream_value struct in a [gs]etsockopt syscall. */
struct sctp_stream_value_expr {
struct expression *stream_id;
struct expression *stream_value;
};
#endif
/* The errno-related info from strace to summarize a system call error */ /* The errno-related info from strace to summarize a system call error */
struct errno_spec { struct errno_spec {
const char *errno_macro; /* errno symbol (C macro name) */ const char *errno_macro; /* errno symbol (C macro name) */
......
...@@ -105,6 +105,7 @@ struct int_symbol platform_symbols_table[] = { ...@@ -105,6 +105,7 @@ struct int_symbol platform_symbols_table[] = {
* The old symbols currently being deployed are also provided. * The old symbols currently being deployed are also provided.
*/ */
{ SCTP_PLUGGABLE_SS, "SCTP_PLUGGABLE_SS" }, { SCTP_PLUGGABLE_SS, "SCTP_PLUGGABLE_SS" },
{ SCTP_SS_VALUE, "SCTP_SS_VALUE" },
{ SCTP_SS_DEFAULT, "SCTP_SS_DEFAULT" }, { SCTP_SS_DEFAULT, "SCTP_SS_DEFAULT" },
{ SCTP_SS_ROUND_ROBIN, "SCTP_SS_ROUND_ROBIN" }, { SCTP_SS_ROUND_ROBIN, "SCTP_SS_ROUND_ROBIN" },
{ SCTP_SS_ROUND_ROBIN_PACKET, "SCTP_SS_ROUND_ROBIN_PACKET" }, { SCTP_SS_ROUND_ROBIN_PACKET, "SCTP_SS_ROUND_ROBIN_PACKET" },
......
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