diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index 7a91d334f8891059d78aef1adfd1f0eccbef401e..da6c940c9cc0da85e00d891a0a031a89aa47e8fc 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -951,7 +951,8 @@ opt_shutdown_complete_flags ; opt_tag -: TAG '=' INTEGER { +: TAG '=' ELLIPSIS { $$ = -1; } +| TAG '=' INTEGER { if (!is_valid_u32($3)) { semantic_error("tag value out of range"); } @@ -1098,23 +1099,11 @@ sctp_data_chunk_spec sctp_init_chunk_spec : INIT '[' opt_flags ',' opt_tag ',' opt_a_rwnd ',' opt_os ',' opt_is ',' opt_tsn opt_parameter_list_spec ']' { - if ($5 == -1) { - semantic_error("tag value must be specified"); - } - if ($13 == -1) { - semantic_error("tsn value must be specified"); - } $$ = sctp_init_chunk_new($3, $5, $7, $9, $11, $13, $14); } sctp_init_ack_chunk_spec : INIT_ACK '[' opt_flags ',' opt_tag ',' opt_a_rwnd ',' opt_os ',' opt_is ',' opt_tsn opt_parameter_list_spec ']' { - if ($5 == -1) { - semantic_error("tag value must be specified"); - } - if ($13 == -1) { - semantic_error("tsn value must be specified"); - } $$ = sctp_init_ack_chunk_new($3, $5, $7, $9, $11, $13, $14); } diff --git a/gtests/net/packetdrill/run_packet.c b/gtests/net/packetdrill/run_packet.c index fb8a0c736d7428b358416d6bf359e079ae1a39ba..303f2f53b16779f1da5a630a2ab8cc545481460a 100644 --- a/gtests/net/packetdrill/run_packet.c +++ b/gtests/net/packetdrill/run_packet.c @@ -1153,10 +1153,11 @@ static int verify_init_chunk(struct sctp_init_chunk *actual_chunk, assert(ntohs(actual_chunk->length) >= sizeof(struct sctp_init_chunk)); parameters_length = ntohs(actual_chunk->length) - sizeof(struct sctp_init_chunk); - if (check_field("sctp_init_chunk_tag", - ntohl(script_chunk->initiate_tag), - ntohl(actual_chunk->initiate_tag), - error) || + if ((flags & FLAG_INIT_CHUNK_TAG_NOCHECK ? STATUS_OK : + check_field("sctp_init_chunk_tag", + ntohl(script_chunk->initiate_tag), + ntohl(actual_chunk->initiate_tag), + error)) || (flags & FLAG_INIT_CHUNK_A_RWND_NOCHECK ? STATUS_OK : check_field("sctp_init_chunk_a_rwnd", ntohl(script_chunk->a_rwnd), @@ -1172,10 +1173,11 @@ static int verify_init_chunk(struct sctp_init_chunk *actual_chunk, ntohs(script_chunk->is), ntohs(actual_chunk->is), error)) || - check_field("sctp_init_chunk_tsn", - ntohl(script_chunk->initial_tsn), - ntohl(actual_chunk->initial_tsn), - error) || + (flags & FLAG_INIT_CHUNK_TSN_NOCHECK? STATUS_OK : + check_field("sctp_init_chunk_tsn", + ntohl(script_chunk->initial_tsn), + ntohl(actual_chunk->initial_tsn), + error)) || (flags & FLAG_INIT_CHUNK_OPT_PARAM_NOCHECK? STATUS_OK : verify_sctp_parameters(actual_chunk->parameter, parameters_length, @@ -1190,10 +1192,11 @@ static int verify_init_ack_chunk(struct sctp_init_ack_chunk *actual_chunk, struct sctp_init_ack_chunk *script_chunk, u32 flags, char **error) { - if (check_field("sctp_init_ack_chunk_tag", - ntohl(script_chunk->initiate_tag), - ntohl(actual_chunk->initiate_tag), - error) || + if ((flags & FLAG_INIT_ACK_CHUNK_TAG_NOCHECK ? STATUS_OK : + check_field("sctp_init_ack_chunk_tag", + ntohl(script_chunk->initiate_tag), + ntohl(actual_chunk->initiate_tag), + error)) || (flags & FLAG_INIT_ACK_CHUNK_A_RWND_NOCHECK ? STATUS_OK : check_field("sctp_init_ack_chunk_a_rwnd", ntohl(script_chunk->a_rwnd), @@ -1209,10 +1212,11 @@ static int verify_init_ack_chunk(struct sctp_init_ack_chunk *actual_chunk, ntohs(script_chunk->is), ntohs(actual_chunk->is), error)) || - check_field("sctp_init_ack_chunk_tsn", - ntohl(script_chunk->initial_tsn), - ntohl(actual_chunk->initial_tsn), - error)) { + (flags & FLAG_INIT_ACK_CHUNK_TSN_NOCHECK? STATUS_OK : + check_field("sctp_init_ack_chunk_tsn", + ntohl(script_chunk->initial_tsn), + ntohl(actual_chunk->initial_tsn), + error))) { return STATUS_ERR; } /* FIXME: Validate parameters */ diff --git a/gtests/net/packetdrill/sctp_packet.c b/gtests/net/packetdrill/sctp_packet.c index b190289e9727dff88c7f6b542fd5a6560703a3cc..f3eec362655eafa63504e269afc32c5fb498f740 100644 --- a/gtests/net/packetdrill/sctp_packet.c +++ b/gtests/net/packetdrill/sctp_packet.c @@ -282,7 +282,12 @@ sctp_init_chunk_new(s64 flgs, s64 tag, s64 a_rwnd, s64 os, s64 is, s64 tsn, chunk->flags = (u8)flgs; } chunk->length = htons(chunk_length); - chunk->initiate_tag = htonl((u32)tag); + if (tag == -1) { + chunk->initiate_tag = htonl(0); + flags |= FLAG_INIT_CHUNK_TAG_NOCHECK; + } else { + chunk->initiate_tag = htonl((u32)tag); + } if (a_rwnd == -1) { chunk->a_rwnd = htonl(0); flags |= FLAG_INIT_CHUNK_A_RWND_NOCHECK; @@ -301,7 +306,12 @@ sctp_init_chunk_new(s64 flgs, s64 tag, s64 a_rwnd, s64 os, s64 is, s64 tsn, } else { chunk->is = htons((u16)is); } - chunk->initial_tsn = htonl((u32)tsn); + if (tsn == -1) { + chunk->initial_tsn = htonl(0); + flags |= FLAG_INIT_CHUNK_TSN_NOCHECK; + } else { + chunk->initial_tsn = htonl((u32)tsn); + } offset = 0; for (item = list->first; item != NULL; item = item->next) { parameter_padding_length = item->length % 4; @@ -355,26 +365,36 @@ sctp_init_ack_chunk_new(s64 flgs, s64 tag, s64 a_rwnd, s64 os, s64 is, s64 tsn, chunk->flags = (u8)flgs; } chunk->length = htons(chunk_length); - chunk->initiate_tag = htonl((u32)tag); + if (tag == -1) { + chunk->initiate_tag = htonl(0); + flags |= FLAG_INIT_ACK_CHUNK_TAG_NOCHECK; + } else { + chunk->initiate_tag = htonl((u32)tag); + } if (a_rwnd == -1) { chunk->a_rwnd = htonl(0); - flags |= FLAG_INIT_CHUNK_A_RWND_NOCHECK; + flags |= FLAG_INIT_ACK_CHUNK_A_RWND_NOCHECK; } else { chunk->a_rwnd = htonl((u32)a_rwnd); } if (os == -1) { chunk->os = htons(0); - flags |= FLAG_INIT_CHUNK_OS_NOCHECK; + flags |= FLAG_INIT_ACK_CHUNK_OS_NOCHECK; } else { chunk->os = htons((u16)os); } if (is == -1) { chunk->is = htons(0); - flags |= FLAG_INIT_CHUNK_IS_NOCHECK; + flags |= FLAG_INIT_ACK_CHUNK_IS_NOCHECK; } else { chunk->is = htons((u16)is); } - chunk->initial_tsn = htonl((u32)tsn); + if (tsn == -1) { + chunk->initial_tsn = htonl(0); + flags |= FLAG_INIT_ACK_CHUNK_TSN_NOCHECK; + } else { + chunk->initial_tsn = htonl((u32)tsn); + } offset = 0; for (item = list->first; item != NULL; item = item->next) { parameter_padding_length = item->length % 4; @@ -1379,6 +1399,11 @@ new_sctp_packet(int address_family, } break; case SCTP_INIT_CHUNK_TYPE: + if (chunk_item->flags & FLAG_INIT_CHUNK_TAG_NOCHECK) { + asprintf(error, + "TAG must be specified for inbound packets"); + return NULL; + } if (chunk_item->flags & FLAG_INIT_CHUNK_A_RWND_NOCHECK) { asprintf(error, "A_RWND must be specified for inbound packets"); @@ -1401,6 +1426,11 @@ new_sctp_packet(int address_family, } break; case SCTP_INIT_ACK_CHUNK_TYPE: + if (chunk_item->flags & FLAG_INIT_ACK_CHUNK_TAG_NOCHECK) { + asprintf(error, + "TAG must be specified for inbound packets"); + return NULL; + } if (chunk_item->flags & FLAG_INIT_ACK_CHUNK_A_RWND_NOCHECK) { asprintf(error, "A_RWND must be specified for inbound packets"); diff --git a/gtests/net/packetdrill/sctp_packet.h b/gtests/net/packetdrill/sctp_packet.h index 36df5f54589908fcc9c0aeea8d7f38f0f3bdb90c..51b0bcc9e15e270ee3cfa31ee62d8d9a44907ade 100644 --- a/gtests/net/packetdrill/sctp_packet.h +++ b/gtests/net/packetdrill/sctp_packet.h @@ -130,19 +130,23 @@ sctp_chunk_list_item_new(struct sctp_chunk *chunk, u32 length, u32 flags, struct sctp_chunk_list_item * sctp_data_chunk_new(s64 flgs, s64 len, s64 tsn, s64 sid, s64 ssn, s64 ppid); -#define FLAG_INIT_CHUNK_A_RWND_NOCHECK 0x00000100 -#define FLAG_INIT_CHUNK_OS_NOCHECK 0x00000200 -#define FLAG_INIT_CHUNK_IS_NOCHECK 0x00000400 -#define FLAG_INIT_CHUNK_OPT_PARAM_NOCHECK 0x00000800 +#define FLAG_INIT_CHUNK_TAG_NOCHECK 0x00000100 +#define FLAG_INIT_CHUNK_A_RWND_NOCHECK 0x00000200 +#define FLAG_INIT_CHUNK_OS_NOCHECK 0x00000400 +#define FLAG_INIT_CHUNK_IS_NOCHECK 0x00000800 +#define FLAG_INIT_CHUNK_TSN_NOCHECK 0x00001000 +#define FLAG_INIT_CHUNK_OPT_PARAM_NOCHECK 0x00002000 struct sctp_chunk_list_item * sctp_init_chunk_new(s64 flgs, s64 tag, s64 a_rwnd, s64 os, s64 is, s64 tsn, struct sctp_parameter_list *parameters); -#define FLAG_INIT_ACK_CHUNK_A_RWND_NOCHECK 0x00000100 -#define FLAG_INIT_ACK_CHUNK_OS_NOCHECK 0x00000200 -#define FLAG_INIT_ACK_CHUNK_IS_NOCHECK 0x00000400 -#define FLAG_INIT_ACK_CHUNK_OPT_PARAM_NOCHECK 0x00000800 +#define FLAG_INIT_ACK_CHUNK_TAG_NOCHECK 0x00000100 +#define FLAG_INIT_ACK_CHUNK_A_RWND_NOCHECK 0x00000200 +#define FLAG_INIT_ACK_CHUNK_OS_NOCHECK 0x00000400 +#define FLAG_INIT_ACK_CHUNK_IS_NOCHECK 0x00000800 +#define FLAG_INIT_ACK_CHUNK_TSN_NOCHECK 0x00001000 +#define FLAG_INIT_ACK_CHUNK_OPT_PARAM_NOCHECK 0x00002000 struct sctp_chunk_list_item * sctp_init_ack_chunk_new(s64 flgs, s64 tag, s64 a_rwnd, s64 os, s64 is, s64 tsn,