diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l index 4478ed2e8e8772fd2ca5606c8c4bbfd834d6da5d..081b52f116af23a819cdfbf5f991467c0e7dd84e 100644 --- a/gtests/net/packetdrill/lexer.l +++ b/gtests/net/packetdrill/lexer.l @@ -222,6 +222,7 @@ sstat_instrms return SSTAT_INSTRMS; sstat_outstrms return SSTAT_OUTSTRMS; sstat_fragmentation_point return SSTAT_FRAGMENTATION_POINT; sstat_primary return SSTAT_PRIMARY; +spinfo_address return SPINFO_ADDRESS; spinfo_state return SPINFO_STATE; spinfo_cwnd return SPINFO_CWND; spinfo_srtt return SPINFO_SRTT; diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index 88dd99e7ae55d88c721594d970e9a7a3f52166ca..0f5229c073bff9ab58db12fd31885defbe358c7d 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -511,7 +511,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %token <reserved> SSTAT_STATE SSTAT_RWND SSTAT_UNACKDATA SSTAT_PENDDATA %token <reserved> SSTAT_INSTRMS SSTAT_OUTSTRMS SSTAT_FRAGMENTATION_POINT %token <reserved> SSTAT_PRIMARY -%token <reserved> SPINFO_STATE SPINFO_CWND SPINFO_SRTT SPINFO_RTO SPINFO_MTU +%token <reserved> SPINFO_ADDRESS SPINFO_STATE SPINFO_CWND SPINFO_SRTT SPINFO_RTO +%token <reserved> SPINFO_MTU %token <reserved> CHUNK DATA INIT INIT_ACK HEARTBEAT HEARTBEAT_ACK ABORT %token <reserved> SHUTDOWN SHUTDOWN_ACK ERROR COOKIE_ECHO COOKIE_ACK ECNE CWR %token <reserved> SHUTDOWN_COMPLETE I_DATA PAD @@ -579,7 +580,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %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 -%type <expression> spinfo_state spinfo_cwnd spinfo_srtt spinfo_rto spinfo_mtu +%type <expression> spinfo_address spinfo_state spinfo_cwnd spinfo_srtt spinfo_rto spinfo_mtu %type <errno_info> opt_errno %type <chunk_list> sctp_chunk_list_spec %type <chunk_list_item> sctp_chunk_spec @@ -2730,6 +2731,11 @@ sstat_primary | SSTAT_PRIMARY '=' sctp_paddrinfo { $$ = $3; } ; +spinfo_address +: SPINFO_ADDRESS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +| SPINFO_ADDRESS '=' sockaddr { $$ = $3; } +; + spinfo_state : SPINFO_STATE '=' INTEGER { if (!is_valid_s32($3)) { @@ -2785,14 +2791,15 @@ spinfo_mtu ; sctp_paddrinfo -: '{' spinfo_state ',' spinfo_cwnd ',' spinfo_srtt ',' spinfo_rto ',' spinfo_mtu '}' { +: '{' spinfo_address ',' spinfo_state ',' spinfo_cwnd ',' spinfo_srtt ',' spinfo_rto ',' spinfo_mtu '}' { $$ = new_expression(EXPR_SCTP_PADDRINFO); $$->value.sctp_paddrinfo = calloc(1, sizeof(struct sctp_paddrinfo_expr)); - $$->value.sctp_paddrinfo->spinfo_state = $2; - $$->value.sctp_paddrinfo->spinfo_cwnd = $4; - $$->value.sctp_paddrinfo->spinfo_srtt = $6; - $$->value.sctp_paddrinfo->spinfo_rto = $8; - $$->value.sctp_paddrinfo->spinfo_mtu = $10; + $$->value.sctp_paddrinfo->spinfo_address = $2; + $$->value.sctp_paddrinfo->spinfo_state = $4; + $$->value.sctp_paddrinfo->spinfo_cwnd = $6; + $$->value.sctp_paddrinfo->spinfo_srtt = $8; + $$->value.sctp_paddrinfo->spinfo_rto = $10; + $$->value.sctp_paddrinfo->spinfo_mtu = $12; } ; diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c index baa01b540cfa68881544da486ffcd5a47fffb573..f2692999039eca64880ffc3e6e4b297cc96a92a9 100644 --- a/gtests/net/packetdrill/run_system_call.c +++ b/gtests/net/packetdrill/run_system_call.c @@ -2206,10 +2206,36 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, live_optlen = (socklen_t)sizeof(struct sctp_status); ((struct sctp_status*) live_optval)->sstat_assoc_id = 0; #endif +#ifdef SCTP_GET_PEER_ADDR_INFO + } else if (val_expression->type == EXPR_SCTP_PADDRINFO) { + struct sctp_paddrinfo_expr *expr_paddrinfo = val_expression->value.sctp_paddrinfo; + struct sctp_paddrinfo *live_paddrinfo = malloc(sizeof(struct sctp_paddrinfo)); + live_optlen = (socklen_t)sizeof(struct sctp_paddrinfo); + memset(live_paddrinfo, 0, sizeof(struct sctp_paddrinfo)); + live_paddrinfo->spinfo_assoc_id = 0; + if (expr_paddrinfo->spinfo_address->type == EXPR_ELLIPSIS) { + socklen_t len_addr = sizeof(live_paddrinfo->spinfo_address); + if (getpeername(live_fd, (struct sockaddr*) &live_paddrinfo->spinfo_address, &len_addr)) { + asprintf(error, "Bad setsockopt, bad get primary peer address"); + free(live_paddrinfo); + return STATUS_ERR; + } + } else if (expr_paddrinfo->spinfo_address->type == EXPR_SOCKET_ADDRESS_IPV4) { + memcpy(&live_paddrinfo->spinfo_address, expr_paddrinfo->spinfo_address->value.socket_address_ipv4, sizeof(struct sockaddr_in)); + } else if (expr_paddrinfo->spinfo_address->type == EXPR_SOCKET_ADDRESS_IPV6) { + memcpy(&live_paddrinfo->spinfo_address, expr_paddrinfo->spinfo_address->value.socket_address_ipv6, sizeof(struct sockaddr_in6)); + } else { + asprintf(error, "Bad setsockopt, bad get input for spinfo_address"); + free(live_paddrinfo); + return STATUS_ERR; + } + live_optval = live_paddrinfo; +#endif #ifdef SCTP_PEER_ADDR_PARAMS } else if (val_expression->type == EXPR_SCTP_PEER_ADDR_PARAMS) { struct sctp_paddrparams_expr *expr_params = val_expression->value.sctp_paddrparams; struct sctp_paddrparams *live_params = malloc(sizeof(struct sctp_paddrparams)); + memset(live_params, 0, sizeof(struct sctp_paddrparams)); live_optlen = sizeof(struct sctp_paddrparams); if (expr_params->spp_address->type == EXPR_ELLIPSIS) { socklen_t len_addr = sizeof(live_params->spp_address); @@ -2301,6 +2327,13 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, return STATUS_ERR; } #endif +#ifdef SCTP_GET_PEER_ADDR_INFO + } else if (val_expression->type == EXPR_SCTP_PADDRINFO) { + if (check_sctp_paddrinfo(val_expression->value.sctp_paddrinfo, live_optval, error)) { + free(live_optval); + return STATUS_ERR; + } +#endif #ifdef SCTP_PEER_ADDR_PARAMS } else if (val_expression->type == EXPR_SCTP_PEER_ADDR_PARAMS) { if (check_sctp_paddrparams(val_expression->value.sctp_paddrparams, live_optval, error)) { @@ -2356,6 +2389,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, #ifdef SCTP_STATUS struct sctp_status status; #endif +#ifdef SCTP_GET_PEER_ADDR_INFO + struct sctp_paddrinfo paddrinfo; +#endif #if defined(SCTP_SS_VALUE) struct sctp_stream_value stream_value; #endif @@ -2482,6 +2518,32 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, optval = &status; break; #endif +#ifdef SCTP_GET_PEER_ADDR_INFO + case EXPR_SCTP_PADDRINFO: + paddrinfo.spinfo_assoc_id = 0; + if (val_expression->value.sctp_paddrinfo->spinfo_address->type == EXPR_SOCKET_ADDRESS_IPV4) { + memcpy(&paddrinfo.spinfo_address, + val_expression->value.sctp_paddrinfo->spinfo_address->value.socket_address_ipv4, + sizeof(struct sockaddr_in)); + } else if (val_expression->value.sctp_paddrinfo->spinfo_address->type == EXPR_SOCKET_ADDRESS_IPV6) { + memcpy(&paddrinfo.spinfo_address, + val_expression->value.sctp_paddrinfo->spinfo_address->value.socket_address_ipv6, + sizeof(struct sockaddr_in6)); + } else if (val_expression->value.sctp_paddrinfo->spinfo_address->type == EXPR_ELLIPSIS) { + socklen_t len_addr = sizeof(struct sockaddr_storage); + if (getpeername(live_fd, + (struct sockaddr*)&paddrinfo.spinfo_address, + &len_addr)) { + asprintf(error, "Bad setsockopt, bad get primary peer address"); + return STATUS_ERR; + } + } else { + asprintf(error, "Bad setsockopt, bad input for spinfo_address for socketoption SCTP_GET_PEER_ADDR_INFO"); + return STATUS_ERR; + } + optval = &paddrinfo; + break; +#endif #ifdef SCTP_PEER_ADDR_PARAMS case EXPR_SCTP_PEER_ADDR_PARAMS: paddrparams.spp_assoc_id = 0; diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c index 9b895398c7988c37970496139ab9b98b9241fc6c..a198c17ddb93d4a21ba0b13b89d277f21caa25f6 100644 --- a/gtests/net/packetdrill/script.c +++ b/gtests/net/packetdrill/script.c @@ -331,9 +331,7 @@ void free_expression(struct expression *expression) #ifdef SCTP_STATUS case EXPR_SCTP_PADDRINFO: assert(expression->value.sctp_paddrinfo); -#if 0 free_expression(expression->value.sctp_paddrinfo->spinfo_address); -#endif free_expression(expression->value.sctp_paddrinfo->spinfo_state); free_expression(expression->value.sctp_paddrinfo->spinfo_cwnd); free_expression(expression->value.sctp_paddrinfo->spinfo_srtt); @@ -700,12 +698,10 @@ static int evaluate_sctp_paddrinfo_expression(struct expression *in, in_paddrinfo = in->value.sctp_paddrinfo; out_paddrinfo = out->value.sctp_paddrinfo; -#if 0 if (evaluate(in_paddrinfo->spinfo_address, - &out_value->spinfo_addresss, + &out_paddrinfo->spinfo_address, error)) return STATUS_ERR; -#endif if (evaluate(in_paddrinfo->spinfo_state, &out_paddrinfo->spinfo_state, error)) diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h index 04bca7879a8b8e95161c4f75ca906f9993972d4a..c25b7e7e665d13f0e3a31ef4a5c93c47cd8c614f 100644 --- a/gtests/net/packetdrill/script.h +++ b/gtests/net/packetdrill/script.h @@ -212,6 +212,7 @@ struct sctp_status_expr { /* Parse tree for a sctp_paddrinfo struct in a [gs]etsockopt syscall. */ struct sctp_paddrinfo_expr { + struct expression *spinfo_address; struct expression *spinfo_state; struct expression *spinfo_cwnd; struct expression *spinfo_srtt; diff --git a/gtests/net/packetdrill/symbols_freebsd.c b/gtests/net/packetdrill/symbols_freebsd.c index 80811b847226e5249b6830d7fbd3c110800a9215..46939e835416c0db3eaaa266999a672c8b4d0300 100644 --- a/gtests/net/packetdrill/symbols_freebsd.c +++ b/gtests/net/packetdrill/symbols_freebsd.c @@ -87,6 +87,7 @@ struct int_symbol platform_symbols_table[] = { { SCTP_MAX_BURST, "SCTP_MAX_BURST" }, { SCTP_PEER_ADDR_PARAMS, "SCTP_PEER_ADDR_PARAMS" }, { SCTP_STATUS, "SCTP_STATUS" }, + { SCTP_GET_PEER_ADDR_INFO, "SCTP_GET_PEER_ADDR_INFO" }, { SCTP_FRAGMENT_INTERLEAVE, "SCTP_FRAGMENT_INTERLEAVE" }, #if defined(SCTP_INTERLEAVING_SUPPORTED) { SCTP_INTERLEAVING_SUPPORTED, "SCTP_INTERLEAVING_SUPPORTED" }, diff --git a/gtests/net/packetdrill/symbols_linux.c b/gtests/net/packetdrill/symbols_linux.c index d175d6a8486561862e37cea376b73fda0e5a8c69..5d9ff5784f38cb0fdfb5e443595d274cd48fd33e 100644 --- a/gtests/net/packetdrill/symbols_linux.c +++ b/gtests/net/packetdrill/symbols_linux.c @@ -108,6 +108,7 @@ struct int_symbol platform_symbols_table[] = { { SCTP_MAX_BURST, "SCTP_MAX_BURST" }, { SCTP_PEER_ADDR_PARAMS, "SCTP_PEER_ADDR_PARAMS" }, { SCTP_STATUS, "SCTP_STATUS" }, + { SCTP_GET_PEER_ADDR_INFO, "SCTP_GET_PEER_ADDR_INFO" }, { SCTP_FRAGMENT_INTERLEAVE, "SCTP_FRAGMENT_INTERLEAVE" }, #if 0 { SCTP_INTERLEAVING_SUPPORTED, "SCTP_INTERLEAVING_SUPPORTED" }, 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 a86b7af248d28a0862d9a9e3da0ee66f3733e066..f304bf8ca495634667a4bbacc137c124bde88760 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 @@ -38,8 +38,24 @@ sstat_penddata=0, sstat_instrms=1, sstat_outstrms=..., sstat_fragmentation_point sstat_penddata=0, sstat_instrms=1, sstat_outstrms=1, sstat_fragmentation_point=..., sstat_primary=...}, [176]) = 0 +0 getsockopt(3, IPPROTO_SCTP, SCTP_STATUS, {sstat_state=SCTP_ESTABLISHED, sstat_rwnd=1500, sstat_unackdata=0, sstat_penddata=0, -sstat_instrms=1, sstat_outstrms=1, sstat_fragmentation_point=..., -sstat_primary={ spinfo_state=SCTP_ACTIVE, spinfo_cwnd=4464, spinfo_srtt=..., spinfo_rto=1000, spinfo_mtu=1468} }, [176]) = 0 +sstat_instrms=1, sstat_outstrms=1, sstat_fragmentation_point=..., sstat_primary={spinfo_address={sa_family=AF_INET,sin_port=htons(8080), +sin_addr=inet_addr("192.0.2.1")}, spinfo_state=SCTP_ACTIVE, spinfo_cwnd=4464, spinfo_srtt=..., spinfo_rto=1000, spinfo_mtu=1468} }, [176]) = 0 + + ++0 setsockopt(3, IPPROTO_SCTP, SCTP_GET_PEER_ADDR_INFO, {spinfo_address={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")}, +spinfo_state=SCTP_ACTIVE, spinfo_cwnd=4464, spinfo_srtt=111, spinfo_rto=1000, spinfo_mtu=1468}, 152) = -1 (ENOPROTOOPT) + ++0 getsockopt(3, IPPROTO_SCTP, SCTP_GET_PEER_ADDR_INFO, {spinfo_address={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")}, +spinfo_state=..., spinfo_cwnd=4464, spinfo_srtt=..., spinfo_rto=1000, spinfo_mtu=1468}, [152]) = 0 + ++0 getsockopt(3, IPPROTO_SCTP, SCTP_GET_PEER_ADDR_INFO, {spinfo_address={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")}, +spinfo_state=SCTP_ACTIVE, spinfo_cwnd=..., spinfo_srtt=..., spinfo_rto=1000, spinfo_mtu=1468}, [152]) = 0 + ++0 getsockopt(3, IPPROTO_SCTP, SCTP_GET_PEER_ADDR_INFO, {spinfo_address={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")}, +spinfo_state=SCTP_ACTIVE, spinfo_cwnd=4464, spinfo_srtt=..., spinfo_rto=..., spinfo_mtu=1468}, [152]) = 0 + ++0 getsockopt(3, IPPROTO_SCTP, SCTP_GET_PEER_ADDR_INFO, {spinfo_address={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")}, +spinfo_state=SCTP_ACTIVE, spinfo_cwnd=4464, spinfo_srtt=..., spinfo_rto=1000, spinfo_mtu=...}, [152]) = 0 +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")}, @@ -60,6 +76,7 @@ spp_hbinterval=300, spp_pathmaxrxt=..., spp_pathmtu=1468, spp_flags=521, spp_ipv +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_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 +0 getsockopt(3, SOL_SOCKET, SO_LINGER, {onoff=128, linger=...}, [8]) = 0