--- /dev/null
+From 1b53515d53d303166b2bbd31e2cc7f16fd0aecd7 Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Fri, 26 Jan 2024 05:54:52 +0800
+Subject: [PATCH] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Patch
+
+REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4539
+
+Bug Details:
+PixieFail Bug #6
+CVE-2023-45234
+CVSS 8.3 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:H
+CWE-119 Improper Restriction of Operations within the Bounds of
+ a Memory Buffer
+
+Buffer overflow when processing DNS Servers option in a DHCPv6
+Advertise message
+
+Change Overview:
+
+Introduces a function to cache the Dns Server and perform sanitizing
+on the incoming DnsServerLen to ensure that the length is valid
+
+> + EFI_STATUS
+> + PxeBcCacheDnsServerAddresses (
+> + IN PXEBC_PRIVATE_DATA *Private,
+> + IN PXEBC_DHCP6_PACKET_CACHE *Cache6
+> + )
+
+Additional code cleanup
+
+Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
+Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>
+
+Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
+Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
+
+CVE: CVE-2023-45234
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/1b53515d53d303166b2bbd31e2cc7f16fd0aecd7]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c | 71 +++++++++++++++++++++++++---
+ 1 file changed, 65 insertions(+), 6 deletions(-)
+
+diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
+index 425e0cf806..2b2d372889 100644
+--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
+@@ -3,6 +3,7 @@
+ \r
+ (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
++ Copyright (c) Microsoft Corporation\r
+ \r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+ \r
+@@ -1312,6 +1313,65 @@ PxeBcSelectDhcp6Offer (
+ }\r
+ }\r
+ \r
++/**\r
++ Cache the DHCPv6 DNS Server addresses\r
++\r
++ @param[in] Private The pointer to PXEBC_PRIVATE_DATA.\r
++ @param[in] Cache6 The pointer to PXEBC_DHCP6_PACKET_CACHE.\r
++\r
++ @retval EFI_SUCCESS Cache the DHCPv6 DNS Server address successfully.\r
++ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
++ @retval EFI_DEVICE_ERROR The DNS Server Address Length provided by a untrusted\r
++ option is not a multiple of 16 bytes (sizeof (EFI_IPv6_ADDRESS)).\r
++**/\r
++EFI_STATUS\r
++PxeBcCacheDnsServerAddresses (\r
++ IN PXEBC_PRIVATE_DATA *Private,\r
++ IN PXEBC_DHCP6_PACKET_CACHE *Cache6\r
++ )\r
++{\r
++ UINT16 DnsServerLen;\r
++\r
++ DnsServerLen = NTOHS (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen);\r
++ //\r
++ // Make sure that the number is nonzero\r
++ //\r
++ if (DnsServerLen == 0) {\r
++ return EFI_DEVICE_ERROR;\r
++ }\r
++\r
++ //\r
++ // Make sure the DnsServerlen is a multiple of EFI_IPv6_ADDRESS (16)\r
++ //\r
++ if (DnsServerLen % sizeof (EFI_IPv6_ADDRESS) != 0) {\r
++ return EFI_DEVICE_ERROR;\r
++ }\r
++\r
++ //\r
++ // This code is currently written to only support a single DNS Server instead\r
++ // of multiple such as is spec defined (RFC3646, Section 3). The proper behavior\r
++ // would be to allocate the full space requested, CopyMem all of the data,\r
++ // and then add a DnsServerCount field to Private and update additional code\r
++ // that depends on this.\r
++ //\r
++ // To support multiple DNS servers the `AllocationSize` would need to be changed to DnsServerLen\r
++ //\r
++ // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886\r
++ //\r
++ Private->DnsServer = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS));\r
++ if (Private->DnsServer == NULL) {\r
++ return EFI_OUT_OF_RESOURCES;\r
++ }\r
++\r
++ //\r
++ // Intentionally only copy over the first server address.\r
++ // To support multiple DNS servers, the `Length` would need to be changed to DnsServerLen\r
++ //\r
++ CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS));\r
++\r
++ return EFI_SUCCESS;\r
++}\r
++\r
+ /**\r
+ Handle the DHCPv6 offer packet.\r
+ \r
+@@ -1335,6 +1395,7 @@ PxeBcHandleDhcp6Offer (
+ UINT32 SelectIndex;\r
+ UINT32 Index;\r
+ \r
++ ASSERT (Private != NULL);\r
+ ASSERT (Private->SelectIndex > 0);\r
+ SelectIndex = (UINT32)(Private->SelectIndex - 1);\r
+ ASSERT (SelectIndex < PXEBC_OFFER_MAX_NUM);\r
+@@ -1342,15 +1403,13 @@ PxeBcHandleDhcp6Offer (
+ Status = EFI_SUCCESS;\r
+ \r
+ //\r
+- // First try to cache DNS server address if DHCP6 offer provides.\r
++ // First try to cache DNS server addresses if DHCP6 offer provides.\r
+ //\r
+ if (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] != NULL) {\r
+- Private->DnsServer = AllocateZeroPool (NTOHS (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen));\r
+- if (Private->DnsServer == NULL) {\r
+- return EFI_OUT_OF_RESOURCES;\r
++ Status = PxeBcCacheDnsServerAddresses (Private, Cache6);\r
++ if (EFI_ERROR (Status)) {\r
++ return Status;\r
+ }\r
+-\r
+- CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS));\r
+ }\r
+ \r
+ if (Cache6->OfferType == PxeOfferTypeDhcpBinl) {\r
+--
+2.40.0
+
--- /dev/null
+From 458c582685fc0e8057d2511c5a0394078d988c17 Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Fri, 26 Jan 2024 05:54:53 +0800
+Subject: [PATCH] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Unit
+ Tests
+
+REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4539
+
+Unit tests to that the bug..
+
+Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise
+message
+
+..has been patched
+
+This contains tests for the following functions:
+PxeBcHandleDhcp6Offer
+PxeBcCacheDnsServerAddresses
+
+Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
+Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>
+
+Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
+Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
+
+CVE: CVE-2023-45234
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/458c582685fc0e8057d2511c5a0394078d988c17]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ .../GoogleTest/PxeBcDhcp6GoogleTest.cpp | 300 ++++++++++++++++++
+ .../GoogleTest/PxeBcDhcp6GoogleTest.h | 50 +++
+ .../GoogleTest/UefiPxeBcDxeGoogleTest.cpp | 19 ++
+ .../GoogleTest/UefiPxeBcDxeGoogleTest.inf | 48 +++
+ 4 files changed, 417 insertions(+)
+ create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
+ create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
+ create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp
+ create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
+
+diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
+new file mode 100644
+index 0000000000..8260eeee50
+--- /dev/null
++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
+@@ -0,0 +1,300 @@
++/** @file\r
++ Host based unit test for PxeBcDhcp6.c.\r
++\r
++ Copyright (c) Microsoft Corporation\r
++ SPDX-License-Identifier: BSD-2-Clause-Patent\r
++**/\r
++#include <gtest/gtest.h>\r
++\r
++extern "C" {\r
++ #include <Uefi.h>\r
++ #include <Library/BaseLib.h>\r
++ #include <Library/DebugLib.h>\r
++ #include "../PxeBcImpl.h"\r
++ #include "../PxeBcDhcp6.h"\r
++ #include "PxeBcDhcp6GoogleTest.h"\r
++}\r
++\r
++///////////////////////////////////////////////////////////////////////////////\r
++// Definitions\r
++///////////////////////////////////////////////////////////////////////////////\r
++\r
++#define PACKET_SIZE (1500)\r
++\r
++typedef struct {\r
++ UINT16 OptionCode; // The option code for DHCP6_OPT_SERVER_ID (e.g., 0x03)\r
++ UINT16 OptionLen; // The length of the option (e.g., 16 bytes)\r
++ UINT8 ServerId[16]; // The 16-byte DHCPv6 Server Identifier\r
++} DHCP6_OPTION_SERVER_ID;\r
++\r
++///////////////////////////////////////////////////////////////////////////////\r
++/// Symbol Definitions\r
++///////////////////////////////////////////////////////////////////////////////\r
++\r
++EFI_STATUS\r
++MockUdpWrite (\r
++ IN EFI_PXE_BASE_CODE_PROTOCOL *This,\r
++ IN UINT16 OpFlags,\r
++ IN EFI_IP_ADDRESS *DestIp,\r
++ IN EFI_PXE_BASE_CODE_UDP_PORT *DestPort,\r
++ IN EFI_IP_ADDRESS *GatewayIp OPTIONAL,\r
++ IN EFI_IP_ADDRESS *SrcIp OPTIONAL,\r
++ IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort OPTIONAL,\r
++ IN UINTN *HeaderSize OPTIONAL,\r
++ IN VOID *HeaderPtr OPTIONAL,\r
++ IN UINTN *BufferSize,\r
++ IN VOID *BufferPtr\r
++ )\r
++{\r
++ return EFI_SUCCESS;\r
++}\r
++\r
++EFI_STATUS\r
++MockUdpRead (\r
++ IN EFI_PXE_BASE_CODE_PROTOCOL *This,\r
++ IN UINT16 OpFlags,\r
++ IN OUT EFI_IP_ADDRESS *DestIp OPTIONAL,\r
++ IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort OPTIONAL,\r
++ IN OUT EFI_IP_ADDRESS *SrcIp OPTIONAL,\r
++ IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort OPTIONAL,\r
++ IN UINTN *HeaderSize OPTIONAL,\r
++ IN VOID *HeaderPtr OPTIONAL,\r
++ IN OUT UINTN *BufferSize,\r
++ IN VOID *BufferPtr\r
++ )\r
++{\r
++ return EFI_SUCCESS;\r
++}\r
++\r
++EFI_STATUS\r
++MockConfigure (\r
++ IN EFI_UDP6_PROTOCOL *This,\r
++ IN EFI_UDP6_CONFIG_DATA *UdpConfigData OPTIONAL\r
++ )\r
++{\r
++ return EFI_SUCCESS;\r
++}\r
++\r
++// Needed by PxeBcSupport\r
++EFI_STATUS\r
++EFIAPI\r
++QueueDpc (\r
++ IN EFI_TPL DpcTpl,\r
++ IN EFI_DPC_PROCEDURE DpcProcedure,\r
++ IN VOID *DpcContext OPTIONAL\r
++ )\r
++{\r
++ return EFI_SUCCESS;\r
++}\r
++\r
++///////////////////////////////////////////////////////////////////////////////\r
++// PxeBcHandleDhcp6OfferTest Tests\r
++///////////////////////////////////////////////////////////////////////////////\r
++\r
++class PxeBcHandleDhcp6OfferTest : public ::testing::Test {\r
++public:\r
++ PXEBC_PRIVATE_DATA Private = { 0 };\r
++ EFI_UDP6_PROTOCOL Udp6Read;\r
++ EFI_PXE_BASE_CODE_MODE Mode = { 0 };\r
++\r
++protected:\r
++ // Add any setup code if needed\r
++ virtual void\r
++ SetUp (\r
++ )\r
++ {\r
++ Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);\r
++\r
++ // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL\r
++ // The function under test really only needs the following:\r
++ // UdpWrite\r
++ // UdpRead\r
++\r
++ Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite;\r
++ Private.PxeBc.UdpRead = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead;\r
++\r
++ // Need to setup EFI_UDP6_PROTOCOL\r
++ // The function under test really only needs the following:\r
++ // Configure\r
++\r
++ Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure;\r
++ Private.Udp6Read = &Udp6Read;\r
++\r
++ // Need to setup the EFI_PXE_BASE_CODE_MODE\r
++ Private.PxeBc.Mode = &Mode;\r
++\r
++ // for this test it doesn't really matter what the Dhcpv6 ack is set to\r
++ }\r
++\r
++ // Add any cleanup code if needed\r
++ virtual void\r
++ TearDown (\r
++ )\r
++ {\r
++ if (Private.Dhcp6Request != NULL) {\r
++ FreePool (Private.Dhcp6Request);\r
++ }\r
++\r
++ // Clean up any resources or variables\r
++ }\r
++};\r
++\r
++// Note:\r
++// Testing PxeBcHandleDhcp6Offer() is difficult because it depends on a\r
++// properly setup Private structure. Attempting to properly test this function\r
++// without a signficant refactor is a fools errand. Instead, we will test\r
++// that we can prevent an overflow in the function.\r
++TEST_F (PxeBcHandleDhcp6OfferTest, BasicUsageTest) {\r
++ PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;\r
++ EFI_DHCP6_PACKET_OPTION Option = { 0 };\r
++\r
++ Private.SelectIndex = 1; // SelectIndex is 1-based\r
++ Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;\r
++\r
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;\r
++ // Setup the DHCPv6 offer packet\r
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;\r
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (1337);\r
++\r
++ ASSERT_EQ (PxeBcHandleDhcp6Offer (&(PxeBcHandleDhcp6OfferTest::Private)), EFI_DEVICE_ERROR);\r
++}\r
++\r
++class PxeBcCacheDnsServerAddressesTest : public ::testing::Test {\r
++public:\r
++ PXEBC_PRIVATE_DATA Private = { 0 };\r
++\r
++protected:\r
++ // Add any setup code if needed\r
++ virtual void\r
++ SetUp (\r
++ )\r
++ {\r
++ }\r
++\r
++ // Add any cleanup code if needed\r
++ virtual void\r
++ TearDown (\r
++ )\r
++ {\r
++ }\r
++};\r
++\r
++// Test Description\r
++// Test that we cache the DNS server address from the DHCPv6 offer packet\r
++TEST_F (PxeBcCacheDnsServerAddressesTest, BasicUsageTest) {\r
++ UINT8 SearchPattern[16] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF };\r
++ EFI_DHCP6_PACKET_OPTION *Option;\r
++ PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;\r
++\r
++ Option = (EFI_DHCP6_PACKET_OPTION *)AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + sizeof (SearchPattern));\r
++ ASSERT_NE (Option, nullptr);\r
++\r
++ Option->OpCode = DHCP6_OPT_SERVER_ID;\r
++ Option->OpLen = NTOHS (sizeof (SearchPattern));\r
++ CopyMem (Option->Data, SearchPattern, sizeof (SearchPattern));\r
++\r
++ Private.SelectIndex = 1; // SelectIndex is 1-based\r
++ Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;\r
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = Option;\r
++\r
++ Private.DnsServer = nullptr;\r
++\r
++ ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS);\r
++ ASSERT_NE (Private.DnsServer, nullptr);\r
++ ASSERT_EQ (CompareMem (Private.DnsServer, SearchPattern, sizeof (SearchPattern)), 0);\r
++\r
++ if (Private.DnsServer) {\r
++ FreePool (Private.DnsServer);\r
++ }\r
++\r
++ if (Option) {\r
++ FreePool (Option);\r
++ }\r
++}\r
++// Test Description\r
++// Test that we can prevent an overflow in the function\r
++TEST_F (PxeBcCacheDnsServerAddressesTest, AttemptOverflowTest) {\r
++ EFI_DHCP6_PACKET_OPTION Option = { 0 };\r
++ PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;\r
++\r
++ Private.SelectIndex = 1; // SelectIndex is 1-based\r
++ Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;\r
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;\r
++ // Setup the DHCPv6 offer packet\r
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;\r
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (1337);\r
++\r
++ Private.DnsServer = NULL;\r
++\r
++ ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);\r
++ ASSERT_EQ (Private.DnsServer, nullptr);\r
++\r
++ if (Private.DnsServer) {\r
++ FreePool (Private.DnsServer);\r
++ }\r
++}\r
++\r
++// Test Description\r
++// Test that we can prevent an underflow in the function\r
++TEST_F (PxeBcCacheDnsServerAddressesTest, AttemptUnderflowTest) {\r
++ EFI_DHCP6_PACKET_OPTION Option = { 0 };\r
++ PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;\r
++\r
++ Private.SelectIndex = 1; // SelectIndex is 1-based\r
++ Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;\r
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;\r
++ // Setup the DHCPv6 offer packet\r
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;\r
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (2);\r
++\r
++ Private.DnsServer = NULL;\r
++\r
++ ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);\r
++ ASSERT_EQ (Private.DnsServer, nullptr);\r
++\r
++ if (Private.DnsServer) {\r
++ FreePool (Private.DnsServer);\r
++ }\r
++}\r
++\r
++// Test Description\r
++// Test that we can handle recursive dns (multiple dns entries)\r
++TEST_F (PxeBcCacheDnsServerAddressesTest, MultipleDnsEntries) {\r
++ EFI_DHCP6_PACKET_OPTION Option = { 0 };\r
++ PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;\r
++\r
++ Private.SelectIndex = 1; // SelectIndex is 1-based\r
++ Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;\r
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;\r
++ // Setup the DHCPv6 offer packet\r
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;\r
++\r
++ EFI_IPv6_ADDRESS addresses[2] = {\r
++ // 2001:db8:85a3::8a2e:370:7334\r
++ { 0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34 },\r
++ // fe80::d478:91c3:ecd7:4ff9\r
++ { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x78, 0x91, 0xc3, 0xec, 0xd7, 0x4f, 0xf9 }\r
++ };\r
++\r
++ CopyMem (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, &addresses, sizeof (addresses));\r
++\r
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (sizeof (addresses));\r
++\r
++ Private.DnsServer = NULL;\r
++\r
++ ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS);\r
++\r
++ ASSERT_NE (Private.DnsServer, nullptr);\r
++\r
++ //\r
++ // This is expected to fail until DnsServer supports multiple DNS servers\r
++ //\r
++ // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886\r
++ //\r
++ // Disabling:\r
++ // ASSERT_EQ (CompareMem(Private.DnsServer, &addresses, sizeof(addresses)), 0);\r
++\r
++ if (Private.DnsServer) {\r
++ FreePool (Private.DnsServer);\r
++ }\r
++}\r
+diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
+new file mode 100644
+index 0000000000..b17c314791
+--- /dev/null
++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
+@@ -0,0 +1,50 @@
++/** @file\r
++ This file exposes the internal interfaces which may be unit tested\r
++ for the PxeBcDhcp6Dxe driver.\r
++\r
++ Copyright (c) Microsoft Corporation.<BR>\r
++ SPDX-License-Identifier: BSD-2-Clause-Patent\r
++**/\r
++\r
++#ifndef PXE_BC_DHCP6_GOOGLE_TEST_H_\r
++#define PXE_BC_DHCP6_GOOGLE_TEST_H_\r
++\r
++//\r
++// Minimal includes needed to compile\r
++//\r
++#include <Uefi.h>\r
++#include "../PxeBcImpl.h"\r
++\r
++/**\r
++ Handle the DHCPv6 offer packet.\r
++\r
++ @param[in] Private The pointer to PXEBC_PRIVATE_DATA.\r
++\r
++ @retval EFI_SUCCESS Handled the DHCPv6 offer packet successfully.\r
++ @retval EFI_NO_RESPONSE No response to the following request packet.\r
++ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
++ @retval EFI_BUFFER_TOO_SMALL Can't cache the offer pacet.\r
++\r
++**/\r
++EFI_STATUS\r
++PxeBcHandleDhcp6Offer (\r
++ IN PXEBC_PRIVATE_DATA *Private\r
++ );\r
++\r
++/**\r
++ Cache the DHCPv6 Server address\r
++\r
++ @param[in] Private The pointer to PXEBC_PRIVATE_DATA.\r
++ @param[in] Cache6 The pointer to PXEBC_DHCP6_PACKET_CACHE.\r
++\r
++ @retval EFI_SUCCESS Cache the DHCPv6 Server address successfully.\r
++ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
++ @retval EFI_DEVICE_ERROR Failed to cache the DHCPv6 Server address.\r
++**/\r
++EFI_STATUS\r
++PxeBcCacheDnsServerAddresses (\r
++ IN PXEBC_PRIVATE_DATA *Private,\r
++ IN PXEBC_DHCP6_PACKET_CACHE *Cache6\r
++ );\r
++\r
++#endif // PXE_BC_DHCP6_GOOGLE_TEST_H_\r
+diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp
+new file mode 100644
+index 0000000000..cc4fdf525b
+--- /dev/null
++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp
+@@ -0,0 +1,19 @@
++/** @file\r
++ Acts as the main entry point for the tests for the UefiPxeBcDxe module.\r
++ Copyright (c) Microsoft Corporation\r
++ SPDX-License-Identifier: BSD-2-Clause-Patent\r
++**/\r
++#include <gtest/gtest.h>\r
++\r
++////////////////////////////////////////////////////////////////////////////////\r
++// Run the tests\r
++////////////////////////////////////////////////////////////////////////////////\r
++int\r
++main (\r
++ int argc,\r
++ char *argv[]\r
++ )\r
++{\r
++ testing::InitGoogleTest (&argc, argv);\r
++ return RUN_ALL_TESTS ();\r
++}\r
+diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
+new file mode 100644
+index 0000000000..301dcdf611
+--- /dev/null
++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
+@@ -0,0 +1,48 @@
++## @file\r
++# Unit test suite for the UefiPxeBcDxe using Google Test\r
++#\r
++# Copyright (c) Microsoft Corporation.<BR>\r
++# SPDX-License-Identifier: BSD-2-Clause-Patent\r
++##\r
++[Defines]\r
++INF_VERSION = 0x00010005\r
++BASE_NAME = UefiPxeBcDxeGoogleTest\r
++FILE_GUID = 77D45C64-EC1E-4174-887B-886E89FD1EDF\r
++MODULE_TYPE = HOST_APPLICATION\r
++VERSION_STRING = 1.0\r
++\r
++#\r
++# The following information is for reference only and not required by the build tools.\r
++#\r
++# VALID_ARCHITECTURES = IA32 X64\r
++#\r
++\r
++[Sources]\r
++ UefiPxeBcDxeGoogleTest.cpp\r
++ PxeBcDhcp6GoogleTest.cpp\r
++ PxeBcDhcp6GoogleTest.h\r
++ ../PxeBcDhcp6.c\r
++ ../PxeBcSupport.c\r
++\r
++[Packages]\r
++ MdePkg/MdePkg.dec\r
++ MdeModulePkg/MdeModulePkg.dec\r
++ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec\r
++ NetworkPkg/NetworkPkg.dec\r
++\r
++[LibraryClasses]\r
++ GoogleTestLib\r
++ DebugLib\r
++ NetLib\r
++ PcdLib\r
++\r
++[Protocols]\r
++ gEfiDhcp6ServiceBindingProtocolGuid\r
++ gEfiDns6ServiceBindingProtocolGuid\r
++ gEfiDns6ProtocolGuid\r
++\r
++[Pcd]\r
++ gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType\r
++\r
++[Guids]\r
++ gZeroGuid\r
+--
+2.40.0
+