Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Address Discovery Support #4648

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion src/core/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -2263,7 +2263,8 @@ QuicConnGenerateLocalTransportParameters(
QUIC_TP_FLAG_MAX_UDP_PAYLOAD_SIZE |
QUIC_TP_FLAG_MAX_ACK_DELAY |
QUIC_TP_FLAG_MIN_ACK_DELAY |
QUIC_TP_FLAG_ACTIVE_CONNECTION_ID_LIMIT;
QUIC_TP_FLAG_ACTIVE_CONNECTION_ID_LIMIT |
QUIC_TP_FLAG_OBSERVED_ADDRESS;

if (Connection->Settings.IdleTimeoutMs != 0) {
LocalTP->Flags |= QUIC_TP_FLAG_IDLE_TIMEOUT;
Expand Down Expand Up @@ -2891,6 +2892,13 @@ QuicConnProcessPeerTransportParameters(
Connection->SourceCidLimit = QUIC_TP_ACTIVE_CONNECTION_ID_LIMIT_DEFAULT;
}

if (Connection->PeerTransportParams.Flags & QUIC_TP_FLAG_OBSERVED_ADDRESS) {
Connection->State.ObservedAddressNegotiated = TRUE;
QuicSendSetSendFlag(
&Connection->Send,
QUIC_CONN_SEND_FLAG_OBSERVED_ADDRESS);
}

if (!FromResumptionTicket) {
if (Connection->Settings.VersionNegotiationExtEnabled &&
Connection->PeerTransportParams.Flags & QUIC_TP_FLAG_VERSION_NEGOTIATION) {
Expand Down Expand Up @@ -5284,6 +5292,23 @@ QuicConnRecvFrames(
break;
}

case QUIC_FRAME_OBSERVED_ADDRESS_V4:
case QUIC_FRAME_OBSERVED_ADDRESS_V6: { // Always accept the frame, because we always enable support.
QUIC_OBSERVED_ADDRESS_EX Frame;
if (!QuicObservedAddressFrameDecode(FrameType, PayloadLength, Payload, &Offset, &Frame)) {
QuicTraceEvent(
ConnError,
"[conn][%p] ERROR, %s.",
Connection,
"Decoding OBSERVED_ADDRESS frame");
QuicConnTransportError(Connection, QUIC_ERROR_FRAME_ENCODING_ERROR);
return FALSE;
}

// TODO - Do something with this.
break;
}

default:
//
// No default case necessary, as we have already validated the frame
Expand Down Expand Up @@ -7342,6 +7367,13 @@ QuicConnApplyNewSettings(
QuicConnIndicateEvent(Connection, &Event);
}

if (QuicConnIsServer(Connection) && Connection->PeerTransportParams.Flags & QUIC_TP_FLAG_OBSERVED_ADDRESS) {
Connection->State.ObservedAddressNegotiated = TRUE;
QuicSendSetSendFlag(
&Connection->Send,
QUIC_CONN_SEND_FLAG_OBSERVED_ADDRESS);
}

if (Connection->Settings.EcnEnabled) {
QUIC_PATH* Path = &Connection->Paths[0];
Path->EcnValidationState = ECN_VALIDATION_TESTING;
Expand Down
10 changes: 10 additions & 0 deletions src/core/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,11 @@ typedef union QUIC_CONNECTION_STATE {
//
BOOLEAN TimestampRecvNegotiated : 1;

//
// Indicates that the peer supports the Observed Address feature.
//
BOOLEAN ObservedAddressNegotiated : 1;

//
// Indicates we received APPLICATION_ERROR transport error and are checking also
// later packets in case they contain CONNECTION_CLOSE frame with application-layer error.
Expand Down Expand Up @@ -467,6 +472,11 @@ typedef struct QUIC_CONNECTION {
//
QUIC_VAR_INT NextSourceCidSequenceNumber;

//
// The sequence number to use for sending a new observed address.
//
QUIC_VAR_INT ObservedAddressSequenceNumber;

//
// The most recent Retire Prior To field received in a NEW_CONNECTION_ID
// frame.
Expand Down
3 changes: 2 additions & 1 deletion src/core/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -2181,7 +2181,8 @@ QuicCryptoEncodeServerTicket(
QUIC_TP_FLAG_INITIAL_MAX_STRM_DATA_BIDI_REMOTE |
QUIC_TP_FLAG_INITIAL_MAX_STRM_DATA_UNI |
QUIC_TP_FLAG_INITIAL_MAX_STRMS_BIDI |
QUIC_TP_FLAG_INITIAL_MAX_STRMS_UNI);
QUIC_TP_FLAG_INITIAL_MAX_STRMS_UNI |
QUIC_TP_FLAG_OBSERVED_ADDRESS);

EncodedHSTP =
QuicCryptoTlsEncodeTransportParameters(
Expand Down
47 changes: 47 additions & 0 deletions src/core/crypto_tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ typedef enum eSniNameType {
#define QUIC_TP_ID_GREASE_QUIC_BIT 0x2AB2 // N/A
#define QUIC_TP_ID_RELIABLE_RESET_ENABLED 0x17f7586d2cb570 // varint
#define QUIC_TP_ID_ENABLE_TIMESTAMP 0x7158 // varint
#define QUIC_TP_ID_OBSERVED_ADDRESS 0x9f81a176 // varint

BOOLEAN
QuicTpIdIsReserved(
Expand Down Expand Up @@ -904,6 +905,12 @@ QuicCryptoTlsEncodeTransportParameters(
QUIC_TP_ID_ENABLE_TIMESTAMP,
QuicVarIntSize(value));
}
if (TransportParams->Flags & QUIC_TP_FLAG_OBSERVED_ADDRESS) {
RequiredTPLen +=
TlsTransportParamLength(
QUIC_TP_ID_OBSERVED_ADDRESS,
QuicVarIntSize(2)); // Hardcode for now
}
if (TestParam != NULL) {
RequiredTPLen +=
TlsTransportParamLength(
Expand Down Expand Up @@ -1246,6 +1253,18 @@ QuicCryptoTlsEncodeTransportParameters(
"TP: Timestamp (%u)",
value);
}
if (TransportParams->Flags & QUIC_TP_FLAG_OBSERVED_ADDRESS) {
TPBuf =
TlsWriteTransportParamVarInt(
QUIC_TP_ID_OBSERVED_ADDRESS,
2,
TPBuf);
QuicTraceLogConnVerbose(
EncodeTPObservedAddress,
Connection,
"TP: Observed Address (%u)",
2);
}
if (TestParam != NULL) {
TPBuf =
TlsWriteTransportParam(
Expand Down Expand Up @@ -1953,6 +1972,34 @@ QuicCryptoTlsDecodeTransportParameters( // NOLINT(readability-function-size, goo
break;
}

case QUIC_TP_ID_OBSERVED_ADDRESS: {
QUIC_VAR_INT value = 0;
if (!TRY_READ_VAR_INT(value)) {
QuicTraceEvent(
ConnErrorStatus,
"[conn][%p] ERROR, %u, %s.",
Connection,
Length,
"Invalid length of QUIC_TP_ID_OBSERVED_ADDRESS");
goto Exit;
}
if (value > 2) {
QuicTraceEvent(
ConnError,
"[conn][%p] ERROR, %s.",
Connection,
"Invalid value of QUIC_TP_ID_OBSERVED_ADDRESS");
goto Exit;
}
QuicTraceLogConnVerbose(
DecodeTPObservedAddress,
Connection,
"TP: Observed Address (%u)",
(uint32_t)value);
TransportParams->Flags |= QUIC_TP_FLAG_OBSERVED_ADDRESS; // TODO - Pass value?
break;
}

default:
if (QuicTpIdIsReserved(Id)) {
QuicTraceLogConnWarning(
Expand Down
142 changes: 130 additions & 12 deletions src/core/frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -1349,6 +1349,101 @@ QuicTimestampFrameDecode(
return TRUE;
}

_Success_(return != FALSE)
BOOLEAN
QuicObservedAddressFrameEncode(
_In_ const QUIC_OBSERVED_ADDRESS_EX * const Frame,
_Inout_ uint16_t* Offset,
_In_ uint16_t BufferLength,
_Out_writes_to_(BufferLength, *Offset)
uint8_t* Buffer
)
{
if (QuicAddrGetFamily(&Frame->Address) == QUIC_ADDRESS_FAMILY_INET) {
const uint16_t RequiredLength =
QuicVarIntSize(QUIC_FRAME_OBSERVED_ADDRESS_V4) +
QuicVarIntSize(Frame->SequenceNumber) +
sizeof(Frame->Address.Ipv4.sin_addr) +
sizeof(Frame->Address.Ipv4.sin_port);

if (BufferLength < *Offset + RequiredLength) {
return FALSE;
}

Buffer = Buffer + *Offset;
Buffer = QuicVarIntEncode(QUIC_FRAME_OBSERVED_ADDRESS_V4, Buffer);
Buffer = QuicVarIntEncode(Frame->SequenceNumber, Buffer);
CxPlatCopyMemory(Buffer, &Frame->Address.Ipv4.sin_addr, sizeof(Frame->Address.Ipv4.sin_addr));
Buffer += sizeof(Frame->Address.Ipv4.sin_addr);
CxPlatCopyMemory(Buffer, &Frame->Address.Ipv4.sin_port, sizeof(Frame->Address.Ipv4.sin_port));
Buffer += sizeof(Frame->Address.Ipv4.sin_port);
*Offset += RequiredLength;

} else {
const uint16_t RequiredLength =
QuicVarIntSize(QUIC_FRAME_OBSERVED_ADDRESS_V4) +
QuicVarIntSize(Frame->SequenceNumber) +
sizeof(Frame->Address.Ipv6.sin6_addr) +
sizeof(Frame->Address.Ipv6.sin6_port);

if (BufferLength < *Offset + RequiredLength) {
return FALSE;
}

Buffer = Buffer + *Offset;
Buffer = QuicVarIntEncode(QUIC_FRAME_OBSERVED_ADDRESS_V6, Buffer);
Buffer = QuicVarIntEncode(Frame->SequenceNumber, Buffer);
CxPlatCopyMemory(Buffer, &Frame->Address.Ipv6.sin6_addr, sizeof(Frame->Address.Ipv6.sin6_addr));
Buffer += sizeof(Frame->Address.Ipv6.sin6_addr);
CxPlatCopyMemory(Buffer, &Frame->Address.Ipv6.sin6_port, sizeof(Frame->Address.Ipv6.sin6_port));
Buffer += sizeof(Frame->Address.Ipv6.sin6_port);
*Offset += RequiredLength;
}

return TRUE;
}

_Success_(return != FALSE)
BOOLEAN
QuicObservedAddressFrameDecode(
_In_ QUIC_FRAME_TYPE FrameType,
_In_ uint16_t BufferLength,
_In_reads_bytes_(BufferLength)
const uint8_t * const Buffer,
_Inout_ uint16_t* Offset,
_Out_ QUIC_OBSERVED_ADDRESS_EX* Frame
)
{
if (!QuicVarIntDecode(BufferLength, Buffer, Offset, &Frame->SequenceNumber)) {
return FALSE;
}

if (FrameType == QUIC_FRAME_OBSERVED_ADDRESS_V4) {
if (BufferLength < *Offset + sizeof(Frame->Address.Ipv4)) {
return FALSE;
}
CxPlatZeroMemory(&Frame->Address.Ipv4, sizeof(Frame->Address.Ipv4));
Frame->Address.Ipv4.sin_family = QUIC_ADDRESS_FAMILY_INET6;
CxPlatCopyMemory(&Frame->Address.Ipv4.sin_addr, Buffer + *Offset, sizeof(Frame->Address.Ipv4.sin_addr));
*Offset += sizeof(Frame->Address.Ipv4.sin_addr);
CxPlatCopyMemory(&Frame->Address.Ipv4.sin_port, Buffer + *Offset, sizeof(Frame->Address.Ipv4.sin_port));
*Offset += sizeof(Frame->Address.Ipv4.sin_port);

} else {
if (BufferLength < *Offset + sizeof(Frame->Address.Ipv6)) {
return FALSE;
}
CxPlatZeroMemory(&Frame->Address.Ipv6, sizeof(Frame->Address.Ipv6));
Frame->Address.Ipv6.sin6_family = QUIC_ADDRESS_FAMILY_INET6;
CxPlatCopyMemory(&Frame->Address.Ipv6.sin6_addr, Buffer + *Offset, sizeof(Frame->Address.Ipv6.sin6_addr));
*Offset += sizeof(Frame->Address.Ipv6.sin6_addr);
CxPlatCopyMemory(&Frame->Address.Ipv6.sin6_port, Buffer + *Offset, sizeof(Frame->Address.Ipv6.sin6_port));
*Offset += sizeof(Frame->Address.Ipv6.sin6_port);
}

return TRUE;
}

_IRQL_requires_max_(DISPATCH_LEVEL)
BOOLEAN
QuicFrameLog(
Expand Down Expand Up @@ -1927,6 +2022,31 @@ QuicFrameLog(
break;
}

case QUIC_FRAME_RELIABLE_RESET_STREAM: {
QUIC_RELIABLE_RESET_STREAM_EX Frame;
if (!QuicReliableResetFrameDecode(PacketLength, Packet, Offset, &Frame)) {
QuicTraceLogVerbose(
FrameLogReliableResetStreamInvalid,
"[%c][%cX][%llu] RELIABLE_RESET_STREAM [Invalid]",
PtkConnPre(Connection),
PktRxPre(Rx),
PacketNumber);
return FALSE;
}

QuicTraceLogVerbose(
FrameLogReliableResetStream,
"[%c][%cX][%llu] RELIABLE_RESET_STREAM ID:%llu ErrorCode:0x%llX FinalSize:%llu ReliableSize:%llu",
PtkConnPre(Connection),
PktRxPre(Rx),
PacketNumber,
Frame.StreamID,
Frame.ErrorCode,
Frame.FinalSize,
Frame.ReliableSize);
break;
}

case QUIC_FRAME_DATAGRAM:
case QUIC_FRAME_DATAGRAM_1: {
QUIC_DATAGRAM_EX Frame;
Expand Down Expand Up @@ -2006,29 +2126,27 @@ QuicFrameLog(
Frame.Timestamp);
break;
}

case QUIC_FRAME_RELIABLE_RESET_STREAM: {
QUIC_RELIABLE_RESET_STREAM_EX Frame;
if (!QuicReliableResetFrameDecode(PacketLength, Packet, Offset, &Frame)) {

case QUIC_FRAME_OBSERVED_ADDRESS_V4:
case QUIC_FRAME_OBSERVED_ADDRESS_V6: {
QUIC_OBSERVED_ADDRESS_EX Frame;
if (!QuicObservedAddressFrameDecode(FrameType, PacketLength, Packet, Offset, &Frame)) {
QuicTraceLogVerbose(
FrameLogReliableResetStreamInvalid,
"[%c][%cX][%llu] RELIABLE_RESET_STREAM [Invalid]",
FrameLogObservedAddressInvalid,
"[%c][%cX][%llu] OBSERVED_ADDRESS [Invalid]",
PtkConnPre(Connection),
PktRxPre(Rx),
PacketNumber);
return FALSE;
}

QuicTraceLogVerbose(
FrameLogReliableResetStream,
"[%c][%cX][%llu] RELIABLE_RESET_STREAM ID:%llu ErrorCode:0x%llX FinalSize:%llu ReliableSize:%llu",
FrameLogObservedAddress,
"[%c][%cX][%llu] OBSERVED_ADDRESS %llu", // TODO - Address
PtkConnPre(Connection),
PktRxPre(Rx),
PacketNumber,
Frame.StreamID,
Frame.ErrorCode,
Frame.FinalSize,
Frame.ReliableSize);
Frame.SequenceNumber);
break;
}

Expand Down
Loading
Loading