QuicDispatcher discards packets with known version but invalid destination connection ID.

Protected by FLAGS_quic_reloadable_flag_quic_discard_packets_with_invalid_cid.

PiperOrigin-RevId: 371762573
Change-Id: Ie34e797be1c97d7fa38b5f68b56c1b5875e7d378
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc
index 1c9c763..ccf2c3f 100644
--- a/quic/core/quic_dispatcher.cc
+++ b/quic/core/quic_dispatcher.cc
@@ -502,6 +502,21 @@
     return true;
   }
 
+  if (GetQuicReloadableFlag(quic_discard_packets_with_invalid_cid)) {
+    QUIC_RELOADABLE_FLAG_COUNT(quic_discard_packets_with_invalid_cid);
+    if (packet_info.version_flag && packet_info.version.IsKnown() &&
+        !QuicUtils::IsConnectionIdLengthValidForVersion(
+            server_connection_id.length(),
+            packet_info.version.transport_version)) {
+      QUIC_DLOG(INFO) << "Packet with destination connection ID "
+                      << server_connection_id << " is invalid with version "
+                      << packet_info.version;
+      // Drop the packet silently.
+      QUIC_CODE_COUNT(quic_dropped_invalid_initial_connection_id);
+      return true;
+    }
+  }
+
   // Packets with connection IDs for active connections are processed
   // immediately.
   auto it = reference_counted_session_map_.find(server_connection_id);
diff --git a/quic/core/quic_dispatcher_test.cc b/quic/core/quic_dispatcher_test.cc
index d113844..5a7a709 100644
--- a/quic/core/quic_dispatcher_test.cc
+++ b/quic/core/quic_dispatcher_test.cc
@@ -167,6 +167,7 @@
 
   std::string custom_packet_context_;
 
+  using QuicDispatcher::MaybeDispatchPacket;
   using QuicDispatcher::SetAllowShortInitialServerConnectionIds;
   using QuicDispatcher::writer;
 
@@ -1101,6 +1102,31 @@
   ProcessFirstFlight(client_address, EmptyQuicConnectionId());
 }
 
+TEST_P(QuicDispatcherTestAllVersions,
+       DropPacketWithKnownVersionAndInvalidInitialConnectionId) {
+  SetQuicReloadableFlag(quic_discard_packets_with_invalid_cid, true);
+  CreateTimeWaitListManager();
+
+  QuicSocketAddress server_address;
+  QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
+
+  // dispatcher_ should drop this packet with invalid connection ID.
+  EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
+  EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _, _))
+      .Times(0);
+  EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _))
+      .Times(0);
+  absl::string_view cid_str = "123456789abcdefg123456789abcdefg";
+  QuicConnectionId invalid_connection_id(cid_str.data(), cid_str.length());
+  QuicReceivedPacket packet("packet", 6, QuicTime::Zero());
+  ReceivedPacketInfo packet_info(server_address, client_address, packet);
+  packet_info.version_flag = true;
+  packet_info.version = version_;
+  packet_info.destination_connection_id = invalid_connection_id;
+
+  ASSERT_TRUE(dispatcher_->MaybeDispatchPacket(packet_info));
+}
+
 void QuicDispatcherTestBase::
     TestVersionNegotiationForUnknownVersionInvalidShortInitialConnectionId(
         const QuicConnectionId& server_connection_id,
diff --git a/quic/core/quic_flags_list.h b/quic/core/quic_flags_list.h
index 023e6a4..b5b0abe 100644
--- a/quic/core/quic_flags_list.h
+++ b/quic/core/quic_flags_list.h
@@ -33,6 +33,7 @@
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_q050, false)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_t051, false)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_discard_initial_packet_with_key_dropped, true)
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_discard_packets_with_invalid_cid, false)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_donot_pto_half_rtt_data, false)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_donot_reset_ideal_next_packet_send_time, false)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_donot_write_mid_packet_processing, true)