diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l index a43c2e669071cf25d4ef9f541476bea61087fc5b..4478ed2e8e8772fd2ca5606c8c4bbfd834d6da5d 100644 --- a/gtests/net/packetdrill/lexer.l +++ b/gtests/net/packetdrill/lexer.l @@ -203,6 +203,8 @@ noecn return NO_ECN; ce return CE; [.][.][.] return ELLIPSIS; assoc_value return ASSOC_VALUE; +stream_id return STREAM_ID; +stream_value return STREAM_VALUE; sack_delay return SACK_DELAY; sack_freq return SACK_FREQ; srto_initial return SRTO_INITIAL; @@ -248,6 +250,7 @@ COOKIE_ACK return COOKIE_ACK; ECNE return ECNE; CWR return CWR; SHUTDOWN_COMPLETE return SHUTDOWN_COMPLETE; +I-DATA return I_DATA; PAD return PAD; type return TYPE; flgs return FLAGS; @@ -259,7 +262,9 @@ os return OS; tsn return TSN; sid return SID; ssn return SSN; +mid return MID; ppid return PPID; +fsn return FSN; cum_tsn return CUM_TSN; gaps return GAPS; dups return DUPS; @@ -273,6 +278,7 @@ COOKIE_PRESERVATIVE return COOKIE_PRESERVATIVE; HOSTNAME_ADDRESS return HOSTNAME_ADDRESS; SUPPORTED_ADDRESS_TYPES return SUPPORTED_ADDRESS_TYPES; ECN_CAPABLE return ECN_CAPABLE; +SUPPORTED_EXTENSIONS return SUPPORTED_EXTENSIONS; addr return ADDR; incr return INCR; types return TYPES; diff --git a/gtests/net/packetdrill/packet_to_string_test.c b/gtests/net/packetdrill/packet_to_string_test.c index 899ef4b743168cce1d774174c076d44aa3cfac8c..8392b65e97c227b988068f43cd1f456225891da8 100644 --- a/gtests/net/packetdrill/packet_to_string_test.c +++ b/gtests/net/packetdrill/packet_to_string_test.c @@ -102,7 +102,7 @@ static void test_sctp_ipv6_packet_to_string(void) /* An IPv6/SCTP packet. */ u8 data[] = { /* IPv6 Base Header: */ - 0x60, 0x00, 0x00, 0x00, 0x01, 0xa0, 0x84, 0xff, + 0x60, 0x00, 0x00, 0x00, 0x01, 0xd8, 0x84, 0xff, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -110,7 +110,7 @@ static void test_sctp_ipv6_packet_to_string(void) /* SCTP Common Header: */ 0x04, 0xd2, 0x1f, 0x90, 0x01, 0x02, 0x03, 0x04, - 0x6e, 0xfc, 0x47, 0x17, + 0x24, 0x25, 0x51, 0x31, /* SCTP DATA Chunk */ 0x00, 0x0f, 0x00, 0x13, 0x01, 0x02, 0x03, 0x04, @@ -118,7 +118,7 @@ static void test_sctp_ipv6_packet_to_string(void) 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, /* SCTP INIT Chunk */ - 0x01, 0x00, 0x00, 0x60, + 0x01, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, @@ -138,6 +138,8 @@ static void test_sctp_ipv6_packet_to_string(void) 0x00, 0x05, 0x00, 0x06, 0x00, 0x0b, 0x00, 0x00, 0x80, 0x00, 0x00, 0x04, + 0x80, 0x08, 0x00, 0x05, + 0x40, 0x00, 0x00, 0x00, 0x80, 0x05, 0x00, 0x10, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, @@ -224,6 +226,20 @@ static void test_sctp_ipv6_packet_to_string(void) 0x01, 0x02, 0x03, 0x04, /* SCTP SHUTDOWN_COMPLETE Chunk */ 0x0e, 0x01, 0x00, 0x04, + /* SCTP I-DATA Chunk */ + 0x40, 0x0f, 0x00, 0x17, + 0x00, 0x00, 0x00, 0x04, + 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x00, + /* SCTP I-DATA Chunk */ + 0x40, 0x0d, 0x00, 0x17, + 0x00, 0x00, 0x00, 0x04, + 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x02, 0x00, /* SCTP PAD Chunk */ 0x84, 0x00, 0x00, 0x10, 0x50, 0x50, 0x50, 0x50, @@ -259,6 +275,7 @@ static void test_sctp_ipv6_packet_to_string(void) "HOSTNAME_ADDRESS[addr=\"@A\"], " "SUPPORTED_ADDRESS_TYPES[types=[IPv4, IPv6, HOSTNAME]], " "ECN_CAPABLE[], " + "SUPPORTED_EXTENSIONS[types=[I-DATA]], " "PAD[len=16, val=...]]; " "INIT_ACK[flgs=0x00, tag=1, a_rwnd=65536, os=15, is=15, tsn=16909060, " "STATE_COOKIE[len=7, val=...], " @@ -294,6 +311,8 @@ static void test_sctp_ipv6_packet_to_string(void) "ECNE[flgs=0x00, tsn=16909060]; " "CWR[flgs=0x00, tsn=16909060]; " "SHUTDOWN_COMPLETE[flgs=T]; " + "I-DATA[flgs=IUBE, len=23, tsn=4, sid=255, mid=1, ppid=0]; " + "I-DATA[flgs=IUE, len=23, tsn=4, sid=255, mid=2, fsn=1]; " "PAD[flgs=0x00, len=16, val=...]"; assert(strcmp(dump, expected) == 0); free(dump); @@ -314,6 +333,7 @@ static void test_sctp_ipv6_packet_to_string(void) "HOSTNAME_ADDRESS[addr=\"@A\"], " "SUPPORTED_ADDRESS_TYPES[types=[IPv4, IPv6, HOSTNAME]], " "ECN_CAPABLE[], " + "SUPPORTED_EXTENSIONS[types=[I-DATA]], " "PAD[len=16, val=...]]; " "INIT_ACK[flgs=0x00, tag=1, a_rwnd=65536, os=15, is=15, tsn=16909060, " "STATE_COOKIE[len=7, val=...], " @@ -349,6 +369,8 @@ static void test_sctp_ipv6_packet_to_string(void) "ECNE[flgs=0x00, tsn=16909060]; " "CWR[flgs=0x00, tsn=16909060]; " "SHUTDOWN_COMPLETE[flgs=T]; " + "I-DATA[flgs=IUBE, len=23, tsn=4, sid=255, mid=1, ppid=0]; " + "I-DATA[flgs=IUE, len=23, tsn=4, sid=255, mid=2, fsn=1]; " "PAD[flgs=0x00, len=16, val=...]"; assert(strcmp(dump, expected) == 0); free(dump); @@ -369,6 +391,7 @@ static void test_sctp_ipv6_packet_to_string(void) "HOSTNAME_ADDRESS[addr=\"@A\"], " "SUPPORTED_ADDRESS_TYPES[types=[IPv4, IPv6, HOSTNAME]], " "ECN_CAPABLE[], " + "SUPPORTED_EXTENSIONS[types=[I-DATA]], " "PAD[len=16, val=...]]; " "INIT_ACK[flgs=0x00, tag=1, a_rwnd=65536, os=15, is=15, tsn=16909060, " "STATE_COOKIE[len=7, val=...], " @@ -404,37 +427,42 @@ static void test_sctp_ipv6_packet_to_string(void) "ECNE[flgs=0x00, tsn=16909060]; " "CWR[flgs=0x00, tsn=16909060]; " "SHUTDOWN_COMPLETE[flgs=T]; " + "I-DATA[flgs=IUBE, len=23, tsn=4, sid=255, mid=1, ppid=0]; " + "I-DATA[flgs=IUE, len=23, tsn=4, sid=255, mid=2, fsn=1]; " "PAD[flgs=0x00, len=16, val=...]" "\n" - "0x0000: 60 00 00 00 01 a0 84 ff 00 02 00 00 00 00 00 00 " "\n" + "0x0000: 60 00 00 00 01 d8 84 ff 00 02 00 00 00 00 00 00 " "\n" "0x0010: 00 00 00 00 00 00 22 22 00 01 00 00 00 00 00 00 " "\n" "0x0020: 00 00 00 00 00 00 11 11 04 d2 1f 90 01 02 03 04 " "\n" - "0x0030: 6e fc 47 17 00 0f 00 13 01 02 03 04 00 ff 01 00 " "\n" - "0x0040: 00 00 00 00 00 01 02 00 01 00 00 60 00 00 00 01 " "\n" + "0x0030: 24 25 51 31 00 0f 00 13 01 02 03 04 00 ff 01 00 " "\n" + "0x0040: 00 00 00 00 00 01 02 00 01 00 00 68 00 00 00 01 " "\n" "0x0050: 00 01 00 00 00 0f 00 0f 01 02 03 04 00 05 00 08 " "\n" "0x0060: 01 02 03 04 00 06 00 14 00 00 00 00 00 00 00 00 " "\n" "0x0070: 00 00 00 00 00 00 00 01 00 09 00 08 00 01 00 00 " "\n" "0x0080: 00 0b 00 06 40 41 00 00 00 0c 00 0a 00 05 00 06 " "\n" - "0x0090: 00 0b 00 00 80 00 00 04 80 05 00 10 50 50 50 50 " "\n" - "0x00a0: 50 50 50 50 50 50 50 50 02 00 00 24 00 00 00 01 " "\n" - "0x00b0: 00 01 00 00 00 0f 00 0f 01 02 03 04 00 07 00 07 " "\n" - "0x00c0: 01 02 03 00 00 08 00 08 80 01 00 04 03 00 00 20 " "\n" - "0x00d0: 01 02 03 04 00 01 00 00 00 03 00 01 00 01 00 03 " "\n" - "0x00e0: 00 05 00 0f 10 00 10 14 01 02 03 04 04 00 00 0a " "\n" - "0x00f0: 00 01 00 06 01 02 00 00 05 00 00 0a 00 01 00 06 " "\n" - "0x0100: 01 02 00 00 06 01 00 04 06 00 00 80 00 01 00 08 " "\n" - "0x0110: 00 ff 00 00 00 02 00 0a 00 00 00 01 00 07 00 00 " "\n" - "0x0120: 00 03 00 08 00 01 00 00 00 04 00 04 00 05 00 0c " "\n" - "0x0130: 00 0b 00 06 40 41 00 00 00 06 00 0c fe 05 00 05 " "\n" - "0x0140: 01 00 00 00 00 07 00 04 00 08 00 10 80 0a 00 04 " "\n" - "0x0150: 80 0b 00 05 01 00 00 00 00 09 00 08 01 02 03 04 " "\n" - "0x0160: 00 0a 00 04 00 0b 00 14 00 05 00 08 01 02 03 04 " "\n" - "0x0170: 00 05 00 08 02 03 04 05 00 0c 00 07 42 59 45 00 " "\n" - "0x0180: 00 0d 00 06 40 40 00 00 07 00 00 08 01 02 03 04 " "\n" - "0x0190: 08 00 00 04 09 00 00 04 0a 00 00 05 45 00 00 00 " "\n" - "0x01a0: 0b 00 00 04 0c 00 00 08 01 02 03 04 0d 00 00 08 " "\n" - "0x01b0: 01 02 03 04 0e 01 00 04 84 00 00 10 50 50 50 50 " "\n" - "0x01c0: 50 50 50 50 50 50 50 50 " "\n"; + "0x0090: 00 0b 00 00 80 00 00 04 80 08 00 05 40 00 00 00 " "\n" + "0x00a0: 80 05 00 10 50 50 50 50 50 50 50 50 50 50 50 50 " "\n" + "0x00b0: 02 00 00 24 00 00 00 01 00 01 00 00 00 0f 00 0f " "\n" + "0x00c0: 01 02 03 04 00 07 00 07 01 02 03 00 00 08 00 08 " "\n" + "0x00d0: 80 01 00 04 03 00 00 20 01 02 03 04 00 01 00 00 " "\n" + "0x00e0: 00 03 00 01 00 01 00 03 00 05 00 0f 10 00 10 14 " "\n" + "0x00f0: 01 02 03 04 04 00 00 0a 00 01 00 06 01 02 00 00 " "\n" + "0x0100: 05 00 00 0a 00 01 00 06 01 02 00 00 06 01 00 04 " "\n" + "0x0110: 06 00 00 80 00 01 00 08 00 ff 00 00 00 02 00 0a " "\n" + "0x0120: 00 00 00 01 00 07 00 00 00 03 00 08 00 01 00 00 " "\n" + "0x0130: 00 04 00 04 00 05 00 0c 00 0b 00 06 40 41 00 00 " "\n" + "0x0140: 00 06 00 0c fe 05 00 05 01 00 00 00 00 07 00 04 " "\n" + "0x0150: 00 08 00 10 80 0a 00 04 80 0b 00 05 01 00 00 00 " "\n" + "0x0160: 00 09 00 08 01 02 03 04 00 0a 00 04 00 0b 00 14 " "\n" + "0x0170: 00 05 00 08 01 02 03 04 00 05 00 08 02 03 04 05 " "\n" + "0x0180: 00 0c 00 07 42 59 45 00 00 0d 00 06 40 40 00 00 " "\n" + "0x0190: 07 00 00 08 01 02 03 04 08 00 00 04 09 00 00 04 " "\n" + "0x01a0: 0a 00 00 05 45 00 00 00 0b 00 00 04 0c 00 00 08 " "\n" + "0x01b0: 01 02 03 04 0d 00 00 08 01 02 03 04 0e 01 00 04 " "\n" + "0x01c0: 40 0f 00 17 00 00 00 04 00 ff 00 00 00 00 00 01 " "\n" + "0x01d0: 00 00 00 00 00 01 02 00 40 0d 00 17 00 00 00 04 " "\n" + "0x01e0: 00 ff 00 00 00 00 00 02 00 00 00 01 00 01 02 00 " "\n" + "0x01f0: 84 00 00 10 50 50 50 50 50 50 50 50 50 50 50 50 " "\n"; printf("expected = '%s'\n", expected); assert(strcmp(dump, expected) == 0); free(dump); diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index 736897851f194bf16791c42db5f9efa678fd7c77..298dca63c6f9728a5bd2aa6edf5223ccd907760b 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -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_MAX_INIT_TIMEO %token <reserved> ASSOC_VALUE +%token <reserved> STREAM_ID STREAM_VALUE %token <reserved> SACK_DELAY SACK_FREQ %token <reserved> SSTAT_STATE SSTAT_RWND SSTAT_UNACKDATA SSTAT_PENDDATA %token <reserved> SSTAT_INSTRMS SSTAT_OUTSTRMS SSTAT_FRAGMENTATION_POINT @@ -513,12 +514,13 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %token <reserved> SPINFO_STATE SPINFO_CWND SPINFO_SRTT SPINFO_RTO 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 PAD +%token <reserved> SHUTDOWN_COMPLETE I_DATA PAD %token <reserved> TYPE FLAGS LEN -%token <reserved> TAG A_RWND OS IS TSN SID SSN PPID CUM_TSN GAPS DUPS +%token <reserved> TAG A_RWND OS IS TSN SID SSN MID PPID FSN CUM_TSN GAPS DUPS %token <reserved> PARAMETER HEARTBEAT_INFORMATION IPV4_ADDRESS IPV6_ADDRESS %token <reserved> STATE_COOKIE UNRECOGNIZED_PARAMETER COOKIE_PRESERVATIVE %token <reserved> HOSTNAME_ADDRESS SUPPORTED_ADDRESS_TYPES ECN_CAPABLE +%token <reserved> SUPPORTED_EXTENSIONS %token <reserved> ADDR INCR TYPES PARAMS %token <reserved> IPV4_TYPE IPV6_TYPE HOSTNAME_TYPE %token <reserved> CAUSE @@ -571,7 +573,7 @@ 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_assocval sctp_sackinfo +%type <expression> sctp_initmsg 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 @@ -591,6 +593,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <chunk_list_item> sctp_cookie_echo_chunk_spec sctp_cookie_ack_chunk_spec %type <chunk_list_item> sctp_ecne_chunk_spec sctp_cwr_chunk_spec %type <chunk_list_item> sctp_shutdown_complete_chunk_spec +%type <chunk_list_item> sctp_i_data_chunk_spec %type <chunk_list_item> sctp_pad_chunk_spec %type <parameter_list> opt_parameter_list_spec sctp_parameter_list_spec %type <parameter_list_item> sctp_parameter_spec @@ -604,6 +607,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <parameter_list_item> sctp_hostname_address_parameter_spec %type <parameter_list_item> sctp_supported_address_types_parameter_spec %type <parameter_list_item> sctp_ecn_capable_parameter_spec +%type <parameter_list_item> sctp_supported_extensions_parameter_spec %type <parameter_list_item> sctp_pad_parameter_spec %type <cause_list> opt_cause_list_spec sctp_cause_list_spec %type <cause_list_item> sctp_cause_spec @@ -621,12 +625,13 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <cause_list_item> sctp_restart_with_new_addresses_cause_spec %type <cause_list_item> sctp_user_initiated_abort_cause_spec %type <cause_list_item> sctp_protocol_violation_cause_spec -%type <integer> opt_chunk_type opt_parameter_type opt_cause_code +%type <integer> chunk_type opt_chunk_type opt_parameter_type opt_cause_code %type <integer> opt_flags opt_data_flags opt_abort_flags -%type <integer> opt_shutdown_complete_flags opt_len +%type <integer> opt_shutdown_complete_flags opt_i_data_flags opt_len %type <integer> opt_tag opt_a_rwnd opt_os opt_is opt_tsn opt_sid opt_ssn +%type <integer> opt_mid opt_fsn %type <integer> opt_cum_tsn opt_ppid -%type <byte_list> opt_val opt_info byte_list +%type <byte_list> opt_val opt_info byte_list chunk_types_list %type <byte_list_item> byte %type <sack_block_list> opt_gaps gap_list opt_dups dup_list %type <sack_block_list_item> gap dup @@ -841,21 +846,79 @@ sctp_chunk_spec | sctp_ecne_chunk_spec { $$ = $1; } | sctp_cwr_chunk_spec { $$ = $1; } | sctp_shutdown_complete_chunk_spec { $$ = $1; } +| sctp_i_data_chunk_spec { $$ = $1; } | sctp_pad_chunk_spec { $$ = $1; } ; -opt_chunk_type -: TYPE '=' ELLIPSIS { $$ = -1; } -| TYPE '=' HEX_INTEGER { - if (!is_valid_u8($3)) { +chunk_type +: HEX_INTEGER { + if (!is_valid_u8($1)) { semantic_error("type value out of range"); - } - $$ = $3; + } + $$ = $1; } -| TYPE '=' INTEGER { - if (!is_valid_u8($3)) { +| INTEGER { + if (!is_valid_u8($1)) { semantic_error("type value out of range"); - } + } + $$ = $1; +} +| DATA { + $$ = SCTP_DATA_CHUNK_TYPE; +} +| INIT { + $$ = SCTP_INIT_CHUNK_TYPE; +} +| INIT_ACK { + $$ = SCTP_INIT_ACK_CHUNK_TYPE; +} +| SACK { + $$ = SCTP_SACK_CHUNK_TYPE; +} +| HEARTBEAT { + $$ = SCTP_HEARTBEAT_CHUNK_TYPE; +} +| HEARTBEAT_ACK { + $$ = SCTP_HEARTBEAT_ACK_CHUNK_TYPE; +} +| ABORT { + $$ = SCTP_ABORT_CHUNK_TYPE; +} +| SHUTDOWN { + $$ = SCTP_SHUTDOWN_CHUNK_TYPE; +} +| SHUTDOWN_ACK { + $$ = SCTP_SHUTDOWN_ACK_CHUNK_TYPE; +} +| ERROR { + $$ = SCTP_ERROR_CHUNK_TYPE; +} +| COOKIE_ECHO { + $$ = SCTP_COOKIE_ECHO_CHUNK_TYPE; +} +| COOKIE_ACK { + $$ = SCTP_COOKIE_ACK_CHUNK_TYPE; +} +| ECNE { + $$ = SCTP_ECNE_CHUNK_TYPE; +} +| CWR { + $$ = SCTP_CWR_CHUNK_TYPE; +} +| SHUTDOWN_COMPLETE{ + $$ = SCTP_SHUTDOWN_COMPLETE_CHUNK_TYPE; +} +| I_DATA { + $$ = SCTP_I_DATA_CHUNK_TYPE; +} +| PAD { + $$ = SCTP_PAD_CHUNK_TYPE; +} +; + +opt_chunk_type +: TYPE '=' ELLIPSIS { $$ = -1; } +| TYPE '=' chunk_type { $$ = $3; } ; @@ -865,13 +928,13 @@ opt_flags | FLAGS '=' HEX_INTEGER { if (!is_valid_u8($3)) { semantic_error("flags value out of range"); - } + } $$ = $3; } | FLAGS '=' INTEGER { if (!is_valid_u8($3)) { semantic_error("flags value out of range"); - } + } $$ = $3; } ; @@ -932,7 +995,7 @@ opt_data_flags | FLAGS '=' INTEGER { if (!is_valid_u8($3)) { semantic_error("flags value out of range"); - } + } $$ = $3; } | FLAGS '=' WORD { @@ -990,7 +1053,7 @@ opt_abort_flags | FLAGS '=' INTEGER { if (!is_valid_u8($3)) { semantic_error("flags value out of range"); - } + } $$ = $3; } | FLAGS '=' WORD { @@ -1053,6 +1116,64 @@ opt_shutdown_complete_flags } ; +opt_i_data_flags +: FLAGS '=' ELLIPSIS { $$ = -1; } +| FLAGS '=' HEX_INTEGER { + if (!is_valid_u8($3)) { + semantic_error("flags value out of range"); + } + $$ = $3; +} +| FLAGS '=' INTEGER { + if (!is_valid_u8($3)) { + semantic_error("flags value out of range"); + } + $$ = $3; +} +| FLAGS '=' WORD { + u64 flags; + char *c; + + flags = 0; + for (c = $3; *c != '\0'; c++) { + switch (*c) { + case 'I': + if (flags & SCTP_I_DATA_CHUNK_I_BIT) { + semantic_error("I-bit specified multiple times"); + } else { + flags |= SCTP_I_DATA_CHUNK_I_BIT; + } + break; + case 'U': + if (flags & SCTP_I_DATA_CHUNK_U_BIT) { + semantic_error("U-bit specified multiple times"); + } else { + flags |= SCTP_I_DATA_CHUNK_U_BIT; + } + break; + case 'B': + if (flags & SCTP_I_DATA_CHUNK_B_BIT) { + semantic_error("B-bit specified multiple times"); + } else { + flags |= SCTP_I_DATA_CHUNK_B_BIT; + } + break; + case 'E': + if (flags & SCTP_I_DATA_CHUNK_E_BIT) { + semantic_error("E-bit specified multiple times"); + } else { + flags |= SCTP_I_DATA_CHUNK_E_BIT; + } + break; + default: + semantic_error("Only expecting IUBE as flags"); + break; + } + } + $$ = flags; +} +; + opt_tag : TAG '=' ELLIPSIS { $$ = -1; } | TAG '=' INTEGER { @@ -1123,6 +1244,16 @@ opt_ssn } ; +opt_mid +: MID '=' ELLIPSIS { $$ = -1; } +| MID '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("mid value out of range"); + } + $$ = $3; +} +; + opt_ppid : PPID '=' ELLIPSIS { $$ = -1; } | PPID '=' INTEGER { @@ -1133,6 +1264,16 @@ opt_ppid } ; +opt_fsn +: FSN '=' ELLIPSIS { $$ = -1; } +| FSN '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("fsn value out of range"); + } + $$ = $3; +} +; + opt_cum_tsn : CUM_TSN '=' ELLIPSIS { $$ = -1; } | CUM_TSN '=' INTEGER { @@ -1268,7 +1409,7 @@ sctp_cookie_echo_chunk_spec (!is_valid_u16($5) || ($5 < sizeof(struct sctp_cookie_echo_chunk)))) { semantic_error("length value out of range"); } - if (($5 != -1) && ($7 != NULL) && + if (($5 != -1) && ($7 != NULL) && ($5 != sizeof(struct sctp_cookie_echo_chunk) + $7->nr_entries)) { semantic_error("length value incompatible with val"); } @@ -1298,6 +1439,22 @@ sctp_shutdown_complete_chunk_spec $$ = sctp_shutdown_complete_chunk_new($3); } +sctp_i_data_chunk_spec +: I_DATA '[' opt_i_data_flags ',' opt_len ',' opt_tsn ',' opt_sid ',' opt_mid ',' opt_ppid ']' { + if (($5 != -1) && + (!is_valid_u16($5) || ($5 < sizeof(struct sctp_i_data_chunk)))) { + semantic_error("length value out of range"); + } + $$ = sctp_i_data_chunk_new($3, $5, $7, $9, 0, $11, $13, -1); +} +| I_DATA '[' opt_i_data_flags ',' opt_len ',' opt_tsn ',' opt_sid ',' opt_mid ',' opt_fsn ']' { + if (($5 != -1) && + (!is_valid_u16($5) || ($5 < sizeof(struct sctp_i_data_chunk)))) { + semantic_error("length value out of range"); + } + $$ = sctp_i_data_chunk_new($3, $5, $7, $9, 0, $11, -1, $13); +} + sctp_pad_chunk_spec : PAD '[' opt_flags ',' opt_len ',' VAL '=' ELLIPSIS ']' { if (($5 != -1) && @@ -1331,6 +1488,7 @@ sctp_parameter_spec | sctp_hostname_address_parameter_spec { $$ = $1; } | sctp_supported_address_types_parameter_spec { $$ = $1; } | sctp_ecn_capable_parameter_spec { $$ = $1; } +| sctp_supported_extensions_parameter_spec { $$ = $1; } | sctp_pad_parameter_spec { $$ = $1; } ; @@ -1485,6 +1643,28 @@ sctp_ecn_capable_parameter_spec $$ = sctp_ecn_capable_parameter_new(); } +chunk_types_list +: { + $$ = sctp_byte_list_new(); +} +| chunk_type { + $$ = sctp_byte_list_new(); + sctp_byte_list_append($$, sctp_byte_list_item_new($1)); +} +| chunk_types_list ',' chunk_type { + $$ = $1; + sctp_byte_list_append($1, sctp_byte_list_item_new($3)); +} +; + +sctp_supported_extensions_parameter_spec +: SUPPORTED_EXTENSIONS '[' TYPES '=' ELLIPSIS ']' { + $$ = sctp_supported_extensions_parameter_new(NULL); +} +| SUPPORTED_EXTENSIONS '[' TYPES '=' '[' chunk_types_list ']' ']' { + $$ = sctp_supported_extensions_parameter_new($6); +} + sctp_pad_parameter_spec : PAD '[' ELLIPSIS ']' { $$ = sctp_pad_parameter_new(-1, NULL); @@ -2162,7 +2342,10 @@ expression | sctp_initmsg { $$ = $1; } -| sctp_assocval { +| sctp_assoc_value { + $$ = $1; +} +| sctp_stream_value { $$ = $1; } | sctp_sackinfo { @@ -2394,14 +2577,25 @@ sctp_initmsg } ; -sctp_assocval -: '{' ASSOC_VALUE '=' INTEGER '}' { -#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) - $$ = new_expression(EXPR_SCTP_ASSOCVAL); - if (!is_valid_u32($4)) { - semantic_error("assoc_value out of range"); - } - $$->value.sctp_assoc_value.assoc_value = $4; +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 +: '{' ASSOC_VALUE '=' expression '}' { +#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED) + $$ = new_expression(EXPR_SCTP_ASSOC_VALUE); + $$->value.sctp_assoc_value = calloc(1, sizeof(struct sctp_assoc_value_expr)); + $$->value.sctp_assoc_value->assoc_value = $4; #else $$ = NULL; #endif diff --git a/gtests/net/packetdrill/run_packet.c b/gtests/net/packetdrill/run_packet.c index 2aa404f1ba57176b3606b61877713f125fcd1b43..ffa0d8278ebadbd5050ee852305ef454b9a01a5c 100644 --- a/gtests/net/packetdrill/run_packet.c +++ b/gtests/net/packetdrill/run_packet.c @@ -581,6 +581,7 @@ static int map_inbound_sctp_packet( struct sctp_shutdown_chunk *shutdown; struct sctp_ecne_chunk *ecne; struct sctp_cwr_chunk *cwr; + struct sctp_i_data_chunk *i_data; u32 local_diff, remote_diff; u16 nr_gap_blocks, nr_dup_tsns, i; @@ -642,6 +643,10 @@ static int map_inbound_sctp_packet( cwr = (struct sctp_cwr_chunk *)chunk; cwr->lowest_tsn = htonl(ntohl(cwr->lowest_tsn) + local_diff); break; + case SCTP_I_DATA_CHUNK_TYPE: + i_data = (struct sctp_i_data_chunk *)chunk; + i_data->tsn = htonl(ntohl(i_data->tsn) + remote_diff); + break; default: break; } @@ -734,6 +739,7 @@ static int map_outbound_live_sctp_packet( struct sctp_shutdown_chunk *shutdown; struct sctp_ecne_chunk *ecne; struct sctp_cwr_chunk *cwr; + struct sctp_i_data_chunk *i_data; u32 local_diff, remote_diff; u16 nr_gap_blocks, nr_dup_tsns, i; @@ -790,6 +796,10 @@ static int map_outbound_live_sctp_packet( cwr = (struct sctp_cwr_chunk *)chunk; cwr->lowest_tsn = htonl(ntohl(cwr->lowest_tsn) + remote_diff); break; + case SCTP_I_DATA_CHUNK_TYPE: + i_data = (struct sctp_i_data_chunk *)chunk; + i_data->tsn = htonl(ntohl(i_data->tsn) + local_diff); + break; default: break; } @@ -1522,6 +1532,44 @@ static int verify_shutdown_complete_chunk(struct sctp_shutdown_complete_chunk *a return STATUS_OK; } +static int verify_i_data_chunk(struct sctp_i_data_chunk *actual_chunk, + struct sctp_i_data_chunk *script_chunk, + u32 flags, char **error) +{ + if (check_field("sctp_i_data_chunk_tsn", + ntohl(script_chunk->tsn), + ntohl(actual_chunk->tsn), + error) || + (flags & FLAG_I_DATA_CHUNK_SID_NOCHECK ? STATUS_OK : + check_field("sctp_i_data_chunk_sid", + ntohs(script_chunk->sid), + ntohs(actual_chunk->sid), + error)) || + (flags & FLAG_I_DATA_CHUNK_RES_NOCHECK ? STATUS_OK : + check_field("sctp_i_data_chunk_res", + ntohs(script_chunk->res), + ntohs(actual_chunk->res), + error)) || + (flags & FLAG_I_DATA_CHUNK_MID_NOCHECK? STATUS_OK : + check_field("sctp_i_data_chunk_mid", + ntohl(script_chunk->mid), + ntohl(actual_chunk->mid), + error)) || + (flags & FLAG_I_DATA_CHUNK_PPID_NOCHECK? STATUS_OK : + check_field("sctp_i_data_chunk_ppid", + ntohl(script_chunk->field.ppid), + ntohl(actual_chunk->field.ppid), + error)) || + (flags & FLAG_I_DATA_CHUNK_FSN_NOCHECK? STATUS_OK : + check_field("sctp_i_data_chunk_fsn", + ntohl(script_chunk->field.fsn), + ntohl(actual_chunk->field.fsn), + error))) { + return STATUS_ERR; + } + return STATUS_OK; +} + static int verify_pad_chunk(struct sctp_pad_chunk *actual_chunk, struct sctp_pad_chunk *script_chunk, u32 flags, char **error) @@ -1660,6 +1708,11 @@ static int verify_sctp( (struct sctp_shutdown_complete_chunk *)script_chunk, flags, error); break; + case SCTP_I_DATA_CHUNK_TYPE: + result = verify_i_data_chunk((struct sctp_i_data_chunk *)actual_chunk, + (struct sctp_i_data_chunk *)script_chunk, + flags, error); + break; case SCTP_PAD_CHUNK_TYPE: result = verify_pad_chunk((struct sctp_pad_chunk *)actual_chunk, (struct sctp_pad_chunk *)script_chunk, diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c index 72ea542661e460baec74c4c5a3819c1fc3b49852..065617b4748edcee0bc0b218e9dff4818078e940 100644 --- a/gtests/net/packetdrill/run_system_call.c +++ b/gtests/net/packetdrill/run_system_call.c @@ -180,6 +180,46 @@ 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 + * valid u32, and matches the expected type. Returns STATUS_OK on + * success; on failure returns STATUS_ERR and sets error message. + */ +static int get_u32(struct expression *expression, + u32 *value, char **error) +{ + if (check_type(expression, EXPR_INTEGER, error)) + return STATUS_ERR; + if ((expression->value.num > UINT32_MAX) || + (expression->value.num < 0)) { + asprintf(error, + "Value out of range for 32-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 * valid s32 or u32, and matches the expected type. Returns STATUS_OK on * success; on failure returns STATUS_ERR and sets error message. @@ -1618,6 +1658,7 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, void *live_optval; socklen_t live_optlen; struct expression *val_expression; + if (check_arg_count(args, 5, error)) return STATUS_ERR; if (s32_arg(args, 0, &script_fd, error)) @@ -1673,6 +1714,24 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, } live_params->spp_assoc_id = 0; live_optval = live_params; +#endif +#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED) + } else if (val_expression->type == EXPR_SCTP_ASSOC_VALUE) { + live_optval = malloc(sizeof(struct sctp_assoc_value)); + live_optlen = (socklen_t)sizeof(struct sctp_assoc_value); + ((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 } else { s32_bracketed_arg(args, 3, &script_optval, error); @@ -1698,6 +1757,7 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, struct expression *l_linger = val_expression->value.linger->l_linger; struct linger *ling = live_optval; int val_onoff = 0; + if (l_onoff->type != EXPR_ELLIPSIS) { if (get_s32(l_onoff, &val_onoff, error)) { free(live_optval); @@ -1830,7 +1890,7 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, if (sstat_instrms->type != EXPR_ELLIPSIS) { if (get_s16(sstat_instrms, &instrms, error)) { free(live_optval); - return STATUS_ERR; + return STATUS_ERR; } if (live_status->sstat_instrms != instrms) { asprintf(error, "Bad getsockopt SCTP_STATUS instreams: expected: %hu actual: %hu", @@ -1888,7 +1948,7 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, asprintf(error, "Bad getsockopt SCTP_STATUS Primary cwnd: expected: %u actual: %u", cwnd, live_paddrinfo.spinfo_cwnd); free(live_optval); - return STATUS_ERR; + return STATUS_ERR; } } if (paddrinfo_expr->spinfo_srtt->type != EXPR_ELLIPSIS) { @@ -1924,7 +1984,7 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, asprintf(error, "Bad getsockopt SCTP_STATUS Primary mtu: expected: %u actual: %u", mtu, live_paddrinfo.spinfo_mtu); free(live_optval); - return STATUS_ERR; + return STATUS_ERR; } } } @@ -2017,6 +2077,57 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, } } #endif +#endif +#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED) + } else if (val_expression->type == EXPR_SCTP_ASSOC_VALUE) { + struct expression *assoc_value = val_expression->value.sctp_assoc_value->assoc_value; + struct sctp_assoc_value *sctp_assoc_value = live_optval; + u32 value; + + if (assoc_value->type != EXPR_ELLIPSIS) { + if (get_u32(assoc_value, &value, error)) { + free(live_optval); + return STATUS_ERR; + } + if (sctp_assoc_value->assoc_value != value) { + asprintf(error, "Bad getsockopt sctp_assoc_value.assoc_value: expected: %u actual: %u", + value, sctp_assoc_value->assoc_value); + free(live_optval); + 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 } else { if (*(int*)live_optval != script_optval) { @@ -2036,6 +2147,12 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, int script_fd, live_fd, level, optname, optval_s32, optlen, result; void *optval = NULL; struct expression *val_expression; +#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED) + 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)) return STATUS_ERR; @@ -2069,20 +2186,20 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, } else if (val_expression->type == EXPR_SCTP_RTOINFO) { struct sctp_rtoinfo *rtoinfo; struct sctp_rtoinfo_expr *expr_rtoinfo = val_expression->value.sctp_rtoinfo; - socklen_t live_optlen = sizeof(struct sctp_paddrparams); + 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)); memset(rtoinfo, 0, sizeof(struct sctp_rtoinfo)); rtoinfo->srto_assoc_id = 0; - if (getsockopt(live_fd, level, optname, rtoinfo, &live_optlen) == -1) { - asprintf(error, "Bad setsockopt, bad get actuall values"); - free(rtoinfo); - return STATUS_ERR; - } if (expr_rtoinfo->srto_initial->type != EXPR_ELLIPSIS) { - rtoinfo->srto_initial = expr_rtoinfo->srto_initial->value.num; + rtoinfo->srto_initial = expr_rtoinfo->srto_initial->value.num; } if (expr_rtoinfo->srto_max->type != EXPR_ELLIPSIS) { - rtoinfo->srto_max = expr_rtoinfo->srto_max->value.num; + rtoinfo->srto_max = expr_rtoinfo->srto_max->value.num; } if (expr_rtoinfo->srto_min->type != EXPR_ELLIPSIS) { rtoinfo->srto_min = expr_rtoinfo->srto_min->value.num; @@ -2093,9 +2210,27 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, } else if (val_expression->type == EXPR_SCTP_INITMSG) { optval = &val_expression->value.sctp_initmsg; #endif -#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) - } else if (val_expression->type == EXPR_SCTP_ASSOCVAL) { - optval = &val_expression->value.sctp_assoc_value; +#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED) + } else if (val_expression->type == EXPR_SCTP_ASSOC_VALUE) { + assoc_value.assoc_id = 0; + if (get_u32(val_expression->value.sctp_assoc_value->assoc_value, + &assoc_value.assoc_value, error)) { + return STATUS_ERR; + } + optval = &assoc_value; +#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 } else if (val_expression->type == EXPR_SCTP_SACKINFO) { @@ -2169,7 +2304,7 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, } #ifdef SPP_IPV6_FLOWLABEL if (expr_params->spp_ipv6_flowlabel->type != EXPR_ELLIPSIS) { - int flowlabel; + int flowlabel; if (get_s32(expr_params->spp_ipv6_flowlabel, &flowlabel, error)) { free(params); return STATUS_ERR; diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c index 2490e907d6dbcb42a5d7e02eefb8ce6d277c6024..7aca4a8fe44908823e54cc3e859c2ae0133ab003 100644 --- a/gtests/net/packetdrill/script.c +++ b/gtests/net/packetdrill/script.c @@ -71,8 +71,8 @@ struct expression_type_entry expression_type_table[] = { #ifdef SCTP_INITMSG { EXPR_SCTP_INITMSG, "sctp_initmsg"}, #endif -#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) - { EXPR_SCTP_ASSOCVAL, "sctp_assocvalue"}, +#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED) + { EXPR_SCTP_ASSOC_VALUE, "sctp_assoc_value"}, #endif #ifdef SCTP_DELAYED_SACK { EXPR_SCTP_SACKINFO, "sctp_sackinfo"}, @@ -83,6 +83,9 @@ struct expression_type_entry expression_type_table[] = { #endif #ifdef SCTP_PEER_ADDR_PARAMS { EXPR_SCTP_PEER_ADDR_PARAMS, "sctp_peer_addr_params"}, +#endif +#ifdef SCTP_SS_VALUE + { EXPR_SCTP_STREAM_VALUE, "sctp_stream_value"}, #endif { NUM_EXPR_TYPES, NULL} }; @@ -291,28 +294,34 @@ void free_expression(struct expression *expression) case EXPR_INTEGER: break; case EXPR_LINGER: + assert(expression->value.linger); free(expression->value.linger->l_onoff); free(expression->value.linger->l_linger); break; #ifdef SCTP_RTOINFO case EXPR_SCTP_RTOINFO: + assert(expression->value.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 +#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED) + case EXPR_SCTP_ASSOC_VALUE: + assert(expression->value.sctp_assoc_value); + free(expression->value.sctp_assoc_value->assoc_value); + break; +#endif #ifdef SCTP_INITMSG case EXPR_SCTP_INITMSG: #endif -#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) - case EXPR_SCTP_ASSOCVAL: -#endif #ifdef SCTP_DELAYED_SACK case EXPR_SCTP_SACKINFO: #endif break; #ifdef SCTP_STATUS case EXPR_SCTP_PADDRINFO: + free(expression->value.sctp_paddrinfo); free(expression->value.sctp_paddrinfo->spinfo_state); free(expression->value.sctp_paddrinfo->spinfo_cwnd); free(expression->value.sctp_paddrinfo->spinfo_srtt); @@ -320,6 +329,7 @@ void free_expression(struct expression *expression) free(expression->value.sctp_paddrinfo->spinfo_mtu); break; case EXPR_SCTP_STATUS: + assert(expression->value.sctp_status); free(expression->value.sctp_status->sstat_state); free(expression->value.sctp_status->sstat_rwnd); free(expression->value.sctp_status->sstat_unackdata); @@ -332,6 +342,7 @@ void free_expression(struct expression *expression) #endif #ifdef SCTP_PEER_ADDR_PARAMS case EXPR_SCTP_PEER_ADDR_PARAMS: + assert(expression->value.sctp_paddrparams); free(expression->value.sctp_paddrparams->spp_address); free(expression->value.sctp_paddrparams->spp_hbinterval); free(expression->value.sctp_paddrparams->spp_pathmaxrxt); @@ -340,6 +351,13 @@ void free_expression(struct expression *expression) free(expression->value.sctp_paddrparams->spp_ipv6_flowlabel); free(expression->value.sctp_paddrparams->spp_dscp); break; +#endif +#ifdef SCTP_SS_VALUE + case EXPR_SCTP_STREAM_VALUE: + assert(expression->value.sctp_stream_value); + free(expression->value.sctp_stream_value->stream_id); + free(expression->value.sctp_stream_value->stream_value); + break; #endif case EXPR_WORD: assert(expression->value.string); @@ -516,7 +534,7 @@ static int evaluate_sctp_status_expression(struct expression *in, in_status = in->value.sctp_status; out_status = out->value.sctp_status; - + if (evaluate(in_status->sstat_state, &out_status->sstat_state, error)) @@ -577,6 +595,56 @@ static int evaluate_pollfd_expression(struct expression *in, return STATUS_OK; } +#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, + char **error) +{ + struct sctp_assoc_value_expr *in_value; + struct sctp_assoc_value_expr *out_value; + + assert(in->type == EXPR_SCTP_ASSOC_VALUE); + assert(in->value.sctp_assoc_value); + assert(out->type == EXPR_SCTP_ASSOC_VALUE); + + out->value.sctp_assoc_value = calloc(1, sizeof(struct sctp_assoc_value_expr)); + + in_value = in->value.sctp_assoc_value; + out_value = out->value.sctp_assoc_value; + + if (evaluate(in_value->assoc_value, &out_value->assoc_value, error)) + return STATUS_ERR; + + return STATUS_OK; +} +#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, struct expression **out_ptr, char **error) { @@ -612,11 +680,9 @@ static int evaluate(struct expression *in, sizeof(in->value.sctp_initmsg)); break; #endif -#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) - case EXPR_SCTP_ASSOCVAL: /* copy as-is */ - memcpy(&out->value.sctp_assoc_value, - &in->value.sctp_assoc_value, - sizeof(in->value.sctp_assoc_value)); +#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED) + case EXPR_SCTP_ASSOC_VALUE: /* copy as-is */ + evaluate_sctp_assoc_value_expression(in, out, error); break; #endif #ifdef SCTP_DELAYED_SACK @@ -640,12 +706,17 @@ static int evaluate(struct expression *in, #endif #ifdef SCTP_PEER_ADDR_PARAMS case EXPR_SCTP_PEER_ADDR_PARAMS: - memcpy(&out->value.sctp_paddrparams, &in->value.sctp_paddrparams, + memcpy(&out->value.sctp_paddrparams, &in->value.sctp_paddrparams, sizeof(in->value.sctp_paddrparams)); if (evaluate(in->value.sctp_paddrparams->spp_flags, &out->value.sctp_paddrparams->spp_flags, error)) - return STATUS_ERR; + return STATUS_ERR; + break; +#endif +#ifdef SCTP_SS_VALUE + case EXPR_SCTP_STREAM_VALUE: + evaluate_sctp_stream_value_expression(in, out, error); break; #endif case EXPR_WORD: diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h index e604d910f73f4d921cb1d693435c06cca6b1677b..cbdfad274d803ccb73ab942f0a75fe01a4b08f52 100644 --- a/gtests/net/packetdrill/script.h +++ b/gtests/net/packetdrill/script.h @@ -51,8 +51,8 @@ enum expression_t { #ifdef SCTP_INITMSG EXPR_SCTP_INITMSG, /* struct sctp_initmsg for SCTP_INITMSG */ #endif -#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) - EXPR_SCTP_ASSOCVAL, /* struct sctp_assoc_value */ +#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED) + EXPR_SCTP_ASSOC_VALUE, /* struct sctp_assoc_value */ #endif #ifdef SCTP_DELAYED_SACK EXPR_SCTP_SACKINFO, /* struct sctp_sack_info for @@ -61,6 +61,9 @@ enum expression_t { #ifdef SCTP_STATUS EXPR_SCTP_STATUS, /* struct sctp_status for SCTP_STATUS */ EXPR_SCTP_PADDRINFO, +#endif +#ifdef SCTP_SS_VALUE + EXPR_SCTP_STREAM_VALUE, /* struct sctp_stream_value for SCTP_SS_VALUE */ #endif EXPR_SCTP_PEER_ADDR_PARAMS, /* struct for sctp_paddrparams for SCTP_PEER_ADDR_PARAMS*/ NUM_EXPR_TYPES, @@ -88,8 +91,8 @@ struct expression { #ifdef SCTP_INITMSG struct sctp_initmsg sctp_initmsg; #endif -#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) - struct sctp_assoc_value sctp_assoc_value; +#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED) + struct sctp_assoc_value_expr *sctp_assoc_value; #endif #ifdef SCTP_DELAYED_SACK struct sctp_sack_info sctp_sack_info; @@ -99,7 +102,10 @@ struct expression { struct sctp_paddrinfo_expr *sctp_paddrinfo; #endif #ifdef SCTP_PEER_ADDR_PARAMS - struct sctp_paddrparams_expr *sctp_paddrparams; + struct sctp_paddrparams_expr *sctp_paddrparams; +#endif +#ifdef SCTP_SS_VALUE + struct sctp_stream_value_expr *sctp_stream_value; #endif } value; const char *format; /* the printf format for printing the value */ @@ -147,7 +153,7 @@ struct linger_expr { struct expression *l_onoff; struct expression *l_linger; }; -/* Parse tree for syscall get/setsockopt for sctp_rtoinfo*/ +/* Parse tree for a sctp_rtoinfo struct in a [gs]etsockopt syscall. */ #ifdef SCTP_RTOINFO struct sctp_rtoinfo_expr { struct expression *srto_initial; @@ -156,7 +162,22 @@ struct sctp_rtoinfo_expr { }; #endif -/* Parse tree for syscall getsockopt for sctp_status*/ +#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 { + struct expression *assoc_value; +}; +#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 + +/* Parse tree for a sctp_status struct in a [gs]etsockopt syscall. */ #ifdef SCTP_STATUS struct sctp_status_expr { struct expression *sstat_state; @@ -169,6 +190,7 @@ struct sctp_status_expr { struct expression *sstat_primary; }; +/* Parse tree for a sctp_paddrinfo struct in a [gs]etsockopt syscall. */ struct sctp_paddrinfo_expr { struct expression *spinfo_state; struct expression *spinfo_cwnd; @@ -178,7 +200,7 @@ struct sctp_paddrinfo_expr { }; #endif -/* Parse tree for syscall set/getsockopt for SCTP_PEER_ADDR_PARAMS*/ +/* Parse tree for a sctp_paddrparams struct in a [gs]etsockopt syscall. */ struct sctp_paddrparams_expr { struct expression *spp_address; struct expression *spp_hbinterval; diff --git a/gtests/net/packetdrill/sctp.h b/gtests/net/packetdrill/sctp.h index 177735b2dccaecdc834d1a816d03ceddafe209a9..dc9d2051513aca263324290f056af93ef26bfb98 100644 --- a/gtests/net/packetdrill/sctp.h +++ b/gtests/net/packetdrill/sctp.h @@ -52,6 +52,7 @@ struct sctp_common_header { #define SCTP_ECNE_CHUNK_TYPE 0x0c #define SCTP_CWR_CHUNK_TYPE 0x0d #define SCTP_SHUTDOWN_COMPLETE_CHUNK_TYPE 0x0e +#define SCTP_I_DATA_CHUNK_TYPE 0x40 #define SCTP_PAD_CHUNK_TYPE 0x84 #define MAX_SCTP_CHUNK_BYTES 0xffff @@ -205,6 +206,26 @@ struct sctp_shutdown_complete_chunk { __be16 length; } __packed; +#define SCTP_I_DATA_CHUNK_I_BIT 0x08 +#define SCTP_I_DATA_CHUNK_U_BIT 0x04 +#define SCTP_I_DATA_CHUNK_B_BIT 0x02 +#define SCTP_I_DATA_CHUNK_E_BIT 0x01 + +struct sctp_i_data_chunk { + __u8 type; + __u8 flags; + __be16 length; + __be32 tsn; + __be16 sid; + __be16 res; + __be32 mid; + union { + __be32 ppid; + __be32 fsn; + } field; + __u8 data[]; +} __packed; + struct sctp_pad_chunk { __u8 type; __u8 flags; @@ -221,6 +242,7 @@ struct sctp_pad_chunk { #define SCTP_HOSTNAME_ADDRESS_PARAMETER_TYPE 0x000b #define SCTP_SUPPORTED_ADDRESS_TYPES_PARAMETER_TYPE 0x000c #define SCTP_ECN_CAPABLE_PARAMETER_TYPE 0x8000 +#define SCTP_SUPPORTED_EXTENSIONS_PARAMETER_TYPE 0x8008 #define SCTP_PAD_PARAMETER_TYPE 0x8005 #define MAX_SCTP_PARAMETER_BYTES 0xffff @@ -284,6 +306,12 @@ struct sctp_ecn_capable_parameter { __be16 length; } __packed; +struct sctp_supported_extensions_parameter { + __be16 type; + __be16 length; + __u8 chunk_type[]; +} __packed; + struct sctp_pad_parameter { __be16 type; __be16 length; diff --git a/gtests/net/packetdrill/sctp_chunk_to_string.c b/gtests/net/packetdrill/sctp_chunk_to_string.c index 59c246a06ed35800c8c189222b11c4446b2f0a56..8dc2ca83547de2a6f006d252430c66093c944937 100644 --- a/gtests/net/packetdrill/sctp_chunk_to_string.c +++ b/gtests/net/packetdrill/sctp_chunk_to_string.c @@ -219,6 +219,86 @@ static int sctp_ecn_capable_parameter_to_string( return STATUS_OK; } +static int sctp_supported_extensions_parameter_to_string( + FILE *s, + struct sctp_supported_extensions_parameter *parameter, + char **error) +{ + u16 length, nr_chunk_types, i; + + length = ntohs(parameter->length); + if (length < sizeof(struct sctp_supported_extensions_parameter)) { + asprintf(error, + "SUPPORTED_EXTENSIONS parameter illegal (length=%u)", + length); + return STATUS_ERR; + } + nr_chunk_types = length - sizeof(struct sctp_supported_extensions_parameter); + fputs("SUPPORTED_EXTENSIONS[types=[", s); + for (i = 0; i < nr_chunk_types; i++) { + if (i > 0) + fputs(", ", s); + switch (parameter->chunk_type[i]) { + case SCTP_DATA_CHUNK_TYPE: + fputs("DATA", s); + break; + case SCTP_INIT_CHUNK_TYPE: + fputs("INIT", s); + break; + case SCTP_INIT_ACK_CHUNK_TYPE: + fputs("INIT-ACK", s); + break; + case SCTP_SACK_CHUNK_TYPE: + fputs("SACK", s); + break; + case SCTP_HEARTBEAT_CHUNK_TYPE: + fputs("HEARTBEAT", s); + break; + case SCTP_HEARTBEAT_ACK_CHUNK_TYPE: + fputs("HEARTBEAT-ACK", s); + break; + case SCTP_ABORT_CHUNK_TYPE: + fputs("ABORT", s); + break; + case SCTP_SHUTDOWN_CHUNK_TYPE: + fputs("SHUTDOWN", s); + break; + case SCTP_SHUTDOWN_ACK_CHUNK_TYPE: + fputs("SHUTDOWN-ACK", s); + break; + case SCTP_ERROR_CHUNK_TYPE: + fputs("ERROR", s); + break; + case SCTP_COOKIE_ECHO_CHUNK_TYPE: + fputs("COOKIE-ECHO", s); + break; + case SCTP_COOKIE_ACK_CHUNK_TYPE: + fputs("COOKIE-ACK", s); + break; + case SCTP_ECNE_CHUNK_TYPE: + fputs("ECNE", s); + break; + case SCTP_CWR_CHUNK_TYPE: + fputs("CWR", s); + break; + case SCTP_SHUTDOWN_COMPLETE_CHUNK_TYPE: + fputs("SHUTDOWN-COMPLETE", s); + break; + case SCTP_I_DATA_CHUNK_TYPE: + fputs("I-DATA", s); + break; + case SCTP_PAD_CHUNK_TYPE: + fputs("PAD", s); + break; + default: + fprintf(s, "0x%02x", parameter->chunk_type[i]); + break; + } + } + fputs("]]", s); + return STATUS_OK; +} + static int sctp_pad_parameter_to_string( FILE *s, struct sctp_pad_parameter *parameter, @@ -305,6 +385,11 @@ static int sctp_parameter_to_string(FILE *s, result = sctp_ecn_capable_parameter_to_string(s, (struct sctp_ecn_capable_parameter *)parameter, error); break; + case SCTP_SUPPORTED_EXTENSIONS_PARAMETER_TYPE: + result = sctp_supported_extensions_parameter_to_string(s, + (struct sctp_supported_extensions_parameter *)parameter, + error); + break; case SCTP_PAD_PARAMETER_TYPE: result = sctp_pad_parameter_to_string(s, (struct sctp_pad_parameter *)parameter, error); @@ -1206,6 +1291,49 @@ static int sctp_shutdown_complete_chunk_to_string( return STATUS_OK; } +static int sctp_i_data_chunk_to_string(FILE *s, + struct sctp_i_data_chunk *chunk, + char **error) +{ + u16 length; + u8 flags; + + flags = chunk->flags; + length = ntohs(chunk->length); + if (length < sizeof(struct sctp_i_data_chunk)) { + asprintf(error, "I-DATA chunk too short (length=%u)", length); + return STATUS_ERR; + } + fputs("I-DATA[", s); + fputs("flgs=", s); + if ((flags & ~(SCTP_I_DATA_CHUNK_I_BIT | + SCTP_I_DATA_CHUNK_U_BIT | + SCTP_I_DATA_CHUNK_B_BIT | + SCTP_I_DATA_CHUNK_E_BIT)) || (flags == 0x00)) + fprintf(s, "0x%02x", chunk->flags); + else { + if (flags & SCTP_I_DATA_CHUNK_I_BIT) + fputc('I', s); + if (flags & SCTP_I_DATA_CHUNK_U_BIT) + fputc('U', s); + if (flags & SCTP_I_DATA_CHUNK_B_BIT) + fputc('B', s); + if (flags & SCTP_I_DATA_CHUNK_E_BIT) + fputc('E', s); + } + fputs(", ", s); + fprintf(s, "len=%u, ", length); + fprintf(s, "tsn=%u, ", ntohl(chunk->tsn)); + fprintf(s, "sid=%d, ", ntohs(chunk->sid)); + fprintf(s, "mid=%u, ", ntohl(chunk->mid)); + if (flags & SCTP_I_DATA_CHUNK_B_BIT) + fprintf(s, "ppid=%u", ntohl(chunk->field.ppid)); + else + fprintf(s, "fsn=%u", ntohl(chunk->field.fsn)); + fputc(']', s); + return STATUS_OK; +} + static int sctp_pad_chunk_to_string( FILE *s, struct sctp_pad_chunk *chunk, @@ -1305,6 +1433,10 @@ int sctp_chunk_to_string(FILE *s, struct sctp_chunk *chunk, char **error) result = sctp_shutdown_complete_chunk_to_string(s, (struct sctp_shutdown_complete_chunk *)chunk, error); break; + case SCTP_I_DATA_CHUNK_TYPE: + result = sctp_i_data_chunk_to_string(s, + (struct sctp_i_data_chunk *)chunk, error); + break; case SCTP_PAD_CHUNK_TYPE: result = sctp_pad_chunk_to_string(s, (struct sctp_pad_chunk *)chunk, error); diff --git a/gtests/net/packetdrill/sctp_packet.c b/gtests/net/packetdrill/sctp_packet.c index ac26f2082a8d57ecdf84a538dfe0c32c52c8b2f1..23112204244cf2c4fc15ca35821e0ce182d8b48b 100644 --- a/gtests/net/packetdrill/sctp_packet.c +++ b/gtests/net/packetdrill/sctp_packet.c @@ -1097,6 +1097,83 @@ sctp_shutdown_complete_chunk_new(s64 flgs) sctp_cause_list_new()); } +struct sctp_chunk_list_item * +sctp_i_data_chunk_new(s64 flgs, s64 len, s64 tsn, s64 sid, s64 res, s64 mid, + s64 ppid, s64 fsn) +{ + struct sctp_i_data_chunk *chunk; + u32 flags; + u16 length, padding_length; + + flags = 0; + if (len == -1) { + length = (u16)sizeof(struct sctp_i_data_chunk); + } else { + length = (u16)len; + } + padding_length = length % 4; + if (padding_length > 0) { + padding_length = 4 - padding_length; + } + chunk = malloc(length + padding_length); + assert(chunk != NULL); + chunk->type = SCTP_I_DATA_CHUNK_TYPE; + if (flgs == -1) { + chunk->flags = 0; + flags |= FLAG_CHUNK_FLAGS_NOCHECK; + } else { + chunk->flags = (u8)flgs; + } + chunk->length = htons(length); + if (len == -1) { + flags |= FLAG_CHUNK_LENGTH_NOCHECK; + flags |= FLAG_CHUNK_VALUE_NOCHECK; + } + if (tsn == -1) { + chunk->tsn = htonl(0); + flags |= FLAG_I_DATA_CHUNK_TSN_NOCHECK; + } else { + chunk->tsn = htonl((u32)tsn); + } + if (sid == -1) { + chunk->sid = htons(0); + flags |= FLAG_I_DATA_CHUNK_SID_NOCHECK; + } else { + chunk->sid = htons((u16)sid); + } + if (res == -1) { + chunk->res = htons(0); + flags |= FLAG_I_DATA_CHUNK_RES_NOCHECK; + } else { + chunk->res = htons((u16)res); + } + if (mid == -1) { + chunk->mid = htonl(0); + flags |= FLAG_I_DATA_CHUNK_MID_NOCHECK; + } else { + chunk->mid = htonl((u32)mid); + } + if (ppid == -1) { + flags |= FLAG_I_DATA_CHUNK_PPID_NOCHECK; + } else { + chunk->field.ppid = htonl((u32)ppid); + } + if (fsn == -1) { + flags |= FLAG_I_DATA_CHUNK_FSN_NOCHECK; + } else { + chunk->field.fsn = htonl((u32)fsn); + } + if (ppid == -1 && fsn == -1) { + chunk->field.ppid = htonl(0); + } + memset(chunk->data, 0, + length + padding_length - sizeof(struct sctp_i_data_chunk)); + return sctp_chunk_list_item_new((struct sctp_chunk *)chunk, + length + padding_length, flags, + sctp_parameter_list_new(), + sctp_cause_list_new()); +} + struct sctp_chunk_list_item * sctp_pad_chunk_new(s64 flgs, s64 len, u8* padding) { @@ -1256,7 +1333,7 @@ sctp_generic_parameter_new(s64 type, s64 len, struct sctp_byte_list *bytes) struct sctp_parameter_list_item * sctp_heartbeat_information_parameter_new(s64 len, struct sctp_byte_list *bytes) { - return sctp_generic_parameter_new(SCTP_HEARTBEAT_INFORMATION_PARAMETER_TYPE, len,bytes); + return sctp_generic_parameter_new(SCTP_HEARTBEAT_INFORMATION_PARAMETER_TYPE, len, bytes); } struct sctp_parameter_list_item * @@ -1493,6 +1570,47 @@ sctp_supported_address_types_parameter_new(struct sctp_address_type_list *list) parameter_length, flags); } +struct sctp_parameter_list_item * +sctp_supported_extensions_parameter_new(struct sctp_byte_list *list) +{ + struct sctp_supported_extensions_parameter *parameter; + + u32 flags; + u16 i, parameter_length, padding_length; + struct sctp_byte_list_item *item; + + flags = 0; + parameter_length = sizeof(struct sctp_supported_extensions_parameter); + if (list == NULL) { + flags |= FLAG_PARAMETER_LENGTH_NOCHECK; + flags |= FLAG_PARAMETER_VALUE_NOCHECK; + } else { + assert(list->nr_entries <= + (MAX_SCTP_PARAMETER_BYTES - sizeof(struct sctp_supported_extensions_parameter)) / sizeof(u8)); + parameter_length += list->nr_entries * sizeof(u8); + } + padding_length = parameter_length % 4; + if (padding_length > 0) { + padding_length = 4 - padding_length; + } + assert(padding_length < 4); + parameter = malloc(parameter_length + padding_length); + assert(parameter != NULL); + parameter->type = htons(SCTP_SUPPORTED_EXTENSIONS_PARAMETER_TYPE); + parameter->length = htons(parameter_length); + if (list != NULL) { + for (i = 0, item = list->first; + (i < list->nr_entries) && (item != NULL); + i++, item = item->next) { + parameter->chunk_type[i] = item->byte; + } + assert((i == list->nr_entries) && (item == NULL)); + } + memset(parameter->chunk_type + list->nr_entries, 0, padding_length); + return sctp_parameter_list_item_new((struct sctp_parameter *)parameter, + parameter_length, flags); +} + struct sctp_parameter_list_item * sctp_pad_parameter_new(s64 len, u8 *padding) { diff --git a/gtests/net/packetdrill/sctp_packet.h b/gtests/net/packetdrill/sctp_packet.h index ad974346203a7f703df99db63812e90f41f2bcbb..ba972b395bb1bf338093c6b0ef1d742af2c546cc 100644 --- a/gtests/net/packetdrill/sctp_packet.h +++ b/gtests/net/packetdrill/sctp_packet.h @@ -275,6 +275,17 @@ sctp_cwr_chunk_new(s64 flgs, s64 lowest_tsn); struct sctp_chunk_list_item * sctp_shutdown_complete_chunk_new(s64 flgs); +#define FLAG_I_DATA_CHUNK_TSN_NOCHECK 0x00000100 +#define FLAG_I_DATA_CHUNK_SID_NOCHECK 0x00000200 +#define FLAG_I_DATA_CHUNK_RES_NOCHECK 0x00000400 +#define FLAG_I_DATA_CHUNK_MID_NOCHECK 0x00000800 +#define FLAG_I_DATA_CHUNK_PPID_NOCHECK 0x00001000 +#define FLAG_I_DATA_CHUNK_FSN_NOCHECK 0x00002000 + +struct sctp_chunk_list_item * +sctp_i_data_chunk_new(s64 flgs, s64 len, s64 tsn, s64 sid, s64 res, s64 mid, + s64 ppid, s64 fsn); + struct sctp_chunk_list_item * sctp_pad_chunk_new(s64 flgs, s64 len, u8* padding); @@ -329,6 +340,12 @@ sctp_ecn_capable_parameter_new(void); struct sctp_parameter_list_item * sctp_pad_parameter_new(s64 len, u8 *padding); +struct sctp_parameter_list_item * +sctp_supported_extensions_parameter_new(struct sctp_byte_list *list); + +struct sctp_parameter_list_item * +sctp_pad_parameter_new(s64 len, u8 *padding); + struct sctp_parameter_list * sctp_parameter_list_new(void); diff --git a/gtests/net/packetdrill/symbols_freebsd.c b/gtests/net/packetdrill/symbols_freebsd.c index 14eda9cf01e377000c9e3fcc118df62461ea40d3..76ca731740018907a56a8ef748efd087bc914d23 100644 --- a/gtests/net/packetdrill/symbols_freebsd.c +++ b/gtests/net/packetdrill/symbols_freebsd.c @@ -78,7 +78,7 @@ struct int_symbol platform_symbols_table[] = { { SO_SETFIB, "SO_SETFIB" }, { SO_USER_COOKIE, "SO_USER_COOKIE" }, - /* /usr/include/netinet/sctp.h */ + /* /usr/include/netinet/sctp.h and /usr/include/netinet/sctp_uio.h */ { SCTP_RTOINFO, "SCTP_RTOINFO" }, { SCTP_INITMSG, "SCTP_INITMSG" }, { SCTP_NODELAY, "SCTP_NODELAY" }, @@ -87,6 +87,10 @@ 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_FRAGMENT_INTERLEAVE, "SCTP_FRAGMENT_INTERLEAVE" }, +#if defined(SCTP_INTERLEAVING_SUPPORTED) + { SCTP_INTERLEAVING_SUPPORTED, "SCTP_INTERLEAVING_SUPPORTED" }, +#endif { SCTP_CLOSED, "SCTP_CLOSED" }, { SCTP_BOUND, "SCTP_BOUND" }, { SCTP_LISTEN, "SCTP_LISTEN" }, @@ -97,8 +101,52 @@ struct int_symbol platform_symbols_table[] = { { SCTP_SHUTDOWN_RECEIVED, "SCTP_SHUTDOWN_RECEIVED" }, { SCTP_SHUTDOWN_ACK_SENT, "SCTP_SHUTDOWN_ACK_SENT" }, { SCTP_SHUTDOWN_PENDING, "SCTP_SHUTDOWN_PENDING" }, - - /* /usr/include/netinet/sctp_uio.h */ + /* The following constants are from + * https://tools.ietf.org/html/draft-ietf-tsvwg-sctp-ndata-04 + * The old symbols currently being deployed are also provided. + */ + { SCTP_PLUGGABLE_SS, "SCTP_PLUGGABLE_SS" }, + { SCTP_SS_VALUE, "SCTP_SS_VALUE" }, + { SCTP_SS_DEFAULT, "SCTP_SS_DEFAULT" }, + { SCTP_SS_ROUND_ROBIN, "SCTP_SS_ROUND_ROBIN" }, + { SCTP_SS_ROUND_ROBIN_PACKET, "SCTP_SS_ROUND_ROBIN_PACKET" }, + { SCTP_SS_PRIORITY, "SCTP_SS_PRIORITY" }, + /* The following is a typo in FreeBSD's sctp.h */ + { SCTP_SS_FAIR_BANDWITH, "SCTP_SS_FAIR_BANDWITH" }, + { SCTP_SS_FIRST_COME, "SCTP_SS_FIRST_COME" }, +#if defined(SCTP_SS_FCFS) + { SCTP_SS_FCFS, "SCTP_SS_FCFS" }, +#endif +#if defined(SCTP_SS_RR) + { SCTP_SS_RR, "SCTP_SS_RR" }, +#endif +#if defined(SCTP_SS_RR_PKT) + { SCTP_SS_RR_PKT, "SCTP_SS_RR_PKT" }, +#endif +#if defined(SCTP_SS_PRIO) + { SCTP_SS_PRIO, "SCTP_SS_PRIO" }, +#endif +#if defined(SCTP_SS_FB) + { SCTP_SS_FB, "SCTP_SS_FB" }, +#endif +#if defined(SCTP_SS_WFQ) + { SCTP_SS_WFQ, "SCTP_SS_WFQ" }, +#endif +#if defined(SCTP_SS_RR_INTER) + { SCTP_SS_RR_INTER, "SCTP_SS_RR_INTER" }, +#endif +#if defined(SCTP_SS_RR_PKT_INTER) + { SCTP_SS_RR_PKT_INTER, "SCTP_SS_RR_PKT_INTER" }, +#endif +#if defined(SCTP_SS_PRIO_INTER) + { SCTP_SS_PRIO_INTER, "SCTP_SS_PRIO_INTER" }, +#endif +#if defined(SCTP_SS_FB_INTER) + { SCTP_SS_FB_INTER, "SCTP_SS_FB_INTER" }, +#endif +#if defined(SCTP_SS_WFQ_INTER) + { SCTP_SS_WFQ_INTER, "SCTP_SS_WFQ_INTER" }, +#endif { SCTP_UNCONFIRMED, "SCTP_UNCONFIRMED" }, { SCTP_ACTIVE, "SCTP_ACTIVE" }, { SCTP_INACTIVE, "SCTP_INACTIVE" }, @@ -111,7 +159,7 @@ struct int_symbol platform_symbols_table[] = { { SPP_IPV6_FLOWLABEL, "SPP_IPV6_FLOWLABEL" }, { SPP_DSCP, "SPP_DSCP" }, { SPP_IPV4_TOS, "SPP_IPV4_TOS" }, - + /* /usr/include/netinet/tcp.h */ { TCP_NODELAY, "TCP_NODELAY" }, { TCP_MAXSEG, "TCP_MAXSEG" }, diff --git a/gtests/net/packetdrill/symbols_linux.c b/gtests/net/packetdrill/symbols_linux.c index db4e25599a982a3bdfbd95aa9d4f02da43ee2b88..df65a2cf13e77a8de902269a3c19bdeb9b61181c 100644 --- a/gtests/net/packetdrill/symbols_linux.c +++ b/gtests/net/packetdrill/symbols_linux.c @@ -123,6 +123,12 @@ struct int_symbol platform_symbols_table[] = { #endif #ifdef SCTP_STATUS { SCTP_STATUS, "SCTP_STATUS" }, +#endif +#ifdef SCTP_FRAGMENT_INTERLEAVE + { SCTP_FRAGMENT_INTERLEAVE, "SCTP_FRAGMENT_INTERLEAVE" }, +#endif +#ifdef SCTP_INTERLEAVING_SUPPORTED + { SCTP_INTERLEAVING_SUPPORTED, "SCTP_INTERLEAVING_SUPPORTED" }, #endif { SCTP_CLOSED, "SCTP_CLOSED" }, #if 0 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 4b619548f3647f87e74a8a4f2e1b533a2e0b44bc..7983e824febd71050c39bb4972f7f0f8fff03681 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 @@ -71,5 +71,5 @@ spp_hbinterval=300, spp_pathmtu=1468, spp_pathmaxrxt=..., spp_flags=521, spp_ipv +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 getsockopt(3, IPPROTO_SCTP, SCTP_MAXSEG, {assoc_value=1452}, [8]) = 0 +0 close(3) = 0 diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_i_data.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_i_data.pkt new file mode 100644 index 0000000000000000000000000000000000000000..7303482b38ea2b51bf88298048285b86bc7c8262 --- /dev/null +++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_i_data.pkt @@ -0,0 +1,25 @@ ++0.0 socket(..., SOCK_STREAM, IPPROTO_SCTP) = 3 +// Check the handshake with en empty(!) cookie ++0.0 bind(3, ..., ...) = 0 ++0.0 listen(3, 1) = 0 ++0.0 setsockopt(3, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, [2], 4) = 0 ++0.0 setsockopt(3, IPPROTO_SCTP, SCTP_INTERLEAVING_SUPPORTED, {assoc_value=1}, 8) = 0 ++0.0 < sctp: INIT[flgs=0, tag=1, a_rwnd=1500, os=2, is=2, tsn=1, + SUPPORTED_EXTENSIONS[types=[I-DATA, PAD]]] ++0.0 > sctp: INIT_ACK[flgs=0, tag=2, a_rwnd=..., os=..., is=..., tsn=1, ...] ++0.1 < sctp: COOKIE_ECHO[flgs=0, len=..., val=...] ++0.0 > sctp: COOKIE_ACK[flgs=0] ++0.0 accept(3, ..., ...) = 4 ++0.1 send(4, ..., 100, 0) = 100 ++0.0 > sctp: I-DATA[flgs=BE, len=120, tsn=1, sid=0, mid=0, ppid=0] ++0.0 < sctp: SACK[flgs=0, cum_tsn=1, a_rwnd=1500, gaps=[], dups=[]] +// Insert a I-DATA chunk ++0.0 < sctp: I-DATA[flgs=BE, len=24, tsn=1, sid=1, mid=0, ppid=1234] ++0.0 > sctp: SACK[flgs=0, cum_tsn=1, a_rwnd=..., gaps=[], dups=[]] ++0.0 recv(4, ..., 100, 0) = 4 +// Tear down the association ++1.0 < sctp: SHUTDOWN[flgs=0, cum_tsn=1] ++0.0 > sctp: SHUTDOWN_ACK[flgs=0] ++0.0 < sctp: SHUTDOWN_COMPLETE[flgs=0] ++0.0 close(4) = 0 ++0.0 close(3) = 0