diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l index d08de406abf29e75d688d980ae48386a0358d02d..5ad8469738501d5cc0e150ea61e5605dff2b6d4d 100644 --- a/gtests/net/packetdrill/lexer.l +++ b/gtests/net/packetdrill/lexer.l @@ -572,6 +572,7 @@ SSN_TSN_RESET return SSN_TSN_RESET; RECONFIG_RESPONSE return RECONFIG_RESPONSE; ADD_OUTGOING_STREAMS return ADD_OUTGOING_STREAMS; ADD_INCOMING_STREAMS return ADD_INCOMING_STREAMS; +RECONFIG_REQUEST_GENERIC return RECONFIG_REQUEST_GENERIC; req_sn return REQ_SN; resp_sn return RESP_SN; last_tsn return LAST_TSN; diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index 8fc4ff21c6a17c58fea7acd92946352fec23cf54..ecb74c63b45917a779c0e47f583cb8ec877f2c97 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -528,7 +528,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %token <reserved> OUTGOING_SSN_RESET REQ_SN RESP_SN LAST_TSN SIDS INCOMING_SSN_RESET %token <reserved> RECONFIG_RESPONSE RESULT SENDER_NEXT_TSN RECEIVER_NEXT_TSN %token <reserved> SSN_TSN_RESET ADD_INCOMING_STREAMS NUMBER_OF_NEW_STREAMS -%token <reserved> ADD_OUTGOING_STREAMS +%token <reserved> ADD_OUTGOING_STREAMS RECONFIG_REQUEST_GENERIC %token <reserved> ADDR INCR TYPES PARAMS %token <reserved> IPV4_TYPE IPV6_TYPE HOSTNAME_TYPE %token <reserved> CAUSE @@ -690,7 +690,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <parameter_list_item> sctp_adaptation_indication_parameter_spec %type <parameter_list_item> sctp_pad_parameter_spec sctp_reconfig_parameter_spec %type <parameter_list_item> outgoing_ssn_reset_request incoming_ssn_reset_request -%type <parameter_list_item> reconfig_response ssn_tsn_reset_request +%type <parameter_list_item> reconfig_response ssn_tsn_reset_request generic_reconfig_request %type <parameter_list_item> add_outgoing_streams_request add_incoming_streams_request %type <cause_list> opt_cause_list_spec sctp_cause_list_spec %type <cause_list_item> sctp_cause_spec @@ -1752,6 +1752,7 @@ sctp_reconfig_parameter_spec | reconfig_response { $$ = $1; } | add_outgoing_streams_request { $$ = $1; } | add_incoming_streams_request { $$ = $1; } +| generic_reconfig_request { $$ = $1; } ; opt_sender_next_tsn @@ -1761,6 +1762,12 @@ opt_sender_next_tsn } $$ = $3; } +| SENDER_NEXT_TSN '=' HEX_INTEGER { + if (!is_valid_u32($3)) { + semantic_error("sender_next_tsn out of range"); + } + $$ = $3; +} | SENDER_NEXT_TSN '=' ELLIPSIS { $$ = -1; } ; @@ -1771,6 +1778,12 @@ opt_receiver_next_tsn } $$ = $3; } +| RECEIVER_NEXT_TSN '=' HEX_INTEGER { + if (!is_valid_u32($3)) { + semantic_error("receiver_next_tsn out of range"); + } + $$ = $3; +} | RECEIVER_NEXT_TSN '=' ELLIPSIS { $$ = -1; } ; @@ -1829,10 +1842,19 @@ add_incoming_streams_request } ; +generic_reconfig_request +: RECONFIG_REQUEST_GENERIC '[' opt_parameter_type ',' opt_len ',' opt_req_sn ',' opt_val ']' { + $$ = sctp_generic_reconfig_request_parameter_new($3, $5, $7, $9); +} +; + sctp_reconfig_chunk_spec : RECONFIG '[' opt_flags ',' sctp_reconfig_parameter_list_spec ']' { $$ = sctp_reconfig_chunk_new($3, $5); } +| RECONFIG '[' opt_flags ']' { + $$ = sctp_reconfig_chunk_new($3, NULL); +} ; opt_parameter_list_spec @@ -5151,6 +5173,9 @@ srs_flags $$ = new_expression(EXPR_WORD); $$->value.string = $3; } +| SRS_FLAGS '=' binary_expression { + $$ = $3; +} ; sctp_reset_streams @@ -5304,6 +5329,12 @@ assocreset_local_tsn } $$ = new_integer_expression($3, "%u"); } +| ASSOCRESET_LOCAL_TSN '=' HEX_INTEGER { + if (!is_valid_u32($3)) { + semantic_error("assocreset_local_tsn out of range"); + } + $$ = new_integer_expression($3, "%u"); +} | ASSOCRESET_LOCAL_TSN '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } ; @@ -5314,6 +5345,12 @@ assocreset_remote_tsn } $$ = new_integer_expression($3, "%u"); } +| ASSOCRESET_REMOTE_TSN '=' HEX_INTEGER { + if (!is_valid_u32($3)) { + semantic_error("assocreset_remote_tsn out of range"); + } + $$ = new_integer_expression($3, "%u"); +} | ASSOCRESET_REMOTE_TSN '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } ; diff --git a/gtests/net/packetdrill/run_packet.c b/gtests/net/packetdrill/run_packet.c index e93c4dca40aff5c80b4ca2abcdbc53cd332026b7..0df2fc2e0c27796bbfe02de963b676b1ae4ea4e3 100644 --- a/gtests/net/packetdrill/run_packet.c +++ b/gtests/net/packetdrill/run_packet.c @@ -774,7 +774,7 @@ static int map_inbound_sctp_packet( struct sctp_reconfig_response_parameter *response; response = (struct sctp_reconfig_response_parameter *)parameter; response->respsn = htonl(htonl(response->respsn) + local_diff); - if (response->length == sizeof(struct sctp_reconfig_response_parameter)) { + if (htons(response->length) == sizeof(struct sctp_reconfig_response_parameter)) { response->receiver_next_tsn = htonl(htonl(response->receiver_next_tsn) + local_diff); response->sender_next_tsn = htonl(htonl(response->sender_next_tsn) + remote_diff); } @@ -1029,9 +1029,9 @@ static int map_outbound_live_sctp_packet( struct sctp_reconfig_response_parameter *response; response = (struct sctp_reconfig_response_parameter *)parameter; response->respsn = htonl(htonl(response->respsn) + remote_diff); - if (response->length == sizeof(struct sctp_reconfig_response_parameter)) { - response->receiver_next_tsn = htonl(htonl(response->receiver_next_tsn) + local_diff); - response->sender_next_tsn = htonl(htonl(response->sender_next_tsn) + remote_diff); + if (htons(response->length) == sizeof(struct sctp_reconfig_response_parameter)) { + response->receiver_next_tsn = htonl(htonl(response->receiver_next_tsn) + remote_diff); + response->sender_next_tsn = htonl(htonl(response->sender_next_tsn) + local_diff); } break; } @@ -1460,7 +1460,7 @@ static int verify_sctp_parameters(u8 *begin, u16 length, error))) { return STATUS_ERR; } - if (live_resp->length == sizeof(struct sctp_reconfig_response_parameter)) { + if (ntohs(live_resp->length) == sizeof(struct sctp_reconfig_response_parameter)) { if ((flags & FLAG_RECONFIG_SENDER_NEXT_TSN_NOCHECK ? STATUS_OK : check_field("ssn_tsn_reset_request_parameter.sender_next_tsn", ntohl(script_resp->sender_next_tsn), diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c index 3e1ff0638432e0c72d49bf62bf0288a5e20775c1..072dc959d4ed27c3d130874485c3a94a4a2360e0 100644 --- a/gtests/net/packetdrill/run_system_call.c +++ b/gtests/net/packetdrill/run_system_call.c @@ -56,7 +56,7 @@ struct sctp_tlv { }; #endif #if defined(__FreeBSD__) || defined(linux) -static int check_sctp_notification(struct iovec *iov, struct expression *iovec_expr, +static int check_sctp_notification(struct socket *socket, struct iovec *iov, struct expression *iovec_expr, char **error); static int parse_expression_to_sctp_initmsg(struct expression *expr, struct sctp_initmsg *init, char **error); @@ -2217,7 +2217,8 @@ static int syscall_recvmsg(struct state *state, struct syscall_spec *syscall, } #if defined(__FreeBSD__) || defined(linux) if (msg->msg_flags & MSG_NOTIFICATION) { - if (check_sctp_notification(msg->msg_iov, msg_expression->value.msghdr->msg_iov, error)) + struct socket *socket = find_socket_by_script_fd(state, script_fd); + if (check_sctp_notification(socket, msg->msg_iov, msg_expression->value.msghdr->msg_iov, error)) goto error_out; } #endif @@ -5270,7 +5271,7 @@ static int check_sctp_stream_reset_event(struct sctp_stream_reset_event_expr *ex "sctp_stream_reset_event.strreset_assoc_id", error)) return STATUS_ERR; if (check_u16array_expr(expr->strreset_stream_list, sctp_stream_reset_event->strreset_stream_list, - sctp_stream_reset_event->strreset_length - sizeof(u16) - sizeof(u16) - sizeof(u32) - sizeof(sctp_assoc_t), + (sctp_stream_reset_event->strreset_length - sizeof(u16) - sizeof(u16) - sizeof(u32) - sizeof(sctp_assoc_t)) / sizeof(u16), "sctp_stream_reset_event.strreset_stream_list", error)) return STATUS_ERR; @@ -5279,9 +5280,16 @@ static int check_sctp_stream_reset_event(struct sctp_stream_reset_event_expr *ex #endif #if defined(__FreeBSD__) -static int check_sctp_assoc_reset_event(struct sctp_assoc_reset_event_expr *expr, +static int check_sctp_assoc_reset_event(struct socket *socket, struct sctp_assoc_reset_event_expr *expr, struct sctp_assoc_reset_event *sctp_assoc_reset_event, char **error) { + u32 local_diff = 0; + u32 remote_diff = 0; + + assert(socket != NULL); + local_diff = socket->live.local_initial_tsn - socket->script.local_initial_tsn; + remote_diff = socket->live.remote_initial_tsn - socket->script.remote_initial_tsn; + if (check_u16_expr(expr->assocreset_type, sctp_assoc_reset_event->assocreset_type, "sctp_assoc_reset_event.assocreset_type", error)) return STATUS_ERR; @@ -5294,10 +5302,10 @@ static int check_sctp_assoc_reset_event(struct sctp_assoc_reset_event_expr *expr if (check_sctp_assoc_t_expr(expr->assocreset_assoc_id, sctp_assoc_reset_event->assocreset_assoc_id, "sctp_assoc_reset_event.assocreset_assoc_id", error)) return STATUS_ERR; - if (check_u32_expr(expr->assocreset_local_tsn, sctp_assoc_reset_event->assocreset_local_tsn, + if (check_u32_expr(expr->assocreset_local_tsn, sctp_assoc_reset_event->assocreset_local_tsn - local_diff, "sctp_assoc_reset_event.assocreset_local_tsn", error)) return STATUS_ERR; - if (check_u32_expr(expr->assocreset_remote_tsn, sctp_assoc_reset_event->assocreset_remote_tsn, + if (check_u32_expr(expr->assocreset_remote_tsn, sctp_assoc_reset_event->assocreset_remote_tsn - remote_diff, "sctp_assoc_reset_event.assocreset_remote_tsn", error)) return STATUS_ERR; @@ -5333,7 +5341,8 @@ static int check_sctp_stream_change_event(struct sctp_stream_change_event_expr * #endif #if defined(__FreeBSD__) || defined(linux) -static int check_sctp_notification(struct iovec *iov, +static int check_sctp_notification(struct socket *socket, + struct iovec *iov, struct expression *iovec_expr, char **error) { struct expression_list *iovec_expr_list; @@ -5428,7 +5437,7 @@ static int check_sctp_notification(struct iovec *iov, #endif #if defined(__FreeBSD__) case EXPR_SCTP_ASSOC_RESET_EVENT: - if (check_sctp_assoc_reset_event(script_iov_base->value.sctp_assoc_reset_event, + if (check_sctp_assoc_reset_event(socket, script_iov_base->value.sctp_assoc_reset_event, (struct sctp_assoc_reset_event *) iov[i].iov_base, error)) return STATUS_ERR; @@ -5610,7 +5619,8 @@ static int syscall_sctp_recvv(struct state *state, struct syscall_spec *syscall, script_flags, flags); goto error_out; } else if (flags & MSG_NOTIFICATION) { - if (check_sctp_notification(iov, iovec_expr_list, error)) + struct socket *socket = find_socket_by_script_fd(state, script_fd); + if (check_sctp_notification(socket, iov, iovec_expr_list, error)) goto error_out; } } diff --git a/gtests/net/packetdrill/sctp.h b/gtests/net/packetdrill/sctp.h index badde3425886c0ce13f01fa1d9bbf36e84d542ea..0b95445b49bdb9ea78db841600e1e70a14199074 100644 --- a/gtests/net/packetdrill/sctp.h +++ b/gtests/net/packetdrill/sctp.h @@ -387,6 +387,13 @@ struct sctp_add_incoming_streams_request_parameter { __be16 reserved; } __packed; +struct sctp_reconfig_generic_request_parameter { + __be16 type; + __be16 length; + __be32 reqsn; + __u8 value[]; +} __packed; + #define SCTP_INVALID_STREAM_IDENTIFIER_CAUSE_CODE 0x0001 #define SCTP_MISSING_MANDATORY_PARAMETER_CAUSE_CODE 0x0002 #define SCTP_STALE_COOKIE_ERROR_CAUSE_CODE 0x0003 diff --git a/gtests/net/packetdrill/sctp_packet.c b/gtests/net/packetdrill/sctp_packet.c index 6e61ad52f0a3ce97225e087567d4209060240465..725d59ba4cb345b78711a541eadbf5f551612c15 100644 --- a/gtests/net/packetdrill/sctp_packet.c +++ b/gtests/net/packetdrill/sctp_packet.c @@ -1295,6 +1295,8 @@ sctp_reconfig_chunk_new(s64 flgs, struct sctp_parameter_list *parameters) chunk_length = (u16)sizeof(struct sctp_reconfig_chunk); if (parameters != NULL) { chunk_length += parameters->length; + } else { + parameters = sctp_parameter_list_new(); } padding_length = chunk_length % 4; if (padding_length > 0) { @@ -1311,8 +1313,8 @@ sctp_reconfig_chunk_new(s64 flgs, struct sctp_parameter_list *parameters) chunk->flags = (u8)flgs; } chunk->length = htons(chunk_length); - offset = 0; + for (item = parameters->first; item != NULL; item = item->next) { parameter_padding_length = item->length % 4; if (parameter_padding_length > 0) { @@ -1907,20 +1909,21 @@ sctp_reconfig_response_parameter_new(s64 respsn, s64 result, s64 sender_next_tsn } else { parameter->result = htonl((u32)result); } - if (receiver_next_tsn != -2 && sender_next_tsn != -2) { - if (sender_next_tsn == -1) { - flags |= FLAG_RECONFIG_SENDER_NEXT_TSN_NOCHECK; - parameter->sender_next_tsn = 0; - } else { - parameter->sender_next_tsn = htonl((u32)sender_next_tsn); - } - if (receiver_next_tsn == -1) { - flags |= FLAG_RECONFIG_RECEIVER_NEXT_TSN_NOCHECK; - parameter->receiver_next_tsn = 0; - } else { - parameter->receiver_next_tsn = htonl((u32)receiver_next_tsn); - } + + if (sender_next_tsn == -1) { + flags |= FLAG_RECONFIG_SENDER_NEXT_TSN_NOCHECK; + parameter->sender_next_tsn = 0; + } else if (sender_next_tsn != -2) { + parameter->sender_next_tsn = htonl((u32)sender_next_tsn); } + + if (receiver_next_tsn == -1) { + flags |= FLAG_RECONFIG_RECEIVER_NEXT_TSN_NOCHECK; + parameter->receiver_next_tsn = 0; + } else if (sender_next_tsn != -2) { + parameter->receiver_next_tsn = htonl((u32)receiver_next_tsn); + } + return sctp_parameter_list_item_new((struct sctp_parameter *)parameter, parameter_length, flags); } @@ -1973,7 +1976,7 @@ sctp_add_outgoing_streams_request_parameter_new(s64 reqsn, s32 number_of_new_str } else { parameter->reqsn = htonl((u32)reqsn); } - if (reqsn == -1) { + if (number_of_new_streams == -1) { flags |= FLAG_RECONFIG_NUMBER_OF_NEW_STREAMS_NOCHECK; parameter->number_of_new_streams = 0; } else { @@ -2006,7 +2009,7 @@ sctp_add_incoming_streams_request_parameter_new(s64 reqsn, s32 number_of_new_str } else { parameter->reqsn = htonl((u32)reqsn); } - if (reqsn == -1) { + if (number_of_new_streams == -1) { flags |= FLAG_RECONFIG_NUMBER_OF_NEW_STREAMS_NOCHECK; parameter->number_of_new_streams = 0; } else { @@ -2017,6 +2020,50 @@ sctp_add_incoming_streams_request_parameter_new(s64 reqsn, s32 number_of_new_str parameter_length, flags); } +struct sctp_parameter_list_item * +sctp_generic_reconfig_request_parameter_new(s32 type, s32 len, s64 reqsn, struct sctp_byte_list *payload) +{ + struct sctp_reconfig_generic_request_parameter *parameter; + struct sctp_byte_list_item *item; + u32 flags = 0; + u16 parameter_length; + u16 payload_len=0; + + if (payload != NULL) { + payload_len = payload->nr_entries; + } + parameter_length = sizeof(struct sctp_reconfig_generic_request_parameter) + payload_len; + + parameter = malloc(parameter_length); + assert(parameter != NULL); + + if (type == -1) { + parameter->type = 0; + } else { + parameter->type = htons((u16)type); + } + if (len == -1) { + parameter->length = 0; + } else { + parameter->length = htons((u16)len); + } + if (reqsn == -1) { + flags |= FLAG_RECONFIG_REQ_SN_NOCHECK; + parameter->reqsn = 0; + } else { + parameter->reqsn = htonl((u32)reqsn); + } + if (payload != NULL) { + int i = 0; + for (i = 0, item = payload->first; item != NULL; i++, item = item->next) { + parameter->value[i] = item->byte; + } + } + + return sctp_parameter_list_item_new((struct sctp_parameter *)parameter, + parameter_length, flags); +} + struct sctp_parameter_list_item * sctp_ecn_capable_parameter_new(void) { diff --git a/gtests/net/packetdrill/sctp_packet.h b/gtests/net/packetdrill/sctp_packet.h index 74f93229200f29b6656a768436551e0cb510ea95..7581f207e72d32e1df27900dd80f5416d09657b8 100644 --- a/gtests/net/packetdrill/sctp_packet.h +++ b/gtests/net/packetdrill/sctp_packet.h @@ -1,3 +1,4 @@ + /* * Copyright 2015 Michael Tuexen * @@ -404,6 +405,9 @@ sctp_add_outgoing_streams_request_parameter_new(s64 reqsn, s32 number_of_new_str struct sctp_parameter_list_item * sctp_add_incoming_streams_request_parameter_new(s64 reqsn, s32 number_of_new_streams); +struct sctp_parameter_list_item * +sctp_generic_reconfig_request_parameter_new(s32 type, s32 len, s64 reqsn, struct sctp_byte_list *payload); + struct sctp_parameter_list * sctp_parameter_list_new(void); diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/reset_ssn_tsn.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/reset_ssn_tsn.pkt index 2d38a7d3b1c801d1f258109f16ff9fe9f253229c..be613ee1d9df5844f8ceca40fa7208d28a8564ae 100644 --- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/reset_ssn_tsn.pkt +++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/reset_ssn_tsn.pkt @@ -27,7 +27,7 @@ +0.0 < sctp: SACK[flgs=0, cum_tsn=2, a_rwnd=1500, gaps=[], dups=[]] // Reset Stream 0 -+0.0 setsockopt(3, IPPROTO_SCTP, SCTP_RESET_ASSOC, [3], 12) = 0 ++0.0 setsockopt(3, IPPROTO_SCTP, SCTP_RESET_ASSOC, [3], 4) = 0 +0.0 > sctp: RECONFIG[flgs=0, SSN_TSN_RESET[req_sn=1]] +0.0 < sctp: RECONFIG[flgs=0, RECONFIG_RESPONSE[resp_sn=1, result=1]]