Mandatory Connection-ID Transport Parameter Absence Uses the Wrong Close Code
Summary
RFC 9000 requires a TRANSPORT_PARAMETER_ERROR when a peer omits a mandatory connection-ID transport parameter. This applies when initial_source_connection_id is absent from either endpoint, and when a client receives server transport parameters without original_destination_connection_id.
quiche detects these missing parameters, but the failure path closes the connection with IETF_QUIC_PROTOCOL_VIOLATION. For IETF QUIC, that maps to the wire transport error PROTOCOL_VIOLATION, not TRANSPORT_PARAMETER_ERROR.
Standard Requirement
An endpoint MUST treat the absence of the initial_source_connection_id
transport parameter from either endpoint or the absence of the
original_destination_connection_id transport parameter from the server as a
connection error of type TRANSPORT_PARAMETER_ERROR.
TRANSPORT_PARAMETER_ERROR (0x08):
An endpoint received transport parameters that were badly formatted, included
an invalid value, omitted a mandatory transport parameter, included a forbidden
transport parameter, or were otherwise in error.
The standard requires the specific transport error code TRANSPORT_PARAMETER_ERROR for the missing mandatory connection-ID parameters.
Relevant Source Code
Source: quiche-main/quiche-main/quiche/quic/core/quic_config.cc:1428-1434
1428: if (params.initial_source_connection_id.has_value()) {
1429: received_initial_source_connection_id_ =
1430: *params.initial_source_connection_id;
1431: }
1432: if (params.retry_source_connection_id.has_value()) {
1433: received_retry_source_connection_id_ = *params.retry_source_connection_id;
1434: }
quiche records initial_source_connection_id only if it is present.
Source: quiche-main/quiche-main/quiche/quic/core/quic_config.cc:1323-1325
1323: if (!is_resumption && params.original_destination_connection_id.has_value()) {
1324: received_original_destination_connection_id_ =
1325: *params.original_destination_connection_id;
quiche records original_destination_connection_id only if it is present.
Source: quiche-main/quiche-main/quiche/quic/core/quic_connection.cc:329-352
329: // Validate initial_source_connection_id.
330: QuicConnectionId expected_initial_source_connection_id;
331: if (perspective_ == Perspective::IS_CLIENT) {
332: expected_initial_source_connection_id = default_path_.server_connection_id;
333: } else {
334: expected_initial_source_connection_id = default_path_.client_connection_id;
335: }
336: if (!config.HasReceivedInitialSourceConnectionId() ||
337: config.ReceivedInitialSourceConnectionId() !=
338: expected_initial_source_connection_id) {
345: std::string error_details =
346: absl::StrCat("Bad initial_source_connection_id: expected ",
347: expected_initial_source_connection_id.ToString(),
348: ", received ", received_value);
349: CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION, error_details,
350: ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
351: return false;
352: }
The missing initial_source_connection_id branch closes with IETF_QUIC_PROTOCOL_VIOLATION.
Source: quiche-main/quiche-main/quiche/quic/core/quic_connection.cc:353-371
353: if (perspective_ == Perspective::IS_CLIENT) {
354: // Validate original_destination_connection_id.
355: if (!config.HasReceivedOriginalConnectionId() ||
356: config.ReceivedOriginalConnectionId() !=
357: GetOriginalDestinationConnectionId()) {
364: std::string error_details =
365: absl::StrCat("Bad original_destination_connection_id: expected ",
366: GetOriginalDestinationConnectionId().ToString(),
367: ", received ", received_value);
368: CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION, error_details,
369: ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
370: return false;
371: }
The missing server original_destination_connection_id branch also closes with IETF_QUIC_PROTOCOL_VIOLATION.
Source: quiche-main/quiche-main/quiche/quic/core/quic_error_codes.cc:578-579
578: case IETF_QUIC_PROTOCOL_VIOLATION:
579: return {true, static_cast<uint64_t>(PROTOCOL_VIOLATION)};
For IETF QUIC, IETF_QUIC_PROTOCOL_VIOLATION maps to the wire error PROTOCOL_VIOLATION.
Source: quiche-main/quiche-main/quiche/quic/core/frames/quic_connection_close_frame.cc:28-34
28: QuicErrorCodeToIetfMapping mapping =
29: QuicErrorCodeToTransportErrorCode(error_code);
30: if (ietf_error != NO_IETF_QUIC_ERROR) {
31: wire_error_code = ietf_error;
32: } else {
33: wire_error_code = mapping.error_code;
34: }
When no explicit IETF transport error override is supplied, the close frame uses the mapped wire error.
Implementation Behavior
quiche validates both mandatory connection-ID transport parameters after transport parameter processing. If either initial_source_connection_id is absent, or the client-side server original_destination_connection_id is absent, validation fails and the connection is closed.
The close code used by these branches is IETF_QUIC_PROTOCOL_VIOLATION, which becomes PROTOCOL_VIOLATION on the wire.
Inconsistency Reason
The standard requires TRANSPORT_PARAMETER_ERROR when a mandatory connection-ID transport parameter is absent. quiche instead sends PROTOCOL_VIOLATION for the missing-parameter branches.
This is a close-code mismatch: the connection is rejected, but the observable IETF transport error code does not match RFC 9000 Section 7.3.
Impact
The CID authentication check still prevents the connection from continuing with missing mandatory parameters. The interoperability issue is that peers and conformance tests observe PROTOCOL_VIOLATION instead of the required TRANSPORT_PARAMETER_ERROR.
Fix Direction
Separate missing-parameter checks from value-mismatch checks in ValidateConfigConnectionIds.
When initial_source_connection_id is absent, or when a client sees that server original_destination_connection_id is absent, close with an explicit IETF transport error of TRANSPORT_PARAMETER_ERROR.
Mandatory Connection-ID Transport Parameter Absence Uses the Wrong Close Code
Summary
RFC 9000 requires a
TRANSPORT_PARAMETER_ERRORwhen a peer omits a mandatory connection-ID transport parameter. This applies wheninitial_source_connection_idis absent from either endpoint, and when a client receives server transport parameters withoutoriginal_destination_connection_id.quiche detects these missing parameters, but the failure path closes the connection with
IETF_QUIC_PROTOCOL_VIOLATION. For IETF QUIC, that maps to the wire transport errorPROTOCOL_VIOLATION, notTRANSPORT_PARAMETER_ERROR.Standard Requirement
The standard requires the specific transport error code
TRANSPORT_PARAMETER_ERRORfor the missing mandatory connection-ID parameters.Relevant Source Code
Source:
quiche-main/quiche-main/quiche/quic/core/quic_config.cc:1428-1434quiche records
initial_source_connection_idonly if it is present.Source:
quiche-main/quiche-main/quiche/quic/core/quic_config.cc:1323-1325quiche records
original_destination_connection_idonly if it is present.Source:
quiche-main/quiche-main/quiche/quic/core/quic_connection.cc:329-352The missing
initial_source_connection_idbranch closes withIETF_QUIC_PROTOCOL_VIOLATION.Source:
quiche-main/quiche-main/quiche/quic/core/quic_connection.cc:353-371The missing server
original_destination_connection_idbranch also closes withIETF_QUIC_PROTOCOL_VIOLATION.Source:
quiche-main/quiche-main/quiche/quic/core/quic_error_codes.cc:578-579For IETF QUIC,
IETF_QUIC_PROTOCOL_VIOLATIONmaps to the wire errorPROTOCOL_VIOLATION.Source:
quiche-main/quiche-main/quiche/quic/core/frames/quic_connection_close_frame.cc:28-34When no explicit IETF transport error override is supplied, the close frame uses the mapped wire error.
Implementation Behavior
quiche validates both mandatory connection-ID transport parameters after transport parameter processing. If either
initial_source_connection_idis absent, or the client-side serveroriginal_destination_connection_idis absent, validation fails and the connection is closed.The close code used by these branches is
IETF_QUIC_PROTOCOL_VIOLATION, which becomesPROTOCOL_VIOLATIONon the wire.Inconsistency Reason
The standard requires
TRANSPORT_PARAMETER_ERRORwhen a mandatory connection-ID transport parameter is absent. quiche instead sendsPROTOCOL_VIOLATIONfor the missing-parameter branches.This is a close-code mismatch: the connection is rejected, but the observable IETF transport error code does not match RFC 9000 Section 7.3.
Impact
The CID authentication check still prevents the connection from continuing with missing mandatory parameters. The interoperability issue is that peers and conformance tests observe
PROTOCOL_VIOLATIONinstead of the requiredTRANSPORT_PARAMETER_ERROR.Fix Direction
Separate missing-parameter checks from value-mismatch checks in
ValidateConfigConnectionIds.When
initial_source_connection_idis absent, or when a client sees that serveroriginal_destination_connection_idis absent, close with an explicit IETF transport error ofTRANSPORT_PARAMETER_ERROR.