diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index a8aa42363c5ab2ca6a32c6a55ecf3b73a1d177e7..8f353410b201060a80ebbcd1c7cfa2262974a2f4 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -564,9 +564,10 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <expression_list> expression_list function_arguments %type <expression> expression binary_expression array %type <expression> decimal_integer hex_integer -%type <expression> inaddr sockaddr msghdr iovec pollfd opt_revents linger -%type <expression> sctp_rtoinfo sctp_initmsg sctp_assocval sctp_sackinfo -%type <expression> sctp_status +%type <expression> inaddr sockaddr msghdr iovec pollfd opt_revents +%type <expression> linger l_onoff l_linger +%type <expression> sctp_status sctp_initmsg sctp_assocval sctp_sackinfo +%type <expression> sctp_rtoinfo srto_initial srto_max srto_min %type <errno_info> opt_errno %type <chunk_list> sctp_chunk_list_spec %type <chunk_list_item> sctp_chunk_spec @@ -2280,30 +2281,74 @@ opt_revents | ',' REVENTS '=' expression { $$ = $4; } ; +l_onoff +: ONOFF '=' INTEGER { + if (!is_valid_s32($3)) { + semantic_error("linger onoff out of range"); + } else { + $$ = new_integer_expression($3, "%ld"); + } +} +| ONOFF '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +l_linger +: LINGER '=' INTEGER { + if (!is_valid_s32($3)) { + semantic_error("linger out of range"); + } + $$ = new_integer_expression($3, "%ld"); +} +| LINGER '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + linger -: '{' ONOFF '=' INTEGER ',' LINGER '=' INTEGER '}' { +: '{' l_onoff ',' l_linger '}' { $$ = new_expression(EXPR_LINGER); - $$->value.linger.l_onoff = $4; - $$->value.linger.l_linger = $8; + $$->value.linger = (struct linger_expr*) calloc(1, sizeof(struct linger_expr)); + $$->value.linger->l_onoff = $2; + $$->value.linger->l_linger = $4; } ; -sctp_rtoinfo -: '{' SRTO_INITIAL '=' INTEGER ',' SRTO_MAX '=' INTEGER ',' SRTO_MIN '=' INTEGER '}' { -#ifdef SCTP_RTOINFO - $$ = new_expression(EXPR_SCTP_RTOINFO); - if (!is_valid_u32($4)) { +srto_initial +: SRTO_INITIAL '=' INTEGER { + if (!is_valid_u32($3)){ semantic_error("srto_initial out of range"); } - $$->value.sctp_rtoinfo.srto_initial = $4; - if (!is_valid_u32($8)) { + $$ = new_integer_expression($3, "%u"); +} +| SRTO_INITIAL '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +srto_max +: SRTO_MAX '=' INTEGER { + if (!is_valid_u32($3)) { semantic_error("srto_max out of range"); } - $$->value.sctp_rtoinfo.srto_max = $8; - if (!is_valid_u32($12)) { + $$ = new_integer_expression($3, "%u"); +} +| SRTO_MAX '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +srto_min +: SRTO_MIN '=' INTEGER { + if (!is_valid_u32($3)) { semantic_error("srto_min out of range"); } - $$->value.sctp_rtoinfo.srto_min = $12; + $$ = new_integer_expression($3, "%u"); +} +| SRTO_MIN '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +sctp_rtoinfo +: '{' srto_initial ',' srto_max ',' srto_min '}' { +#ifdef SCTP_RTOINFO + $$ = new_expression(EXPR_SCTP_RTOINFO); + $$->value.sctp_rtoinfo = (struct sctp_rtoinfo_expr*) calloc(1, sizeof(struct sctp_rtoinfo_expr)); + $$->value.sctp_rtoinfo->srto_initial = $2; + $$->value.sctp_rtoinfo->srto_max = $4; + $$->value.sctp_rtoinfo->srto_min = $6; #else $$ = NULL; #endif diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c index 6f5a018b38f53adee2f175b76498b861234524d2..5457c70580d851771f3834e2507778f75881e714 100644 --- a/gtests/net/packetdrill/run_system_call.c +++ b/gtests/net/packetdrill/run_system_call.c @@ -1582,12 +1582,13 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, if (val_expression == NULL) { return STATUS_ERR; } else if (val_expression->type == EXPR_LINGER) { - live_optval = malloc(sizeof(val_expression->value.linger)); - live_optlen = (socklen_t)sizeof(val_expression->value.linger); + live_optval = malloc(sizeof(struct linger)); + live_optlen = (socklen_t)sizeof(struct linger); #ifdef SCTP_RTOINFO } else if (val_expression->type == EXPR_SCTP_RTOINFO) { - live_optval = malloc(sizeof(val_expression->value.sctp_rtoinfo)); - live_optlen = (socklen_t)sizeof(val_expression->value.sctp_rtoinfo); + live_optval = malloc(sizeof(struct sctp_rtoinfo)); + live_optlen = (socklen_t)sizeof(struct sctp_rtoinfo); + ((struct sctp_rtoinfo*)live_optval)->srto_assoc_id = 0; #endif #ifdef SCTP_STATUS } else if (val_expression->type == EXPR_SCTP_STATUS) { @@ -1614,39 +1615,77 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, free(live_optval); return STATUS_ERR; } - if (val_expression->type == EXPR_LINGER) { + struct expression *l_onoff = val_expression->value.linger->l_onoff; + struct expression *l_linger = val_expression->value.linger->l_linger; struct linger *ling = live_optval; - if (ling->l_onoff != val_expression->value.linger.l_onoff) { - asprintf(error, "Bad getsockopt Linger onoff: expected: %d actual: %d", - val_expression->value.linger.l_onoff, ling->l_onoff); - free(live_optval); - return STATUS_ERR; + int val_onoff = 0; + if (l_onoff->type == EXPR_INTEGER) { + if (get_s32(l_onoff, &val_onoff, error)) { + free(live_optval); + return STATUS_ERR; + } + if (val_onoff != ling->l_onoff) { + asprintf(error, "Bad getsockopt Linger onoff: expected: %d actual: %d", + (int) val_onoff, ling->l_onoff); + free(live_optval); + return STATUS_ERR; + } } - if (ling->l_linger != val_expression->value.linger.l_linger) { - asprintf(error, "Bad getsockopt Linger Value: expected: %d actual: %d", - val_expression->value.linger.l_linger, ling->l_linger); - free(live_optval); - return STATUS_ERR; + int val_linger = 0; + if (l_linger->type == EXPR_INTEGER) { + if (get_s32(l_linger, &val_linger, error)) { + free(live_optval); + return STATUS_ERR; + } + if (ling->l_linger != val_linger) { + asprintf(error, "Bad getsockopt Linger Value: expected: %d actual: %d", + val_linger, ling->l_linger); + free(live_optval); + return STATUS_ERR; + } } + #ifdef SCTP_RTOINFO } else if (val_expression->type == EXPR_SCTP_RTOINFO) { + struct expression *srto_initial = val_expression->value.sctp_rtoinfo->srto_initial; + struct expression *srto_max = val_expression->value.sctp_rtoinfo->srto_max; + struct expression *srto_min = val_expression->value.sctp_rtoinfo->srto_min; struct sctp_rtoinfo *rtoinfo = live_optval; - if (rtoinfo->srto_initial != val_expression->value.sctp_rtoinfo.srto_initial){ - asprintf(error, "Bad getsockopt SCTP_RTOINFO initial: expected: %u actual: %u", - val_expression->value.sctp_rtoinfo.srto_initial, rtoinfo->srto_initial); - free(live_optval); - return STATUS_ERR; - } else if (rtoinfo->srto_max != val_expression->value.sctp_rtoinfo.srto_max){ - asprintf(error, "Bad getsockopt SCTP_RTOINFO SRTO_MAX: expected: %u actual: %u", - val_expression->value.sctp_rtoinfo.srto_max, rtoinfo->srto_max); - free(live_optval); - return STATUS_ERR; - } else if (rtoinfo->srto_min != val_expression->value.sctp_rtoinfo.srto_min){ - asprintf(error, "Bad getsockopt SCTP_RTOINFO SRTO_MIN: expected: %u actual: %u", - val_expression->value.sctp_rtoinfo.srto_min, rtoinfo->srto_min); - free(live_optval); - return STATUS_ERR; + int initial=0, max=0, min=0; + if (srto_initial->type == EXPR_INTEGER) { + if (get_s32(srto_initial, &initial, error)) { + free(live_optval); + return STATUS_ERR; + } + if (rtoinfo->srto_initial != initial) { + asprintf(error, "Bad getsockopt SCTP_RTOINFO initial: expected: %u actual: %u", + initial, rtoinfo->srto_initial); + free(live_optval); + return STATUS_ERR; + } + } else if (srto_max->type == EXPR_INTEGER) { + if (get_s32(srto_max, &max, error)) { + free(live_optval); + return STATUS_ERR; + } + if (rtoinfo->srto_max != max) { + asprintf(error, "Bad getsockopt SCTP_RTOINFO SRTO_MAX: expected: %u actual: %u", + max, rtoinfo->srto_max); + free(live_optval); + return STATUS_ERR; + } + } else if (srto_min->type == EXPR_INTEGER) { + if (get_s32(srto_min, &min, error)) { + free(live_optval); + return STATUS_ERR; + } + if (rtoinfo->srto_min != min) { + asprintf(error, "Bad getsockopt SCTP_RTOINFO SRTO_MIN: expected: %u actual: %u", + min, rtoinfo->srto_min); + free(live_optval); + return STATUS_ERR; + } } #endif #ifdef SCTP_STATUS @@ -1726,7 +1765,11 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, if (val_expression == NULL) return STATUS_ERR; if (val_expression->type == EXPR_LINGER) { - optval = &val_expression->value.linger; + optval = malloc(sizeof(struct linger)); + get_s32(val_expression->value.linger->l_onoff, + &(((struct linger*) optval)->l_onoff), error); + get_s32(val_expression->value.linger->l_linger, + &(((struct linger*) optval)->l_linger), error); } else if (val_expression->type == EXPR_STRING) { optval = val_expression->value.string; } else if (val_expression->type == EXPR_LIST) { @@ -1735,7 +1778,20 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, optval = &optval_s32; #ifdef SCTP_RTOINFO } else if (val_expression->type == EXPR_SCTP_RTOINFO) { - optval = &val_expression->value.sctp_rtoinfo; + struct sctp_rtoinfo *rtoinfo; + struct sctp_rtoinfo_expr *expr_rtoinfo = val_expression->value.sctp_rtoinfo; + if (expr_rtoinfo->srto_initial->type != EXPR_INTEGER || + expr_rtoinfo->srto_max->type != EXPR_INTEGER || + expr_rtoinfo->srto_min->type != EXPR_INTEGER) { + asprintf(error, "Bad setsockopt, bad inputtype for rtoinfo"); + return STATUS_ERR; + } + rtoinfo = malloc(sizeof(struct sctp_rtoinfo)); + rtoinfo->srto_initial = expr_rtoinfo->srto_initial->value.num; + rtoinfo->srto_max = expr_rtoinfo->srto_max->value.num; + rtoinfo->srto_min = expr_rtoinfo->srto_min->value.num; + rtoinfo->srto_assoc_id = 0; + optval = rtoinfo; #endif #ifdef SCTP_INITMSG } else if (val_expression->type == EXPR_SCTP_INITMSG) { @@ -1765,6 +1821,7 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, result = setsockopt(live_fd, level, optname, optval, optlen); return end_syscall(state, syscall, CHECK_EXACT, result, error); + free(optval); } static int syscall_poll(struct state *state, struct syscall_spec *syscall, diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c index c4fdb4b2aedff29ebc5592f6bb95651b6cdd9b35..7b7d656577e63322f865f600d38a354e1280bd73 100644 --- a/gtests/net/packetdrill/script.c +++ b/gtests/net/packetdrill/script.c @@ -285,9 +285,17 @@ void free_expression(struct expression *expression) switch (expression->type) { case EXPR_ELLIPSIS: case EXPR_INTEGER: + break; case EXPR_LINGER: + free(expression->value.linger->l_onoff); + free(expression->value.linger->l_linger); + break; #ifdef SCTP_RTOINFO case EXPR_SCTP_RTOINFO: + free(expression->value.sctp_rtoinfo->srto_initial); + free(expression->value.sctp_rtoinfo->srto_max); + free(expression->value.sctp_rtoinfo->srto_min); + break; #endif #ifdef SCTP_INITMSG case EXPR_SCTP_INITMSG: diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h index a2b2e46b118718d717504bb56fc35586d0c9e21b..cba02337b50e441dd038f2b8a4e5f6fcc50a81cc 100644 --- a/gtests/net/packetdrill/script.h +++ b/gtests/net/packetdrill/script.h @@ -72,7 +72,7 @@ struct expression { union { s64 num; char *string; - struct linger linger; + struct linger_expr *linger; struct sockaddr_in *socket_address_ipv4; struct sockaddr_in6 *socket_address_ipv6; struct binary_expression *binary; @@ -81,7 +81,7 @@ struct expression { struct msghdr_expr *msghdr; struct pollfd_expr *pollfd; #ifdef SCTP_RTOINFO - struct sctp_rtoinfo sctp_rtoinfo; + struct sctp_rtoinfo_expr *sctp_rtoinfo; #endif #ifdef SCTP_INITMSG struct sctp_initmsg sctp_initmsg; @@ -136,6 +136,20 @@ struct pollfd_expr { struct expression *revents; /* returned events */ }; +/* Handle values for socketoption SO_Linger with inputtypes and values*/ +struct linger_expr { + struct expression *l_onoff; + struct expression *l_linger; +}; +/* Parse tree for syscall get/setsockopt for sctp_rtoinfo*/ +#ifdef SCTP_RTOINFO +struct sctp_rtoinfo_expr { + struct expression *srto_initial; + struct expression *srto_max; + struct expression *srto_min; +}; +#endif + /* 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/tests/bsd/sctp/sctp_get_socket_options.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt index 3310fd898266cb57a1efbbe9445c2d0775544a8e..8374c2c9fb78140ccaaeeeefef61792e53cb6ef0 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 @@ -10,15 +10,20 @@ +0.0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0 -+0 setsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=100, srto_max=200, srto_min=50}, 16) = 0 -+0 getsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=100, srto_max=200, srto_min=50}, [16]) = 0 - +0 getsockopt(3, IPPROTO_SCTP, SCTP_STATUS, {sstat_state=8, sstat_rwnd=1500, sstat_unackdata=0, sstat_penddata=0, sstat_instrms=1, sstat_outstrms=1, - sstat_fragmentation_point=1452, sstat_primary=...}, [176])= 0 + sstat_fragmentation_point=1452, sstat_primary=...}, [176])= 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 ++0 getsockopt(3, SOL_SOCKET, SO_LINGER, {onoff=128, linger=...}, [8]) = 0 ++0 getsockopt(3, SOL_SOCKET, SO_LINGER, {onoff=..., linger=30}, [8]) = 0 ++0 getsockopt(3, SOL_SOCKET, SO_LINGER, {onoff=..., linger=...}, [8]) = 0 ++0 setsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=100, srto_max=200, srto_min=50}, 16) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=100, srto_max=200, srto_min=50}, [16]) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=..., srto_max=200, srto_min=50}, [16]) = 0 ++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 close(3) = 0