diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index a33fc4e83a68707c95dc53acd2f756a333ec9c4f..14a3a50f246a98964b4a0f5940685329564552ae 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -573,7 +573,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <expression> linger l_onoff l_linger %type <expression> sctp_status sstat_state sstat_rwnd sstat_unackdata sstat_penddata %type <expression> sstat_instrms sstat_outstrms sstat_fragmentation_point sstat_primary -%type <expression> sctp_initmsg sctp_assoc_value sctp_stream_value sctp_sackinfo +%type <expression> sctp_initmsg sinit_num_ostreams sinit_max_instreams sinit_max_attempts +%type <expression> sinit_max_init_timeo sctp_assoc_value sctp_stream_value sctp_sackinfo %type <expression> sctp_rtoinfo srto_initial srto_max srto_min sctp_paddrinfo %type <expression> sctp_paddrparams spp_address spp_hbinterval spp_pathmtu spp_pathmaxrxt %type <expression> spp_flags spp_ipv6_flowlabel spp_dscp @@ -2551,29 +2552,55 @@ sctp_rtoinfo } ; -sctp_initmsg -: '{' SINIT_NUM_OSTREAMS '=' INTEGER ',' SINIT_MAX_INSTREAMS '=' INTEGER ',' SINIT_MAX_ATTEMPTS '=' INTEGER ',' SINIT_MAX_INIT_TIMEO '=' INTEGER '}' { -#ifdef SCTP_INITMSG - $$ = new_expression(EXPR_SCTP_INITMSG); - if (!is_valid_u16($4)) { +sinit_num_ostreams +: SINIT_NUM_OSTREAMS '=' INTEGER { + if (!is_valid_u16($3)) { semantic_error("sinit_num_ostreams out of range"); } - $$->value.sctp_initmsg.sinit_num_ostreams = $4; - if (!is_valid_u16($8)) { + $$ = new_integer_expression($3, "%hu"); +} +| SINIT_NUM_OSTREAMS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +sinit_max_instreams +: SINIT_MAX_INSTREAMS '=' INTEGER { + if (!is_valid_u16($3)) { semantic_error("sinit_max_instreams out of range"); } - $$->value.sctp_initmsg.sinit_max_instreams = $8; - if (!is_valid_u16($12)) { + $$ = new_integer_expression($3, "%hu"); +} +| SINIT_MAX_INSTREAMS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +sinit_max_attempts +: SINIT_MAX_ATTEMPTS '=' INTEGER { + if (!is_valid_u16($3)) { semantic_error("sinit_max_attempts out of range"); } - $$->value.sctp_initmsg.sinit_max_attempts = $12; - if (!is_valid_u16($16)) { + $$ = new_integer_expression($3, "%hu"); +} +| SINIT_MAX_ATTEMPTS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +sinit_max_init_timeo +: SINIT_MAX_INIT_TIMEO '=' INTEGER { + if (!is_valid_u16($3)) { semantic_error("sinit_max_init_timeo out of range"); } - $$->value.sctp_initmsg.sinit_max_init_timeo = $16; -#else - $$ = NULL; -#endif + $$ = new_integer_expression($3, "%hu"); +} +| SINIT_MAX_INIT_TIMEO '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +sctp_initmsg +: '{' sinit_num_ostreams ',' sinit_max_instreams ',' sinit_max_attempts ',' sinit_max_init_timeo '}' +{ + $$ = new_expression(EXPR_SCTP_INITMSG); + $$->value.sctp_paddrinfo = calloc(1, sizeof(struct sctp_initmsg_expr)); + $$->value.sctp_initmsg->sinit_num_ostreams = $2; + $$->value.sctp_initmsg->sinit_max_instreams = $4; + $$->value.sctp_initmsg->sinit_max_attempts = $6; + $$->value.sctp_initmsg->sinit_max_init_timeo = $8; } ; diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c index ad128901682d6bfea219162924589f20794aa30e..15fcbaf71e4cfd454cae7fefc94bd800951d53d4 100644 --- a/gtests/net/packetdrill/run_system_call.c +++ b/gtests/net/packetdrill/run_system_call.c @@ -1748,6 +1748,62 @@ static int check_sctp_rtoinfo(struct sctp_rtoinfo_expr *expr, } #endif +#ifdef SCTP_INITMSG +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, "Bad getsockopt 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, "Bad getsockopt 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, "Bad getsockopt 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 (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, "Bad getsockopt 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 + #ifdef SCTP_STATUS static int check_sctp_paddrinfo(struct sctp_paddrinfo_expr *expr, struct sctp_paddrinfo *sctp_paddrinfo, @@ -2093,6 +2149,11 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, live_optlen = (socklen_t)sizeof(struct sctp_rtoinfo); ((struct sctp_rtoinfo*)live_optval)->srto_assoc_id = 0; #endif +#ifdef SCTP_INITMSG + } else if (val_expression->type == EXPR_SCTP_INITMSG) { + live_optval = malloc(sizeof(struct sctp_initmsg)); + live_optlen = (socklen_t)sizeof(struct sctp_initmsg); +#endif #ifdef SCTP_STATUS } else if (val_expression->type == EXPR_SCTP_STATUS) { live_optval = malloc(sizeof(struct sctp_status)); @@ -2173,6 +2234,13 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, return STATUS_ERR; } #endif +#ifdef SCTP_INITMSG + } else if (val_expression->type == EXPR_SCTP_INITMSG) { + if (check_sctp_initmsg(val_expression->value.sctp_initmsg, live_optval, error)) { + free(live_optval); + return STATUS_ERR; + } +#endif #ifdef SCTP_STATUS } else if (val_expression->type == EXPR_SCTP_STATUS) { if (check_sctp_status(val_expression->value.sctp_status, live_optval, error)) { @@ -2221,6 +2289,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, struct expression *val_expression; struct linger linger; struct sctp_rtoinfo rtoinfo; +#if defined(SCTP_INITMSG) + struct sctp_initmsg initmsg; +#endif #if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED) struct sctp_assoc_value assoc_value; #endif @@ -2286,7 +2357,23 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, #endif #ifdef SCTP_INITMSG case EXPR_SCTP_INITMSG: - optval = &val_expression->value.sctp_initmsg; + if (get_u16(val_expression->value.sctp_initmsg->sinit_num_ostreams, + &initmsg.sinit_num_ostreams, error)) { + return STATUS_ERR; + } + if (get_u16(val_expression->value.sctp_initmsg->sinit_max_instreams, + &initmsg.sinit_max_instreams, error)) { + return STATUS_ERR; + } + if (get_u16(val_expression->value.sctp_initmsg->sinit_max_attempts, + &initmsg.sinit_max_attempts, error)) { + return STATUS_ERR; + } + if (get_u16(val_expression->value.sctp_initmsg->sinit_max_init_timeo, + &initmsg.sinit_max_init_timeo, error)) { + return STATUS_ERR; + } + optval = &initmsg; break; #endif #if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED) diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c index 419f45ca34f4dbef4bc2c0dd542e3c6c8cd40471..6088b01fc4ad757018e05891deff74d569044270 100644 --- a/gtests/net/packetdrill/script.c +++ b/gtests/net/packetdrill/script.c @@ -314,6 +314,12 @@ void free_expression(struct expression *expression) #endif #ifdef SCTP_INITMSG case EXPR_SCTP_INITMSG: + assert(expression->value.sctp_initmsg); + free_expression(expression->value.sctp_initmsg->sinit_num_ostreams); + free_expression(expression->value.sctp_initmsg->sinit_max_instreams); + free_expression(expression->value.sctp_initmsg->sinit_max_attempts); + free_expression(expression->value.sctp_initmsg->sinit_max_init_timeo); + break; #endif #ifdef SCTP_DELAYED_SACK case EXPR_SCTP_SACKINFO: @@ -581,6 +587,43 @@ static int evaluate_sctp_rtoinfo_expression(struct expression *in, } #endif +#ifdef SCTP_INITMSG +static int evaluate_sctp_initmsg_expression(struct expression *in, + struct expression *out, + char **error) +{ + struct sctp_initmsg_expr *in_initmsg; + struct sctp_initmsg_expr *out_initmsg; + + assert(in->type == EXPR_SCTP_INITMSG); + assert(in->value.sctp_initmsg); + assert(out->type == EXPR_SCTP_INITMSG); + + out->value.sctp_initmsg = calloc(1, sizeof(struct sctp_initmsg_expr)); + + in_initmsg = in->value.sctp_initmsg; + out_initmsg = out->value.sctp_initmsg; + + if (evaluate(in_initmsg->sinit_num_ostreams, + &out_initmsg->sinit_num_ostreams, + error)) + return STATUS_ERR; + if (evaluate(in_initmsg->sinit_max_instreams, + &out_initmsg->sinit_max_instreams, + error)) + return STATUS_ERR; + if (evaluate(in_initmsg->sinit_max_attempts, + &out_initmsg->sinit_max_attempts, + error)) + return STATUS_ERR; + if (evaluate(in_initmsg->sinit_max_init_timeo, + &out_initmsg->sinit_max_init_timeo, + error)) + return STATUS_ERR; + return STATUS_OK; +} +#endif + #if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED) static int evaluate_sctp_assoc_value_expression(struct expression *in, struct expression *out, @@ -814,9 +857,8 @@ static int evaluate(struct expression *in, break; #endif #ifdef SCTP_INITMSG - case EXPR_SCTP_INITMSG: /* copy as-is */ - memcpy(&out->value.sctp_initmsg, &in->value.sctp_initmsg, - sizeof(in->value.sctp_initmsg)); + case EXPR_SCTP_INITMSG: + evaluate_sctp_initmsg_expression(in, out, error); break; #endif #if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED) diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h index cbdfad274d803ccb73ab942f0a75fe01a4b08f52..d0401bb9efeddbd2a845752b64a75cf606b23eb7 100644 --- a/gtests/net/packetdrill/script.h +++ b/gtests/net/packetdrill/script.h @@ -89,7 +89,7 @@ struct expression { struct sctp_rtoinfo_expr *sctp_rtoinfo; #endif #ifdef SCTP_INITMSG - struct sctp_initmsg sctp_initmsg; + struct sctp_initmsg_expr *sctp_initmsg; #endif #if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED) struct sctp_assoc_value_expr *sctp_assoc_value; @@ -162,6 +162,17 @@ struct sctp_rtoinfo_expr { }; #endif + +#ifdef SCTP_INITMSG +/* Parse tree for a sctp_initmsg struct in a [gs]etsockopt syscall. */ +struct sctp_initmsg_expr { + struct expression *sinit_num_ostreams; + struct expression *sinit_max_instreams; + struct expression *sinit_max_attempts; + struct expression *sinit_max_init_timeo; +}; +#endif + #if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED) /* Parse tree for a sctp_assoc_value struct in a [gs]etsockopt syscall. */ struct sctp_assoc_value_expr { diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt index 7983e824febd71050c39bb4972f7f0f8fff03681..a2ec201acded1bd0da5a27c7f3419a827ed6b4d6 100644 --- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt +++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt @@ -43,22 +43,22 @@ sstat_primary={ spinfo_state=SCTP_ACTIVE, spinfo_cwnd=4464, spinfo_srtt=..., spi +0 setsockopt(3, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, {spp_address={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")}, -spp_hbinterval=300, spp_pathmtu=1468, spp_pathmaxrxt=..., spp_flags=SPP_DSCP|SPP_HB_ENABLE, spp_ipv6_flowlabel=0, spp_dscp=0}, 152) = 0 +spp_hbinterval=300, spp_pathmaxrxt=8, spp_pathmtu=1468, spp_flags=SPP_DSCP|SPP_HB_ENABLE, spp_ipv6_flowlabel=0, spp_dscp=0}, 152) = 0 +0 getsockopt(3, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, {spp_address={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")}, -spp_hbinterval=300, spp_pathmtu=1468, spp_pathmaxrxt=..., spp_flags=SPP_DSCP|SPP_HB_ENABLE|SPP_PMTUD_ENABLE, spp_ipv6_flowlabel=0, spp_dscp=0}, [152]) = 0 +spp_hbinterval=300, spp_pathmaxrxt=8, spp_pathmtu=1468, spp_flags=SPP_DSCP|SPP_HB_ENABLE|SPP_PMTUD_ENABLE, spp_ipv6_flowlabel=0, spp_dscp=0}, [152]) = 0 +0 getsockopt(3, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, {spp_address={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")}, -spp_hbinterval=..., spp_pathmtu=1468, spp_pathmaxrxt=..., spp_flags=..., spp_ipv6_flowlabel=0, spp_dscp=0}, [152]) = 0 +spp_hbinterval=..., spp_pathmaxrxt=..., spp_pathmtu=1468, spp_flags=..., spp_ipv6_flowlabel=0, spp_dscp=0}, [152]) = 0 +0 getsockopt(3, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, {spp_address={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")}, -spp_hbinterval=300, spp_pathmtu=..., spp_pathmaxrxt=..., spp_flags=521, spp_ipv6_flowlabel=0, spp_dscp=0}, [152]) = 0 +spp_hbinterval=300, spp_pathmaxrxt=..., spp_pathmtu=..., spp_flags=521, spp_ipv6_flowlabel=0, spp_dscp=0}, [152]) = 0 +0 getsockopt(3, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, {spp_address={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")}, -spp_hbinterval=300, spp_pathmtu=1468, spp_pathmaxrxt=..., spp_flags=521, spp_ipv6_flowlabel=..., spp_dscp=0}, [152]) = 0 +spp_hbinterval=300, spp_pathmaxrxt=..., spp_pathmtu=1468, spp_flags=521, spp_ipv6_flowlabel=..., spp_dscp=0}, [152]) = 0 +0 getsockopt(3, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, {spp_address={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")}, -spp_hbinterval=300, spp_pathmtu=1468, spp_pathmaxrxt=..., spp_flags=521, spp_ipv6_flowlabel=0, spp_dscp=...}, [152]) = 0 +spp_hbinterval=300, spp_pathmaxrxt=..., spp_pathmtu=1468, spp_flags=521, spp_ipv6_flowlabel=0, spp_dscp=...}, [152]) = 0 +0 setsockopt(3, SOL_SOCKET, SO_LINGER, {onoff=1, linger=30}, 8) = 0 +0 getsockopt(3, SOL_SOCKET, SO_LINGER, {onoff=128, linger=30}, [8]) = 0 @@ -72,4 +72,10 @@ spp_hbinterval=300, spp_pathmtu=1468, spp_pathmaxrxt=..., spp_flags=521, spp_ipv +0 getsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=100, srto_max=..., srto_min=50}, [16]) = 0 +0 getsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=100, srto_max=200, srto_min=...}, [16]) = 0 +0 getsockopt(3, IPPROTO_SCTP, SCTP_MAXSEG, {assoc_value=1452}, [8]) = 0 + ++0 setsockopt(3, IPPROTO_SCTP, SCTP_INITMSG, {sinit_num_ostreams=2, sinit_max_instreams=2, sinit_max_attempts=2, sinit_max_init_timeo=30}, 8) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_INITMSG, {sinit_num_ostreams=2, sinit_max_instreams=2, sinit_max_attempts=2, sinit_max_init_timeo=30}, [8]) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_INITMSG, {sinit_num_ostreams=..., sinit_max_instreams=2, sinit_max_attempts=2, sinit_max_init_timeo=30}, [8]) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_INITMSG, {sinit_num_ostreams=2, sinit_max_instreams=..., sinit_max_attempts=2, sinit_max_init_timeo=30}, [8]) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_INITMSG, {sinit_num_ostreams=2, sinit_max_instreams=2, sinit_max_attempts=..., sinit_max_init_timeo=30}, [8]) = 0 +0 close(3) = 0