diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index 8e09bcc1b40d558e9f9fa88ff4d59357a58962c8..ab4268807a8cad6c0ea62b98dd0e657c0fde87e6 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -1828,11 +1828,8 @@ generic_reconfig_request ; sctp_reconfig_chunk_spec -: RECONFIG '[' opt_flags ',' sctp_parameter_list_spec ']' { - $$ = sctp_reconfig_chunk_new($3, $5); -} -| RECONFIG '[' opt_flags ']' { - $$ = sctp_reconfig_chunk_new($3, NULL); +: RECONFIG '[' opt_flags opt_parameter_list_spec ']' { + $$ = sctp_reconfig_chunk_new($3, $4); } ; diff --git a/gtests/net/packetdrill/run_packet.c b/gtests/net/packetdrill/run_packet.c index 0df2fc2e0c27796bbfe02de963b676b1ae4ea4e3..0949c1e26a17c6f9770aa79d39f99b76d5113b46 100644 --- a/gtests/net/packetdrill/run_packet.c +++ b/gtests/net/packetdrill/run_packet.c @@ -661,7 +661,6 @@ static int map_inbound_sctp_packet( reflect_v_tag = false; contains_init_chunk = false; - /* Map the TSNs and the initiate tags in the INIT and INIT-ACK chunk */ for (chunk = sctp_chunks_begin(live_packet, &iter, error); chunk != NULL; @@ -741,7 +740,7 @@ static int map_inbound_sctp_packet( break; case SCTP_RECONFIG_CHUNK_TYPE: reconfig = (struct sctp_reconfig_chunk *)chunk; - if (reconfig->length > sizeof(struct sctp_reconfig_chunk)) { + if (htons(reconfig->length) >= sizeof(struct sctp_reconfig_chunk) + 4) { struct sctp_parameter *parameter; struct sctp_parameters_iterator iter; int parameters_length = ntohs(reconfig->length) - sizeof(struct sctp_reconfig_chunk); @@ -753,29 +752,41 @@ static int map_inbound_sctp_packet( case SCTP_OUTGOING_SSN_RESET_REQUEST_PARAMETER_TYPE: { struct sctp_outgoing_ssn_reset_request_parameter *reset; reset = (struct sctp_outgoing_ssn_reset_request_parameter *)parameter; - reset->reqsn = htonl(ntohl(reset->reqsn) + remote_diff); - reset->respsn = htonl(ntohl(reset->respsn) + local_diff); - reset->last_tsn = htonl(ntohl(reset->last_tsn) + remote_diff); + if (htons(reset->length) >= 8) { + reset->reqsn = htonl(ntohl(reset->reqsn) + remote_diff); + } + if (htons(reset->length) >= 12) { + reset->respsn = htonl(ntohl(reset->respsn) + local_diff); + } + if (htons(reset->length) >= 16) { + reset->last_tsn = htonl(ntohl(reset->last_tsn) + remote_diff); + } break; } case SCTP_INCOMING_SSN_RESET_REQUEST_PARAMETER_TYPE: { struct sctp_incoming_ssn_reset_request_parameter *reset; reset = (struct sctp_incoming_ssn_reset_request_parameter *)parameter; - reset->reqsn = htonl(ntohl(reset->reqsn) + remote_diff); + if (htons(reset->length) >= 8) { + reset->reqsn = htonl(ntohl(reset->reqsn) + remote_diff); + } break; } case SCTP_SSN_TSN_RESET_REQUEST_PARAMETER_TYPE: { struct sctp_ssn_tsn_reset_request_parameter *reset; reset = (struct sctp_ssn_tsn_reset_request_parameter *)parameter; - reset->reqsn = htonl(ntohl(reset->reqsn) + remote_diff); + if (htons(reset->length) >= 8) { + reset->reqsn = htonl(ntohl(reset->reqsn) + remote_diff); + } break; } case SCTP_RECONFIG_RESPONSE_PARAMETER_TYPE: { struct sctp_reconfig_response_parameter *response; response = (struct sctp_reconfig_response_parameter *)parameter; response->respsn = htonl(htonl(response->respsn) + local_diff); - if (htons(response->length) == sizeof(struct sctp_reconfig_response_parameter)) { + if (htons(response->length) >= 12) { response->receiver_next_tsn = htonl(htonl(response->receiver_next_tsn) + local_diff); + } + if (htons(response->length) >= 16) { response->sender_next_tsn = htonl(htonl(response->sender_next_tsn) + remote_diff); } break; @@ -783,13 +794,17 @@ static int map_inbound_sctp_packet( case SCTP_ADD_OUTGOING_STREAMS_REQUEST_PARAMETER_TYPE: { struct sctp_add_outgoing_streams_request_parameter *request; request = (struct sctp_add_outgoing_streams_request_parameter *)parameter; - request->reqsn = htonl(htonl(request->reqsn) + remote_diff); + if (htons(request->length) >= 8) { + request->reqsn = htonl(htonl(request->reqsn) + remote_diff); + } break; } case SCTP_ADD_INCOMING_STREAMS_REQUEST_PARAMETER_TYPE: { struct sctp_add_incoming_streams_request_parameter *request; request = (struct sctp_add_incoming_streams_request_parameter *)parameter; - request->reqsn = htonl(htonl(request->reqsn) + remote_diff); + if (htons(request->length) >= 8) { + request->reqsn = htonl(htonl(request->reqsn) + remote_diff); + } break; } default: diff --git a/gtests/net/packetdrill/sctp_chunk_to_string.c b/gtests/net/packetdrill/sctp_chunk_to_string.c index ab647ae7de6e5d3307cc4a937aa8288be64404ae..3545fb1063bb0893e1bdb41654ac5face7d93544 100644 --- a/gtests/net/packetdrill/sctp_chunk_to_string.c +++ b/gtests/net/packetdrill/sctp_chunk_to_string.c @@ -328,6 +328,12 @@ static int sctp_outgoing_ssn_reset_request_parameter_to_string( int len; length = ntohs(parameter->length); + if (length != sizeof(struct sctp_outgoing_ssn_reset_request_parameter)) { + fputs("invalid OUTGOING_SSN_RESET_REQUEST parameter", s); + asprintf(error, "OUTGOING_SSN_RESET_REQUEST parameter illegal (length=%u)", + length); + return STATUS_ERR; + } reqsn = ntohl(parameter->reqsn); respsn = ntohl(parameter->respsn); last_tsn = ntohl(parameter->last_tsn); @@ -358,6 +364,12 @@ static int sctp_incoming_ssn_reset_request_parameter_to_string( int len; length = ntohs(parameter->length); + if (length != sizeof(struct sctp_incoming_ssn_reset_request_parameter)) { + fputs("invalid INCOMING_SSN_RESET_REQUEST parameter", s); + asprintf(error, "INCOMING_SSN_RESET_REQUEST parameter illegal (length=%u)", + length); + return STATUS_ERR; + } reqsn = ntohl(parameter->reqsn); fputs("INCOMING_SSN_RESET[", s); fprintf(s, "len=%hu, ", length); @@ -383,6 +395,12 @@ static int sctp_ssn_tsn_reset_request_parameter_to_string( u32 reqsn; length = ntohs(parameter->length); + if (length != sizeof(struct sctp_ssn_tsn_reset_request_parameter)) { + fputs("invalid SSN_TSN_RESET_REQUEST parameter", s); + asprintf(error, "SSN_TSN_RESET_REQUEST parameter illegal (length=%u)", + length); + return STATUS_ERR; + } reqsn = ntohl(parameter->reqsn); fputs("SSN_TSN_RESET[", s); @@ -404,6 +422,12 @@ static int sctp_reconfig_response_parameter_to_string( u32 receiver_next_tsn; length = ntohs(parameter->length); + if (length != sizeof(struct sctp_reconfig_response_parameter)) { + fputs("invalid RECONFIG_RESPONSE parameter", s); + asprintf(error, "RECONFIG_RESPONSE parameter illegal (length=%u)", + length); + return STATUS_ERR; + } respsn = ntohl(parameter->respsn); result = ntohl(parameter->result); @@ -431,6 +455,12 @@ static int sctp_add_outgoing_streams_request_parameter_to_string( u16 number_of_new_streams; length = ntohs(parameter->length); + if (length != sizeof(struct sctp_add_outgoing_streams_request_parameter)) { + fputs("invalid ADD_OUTGOING_STREAMS_REQUEST parameter", s); + asprintf(error, "ADD_OUTGOING_STREAMS_REQUEST parameter illegal (length=%u)", + length); + return STATUS_ERR; + } reqsn = ntohl(parameter->reqsn); number_of_new_streams = ntohs(parameter->number_of_new_streams); @@ -452,6 +482,12 @@ static int sctp_add_incoming_streams_request_parameter_to_string( u16 number_of_new_streams; length = ntohs(parameter->length); + if (length != sizeof(struct sctp_add_incoming_streams_request_parameter)) { + fputs("invalid ADD_INCOMING_STREAMS_REQUEST parameter", s); + asprintf(error, "ADD_INCOMING_STREAMS_REQUEST parameter illegal (length=%u)", + length); + return STATUS_ERR; + } reqsn = ntohl(parameter->reqsn); number_of_new_streams = ntohs(parameter->number_of_new_streams); @@ -1554,12 +1590,15 @@ static int sctp_reconfig_chunk_to_string( char **error) { u16 length; - int result, parameters_length; + int result = STATUS_OK; + int parameters_length; struct sctp_parameter *parameter; struct sctp_parameters_iterator iter; length = ntohs(chunk->length); - if (length < sizeof(struct sctp_reconfig_chunk)) { + if (length < sizeof(struct sctp_reconfig_chunk) || + (length > sizeof(struct sctp_reconfig_chunk) && + length < sizeof(struct sctp_reconfig_chunk) + 4)) { asprintf(error, "RECONFIG chunk too short (length=%u)", length); return STATUS_ERR; } @@ -1567,21 +1606,23 @@ static int sctp_reconfig_chunk_to_string( fputs("RECONFIG[", s); fprintf(s, "flgs=0x%02x, ", chunk->flags); fprintf(s, "len=%u", length); - - for (parameter = sctp_parameters_begin(chunk->parameter, - parameters_length, - &iter, error); - parameter != NULL; - parameter = sctp_parameters_next(&iter, error)) { - fputs(", ", s); - if (*error != NULL) - break; - result = sctp_parameter_to_string(s, parameter, error); - if (result != STATUS_OK) - break; + + if (length >= sizeof(struct sctp_reconfig_chunk) + 4) { + for (parameter = sctp_parameters_begin(chunk->parameter, + parameters_length, + &iter, error); + parameter != NULL; + parameter = sctp_parameters_next(&iter, error)) { + fputs(", ", s); + if (*error != NULL) + break; + result = sctp_parameter_to_string(s, parameter, error); + if (result != STATUS_OK) + break; + } } fputs("]", s); - return STATUS_OK; + return result; } static int sctp_unknown_chunk_to_string(FILE *s,