From 74cc1a5b735f61a4a5f36cbb471c67cf3267d32d Mon Sep 17 00:00:00 2001 From: Anthony <41394064+anrossi@users.noreply.github.com> Date: Thu, 16 Jan 2020 14:08:52 -0800 Subject: [PATCH] Add test cases for QuicDrill Initial Packet fuzzing (#44) These test cases cover fuzzing the Connection ID (CID) in the initial packet, as well the optional Token field. Changes are passing in both TAEF and gtest. --- test/MsQuicTests.h | 32 ++- test/bin/quic_gtest.cpp | 33 +++ test/bin/quic_gtest.h | 52 +++++ test/lib/DrillDescriptor.cpp | 71 ++++-- test/lib/DrillDescriptor.h | 25 ++- test/lib/QuicDrill.cpp | 414 +++++++++++++++++++++++++++++++++++ test/lib/TestListener.cpp | 15 ++ test/lib/TestListener.h | 1 + 8 files changed, 619 insertions(+), 24 deletions(-) diff --git a/test/MsQuicTests.h b/test/MsQuicTests.h index 685ee7ee3..eecccafb2 100644 --- a/test/MsQuicTests.h +++ b/test/MsQuicTests.h @@ -219,6 +219,20 @@ void QuicDrillTestVarIntEncoder( ); +void +QuicDrillTestInitialCid( + _In_ int Family, + _In_ bool Source, // or Dest + _In_ bool ValidActualLength, // or invalid + _In_ bool Short, // or long + _In_ bool ValidLengthField // or invalid + ); + +void +QuicDrillTestInitialToken( + _In_ int Family + ); + // // Platform Specific Functions // @@ -470,6 +484,22 @@ typedef struct { #define IOCTL_QUIC_RUN_DRILL_ENCODE_VAR_INT \ QUIC_CTL_CODE(35, METHOD_BUFFERED, FILE_WRITE_DATA) -#define QUIC_MAX_IOCTL_FUNC_CODE 35 +typedef struct { + INT32 Family; + BOOLEAN SourceOrDest; + BOOLEAN ActualCidLengthValid; + BOOLEAN ShortCidLength; + BOOLEAN CidLengthFieldValid; +} QUIC_RUN_DRILL_INITIAL_PACKET_CID_PARAMS; + +#define IOCTL_QUIC_RUN_DRILL_INITIAL_PACKET_CID \ + QUIC_CTL_CODE(36, METHOD_BUFFERED, FILE_WRITE_DATA) + // QUIC_RUN_DRILL_INITIAL_PACKET_CID_PARAMS + +#define IOCTL_QUIC_RUN_DRILL_INITIAL_PACKET_TOKEN \ + QUIC_CTL_CODE(37, METHOD_BUFFERED, FILE_WRITE_DATA) + // INT32 - Family + +#define QUIC_MAX_IOCTL_FUNC_CODE 37 #endif // _WIN32 \ No newline at end of file diff --git a/test/bin/quic_gtest.cpp b/test/bin/quic_gtest.cpp index beaddd6b8..600afad44 100644 --- a/test/bin/quic_gtest.cpp +++ b/test/bin/quic_gtest.cpp @@ -19,8 +19,13 @@ QUIC_SEC_CONFIG* SecurityConfig; extern "C" _IRQL_requires_max_(PASSIVE_LEVEL) void QuicTraceRundown(void) { } class QuicTestEnvironment : public ::testing::Environment { + bool PlatformInitialized; public: void SetUp() override { + if (QUIC_FAILED(QuicPlatformInitialize())) { + return; // TODO - FAIL SetUp + } + PlatformInitialized = true; if (QUIC_FAILED(MsQuicOpenV1(&MsQuic))) { return; // TODO - FAIL SetUp } @@ -51,6 +56,9 @@ public: Registration = nullptr; MsQuicClose(MsQuic); MsQuic = nullptr; + if (PlatformInitialized) { + QuicPlatformUninitialize(); + } } _Function_class_(QUIC_SEC_CONFIG_CREATE_COMPLETE) static void @@ -419,6 +427,21 @@ TEST_P(WithReceiveResumeNoDataArgs, ReceiveResumeNoData) { QuicTestReceiveResumeNoData(GetParam().Family, GetParam().ShutdownType); } +TEST_P(WithDrillInitialPacketCidArgs, DrillInitialPacketCids) { + TestLoggerT Logger("QuicDrillInitialPacketCids", GetParam()); + QuicDrillTestInitialCid( + GetParam().Family, + GetParam().SourceOrDest, + GetParam().ActualCidLengthValid, + GetParam().ShortCidLength, + GetParam().CidLengthFieldValid); +} + +TEST_P(WithDrillInitialPacketTokenArgs, DrillInitialPacketToken) { + TestLoggerT Logger("QuicDrillInitialPacketToken", GetParam()); + QuicDrillTestInitialToken(GetParam().Family); +} + INSTANTIATE_TEST_CASE_P( ParameterValidation, WithBool, @@ -479,6 +502,16 @@ INSTANTIATE_TEST_CASE_P( WithReceiveResumeNoDataArgs, testing::ValuesIn(ReceiveResumeNoDataArgs::Generate())); +INSTANTIATE_TEST_CASE_P( + Drill, + WithDrillInitialPacketCidArgs, + testing::ValuesIn(DrillInitialPacketCidArgs::Generate())); + +INSTANTIATE_TEST_CASE_P( + Drill, + WithDrillInitialPacketTokenArgs, + testing::ValuesIn(DrillInitialPacketTokenArgs::Generate())); + int main(int argc, char** argv) { ::testing::AddGlobalTestEnvironment(new QuicTestEnvironment); ::testing::InitGoogleTest(&argc, argv); diff --git a/test/bin/quic_gtest.h b/test/bin/quic_gtest.h index a6eabf5b2..3d69e5374 100644 --- a/test/bin/quic_gtest.h +++ b/test/bin/quic_gtest.h @@ -318,3 +318,55 @@ std::ostream& operator << (std::ostream& o, const ReceiveResumeNoDataArgs& args) class WithReceiveResumeNoDataArgs : public testing::Test, public testing::WithParamInterface { }; + +struct DrillInitialPacketCidArgs { + int Family; + bool SourceOrDest; + bool ActualCidLengthValid; + bool ShortCidLength; + bool CidLengthFieldValid; + + static ::std::vector Generate() { + ::std::vector list; + for (int Family : { 4, 6 }) + for (bool SourceOrDest : { true, false }) + for (bool ActualCidLengthValid : { true, false }) + for (bool ShortCidLength : { true, false }) + for (bool CidLengthFieldValid : { true, false }) + list.push_back({ Family, SourceOrDest, ActualCidLengthValid, ShortCidLength, CidLengthFieldValid }); + return list; + } +}; + +std::ostream& operator << (std::ostream& o, const DrillInitialPacketCidArgs& args) { + return o << + (args.Family == 4 ? "v4" : "v6") << "/" << + (args.SourceOrDest ? "SourceCid" : "DestCid") << "/" << + (args.ActualCidLengthValid ? "Valid" : "Invalid") << "/" << + (args.ShortCidLength ? "Short" : "Long") << "/" << + (args.CidLengthFieldValid ? "Valid" : "Invalid") << " length"; +} + +class WithDrillInitialPacketCidArgs: public testing::Test, + public testing::WithParamInterface { +}; + +struct DrillInitialPacketTokenArgs { + int Family; + + static ::std::vector Generate() { + ::std::vector list; + for (int Family : { 4, 6 }) + list.push_back({ Family, }); + return list; + } +}; + +std::ostream& operator << (std::ostream& o, const DrillInitialPacketTokenArgs& args) { + return o << + (args.Family == 4 ? "v4" : "v6"); +} + +class WithDrillInitialPacketTokenArgs: public testing::Test, + public testing::WithParamInterface { +}; diff --git a/test/lib/DrillDescriptor.cpp b/test/lib/DrillDescriptor.cpp index 0d6e289a6..06c585963 100644 --- a/test/lib/DrillDescriptor.cpp +++ b/test/lib/DrillDescriptor.cpp @@ -9,23 +9,28 @@ DrillBuffer QuicDrillEncodeQuicVarInt( - uint64_t input + uint64_t input, + const DrillVarIntSize size ) { DrillBuffer result; uint8_t* inputPointer = ((uint8_t*)&input); - if (input < 0x40) { + if (size == OneByte) { + QUIC_FRE_ASSERT(input < 0x40); result.push_back((uint8_t) input); - } else if (input < 0x4000) { + } else if (size == TwoBytes) { + QUIC_FRE_ASSERT(input < 0x4000); result.push_back(0x40 | inputPointer[1]); result.push_back(inputPointer[0]); - } else if (input < 0x40000000) { + } else if (size == FourBytes) { + QUIC_FRE_ASSERT(input < 0x40000000); result.push_back(0x80 | inputPointer[3]); result.push_back(inputPointer[2]); result.push_back(inputPointer[1]); result.push_back(inputPointer[0]); - } else if (input < 0x4000000000000000ull) { + } else if (size == EightBytes) { + QUIC_FRE_ASSERT(input < 0x4000000000000000ull); result.push_back(0xc0 | inputPointer[7]); result.push_back(inputPointer[6]); result.push_back(inputPointer[5]); @@ -36,15 +41,37 @@ QuicDrillEncodeQuicVarInt( result.push_back(inputPointer[0]); } else { QUIC_FRE_ASSERTMSG( - input < 0x4000000000000000ull, - "Supplied value is larger than QUIC_VAR_INT allowed (2^62)"); + size == EightBytes, + "Supplied size is not a valid QUIC_VAR_INT size"); } return result; } DrillBuffer -DrillPacketDescriptor::write( +QuicDrillEncodeQuicVarInt ( + uint64_t input ) +{ + if (input < 0x40) { + return QuicDrillEncodeQuicVarInt(input, OneByte); + } else if (input < 0x4000) { + return QuicDrillEncodeQuicVarInt(input, TwoBytes); + } else if (input < 0x40000000) { + return QuicDrillEncodeQuicVarInt(input, FourBytes); + } else if (input < 0x4000000000000000ull) { + return QuicDrillEncodeQuicVarInt(input, EightBytes); + } else { + QUIC_FRE_ASSERTMSG( + input < 0x4000000000000000ull, + "Supplied value is larger than QUIC_VAR_INT allowed (2^62)"); + return DrillBuffer(); + } + return DrillBuffer(); +} + +DrillBuffer +DrillPacketDescriptor::write( + ) const { size_t RequiredSize = 0; @@ -52,11 +79,11 @@ DrillPacketDescriptor::write( // Calculate the size required to write the packet. // RequiredSize += 1; // For the bit fields. - RequiredSize += sizeof(this->Version); + RequiredSize += sizeof(Version); RequiredSize += 1; // For the size of DestCid. - RequiredSize += this->DestCid.size(); + RequiredSize += DestCid.size(); RequiredSize += 1; // For the size of SourceCid. - RequiredSize += this->SourceCid.size(); + RequiredSize += SourceCid.size(); QUIC_FRE_ASSERTMSG( RequiredSize <= UINT16_MAX, @@ -77,8 +104,8 @@ DrillPacketDescriptor::write( // // Copy version. // - for (int i = 0; i < sizeof(this->Version); ++i) { - PacketBuffer.push_back((uint8_t) (Version >> ((3 - i) * 8))); + for (int i = 0; i < sizeof(Version); ++i) { + PacketBuffer.push_back((uint8_t) (Version >> (((sizeof(Version) - 1) - i) * 8))); } // @@ -109,17 +136,23 @@ DrillPacketDescriptor::write( } DrillInitialPacketDescriptor::DrillInitialPacketDescriptor( - ) + ) : DrillPacketDescriptor(), TokenLen(nullptr), PacketLength(nullptr), PacketNumber(0) { - this->Type = Initial; - this->Header.LongHeader = 1; - this->Header.FixedBit = 1; - this->Version = 1; + Type = Initial; + Header.LongHeader = 1; + Header.FixedBit = 1; + Version = QUIC_VERSION_LATEST_H; + + const uint8_t CidValMax = 8; + for (uint8_t CidVal = 0; CidVal <= CidValMax; CidVal++) { + DestCid.push_back(CidVal); + SourceCid.push_back(CidValMax - CidVal); + } } DrillBuffer DrillInitialPacketDescriptor::write( - ) + ) const { DrillBuffer PacketBuffer = DrillPacketDescriptor::write(); diff --git a/test/lib/DrillDescriptor.h b/test/lib/DrillDescriptor.h index 81ebcff76..a697cfc17 100644 --- a/test/lib/DrillDescriptor.h +++ b/test/lib/DrillDescriptor.h @@ -18,7 +18,9 @@ class DrillBuffer : public Rtl::KArray QUIC_FRE_ASSERT(append(value)); } - size_t size() { return count(); } + const uint8_t* data() const { return &(*this)[0]; } + + size_t size() const { return count(); } void insert( @@ -80,10 +82,12 @@ struct DrillPacketDescriptor { uint8_t* SourceCidLen; DrillBuffer SourceCid; + DrillPacketDescriptor() : SourceCidLen(nullptr), DestCidLen(nullptr) {}; + // // Write this descriptor to a byte array to send on the wire. // - virtual DrillBuffer write(); + virtual DrillBuffer write() const; }; @@ -117,10 +121,23 @@ struct DrillInitialPacketDescriptor : DrillPacketDescriptor { // // Write this descriptor to a byte array to send on the wire. // - virtual DrillBuffer write(); + virtual DrillBuffer write() const; +}; + +enum DrillVarIntSize { + OneByte = 1, + TwoBytes = 2, + FourBytes = 4, + EightBytes = 8 }; DrillBuffer QuicDrillEncodeQuicVarInt ( + const uint64_t input, + const DrillVarIntSize size + ); + +DrillBuffer +QuicDrillEncodeQuicVarInt( uint64_t input - ); \ No newline at end of file + ); diff --git a/test/lib/QuicDrill.cpp b/test/lib/QuicDrill.cpp index f7316ec9a..3d1717454 100644 --- a/test/lib/QuicDrill.cpp +++ b/test/lib/QuicDrill.cpp @@ -7,9 +7,18 @@ Abstract: MsQuic Packet-level tests. +Future: + Additional test cases to implement: + * Test packet number encoded larger than necessary with valid Initial + packet. + * Test reserved header flags, and packet number size mismatch. + --*/ #include "precomp.h" +extern "C" { +#include +} void QuicDrillTestVarIntEncoder( @@ -56,4 +65,409 @@ QuicDrillTestVarIntEncoder( TEST_EQUAL(output[5], 0xff); TEST_EQUAL(output[6], 0xff); TEST_EQUAL(output[7], 0xff); +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +_Function_class_(NEW_CONNECTION_CALLBACK) +static +void +QuicDrillConnectionCallbackHandler( + _In_ TestListener* /* Listener */, + _In_ HQUIC ConnectionHandle + ) +{ + TEST_FAILURE("Quic Drill listener received an unexpected event!"); + MsQuic->ConnectionClose(ConnectionHandle); +} + +struct DrillSender { + QUIC_DATAPATH* Datapath; + QUIC_DATAPATH_BINDING* Binding; + QUIC_ADDR ServerAddress; + + _IRQL_requires_max_(DISPATCH_LEVEL) + _Function_class_(QUIC_DATAPATH_RECEIVE_CALLBACK) + static void + DrillUdpRecvCallback( + _In_ QUIC_DATAPATH_BINDING* /* Binding */, + _In_ void* /* Context */, + _In_ QUIC_RECV_DATAGRAM* RecvBufferChain + ) + { + QuicDataPathBindingReturnRecvDatagrams(RecvBufferChain); + } + + _IRQL_requires_max_(DISPATCH_LEVEL) + _Function_class_(QUIC_DATAPATH_UNREACHABLE_CALLBACK) + static void + DrillUdpUnreachCallback( + _In_ QUIC_DATAPATH_BINDING* /* Binding */, + _In_ void* /* Context */, + _In_ const QUIC_ADDR* /* RemoteAddress */ + ) + { + } + + DrillSender() : Datapath(nullptr), Binding(nullptr) {} + + ~DrillSender() { + if (Binding != nullptr) { + QuicDataPathBindingDelete(Binding); + } + + if (Datapath != nullptr) { + QuicDataPathUninitialize(Datapath); + } + } + + QUIC_STATUS + Initialize( + _In_ const char* HostName, + _In_ QUIC_ADDRESS_FAMILY Family, + _In_ uint16_t NetworkPort + ) + { + QUIC_ADDR ServerAddress; + QUIC_STATUS Status = + QuicDataPathInitialize( + 0, + DrillUdpRecvCallback, + DrillUdpUnreachCallback, + &Datapath); + if (QUIC_FAILED(Status)) { + TEST_FAILURE("Datapath init failed 0x%x", Status); + return Status; + } + + ServerAddress.si_family = Family; + + Status = + QuicDataPathResolveAddress( + Datapath, + HostName, + &ServerAddress); + if (QUIC_FAILED(Status)) { + TEST_FAILURE("Address resolution failed 0x%x", Status); + return Status; + } + + if (Family == AF_INET) { + ServerAddress.Ipv4.sin_port = NetworkPort; + } else { + ServerAddress.Ipv6.sin6_port = NetworkPort; + } + + Status = + QuicDataPathBindingCreate( + Datapath, + nullptr, + &ServerAddress, + this, + &Binding); + if (QUIC_FAILED(Status)) { + TEST_FAILURE("Binding failed: 0x%x", Status); + } + return Status; + } + + QUIC_STATUS + Send( + _In_ const DrillBuffer* PacketBuffer + ) + { + QUIC_STATUS Status = QUIC_STATUS_SUCCESS; + QUIC_FRE_ASSERT(PacketBuffer->size() <= UINT16_MAX); + const uint16_t DatagramLength = (uint16_t) PacketBuffer->size(); + + QUIC_DATAPATH_SEND_CONTEXT* SendContext = + QuicDataPathBindingAllocSendContext(Binding, DatagramLength); + + QUIC_BUFFER* SendBuffer = + QuicDataPathBindingAllocSendDatagram(SendContext, DatagramLength); + + if (SendBuffer == nullptr) { + TEST_FAILURE("Buffer null"); + Status = QUIC_STATUS_OUT_OF_MEMORY; + return Status; + } + + // Copy test packet into SendBuffer. + memcpy(SendBuffer->Buffer, PacketBuffer->data(), DatagramLength); + + QuicDataPathBindingSendTo( + Binding, + &ServerAddress, + SendContext); + + return Status; + } + + +}; + +bool +QuicDrillInitialPacketFailureTest( + _In_ QUIC_ADDRESS_FAMILY QuicAddrFamily, + _In_ const DrillInitialPacketDescriptor& InitialPacketDescriptor + ) +{ + QUIC_STATUS Status; + QUIC_LISTENER_STATISTICS Stats; + uint64_t DroppedPacketsBefore; + uint64_t DroppedPacketsAfter; + uint8_t Disabled = FALSE; + + QuicAddr ServerAddress(QuicAddrFamily); + MsQuicRegistration QuicDrillRegistration; + if (!QuicDrillRegistration.IsValid()) { + TEST_FAILURE("QuicDrillRegistration not valid!"); + return false; + } + DrillSender Sender; + + Status = + MsQuic->SetParam( + QuicDrillRegistration, + QUIC_PARAM_LEVEL_REGISTRATION, + QUIC_PARAM_REGISTRATION_ENCRYPTION, + sizeof(Disabled), + &Disabled); + if (QUIC_FAILED(Status)) { + TEST_FAILURE("Failed to disable encryption for test. 0x%x", Status); + return false; + } + + MsQuicSession Session(QuicDrillRegistration); + if (!Session.IsValid()) { + TEST_FAILURE("Session not valid!"); + return false; + } + + { + // + // Start the server. + // + TestListener Listener(Session.Handle, QuicDrillConnectionCallbackHandler); + + Status = Listener.Start(&ServerAddress.SockAddr); + if (QUIC_FAILED(Status)) { + TEST_FAILURE("ListenerStart failed, 0x%x.", Status); + return false; + } + + // + // Get server address (port) here. + // + Status = Listener.GetLocalAddr(ServerAddress); + if (QUIC_FAILED(Status)) { + TEST_FAILURE("MsQuic->GetParam failed, 0x%x.", Status); + return false; + } + + Status = + Sender.Initialize( + QUIC_LOCALHOST_FOR_AF(QuicAddrFamily), + QuicAddrFamily, + (QuicAddrFamily == AF_INET) ? + ServerAddress.SockAddr.Ipv4.sin_port : + ServerAddress.SockAddr.Ipv6.sin6_port); + if (QUIC_FAILED(Status)) { + return false; + } + + DrillBuffer PacketBuffer = InitialPacketDescriptor.write(); + + Status = Listener.GetStatistics(Stats); + if (QUIC_FAILED(Status)) { + TEST_FAILURE("Get Listener statistics before test failed, 0x%x.", Status); + return false; + } + DroppedPacketsBefore = Stats.Binding.Recv.DroppedPackets; + + // + // Send test packet to the server. + // + Status = Sender.Send(&PacketBuffer); + if (QUIC_FAILED(Status)) { + return false; + } + + // + // Generously wait for server to process packet. + // + QuicSleep(100); + + Status = Listener.GetStatistics(Stats); + if (QUIC_FAILED(Status)) { + TEST_FAILURE("Get Listener statistics after test failed, 0x%x.", Status); + return false; + } + DroppedPacketsAfter = Stats.Binding.Recv.DroppedPackets; + + // + // Validate the server rejected the packet just sent. + // N.B. Could fail if the server has other packets sent to it accidentally. + // + if (DroppedPacketsAfter - DroppedPacketsBefore != 1) { + TEST_FAILURE("DroppedPacketsAfter - DroppedPacketsBefore not equal to 1"); + return false; + } + } + return true; +} + +#define VALID_CID_LENGTH_SHORT 8 +#define VALID_CID_LENGTH_LONG 20 +#define INVALID_CID_LENGTH_SHORT 7 +#define INVALID_CID_LENGTH_LONG 21 + +void +QuicDrillTestInitialCid( + _In_ int Family, + _In_ bool Source, // or Dest + _In_ bool ValidActualLength, // or invalid + _In_ bool Short, // or long + _In_ bool ValidLengthField // or invalid + ) +{ +/** + * SourceCid valid length, but longer than valid length field indicates. + * SourceCid valid length, but shorter than valid length field indicates. + * SourceCid valid length, but shorter than invalid length field. + * SourceCid valid length, but longer than invalid length field. + * SourceCid invalidly short, but length field indicates valid length. + * SourceCid invalidly long, but length field indicates valid length. + * SourceCid invalidly short, and length field matches. + * SourceCid invalidly long, and length field matches. + * (Ditto for DestCid) + + (source, dest), [(valid length, invalid length), (valid length field, invalid length field)], (short, long) + +*/ + + uint8_t ActualCidLength; + uint8_t CidLengthField; + + QUIC_ADDRESS_FAMILY QuicAddrFamily = (Family == 4) ? AF_INET : AF_INET6; + DrillInitialPacketDescriptor InitialDescriptor; + + // Calculate the test parameters + if (ValidActualLength) { + if (Short) { + ActualCidLength = VALID_CID_LENGTH_SHORT; + } else { + ActualCidLength = VALID_CID_LENGTH_LONG; + } + + if (ValidLengthField) { + // When both lengths are valid, we want to make the field different + // than the actual length so they don't agree. + if (!Short) { + CidLengthField = VALID_CID_LENGTH_SHORT; + } else { + CidLengthField = VALID_CID_LENGTH_LONG; + } + } else { + // When the length field is invalid, but the actual length valid, + // we want to make the length field very invalid. + if (!Short) { + CidLengthField = INVALID_CID_LENGTH_SHORT; + } else { + CidLengthField = INVALID_CID_LENGTH_LONG; + } + } + } else { + if (Short) { + ActualCidLength = INVALID_CID_LENGTH_SHORT; + } else { + ActualCidLength = INVALID_CID_LENGTH_LONG; + } + + if (ValidLengthField) { + // When the actual length is invalid, but the length field valid, + // make the field the closest valid value. + if (Short) { + CidLengthField = VALID_CID_LENGTH_SHORT; + } else { + CidLengthField = VALID_CID_LENGTH_LONG; + } + } else { + // When both length field and actual length are invalid, make the + // values agree. + if (Short) { + CidLengthField = INVALID_CID_LENGTH_SHORT; + } else { + CidLengthField = INVALID_CID_LENGTH_LONG; + } + } + } + + DrillBuffer TestCid; + for (int value = 0; value < ActualCidLength; value++) { + TestCid.push_back(0xff - (uint8_t) value); // Make this Cid look different from the default one. + } + + if (Source) { + InitialDescriptor.SourceCid.clear(); + InitialDescriptor.SourceCid.insert(InitialDescriptor.SourceCid.begin(), TestCid.begin(), TestCid.end()); + InitialDescriptor.SourceCidLen = &CidLengthField; + } else { + InitialDescriptor.DestCid.clear(); + InitialDescriptor.DestCid.insert(InitialDescriptor.DestCid.begin(), TestCid.begin(), TestCid.end()); + InitialDescriptor.DestCidLen = &CidLengthField; + } + + QuicDrillInitialPacketFailureTest(QuicAddrFamily, InitialDescriptor); +} + +void +QuicDrillTestInitialToken( + _In_ int Family + ) +{ + QUIC_ADDRESS_FAMILY QuicAddrFamily = (Family == 4) ? AF_INET : AF_INET6; + const uint8_t GeneratedTokenLength = 20; + uint64_t TokenLen; + + // Token length is larger than actual token. + { + DrillInitialPacketDescriptor InitialDescriptor; + + for (uint8_t TokenValue = 0; TokenValue < GeneratedTokenLength; TokenValue++) { + InitialDescriptor.Token.push_back(TokenValue); + } + TokenLen = GeneratedTokenLength + 1; + InitialDescriptor.TokenLen = &TokenLen; + + if (!QuicDrillInitialPacketFailureTest(QuicAddrFamily, InitialDescriptor)) { + return; + } + } + + // Token length is shorter than actual token. + { + DrillInitialPacketDescriptor InitialDescriptor; + + for (uint8_t TokenValue = 0; TokenValue < GeneratedTokenLength; TokenValue++) { + InitialDescriptor.Token.push_back(TokenValue); + } + TokenLen = GeneratedTokenLength - 1; + InitialDescriptor.TokenLen = &TokenLen; + + if (!QuicDrillInitialPacketFailureTest(QuicAddrFamily, InitialDescriptor)) { + return; + } + } + + // Token length is non-zero and token is not present. + { + DrillInitialPacketDescriptor InitialDescriptor; + + TokenLen = 1; + InitialDescriptor.TokenLen = &TokenLen; + + if (!QuicDrillInitialPacketFailureTest(QuicAddrFamily, InitialDescriptor)) { + return; + } + } } \ No newline at end of file diff --git a/test/lib/TestListener.cpp b/test/lib/TestListener.cpp index ceda6e68c..cf7e021b1 100644 --- a/test/lib/TestListener.cpp +++ b/test/lib/TestListener.cpp @@ -78,6 +78,21 @@ TestListener::GetLocalAddr( &localAddr.SockAddr); } +QUIC_STATUS +TestListener::GetStatistics( + _Out_ QUIC_LISTENER_STATISTICS &stats + ) +{ + uint32_t Size = sizeof(stats); + return + MsQuic->GetParam( + QuicListener, + QUIC_PARAM_LEVEL_LISTENER, + QUIC_PARAM_LISTENER_STATS, + &Size, + &stats); +} + QUIC_STATUS TestListener::HandleListenerEvent( _Inout_ QUIC_LISTENER_EVENT* Event diff --git a/test/lib/TestListener.h b/test/lib/TestListener.h index 2864d0bfe..65254fde9 100644 --- a/test/lib/TestListener.h +++ b/test/lib/TestListener.h @@ -92,4 +92,5 @@ public: // QUIC_STATUS GetLocalAddr(_Out_ QuicAddr &localAddr); + QUIC_STATUS GetStatistics(_Out_ QUIC_LISTENER_STATISTICS &stats); };