diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l index 4f8b391f11fb09ce9859c30e84e788e9fc2033c5..0e4bb734030b51512df8d8d119ef1bcd9c2f2779 100644 --- a/gtests/net/packetdrill/lexer.l +++ b/gtests/net/packetdrill/lexer.l @@ -227,6 +227,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 5f02e51ce4d15e5984e06bf251c6a9acf6597cfe..aff97c189b49cf1b02a773521c1ecbcc2f3846fd 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 @@ -581,7 +582,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 <expression> sasoc_asocmaxrxt sasoc_number_peer_destinations sasoc_peer_rwnd %type <expression> sasoc_local_rwnd sasoc_cookie_life sctp_assocparams %type <errno_info> opt_errno @@ -2737,6 +2738,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)) { @@ -2792,14 +2798,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 2a18bfbe7844c1c51f1d97e0013a853a2d6bc61a..15fe76adfc7a1e059f622b4610bcb011ceea27c1 100644 --- a/gtests/net/packetdrill/run_system_call.c +++ b/gtests/net/packetdrill/run_system_call.c @@ -2282,10 +2282,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); @@ -2384,6 +2410,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)) { @@ -2442,6 +2475,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 @@ -2594,6 +2630,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 0b486f3055287c9fd746559c4a2bf5a1e6bf47ea..3f2d056b2505a7c3e3745e5ce549db0a7e9aeee1 100644 --- a/gtests/net/packetdrill/script.c +++ b/gtests/net/packetdrill/script.c @@ -334,9 +334,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); @@ -712,12 +710,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 ea062ce6f9ed247646f63180f434b5b97dbf9b87..037a3720cc0b2262614b8ce56da041b880ca2b6f 100644 --- a/gtests/net/packetdrill/script.h +++ b/gtests/net/packetdrill/script.h @@ -217,6 +217,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 5932f39f591020104a01f0d6aec4e482797a34a8..79511960ade2bd1ba7bb9a87a0a67b54c3664e76 100644 --- a/gtests/net/packetdrill/symbols_freebsd.c +++ b/gtests/net/packetdrill/symbols_freebsd.c @@ -88,6 +88,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 9116c17e9f15ff9fbb06b51c79e2c2dd95c3f1e3..e1c06f248cea611e29422678184934ff0220e80c 100644 --- a/gtests/net/packetdrill/symbols_linux.c +++ b/gtests/net/packetdrill/symbols_linux.c @@ -109,6 +109,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 2dcd9dbee98a079bb1365c0132029ebf3b7c895e..382334acdf79156a54437136cefce6dd77732e38 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