--- /dev/null
+/** @file\r
+Implementation of EFI_COMPONENT_NAME_PROTOCOL and EFI_COMPONENT_NAME2_PROTOCOL protocol.\r
+\r
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "DnsImpl.h"\r
+\r
+//\r
+// EFI Component Name Functions\r
+//\r
+/**\r
+ Retrieves a Unicode string that is the user-readable name of the EFI Driver.\r
+\r
+ @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.\r
+ @param Language A pointer to a three-character ISO 639-2 language identifier.\r
+ This is the language of the driver name that that the caller\r
+ is requesting, and it must match one of the languages specified\r
+ in SupportedLanguages. The number of languages supported by a\r
+ driver is up to the driver writer.\r
+ @param DriverName A pointer to the Unicode string to return. This Unicode string\r
+ is the name of the driver specified by This in the language\r
+ specified by Language.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This\r
+ and the language specified by Language was returned\r
+ in DriverName.\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the\r
+ language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DnsComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ );\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the controller\r
+ that is being managed by an EFI Driver.\r
+\r
+ @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.\r
+ @param ControllerHandle The handle of a controller that the driver specified by\r
+ This is managing. This handle specifies the controller\r
+ whose name is to be returned.\r
+ @param ChildHandle The handle of the child controller to retrieve the name\r
+ of. This is an optional parameter that may be NULL. It\r
+ will be NULL for device drivers. It will also be NULL\r
+ for a bus drivers that wish to retrieve the name of the\r
+ bus controller. It will not be NULL for a bus driver\r
+ that wishes to retrieve the name of a child controller.\r
+ @param Language A pointer to a three character ISO 639-2 language\r
+ identifier. This is the language of the controller name\r
+ that the caller is requesting, and it must match one\r
+ of the languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up to the\r
+ driver writer.\r
+ @param ControllerName A pointer to the Unicode string to return. This Unicode\r
+ string is the name of the controller specified by\r
+ ControllerHandle and ChildHandle in the language specified\r
+ by Language, from the point of view of the driver specified\r
+ by This.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the user-readable name in the\r
+ language specified by Language for the driver\r
+ specified by This was returned in DriverName.\r
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.\r
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently managing\r
+ the controller specified by ControllerHandle and\r
+ ChildHandle.\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the\r
+ language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DnsComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ );\r
+\r
+\r
+///\r
+/// Component Name Protocol instance\r
+///\r
+GLOBAL_REMOVE_IF_UNREFERENCED \r
+EFI_COMPONENT_NAME_PROTOCOL gDnsComponentName = {\r
+ DnsComponentNameGetDriverName,\r
+ DnsComponentNameGetControllerName,\r
+ "eng"\r
+};\r
+\r
+///\r
+/// Component Name 2 Protocol instance\r
+///\r
+GLOBAL_REMOVE_IF_UNREFERENCED \r
+EFI_COMPONENT_NAME2_PROTOCOL gDnsComponentName2 = {\r
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) DnsComponentNameGetDriverName,\r
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) DnsComponentNameGetControllerName,\r
+ "en"\r
+};\r
+\r
+///\r
+/// Table of driver names\r
+///\r
+GLOBAL_REMOVE_IF_UNREFERENCED \r
+EFI_UNICODE_STRING_TABLE mDnsDriverNameTable[] = {\r
+ { "eng;en", (CHAR16 *)L"DNS Network Service Driver" },\r
+ { NULL, NULL }\r
+};\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE *gDnsControllerNameTable = NULL;\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user-readable name of the EFI Driver.\r
+\r
+ @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.\r
+ @param Language A pointer to a three-character ISO 639-2 language identifier.\r
+ This is the language of the driver name that that the caller\r
+ is requesting, and it must match one of the languages specified\r
+ in SupportedLanguages. The number of languages supported by a\r
+ driver is up to the driver writer.\r
+ @param DriverName A pointer to the Unicode string to return. This Unicode string\r
+ is the name of the driver specified by This in the language\r
+ specified by Language.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This\r
+ and the language specified by Language was returned\r
+ in DriverName.\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the\r
+ language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DnsComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ )\r
+{\r
+ return LookupUnicodeString2 (\r
+ Language,\r
+ This->SupportedLanguages,\r
+ mDnsDriverNameTable,\r
+ DriverName,\r
+ (BOOLEAN)(This == &gDnsComponentName)\r
+ );\r
+}\r
+\r
+/**\r
+ Update the component name for the Dns4 child handle.\r
+\r
+ @param Dns4 A pointer to the EFI_DNS4_PROTOCOL.\r
+\r
+ \r
+ @retval EFI_SUCCESS Update the ControllerNameTable of this instance successfully.\r
+ @retval EFI_INVALID_PARAMETER The input parameter is invalid.\r
+ \r
+**/\r
+EFI_STATUS\r
+UpdateDns4Name (\r
+ EFI_DNS4_PROTOCOL *Dns4\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 HandleName[80];\r
+ EFI_DNS4_MODE_DATA ModeData;\r
+\r
+ if (Dns4 == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ //\r
+ // Format the child name into the string buffer as:\r
+ // DNSv4 (StationIp=?, LocalPort=?)\r
+ //\r
+ Status = Dns4->GetModeData (Dns4, &ModeData);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ UnicodeSPrint (\r
+ HandleName,\r
+ sizeof (HandleName),\r
+ L"DNSv4 (StationIp=%d.%d.%d.%d, LocalPort=%d)",\r
+ ModeData.DnsConfigData.StationIp.Addr[0],\r
+ ModeData.DnsConfigData.StationIp.Addr[1],\r
+ ModeData.DnsConfigData.StationIp.Addr[2],\r
+ ModeData.DnsConfigData.StationIp.Addr[3],\r
+ ModeData.DnsConfigData.LocalPort\r
+ );\r
+\r
+ if (gDnsControllerNameTable != NULL) {\r
+ FreeUnicodeStringTable (gDnsControllerNameTable);\r
+ gDnsControllerNameTable = NULL;\r
+ }\r
+ \r
+ Status = AddUnicodeString2 (\r
+ "eng",\r
+ gDnsComponentName.SupportedLanguages,\r
+ &gDnsControllerNameTable,\r
+ HandleName,\r
+ TRUE\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ return AddUnicodeString2 (\r
+ "en",\r
+ gDnsComponentName2.SupportedLanguages,\r
+ &gDnsControllerNameTable,\r
+ HandleName,\r
+ FALSE\r
+ );\r
+}\r
+\r
+/**\r
+ Update the component name for the Dns6 child handle.\r
+\r
+ @param Dns6 A pointer to the EFI_DNS6_PROTOCOL.\r
+\r
+ \r
+ @retval EFI_SUCCESS Update the ControllerNameTable of this instance successfully.\r
+ @retval EFI_INVALID_PARAMETER The input parameter is invalid.\r
+ \r
+**/\r
+EFI_STATUS\r
+UpdateDns6Name (\r
+ EFI_DNS6_PROTOCOL *Dns6\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 HandleName[128];\r
+ EFI_DNS6_MODE_DATA ModeData;\r
+ CHAR16 Address[sizeof"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"];\r
+\r
+ if (Dns6 == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ //\r
+ // Format the child name into the string buffer as:\r
+ // DNSv6 (StationIp=?, LocalPort=?)\r
+ //\r
+ Status = Dns6->GetModeData (Dns6, &ModeData);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = NetLibIp6ToStr (&ModeData.DnsConfigData.StationIp, Address, sizeof (Address));\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ UnicodeSPrint (\r
+ HandleName,\r
+ sizeof (HandleName), \r
+ L"DNSv6 (StationIp=%s, LocalPort=%d)",\r
+ Address,\r
+ ModeData.DnsConfigData.LocalPort\r
+ );\r
+\r
+ if (gDnsControllerNameTable != NULL) {\r
+ FreeUnicodeStringTable (gDnsControllerNameTable);\r
+ gDnsControllerNameTable = NULL;\r
+ }\r
+ \r
+ Status = AddUnicodeString2 (\r
+ "eng",\r
+ gDnsComponentName.SupportedLanguages,\r
+ &gDnsControllerNameTable,\r
+ HandleName,\r
+ TRUE\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ return AddUnicodeString2 (\r
+ "en",\r
+ gDnsComponentName2.SupportedLanguages,\r
+ &gDnsControllerNameTable,\r
+ HandleName,\r
+ FALSE\r
+ );\r
+}\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the controller\r
+ that is being managed by an EFI Driver.\r
+\r
+ @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.\r
+ @param ControllerHandle The handle of a controller that the driver specified by\r
+ This is managing. This handle specifies the controller\r
+ whose name is to be returned.\r
+ @param ChildHandle The handle of the child controller to retrieve the name\r
+ of. This is an optional parameter that may be NULL. It\r
+ will be NULL for device drivers. It will also be NULL\r
+ for a bus drivers that wish to retrieve the name of the\r
+ bus controller. It will not be NULL for a bus driver\r
+ that wishes to retrieve the name of a child controller.\r
+ @param Language A pointer to a three character ISO 639-2 language\r
+ identifier. This is the language of the controller name\r
+ that the caller is requesting, and it must match one\r
+ of the languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up to the\r
+ driver writer.\r
+ @param ControllerName A pointer to the Unicode string to return. This Unicode\r
+ string is the name of the controller specified by\r
+ ControllerHandle and ChildHandle in the language specified\r
+ by Language, from the point of view of the driver specified\r
+ by This.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the user-readable name in the\r
+ language specified by Language for the driver\r
+ specified by This was returned in DriverName.\r
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.\r
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently managing\r
+ the controller specified by ControllerHandle and\r
+ ChildHandle.\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the\r
+ language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DnsComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DNS4_PROTOCOL *Dns4;\r
+ EFI_DNS6_PROTOCOL *Dns6;\r
+ \r
+ //\r
+ // ChildHandle must be NULL for a Device Driver\r
+ //\r
+ if (ChildHandle == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Make sure this driver produced ChildHandle\r
+ //\r
+ Status = EfiTestChildHandle (\r
+ ControllerHandle,\r
+ ChildHandle,\r
+ &gEfiUdp6ProtocolGuid\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Retrieve an instance of a produced protocol from ChildHandle\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ChildHandle,\r
+ &gEfiDns6ProtocolGuid,\r
+ (VOID **)&Dns6,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Update the component name for this child handle.\r
+ //\r
+ Status = UpdateDns6Name (Dns6);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Make sure this driver produced ChildHandle\r
+ //\r
+ Status = EfiTestChildHandle (\r
+ ControllerHandle,\r
+ ChildHandle,\r
+ &gEfiUdp4ProtocolGuid\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Retrieve an instance of a produced protocol from ChildHandle\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ChildHandle,\r
+ &gEfiDns4ProtocolGuid,\r
+ (VOID **)&Dns4,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Update the component name for this child handle.\r
+ //\r
+ Status = UpdateDns4Name (Dns4);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return LookupUnicodeString2 (\r
+ Language,\r
+ This->SupportedLanguages,\r
+ gDnsControllerNameTable,\r
+ ControllerName,\r
+ (BOOLEAN)(This == &gDnsComponentName)\r
+ );\r
+}\r
--- /dev/null
+/** @file\r
+Functions implementation related with DHCPv4/v6 for DNS driver.\r
+\r
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+**/\r
+\r
+#include "DnsImpl.h"\r
+\r
+/**\r
+ This function initialize the DHCP4 message instance.\r
+\r
+ This function will pad each item of dhcp4 message packet.\r
+\r
+ @param Seed Pointer to the message instance of the DHCP4 packet.\r
+ @param InterfaceInfo Pointer to the EFI_IP4_CONFIG2_INTERFACE_INFO instance.\r
+\r
+**/\r
+VOID\r
+DnsInitSeedPacket (\r
+ OUT EFI_DHCP4_PACKET *Seed,\r
+ IN EFI_IP4_CONFIG2_INTERFACE_INFO *InterfaceInfo\r
+ )\r
+{\r
+ EFI_DHCP4_HEADER *Header;\r
+\r
+ //\r
+ // Get IfType and HwAddressSize from SNP mode data.\r
+ //\r
+ Seed->Size = sizeof (EFI_DHCP4_PACKET);\r
+ Seed->Length = sizeof (Seed->Dhcp4);\r
+ Header = &Seed->Dhcp4.Header;\r
+ ZeroMem (Header, sizeof (EFI_DHCP4_HEADER));\r
+ Header->OpCode = DHCP4_OPCODE_REQUEST;\r
+ Header->HwType = InterfaceInfo->IfType;\r
+ Header->HwAddrLen = (UINT8) InterfaceInfo->HwAddressSize;\r
+ CopyMem (Header->ClientHwAddr, &(InterfaceInfo->HwAddress), Header->HwAddrLen);\r
+\r
+ Seed->Dhcp4.Magik = DHCP4_MAGIC;\r
+ Seed->Dhcp4.Option[0] = DHCP4_TAG_EOP;\r
+}\r
+\r
+/**\r
+ The common notify function. \r
+\r
+ @param[in] Event The event signaled.\r
+ @param[in] Context The context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DhcpCommonNotify (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ if ((Event == NULL) || (Context == NULL)) {\r
+ return ;\r
+ }\r
+\r
+ *((BOOLEAN *) Context) = TRUE;\r
+}\r
+\r
+/**\r
+ Parse the ACK to get required information\r
+\r
+ @param Dhcp4 The DHCP4 protocol.\r
+ @param Packet Packet waiting for parse.\r
+ @param DnsServerInfor The required Dns4 server information.\r
+\r
+ @retval EFI_SUCCESS The DNS information is got from the DHCP ACK.\r
+ @retval EFI_NO_MAPPING DHCP failed to acquire address and other information.\r
+ @retval EFI_DEVICE_ERROR Other errors as indicated.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
+\r
+**/\r
+EFI_STATUS\r
+ParseDhcp4Ack (\r
+ IN EFI_DHCP4_PROTOCOL *Dhcp4,\r
+ IN EFI_DHCP4_PACKET *Packet,\r
+ IN DNS4_SERVER_INFOR *DnsServerInfor\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 OptionCount;\r
+ EFI_DHCP4_PACKET_OPTION **OptionList;\r
+ UINT32 ServerCount;\r
+ EFI_IPv4_ADDRESS *ServerList;\r
+ UINT32 Index;\r
+ UINT32 Count;\r
+\r
+ ServerCount = 0;\r
+ ServerList = NULL;\r
+\r
+ OptionCount = 0;\r
+ OptionList = NULL;\r
+\r
+ Status = Dhcp4->Parse (Dhcp4, Packet, &OptionCount, OptionList);\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ OptionList = AllocatePool (OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));\r
+ if (OptionList == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Status = Dhcp4->Parse (Dhcp4, Packet, &OptionCount, OptionList);\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePool (OptionList);\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Status = EFI_NOT_FOUND;\r
+\r
+ for (Index = 0; Index < OptionCount; Index++) {\r
+ //\r
+ // Get DNS server addresses\r
+ //\r
+ if (OptionList[Index]->OpCode == DHCP4_TAG_DNS_SERVER) {\r
+\r
+ if (((OptionList[Index]->Length & 0x3) != 0) || (OptionList[Index]->Length == 0)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ break;\r
+ }\r
+\r
+ ServerCount = OptionList[Index]->Length/4;\r
+ ServerList = AllocatePool (ServerCount * sizeof (EFI_IPv4_ADDRESS));\r
+ if (ServerList == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for(Count=0; Count < ServerCount; Count++){\r
+ CopyMem (ServerList + Count, &OptionList[Index]->Data[4 * Count], sizeof (EFI_IPv4_ADDRESS));\r
+ }\r
+\r
+ *(DnsServerInfor->ServerCount) = ServerCount;\r
+ DnsServerInfor->ServerList = ServerList;\r
+\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ gBS->FreePool (OptionList);\r
+ \r
+ return Status;\r
+}\r
+\r
+/**\r
+ EFI_DHCP6_INFO_CALLBACK is provided by the consumer of the EFI DHCPv6 Protocol \r
+ instance to intercept events that occurs in the DHCPv6 Information Request\r
+ exchange process.\r
+\r
+ @param This Pointer to the EFI_DHCP6_PROTOCOL instance that \r
+ is used to configure this callback function.\r
+ @param Context Pointer to the context that is initialized in\r
+ the EFI_DHCP6_PROTOCOL.InfoRequest().\r
+ @param Packet Pointer to Reply packet that has been received.\r
+ The EFI DHCPv6 Protocol instance is responsible\r
+ for freeing the buffer.\r
+\r
+ @retval EFI_SUCCESS The DNS information is got from the DHCP ACK.\r
+ @retval EFI_DEVICE_ERROR Other errors as indicated.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ParseDhcp6Ack (\r
+ IN EFI_DHCP6_PROTOCOL *This,\r
+ IN VOID *Context,\r
+ IN EFI_DHCP6_PACKET *Packet\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 OptionCount;\r
+ EFI_DHCP6_PACKET_OPTION **OptionList;\r
+ DNS6_SERVER_INFOR *DnsServerInfor;\r
+ UINT32 ServerCount;\r
+ EFI_IPv6_ADDRESS *ServerList;\r
+ UINT32 Index;\r
+ UINT32 Count;\r
+ \r
+ OptionCount = 0;\r
+ ServerCount = 0;\r
+ ServerList = NULL;\r
+ \r
+ Status = This->Parse (This, Packet, &OptionCount, NULL);\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ OptionList = AllocateZeroPool (OptionCount * sizeof (EFI_DHCP6_PACKET_OPTION *));\r
+ if (OptionList == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Status = This->Parse (This, Packet, &OptionCount, OptionList);\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePool (OptionList);\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ \r
+ DnsServerInfor = (DNS6_SERVER_INFOR *) Context;\r
+\r
+ for (Index = 0; Index < OptionCount; Index++) {\r
+ OptionList[Index]->OpCode = NTOHS (OptionList[Index]->OpCode);\r
+ OptionList[Index]->OpLen = NTOHS (OptionList[Index]->OpLen);\r
+\r
+ //\r
+ // Get DNS server addresses from this reply packet.\r
+ //\r
+ if (OptionList[Index]->OpCode == DHCP6_TAG_DNS_SERVER) {\r
+\r
+ if (((OptionList[Index]->OpLen & 0xf) != 0) || (OptionList[Index]->OpLen == 0)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ gBS->FreePool (OptionList);\r
+ return Status;\r
+ }\r
+ \r
+ ServerCount = OptionList[Index]->OpLen/16;\r
+ ServerList = AllocatePool (ServerCount * sizeof (EFI_IPv6_ADDRESS));\r
+ if (ServerList == NULL) {\r
+ gBS->FreePool (OptionList);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for(Count=0; Count < ServerCount; Count++){\r
+ CopyMem (ServerList + Count, &OptionList[Index]->Data[16 * Count], sizeof (EFI_IPv6_ADDRESS));\r
+ }\r
+\r
+ *(DnsServerInfor->ServerCount) = ServerCount;\r
+ DnsServerInfor->ServerList = ServerList;\r
+ }\r
+ }\r
+\r
+ gBS->FreePool (OptionList);\r
+ \r
+ return Status;\r
+\r
+}\r
+\r
+/**\r
+ Parse the DHCP ACK to get Dns4 server information.\r
+\r
+ @param Instance The DNS instance.\r
+ @param DnsServerCount Retrieved Dns4 server Ip count.\r
+ @param DnsServerList Retrieved Dns4 server Ip list.\r
+\r
+ @retval EFI_SUCCESS The Dns4 information is got from the DHCP ACK.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
+ @retval EFI_NO_MEDIA There was a media error.\r
+ @retval Others Other errors as indicated.\r
+\r
+**/\r
+EFI_STATUS\r
+GetDns4ServerFromDhcp4 (\r
+ IN DNS_INSTANCE *Instance,\r
+ OUT UINT32 *DnsServerCount,\r
+ OUT EFI_IPv4_ADDRESS **DnsServerList\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Image;\r
+ EFI_HANDLE Controller;\r
+ BOOLEAN MediaPresent;\r
+ EFI_HANDLE MnpChildHandle; \r
+ EFI_MANAGED_NETWORK_PROTOCOL *Mnp;\r
+ EFI_MANAGED_NETWORK_CONFIG_DATA MnpConfigData;\r
+ EFI_HANDLE Dhcp4Handle; \r
+ EFI_DHCP4_PROTOCOL *Dhcp4;\r
+ EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2;\r
+ UINTN DataSize;\r
+ VOID *Data;\r
+ EFI_IP4_CONFIG2_INTERFACE_INFO *InterfaceInfo;\r
+ EFI_DHCP4_PACKET SeedPacket;\r
+ EFI_DHCP4_PACKET_OPTION *ParaList[2];\r
+ DNS4_SERVER_INFOR DnsServerInfor;\r
+\r
+ EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN Token;\r
+ BOOLEAN IsDone;\r
+ UINTN Index;\r
+ \r
+ Image = Instance->Service->ImageHandle;\r
+ Controller = Instance->Service->ControllerHandle;\r
+\r
+ MnpChildHandle = NULL;\r
+ Mnp = NULL;\r
+ \r
+ Dhcp4Handle = NULL;\r
+ Dhcp4 = NULL;\r
+\r
+ Ip4Config2 = NULL;\r
+ DataSize = 0;\r
+ Data = NULL;\r
+ InterfaceInfo = NULL;\r
+\r
+ ZeroMem (&MnpConfigData, sizeof (EFI_MANAGED_NETWORK_CONFIG_DATA));\r
+ \r
+ ZeroMem (&DnsServerInfor, sizeof (DNS4_SERVER_INFOR));\r
+ \r
+ ZeroMem (&Token, sizeof (EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN));\r
+ \r
+ DnsServerInfor.ServerCount = DnsServerCount;\r
+\r
+ IsDone = FALSE;\r
+\r
+ //\r
+ // Check media.\r
+ //\r
+ MediaPresent = TRUE;\r
+ NetLibDetectMedia (Controller, &MediaPresent);\r
+ if (!MediaPresent) {\r
+ return EFI_NO_MEDIA;\r
+ }\r
+\r
+ //\r
+ // Create a Mnp child instance, get the protocol and config for it.\r
+ //\r
+ Status = NetLibCreateServiceChild (\r
+ Controller,\r
+ Image,\r
+ &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+ &MnpChildHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ MnpChildHandle,\r
+ &gEfiManagedNetworkProtocolGuid,\r
+ (VOID **) &Mnp,\r
+ Image,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+ \r
+ MnpConfigData.ReceivedQueueTimeoutValue = 0;\r
+ MnpConfigData.TransmitQueueTimeoutValue = 0;\r
+ MnpConfigData.ProtocolTypeFilter = IP4_ETHER_PROTO;\r
+ MnpConfigData.EnableUnicastReceive = TRUE;\r
+ MnpConfigData.EnableMulticastReceive = TRUE;\r
+ MnpConfigData.EnableBroadcastReceive = TRUE;\r
+ MnpConfigData.EnablePromiscuousReceive = FALSE;\r
+ MnpConfigData.FlushQueuesOnReset = TRUE;\r
+ MnpConfigData.EnableReceiveTimestamps = FALSE;\r
+ MnpConfigData.DisableBackgroundPolling = FALSE;\r
+\r
+ Status = Mnp->Configure(Mnp, &MnpConfigData);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+ \r
+ //\r
+ // Create a DHCP4 child instance and get the protocol.\r
+ //\r
+ Status = NetLibCreateServiceChild (\r
+ Controller,\r
+ Image,\r
+ &gEfiDhcp4ServiceBindingProtocolGuid,\r
+ &Dhcp4Handle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ Dhcp4Handle,\r
+ &gEfiDhcp4ProtocolGuid,\r
+ (VOID **) &Dhcp4,\r
+ Image,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Get Ip4Config2 instance info.\r
+ //\r
+ Status = gBS->HandleProtocol (Controller, &gEfiIp4Config2ProtocolGuid, (VOID **) &Ip4Config2);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+ \r
+ Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeInterfaceInfo, &DataSize, Data);\r
+ if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Data = AllocateZeroPool (DataSize);\r
+ if (Data == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeInterfaceInfo, &DataSize, Data);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ InterfaceInfo = (EFI_IP4_CONFIG2_INTERFACE_INFO *)Data;\r
+ \r
+ //\r
+ // Build required Token.\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ DhcpCommonNotify,\r
+ &IsDone,\r
+ &Token.CompletionEvent\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+ \r
+ SetMem (&Token.RemoteAddress, sizeof (EFI_IPv4_ADDRESS), 0xff);\r
+ \r
+ Token.RemotePort = 67;\r
+\r
+ Token.ListenPointCount = 1;\r
+ \r
+ Token.ListenPoints = AllocateZeroPool (Token.ListenPointCount * sizeof (EFI_DHCP4_LISTEN_POINT));\r
+ if (Token.ListenPoints == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ if (Instance->Dns4CfgData.UseDefaultSetting) {\r
+ CopyMem (&(Token.ListenPoints[0].ListenAddress), &(InterfaceInfo->StationAddress), sizeof (EFI_IPv4_ADDRESS));\r
+ CopyMem (&(Token.ListenPoints[0].SubnetMask), &(InterfaceInfo->SubnetMask), sizeof (EFI_IPv4_ADDRESS));\r
+ } else {\r
+ CopyMem (&(Token.ListenPoints[0].ListenAddress), &(Instance->Dns4CfgData.StationIp), sizeof (EFI_IPv4_ADDRESS));\r
+ CopyMem (&(Token.ListenPoints[0].SubnetMask), &(Instance->Dns4CfgData.SubnetMask), sizeof (EFI_IPv4_ADDRESS));\r
+ }\r
+ \r
+ Token.ListenPoints[0].ListenPort = 68;\r
+ \r
+ Token.TimeoutValue = DNS_TIME_TO_GETMAP;\r
+\r
+ DnsInitSeedPacket (&SeedPacket, InterfaceInfo);\r
+\r
+ ParaList[0] = AllocateZeroPool (sizeof (EFI_DHCP4_PACKET_OPTION));\r
+ if (ParaList[0] == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ }\r
+ \r
+ ParaList[0]->OpCode = DHCP4_TAG_TYPE;\r
+ ParaList[0]->Length = 1;\r
+ ParaList[0]->Data[0] = DHCP4_MSG_INFORM;\r
+ \r
+ ParaList[1] = AllocateZeroPool (sizeof (EFI_DHCP4_PACKET_OPTION));\r
+ if (ParaList[1] == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ }\r
+ \r
+ ParaList[1]->OpCode = DHCP4_TAG_PARA_LIST;\r
+ ParaList[1]->Length = 1;\r
+ ParaList[1]->Data[0] = DHCP4_TAG_DNS_SERVER;\r
+\r
+ Status = Dhcp4->Build (Dhcp4, &SeedPacket, 0, NULL, 2, ParaList, &Token.Packet); \r
+\r
+ Token.Packet->Dhcp4.Header.Xid = HTONL(NET_RANDOM (NetRandomInitSeed ()));\r
+ \r
+ Token.Packet->Dhcp4.Header.Reserved = HTONS ((UINT16)0x8000);\r
+ \r
+ if (Instance->Dns4CfgData.UseDefaultSetting) {\r
+ CopyMem (&(Token.Packet->Dhcp4.Header.ClientAddr), &(InterfaceInfo->StationAddress), sizeof (EFI_IPv4_ADDRESS));\r
+ } else {\r
+ CopyMem (&(Token.Packet->Dhcp4.Header.ClientAddr), &(Instance->Dns4CfgData.StationIp), sizeof (EFI_IPv4_ADDRESS));\r
+ }\r
+ \r
+ CopyMem (Token.Packet->Dhcp4.Header.ClientHwAddr, &(InterfaceInfo->HwAddress), InterfaceInfo->HwAddressSize); \r
+ \r
+ Token.Packet->Dhcp4.Header.HwAddrLen = (UINT8)(InterfaceInfo->HwAddressSize);\r
+\r
+ //\r
+ // TransmitReceive Token\r
+ //\r
+ Status = Dhcp4->TransmitReceive (Dhcp4, &Token);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Poll the packet\r
+ //\r
+ do {\r
+ Status = Mnp->Poll (Mnp);\r
+ } while (!IsDone);\r
+ \r
+ //\r
+ // Parse the ACK to get required information if received done.\r
+ //\r
+ if (IsDone && !EFI_ERROR (Token.Status)) {\r
+ for (Index = 0; Index < Token.ResponseCount; Index++) {\r
+ Status = ParseDhcp4Ack (Dhcp4, &Token.ResponseList[Index], &DnsServerInfor);\r
+ if (!EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ *DnsServerList = DnsServerInfor.ServerList;\r
+ } else {\r
+ Status = Token.Status;\r
+ }\r
+ \r
+ON_EXIT:\r
+\r
+ if (Data != NULL) {\r
+ FreePool (Data);\r
+ }\r
+\r
+ for (Index = 0; Index < 2; Index++) {\r
+ if (ParaList[Index] != NULL) {\r
+ FreePool (ParaList[Index]);\r
+ }\r
+ }\r
+\r
+ if (Token.ListenPoints) {\r
+ FreePool (Token.ListenPoints);\r
+ }\r
+\r
+ if (Token.Packet) {\r
+ FreePool (Token.Packet);\r
+ }\r
+ \r
+ if (Token.ResponseList != NULL) {\r
+ FreePool (Token.ResponseList);\r
+ }\r
+ \r
+ if (Token.CompletionEvent != NULL) {\r
+ gBS->CloseEvent (Token.CompletionEvent);\r
+ }\r
+ \r
+ if (Dhcp4 != NULL) {\r
+ Dhcp4->Stop (Dhcp4);\r
+ Dhcp4->Configure (Dhcp4, NULL);\r
+\r
+ gBS->CloseProtocol (\r
+ Dhcp4Handle,\r
+ &gEfiDhcp4ProtocolGuid,\r
+ Image,\r
+ Controller\r
+ );\r
+ }\r
+ \r
+ if (Dhcp4Handle != NULL) {\r
+ NetLibDestroyServiceChild (\r
+ Controller,\r
+ Image,\r
+ &gEfiDhcp4ServiceBindingProtocolGuid,\r
+ Dhcp4Handle\r
+ );\r
+ }\r
+\r
+ if (Mnp != NULL) {\r
+ Mnp->Configure (Mnp, NULL);\r
+\r
+ gBS->CloseProtocol (\r
+ MnpChildHandle,\r
+ &gEfiManagedNetworkProtocolGuid,\r
+ Image,\r
+ Controller\r
+ );\r
+ }\r
+ \r
+ NetLibDestroyServiceChild (\r
+ Controller,\r
+ Image,\r
+ &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+ MnpChildHandle\r
+ );\r
+ \r
+ return Status;\r
+}\r
+\r
+/**\r
+ Parse the DHCP ACK to get Dns6 server information.\r
+\r
+ @param Image The handle of the driver image.\r
+ @param Controller The handle of the controller.\r
+ @param DnsServerCount Retrieved Dns6 server Ip count.\r
+ @param DnsServerList Retrieved Dns6 server Ip list.\r
+\r
+ @retval EFI_SUCCESS The Dns6 information is got from the DHCP ACK.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
+ @retval EFI_NO_MEDIA There was a media error.\r
+ @retval Others Other errors as indicated.\r
+\r
+**/\r
+EFI_STATUS\r
+GetDns6ServerFromDhcp6 (\r
+ IN EFI_HANDLE Image,\r
+ IN EFI_HANDLE Controller,\r
+ OUT UINT32 *DnsServerCount,\r
+ OUT EFI_IPv6_ADDRESS **DnsServerList\r
+ )\r
+{\r
+ EFI_HANDLE Dhcp6Handle;\r
+ EFI_DHCP6_PROTOCOL *Dhcp6;\r
+ EFI_STATUS Status;\r
+ EFI_STATUS TimerStatus;\r
+ EFI_DHCP6_PACKET_OPTION *Oro;\r
+ EFI_DHCP6_RETRANSMISSION InfoReqReXmit;\r
+ EFI_EVENT Timer;\r
+ BOOLEAN MediaPresent;\r
+ DNS6_SERVER_INFOR DnsServerInfor;\r
+\r
+ Dhcp6Handle = NULL;\r
+ Dhcp6 = NULL;\r
+ Oro = NULL;\r
+ Timer = NULL;\r
+\r
+ ZeroMem (&DnsServerInfor, sizeof (DNS6_SERVER_INFOR));\r
+\r
+ DnsServerInfor.ServerCount = DnsServerCount;\r
+\r
+ //\r
+ // Check media status before doing DHCP.\r
+ //\r
+ MediaPresent = TRUE;\r
+ NetLibDetectMedia (Controller, &MediaPresent);\r
+ if (!MediaPresent) {\r
+ return EFI_NO_MEDIA;\r
+ }\r
+\r
+ //\r
+ // Create a DHCP6 child instance and get the protocol.\r
+ //\r
+ Status = NetLibCreateServiceChild (\r
+ Controller,\r
+ Image,\r
+ &gEfiDhcp6ServiceBindingProtocolGuid,\r
+ &Dhcp6Handle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ Dhcp6Handle,\r
+ &gEfiDhcp6ProtocolGuid,\r
+ (VOID **) &Dhcp6,\r
+ Image,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Oro = AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + 1);\r
+ if (Oro == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Ask the server to reply with DNS options.\r
+ // All members in EFI_DHCP6_PACKET_OPTION are in network order.\r
+ //\r
+ Oro->OpCode = HTONS (DHCP6_TAG_DNS_REQUEST);\r
+ Oro->OpLen = HTONS (2);\r
+ Oro->Data[1] = DHCP6_TAG_DNS_SERVER;\r
+\r
+ InfoReqReXmit.Irt = 4;\r
+ InfoReqReXmit.Mrc = 1;\r
+ InfoReqReXmit.Mrt = 10;\r
+ InfoReqReXmit.Mrd = 30;\r
+\r
+ Status = Dhcp6->InfoRequest (\r
+ Dhcp6,\r
+ TRUE,\r
+ Oro,\r
+ 0,\r
+ NULL,\r
+ &InfoReqReXmit,\r
+ NULL,\r
+ ParseDhcp6Ack,\r
+ &DnsServerInfor\r
+ );\r
+ if (Status == EFI_NO_MAPPING) {\r
+ Status = gBS->CreateEvent (EVT_TIMER, TPL_CALLBACK, NULL, NULL, &Timer);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Status = gBS->SetTimer (\r
+ Timer,\r
+ TimerRelative,\r
+ DNS_TIME_TO_GETMAP * TICKS_PER_SECOND\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ do {\r
+ TimerStatus = gBS->CheckEvent (Timer);\r
+ if (!EFI_ERROR (TimerStatus)) {\r
+ Status = Dhcp6->InfoRequest (\r
+ Dhcp6,\r
+ TRUE,\r
+ Oro,\r
+ 0,\r
+ NULL,\r
+ &InfoReqReXmit,\r
+ NULL,\r
+ ParseDhcp6Ack,\r
+ &DnsServerInfor\r
+ );\r
+ }\r
+ } while (TimerStatus == EFI_NOT_READY);\r
+ }\r
+ \r
+ *DnsServerList = DnsServerInfor.ServerList;\r
+\r
+ON_EXIT:\r
+\r
+ if (Oro != NULL) {\r
+ FreePool (Oro);\r
+ } \r
+\r
+ if (Timer != NULL) {\r
+ gBS->CloseEvent (Timer);\r
+ }\r
+\r
+ if (Dhcp6 != NULL) {\r
+ gBS->CloseProtocol (\r
+ Dhcp6Handle,\r
+ &gEfiDhcp6ProtocolGuid,\r
+ Image,\r
+ Controller\r
+ );\r
+ }\r
+\r
+ NetLibDestroyServiceChild (\r
+ Controller,\r
+ Image,\r
+ &gEfiDhcp6ServiceBindingProtocolGuid,\r
+ Dhcp6Handle\r
+ );\r
+\r
+ return Status;\r
+ \r
+}\r
+\r
--- /dev/null
+/** @file\r
+Functions implementation related with DHCPv4/v6 for DNS driver.\r
+\r
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _DNS_DHCP_H_\r
+#define _DNS_DHCP_H_\r
+\r
+//\r
+// DHCP DNS related\r
+//\r
+#pragma pack(1)\r
+\r
+#define IP4_ETHER_PROTO 0x0800\r
+\r
+#define DHCP4_OPCODE_REQUEST 1\r
+#define DHCP4_MAGIC 0x63538263 /// network byte order\r
+#define DHCP4_TAG_EOP 255 /// End Option\r
+\r
+#define DHCP4_TAG_TYPE 53\r
+#define DHCP4_MSG_REQUEST 3\r
+#define DHCP4_MSG_INFORM 8\r
+\r
+#define DHCP4_TAG_PARA_LIST 55\r
+#define DHCP4_TAG_DNS_SERVER 6\r
+\r
+\r
+#define DHCP6_TAG_DNS_REQUEST 6\r
+#define DHCP6_TAG_DNS_SERVER 23\r
+\r
+//\r
+// The required Dns4 server information.\r
+//\r
+typedef struct {\r
+ UINT32 *ServerCount;\r
+ EFI_IPv4_ADDRESS *ServerList;\r
+} DNS4_SERVER_INFOR;\r
+\r
+//\r
+// The required Dns6 server information.\r
+//\r
+typedef struct {\r
+ UINT32 *ServerCount;\r
+ EFI_IPv6_ADDRESS *ServerList;\r
+} DNS6_SERVER_INFOR;\r
+\r
+#pragma pack()\r
+\r
+/**\r
+ Parse the ACK to get required information\r
+\r
+ @param Dhcp4 The DHCP4 protocol.\r
+ @param Packet Packet waiting for parse.\r
+ @param DnsServerInfor The required Dns4 server information.\r
+\r
+ @retval EFI_SUCCESS The DNS information is got from the DHCP ACK.\r
+ @retval EFI_NO_MAPPING DHCP failed to acquire address and other information.\r
+ @retval EFI_DEVICE_ERROR Other errors as indicated.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
+\r
+**/\r
+EFI_STATUS\r
+ParseDhcp4Ack (\r
+ IN EFI_DHCP4_PROTOCOL *Dhcp4,\r
+ IN EFI_DHCP4_PACKET *Packet,\r
+ IN DNS4_SERVER_INFOR *DnsServerInfor\r
+ );\r
+\r
+/**\r
+ EFI_DHCP6_INFO_CALLBACK is provided by the consumer of the EFI DHCPv6 Protocol \r
+ instance to intercept events that occurs in the DHCPv6 Information Request\r
+ exchange process.\r
+\r
+ @param This Pointer to the EFI_DHCP6_PROTOCOL instance that \r
+ is used to configure this callback function.\r
+ @param Context Pointer to the context that is initialized in\r
+ the EFI_DHCP6_PROTOCOL.InfoRequest().\r
+ @param Packet Pointer to Reply packet that has been received.\r
+ The EFI DHCPv6 Protocol instance is responsible\r
+ for freeing the buffer.\r
+\r
+ @retval EFI_SUCCESS The DNS information is got from the DHCP ACK.\r
+ @retval EFI_DEVICE_ERROR Other errors as indicated.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ParseDhcp6Ack (\r
+ IN EFI_DHCP6_PROTOCOL *This,\r
+ IN VOID *Context,\r
+ IN EFI_DHCP6_PACKET *Packet\r
+ );\r
+\r
+/**\r
+ Parse the DHCP ACK to get Dns4 server information.\r
+\r
+ @param Instance The DNS instance.\r
+ @param DnsServerCount Retrieved Dns4 server Ip count.\r
+ @param DnsServerList Retrieved Dns4 server Ip list.\r
+\r
+ @retval EFI_SUCCESS The Dns4 information is got from the DHCP ACK.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
+ @retval EFI_NO_MEDIA There was a media error.\r
+ @retval Others Other errors as indicated.\r
+\r
+**/\r
+EFI_STATUS\r
+GetDns4ServerFromDhcp4 (\r
+ IN DNS_INSTANCE *Instance,\r
+ OUT UINT32 *DnsServerCount,\r
+ OUT EFI_IPv4_ADDRESS **DnsServerList\r
+ );\r
+\r
+/**\r
+ Parse the DHCP ACK to get Dns6 server information.\r
+\r
+ @param Image The handle of the driver image.\r
+ @param Controller The handle of the controller.\r
+ @param DnsServerCount Retrieved Dns6 server Ip count.\r
+ @param DnsServerList Retrieved Dns6 server Ip list.\r
+\r
+ @retval EFI_SUCCESS The Dns6 information is got from the DHCP ACK.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
+ @retval EFI_NO_MEDIA There was a media error.\r
+ @retval Others Other errors as indicated.\r
+\r
+**/\r
+EFI_STATUS\r
+GetDns6ServerFromDhcp6 (\r
+ IN EFI_HANDLE Image,\r
+ IN EFI_HANDLE Controller,\r
+ OUT UINT32 *DnsServerCount,\r
+ OUT EFI_IPv6_ADDRESS **DnsServerList\r
+ );\r
+ \r
+#endif
\ No newline at end of file
--- /dev/null
+/** @file\r
+The driver binding and service binding protocol for DnsDxe driver.\r
+\r
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "DnsImpl.h"\r
+\r
+EFI_DRIVER_BINDING_PROTOCOL gDns4DriverBinding = {\r
+ Dns4DriverBindingSupported,\r
+ Dns4DriverBindingStart,\r
+ Dns4DriverBindingStop,\r
+ DNS_VERSION,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
+EFI_DRIVER_BINDING_PROTOCOL gDns6DriverBinding = {\r
+ Dns6DriverBindingSupported,\r
+ Dns6DriverBindingStart,\r
+ Dns6DriverBindingStop,\r
+ DNS_VERSION,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
+EFI_SERVICE_BINDING_PROTOCOL mDns4ServiceBinding = {\r
+ Dns4ServiceBindingCreateChild,\r
+ Dns4ServiceBindingDestroyChild\r
+};\r
+\r
+EFI_SERVICE_BINDING_PROTOCOL mDns6ServiceBinding = {\r
+ Dns6ServiceBindingCreateChild,\r
+ Dns6ServiceBindingDestroyChild\r
+};\r
+\r
+DNS_DRIVER_DATA *mDriverData = NULL;\r
+\r
+/**\r
+ Destroy the DNS instance and recycle the resources.\r
+\r
+ @param[in] Instance The pointer to the DNS instance.\r
+\r
+**/\r
+VOID\r
+DnsDestroyInstance (\r
+ IN DNS_INSTANCE *Instance\r
+ )\r
+{\r
+ ZeroMem (&Instance->Dns4CfgData, sizeof (EFI_DNS4_CONFIG_DATA));\r
+ \r
+ ZeroMem (&Instance->Dns6CfgData, sizeof (EFI_DNS6_CONFIG_DATA));\r
+ \r
+ if (!NetMapIsEmpty (&Instance->Dns4TxTokens)) {\r
+ Dns4InstanceCancelToken (Instance, NULL);\r
+ }\r
+\r
+ if (!NetMapIsEmpty (&Instance->Dns6TxTokens)) {\r
+ Dns6InstanceCancelToken (Instance, NULL);\r
+ }\r
+ \r
+ if (Instance->UdpIo!= NULL) {\r
+ UdpIoFreeIo (Instance->UdpIo);\r
+ }\r
+ \r
+ FreePool (Instance);\r
+}\r
+\r
+/**\r
+ Create the DNS instance and initialize it.\r
+\r
+ @param[in] Service The pointer to the DNS service.\r
+ @param[out] Instance The pointer to the DNS instance.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
+ @retval EFI_SUCCESS The DNS instance is created.\r
+\r
+**/\r
+EFI_STATUS\r
+DnsCreateInstance (\r
+ IN DNS_SERVICE *Service,\r
+ OUT DNS_INSTANCE **Instance\r
+ )\r
+{\r
+ DNS_INSTANCE *DnsIns;\r
+\r
+ *Instance = NULL;\r
+ \r
+ DnsIns = AllocateZeroPool (sizeof (DNS_INSTANCE));\r
+ if (DnsIns == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ DnsIns->Signature = DNS_INSTANCE_SIGNATURE;\r
+ InitializeListHead (&DnsIns->Link);\r
+ DnsIns->State = DNS_STATE_UNCONFIGED;\r
+ DnsIns->InDestroy = FALSE;\r
+ DnsIns->Service = Service;\r
+ \r
+ if (Service->IpVersion == IP_VERSION_4) {\r
+ CopyMem (&DnsIns->Dns4, &mDns4Protocol, sizeof (DnsIns->Dns4));\r
+ NetMapInit (&DnsIns->Dns4TxTokens);\r
+ } else {\r
+ CopyMem (&DnsIns->Dns6, &mDns6Protocol, sizeof (DnsIns->Dns6));\r
+ NetMapInit (&DnsIns->Dns6TxTokens);\r
+ }\r
+\r
+ DnsIns->UdpIo = UdpIoCreateIo (\r
+ Service->ControllerHandle, /// NicHandle\r
+ Service->ImageHandle,\r
+ DnsConfigNullUdp,\r
+ Service->IpVersion,\r
+ DnsIns\r
+ );\r
+ if (DnsIns->UdpIo == NULL) {\r
+ FreePool (DnsIns);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ \r
+ *Instance = DnsIns;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
+ \r
+ @param[in] Entry The entry to be removed.\r
+ @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
+\r
+ @retval EFI_SUCCESS The entry has been removed successfully.\r
+ @retval Others Fail to remove the entry.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DnsDestroyChildEntryInHandleBuffer (\r
+ IN LIST_ENTRY *Entry,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ DNS_INSTANCE *Instance;\r
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
+ UINTN NumberOfChildren;\r
+ EFI_HANDLE *ChildHandleBuffer;\r
+\r
+ if (Entry == NULL || Context == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Instance = NET_LIST_USER_STRUCT_S (Entry, DNS_INSTANCE, Link, DNS_INSTANCE_SIGNATURE);\r
+ ServiceBinding = ((DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;\r
+ NumberOfChildren = ((DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;\r
+ ChildHandleBuffer = ((DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;\r
+\r
+ if (!NetIsInHandleBuffer (Instance->ChildHandle, NumberOfChildren, ChildHandleBuffer)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return ServiceBinding->DestroyChild (ServiceBinding, Instance->ChildHandle);\r
+}\r
+\r
+/**\r
+ Config a NULL UDP that is used to keep the connection between UDP and DNS.\r
+\r
+ Just leave the Udp child unconfigured. When UDP is unloaded,\r
+ DNS will be informed with DriverBinding Stop.\r
+\r
+ @param UdpIo The UDP_IO to configure\r
+ @param Context The opaque parameter to the callback\r
+\r
+ @retval EFI_SUCCESS It always return EFI_SUCCESS directly.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DnsConfigNullUdp (\r
+ IN UDP_IO *UdpIo,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Release all the resource used the DNS service binding instance.\r
+\r
+ @param DnsSb The Dns service binding instance.\r
+\r
+**/\r
+VOID\r
+DnsDestroyService (\r
+ IN DNS_SERVICE *DnsSb\r
+ )\r
+{\r
+ UdpIoFreeIo (DnsSb->ConnectUdp);\r
+ \r
+ if (DnsSb->TimerToGetMap != NULL){\r
+ gBS->CloseEvent (DnsSb->TimerToGetMap);\r
+ }\r
+\r
+ if (DnsSb->Timer != NULL){\r
+ gBS->CloseEvent (DnsSb->Timer);\r
+ }\r
+\r
+ FreePool (DnsSb);\r
+}\r
+\r
+/**\r
+ Create then initialize a Dns service binding instance.\r
+\r
+ @param Controller The controller to install the DNS service\r
+ binding on\r
+ @param Image The driver binding image of the DNS driver\r
+ @param IpVersion IpVersion for this service\r
+ @param Service The variable to receive the created service\r
+ binding instance.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance.\r
+ @retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep\r
+ connection with UDP.\r
+ @retval EFI_SUCCESS The service instance is created for the\r
+ controller.\r
+\r
+**/\r
+EFI_STATUS\r
+DnsCreateService (\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_HANDLE Image,\r
+ IN UINT8 IpVersion,\r
+ OUT DNS_SERVICE **Service\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ DNS_SERVICE *DnsSb;\r
+ \r
+ Status = EFI_SUCCESS;\r
+ DnsSb = NULL;\r
+\r
+ *Service = NULL;\r
+\r
+ DnsSb = AllocateZeroPool (sizeof (DNS_SERVICE));\r
+ if (DnsSb == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ DnsSb->Signature = DNS_SERVICE_SIGNATURE;\r
+\r
+ if (IpVersion == IP_VERSION_4) {\r
+ DnsSb->ServiceBinding = mDns4ServiceBinding;\r
+ } else {\r
+ DnsSb->ServiceBinding = mDns6ServiceBinding;\r
+ }\r
+ \r
+ DnsSb->Dns4ChildrenNum = 0;\r
+ InitializeListHead (&DnsSb->Dns4ChildrenList);\r
+\r
+ DnsSb->Dns6ChildrenNum = 0;\r
+ InitializeListHead (&DnsSb->Dns6ChildrenList);\r
+\r
+ DnsSb->ControllerHandle = Controller;\r
+ DnsSb->ImageHandle = Image;\r
+\r
+ DnsSb->TimerToGetMap = NULL;\r
+ \r
+ DnsSb->Timer = NULL;\r
+ \r
+ DnsSb->IpVersion = IpVersion;\r
+\r
+ //\r
+ // Create the timer used to time out the procedure which is used to\r
+ // get the default IP address.\r
+ //\r
+ if (DnsSb->IpVersion == IP_VERSION_4) {\r
+ Status = gBS->CreateEvent (\r
+ EVT_TIMER,\r
+ TPL_CALLBACK,\r
+ NULL,\r
+ NULL,\r
+ &DnsSb->TimerToGetMap\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (DnsSb);\r
+ return Status;\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Create the timer to retransmit packets.\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
+ TPL_CALLBACK,\r
+ DnsOnTimerRetransmit,\r
+ DnsSb,\r
+ &DnsSb->Timer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ if (DnsSb->TimerToGetMap != NULL) {\r
+ gBS->CloseEvent (DnsSb->TimerToGetMap);\r
+ }\r
+ FreePool (DnsSb);\r
+ return Status;\r
+ }\r
+ \r
+ DnsSb->ConnectUdp = NULL;\r
+ DnsSb->ConnectUdp = UdpIoCreateIo (\r
+ Controller,\r
+ Image,\r
+ DnsConfigNullUdp,\r
+ DnsSb->IpVersion,\r
+ NULL\r
+ );\r
+ if (DnsSb->ConnectUdp == NULL) {\r
+ if (DnsSb->TimerToGetMap != NULL) {\r
+ gBS->CloseEvent (DnsSb->TimerToGetMap);\r
+ }\r
+ gBS->CloseEvent (DnsSb->Timer);\r
+ FreePool (DnsSb);\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ *Service = DnsSb;\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Unloads an image.\r
+\r
+ @param ImageHandle Handle that identifies the image to be unloaded.\r
+\r
+ @retval EFI_SUCCESS The image has been unloaded.\r
+ @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.\r
+\r
+**/\r
+EFI_STATUS \r
+EFIAPI\r
+DnsUnload (\r
+ IN EFI_HANDLE ImageHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ LIST_ENTRY *Entry;\r
+ DNS4_CACHE *ItemCache4;\r
+ DNS4_SERVER_IP *ItemServerIp4;\r
+ DNS6_CACHE *ItemCache6;\r
+ DNS6_SERVER_IP *ItemServerIp6;\r
+\r
+ ItemCache4 = NULL;\r
+ ItemServerIp4 = NULL;\r
+ ItemCache6 = NULL;\r
+ ItemServerIp6 = NULL;\r
+ \r
+ //\r
+ // Disconnect the driver specified by ImageHandle\r
+ //\r
+ Status = NetLibDefaultUnload(ImageHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Free mDriverData.\r
+ //\r
+ if (mDriverData != NULL) {\r
+ if (mDriverData->Timer != NULL) {\r
+ gBS->CloseEvent (mDriverData->Timer);\r
+ }\r
+ \r
+ while (!IsListEmpty (&mDriverData->Dns4CacheList)) {\r
+ Entry = NetListRemoveHead (&mDriverData->Dns4CacheList);\r
+ ItemCache4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);\r
+ if (ItemCache4->DnsCache.HostName != NULL) {\r
+ FreePool (ItemCache4->DnsCache.HostName);\r
+ }\r
+ if (ItemCache4->DnsCache.IpAddress != NULL) {\r
+ FreePool (ItemCache4->DnsCache.IpAddress);\r
+ }\r
+ FreePool (ItemCache4);\r
+ }\r
+\r
+ while (!IsListEmpty (&mDriverData->Dns4ServerList)) {\r
+ Entry = NetListRemoveHead (&mDriverData->Dns4ServerList);\r
+ ItemServerIp4 = NET_LIST_USER_STRUCT (Entry, DNS4_SERVER_IP, AllServerLink);\r
+ FreePool (ItemServerIp4);\r
+ }\r
+\r
+ while (!IsListEmpty (&mDriverData->Dns6CacheList)) {\r
+ Entry = NetListRemoveHead (&mDriverData->Dns6CacheList);\r
+ ItemCache6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);\r
+ if (ItemCache6->DnsCache.HostName != NULL) {\r
+ FreePool (ItemCache6->DnsCache.HostName);\r
+ }\r
+ if (ItemCache6->DnsCache.IpAddress != NULL) {\r
+ FreePool (ItemCache6->DnsCache.IpAddress);\r
+ }\r
+ FreePool (ItemCache6);\r
+ }\r
+\r
+ while (!IsListEmpty (&mDriverData->Dns6ServerList)) {\r
+ Entry = NetListRemoveHead (&mDriverData->Dns6ServerList);\r
+ ItemServerIp6 = NET_LIST_USER_STRUCT (Entry, DNS6_SERVER_IP, AllServerLink);\r
+ FreePool (ItemServerIp6);\r
+ }\r
+ \r
+ FreePool (mDriverData);\r
+ }\r
+ \r
+ return Status;\r
+}\r
+\r
+/**\r
+ This is the declaration of an EFI image entry point. This entry point is\r
+ the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
+ both device drivers and bus drivers.\r
+\r
+ @param ImageHandle The firmware allocated handle for the UEFI image.\r
+ @param SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval Others An unexpected error occurred.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DnsDriverEntryPoint (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Install the Dns4 Driver Binding Protocol.\r
+ //\r
+ Status = EfiLibInstallDriverBindingComponentName2 (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gDns4DriverBinding,\r
+ ImageHandle,\r
+ &gDnsComponentName,\r
+ &gDnsComponentName2\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Install the Dns6 Driver Binding Protocol.\r
+ //\r
+ Status = EfiLibInstallDriverBindingComponentName2 (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gDns6DriverBinding,\r
+ NULL,\r
+ &gDnsComponentName,\r
+ &gDnsComponentName2\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error1;\r
+ }\r
+\r
+ //\r
+ // Create the driver data structures.\r
+ //\r
+ mDriverData = AllocateZeroPool (sizeof (DNS_DRIVER_DATA));\r
+ if (mDriverData == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error2;\r
+ }\r
+\r
+ //\r
+ // Create the timer event to update DNS cache list.\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
+ TPL_CALLBACK,\r
+ DnsOnTimerUpdate,\r
+ NULL,\r
+ &mDriverData->Timer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error3;\r
+ }\r
+ \r
+ Status = gBS->SetTimer (mDriverData->Timer, TimerPeriodic, TICKS_PER_SECOND);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error4;\r
+ }\r
+\r
+ InitializeListHead (&mDriverData->Dns4CacheList);\r
+ InitializeListHead (&mDriverData->Dns4ServerList);\r
+ InitializeListHead (&mDriverData->Dns6CacheList);\r
+ InitializeListHead (&mDriverData->Dns6ServerList);\r
+ \r
+ return Status;\r
+\r
+ Error4:\r
+ gBS->CloseEvent (mDriverData->Timer);\r
+\r
+ Error3:\r
+ FreePool (mDriverData);\r
+ \r
+ Error2: \r
+ gBS->UninstallMultipleProtocolInterfaces (\r
+ gDns6DriverBinding.DriverBindingHandle,\r
+ &gEfiDriverBindingProtocolGuid,\r
+ &gDns6DriverBinding, \r
+ &gEfiComponentName2ProtocolGuid,\r
+ &gDnsComponentName2,\r
+ &gEfiComponentNameProtocolGuid,\r
+ &gDnsComponentName,\r
+ NULL\r
+ ); \r
+\r
+ Error1:\r
+ gBS->UninstallMultipleProtocolInterfaces (\r
+ ImageHandle,\r
+ &gEfiDriverBindingProtocolGuid,\r
+ &gDns4DriverBinding,\r
+ &gEfiComponentName2ProtocolGuid,\r
+ &gDnsComponentName2,\r
+ &gEfiComponentNameProtocolGuid,\r
+ &gDnsComponentName,\r
+ NULL\r
+ );\r
+ \r
+ return Status;\r
+}\r
+\r
+/**\r
+ Tests to see if this driver supports a given controller. If a child device is provided, \r
+ it further tests to see if this driver supports creating a handle for the specified child device.\r
+\r
+ This function checks to see if the driver specified by This supports the device specified by \r
+ ControllerHandle. Drivers will typically use the device path attached to \r
+ ControllerHandle and/or the services from the bus I/O abstraction attached to \r
+ ControllerHandle to determine if the driver supports ControllerHandle. This function \r
+ may be called many times during platform initialization. In order to reduce boot times, the tests \r
+ performed by this function must be very small, and take as little time as possible to execute. This \r
+ function must not change the state of any hardware devices, and this function must be aware that the \r
+ device specified by ControllerHandle may already be managed by the same driver or a \r
+ different driver. This function must match its calls to AllocatePages() with FreePages(), \r
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). \r
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is \r
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required \r
+ to guarantee the state of ControllerHandle is not modified by this function.\r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to test. This handle \r
+ must support a protocol interface that supplies \r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
+ parameter is ignored by device drivers, and is optional for bus \r
+ drivers. For bus drivers, if this parameter is not NULL, then \r
+ the bus driver must determine if the bus controller specified \r
+ by ControllerHandle and the child controller specified \r
+ by RemainingDevicePath are both supported by this \r
+ bus driver.\r
+\r
+ @retval EFI_SUCCESS The device specified by ControllerHandle and\r
+ RemainingDevicePath is supported by the driver specified by This.\r
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by the driver\r
+ specified by This.\r
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by a different\r
+ driver or an application that requires exclusive access.\r
+ Currently not implemented.\r
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
+ RemainingDevicePath is not supported by the driver specified by This.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4DriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Test for the Dns4ServiceBinding Protocol.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiDns4ServiceBindingProtocolGuid,\r
+ NULL,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ return EFI_ALREADY_STARTED;\r
+ }\r
+\r
+ //\r
+ // Test for the Udp4ServiceBinding Protocol.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiUdp4ServiceBindingProtocolGuid,\r
+ NULL,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Starts a device controller or a bus controller.\r
+\r
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
+ As a result, much of the error checking on the parameters to Start() has been moved into this \r
+ common boot service. It is legal to call Start() from other locations, \r
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE.\r
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
+ EFI_DEVICE_PATH_PROTOCOL.\r
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. \r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to start. This handle \r
+ must support a protocol interface that supplies \r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
+ parameter is ignored by device drivers, and is optional for bus \r
+ drivers. For a bus driver, if this parameter is NULL, then handles \r
+ for all the children of Controller are created by this driver. \r
+ If this parameter is not NULL and the first Device Path Node is \r
+ not the End of Device Path Node, then only the handle for the \r
+ child device specified by the first Device Path Node of \r
+ RemainingDevicePath is created by this driver.\r
+ If the first Device Path Node of RemainingDevicePath is \r
+ the End of Device Path Node, no child handle is created by this\r
+ driver.\r
+\r
+ @retval EFI_SUCCESS The device was started.\r
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval Others The driver failded to start the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4DriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ )\r
+{\r
+ DNS_SERVICE *DnsSb;\r
+ EFI_STATUS Status;\r
+\r
+ Status = DnsCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_4, &DnsSb);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ ASSERT (DnsSb != NULL);\r
+ \r
+ Status = gBS->SetTimer (DnsSb->Timer, TimerPeriodic, TICKS_PER_SECOND);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+ \r
+ //\r
+ // Install the Dns4ServiceBinding Protocol onto ControllerHandle.\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &ControllerHandle,\r
+ &gEfiDns4ServiceBindingProtocolGuid,\r
+ &DnsSb->ServiceBinding,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+ON_ERROR:\r
+ DnsDestroyService (DnsSb);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Stops a device controller or a bus controller.\r
+ \r
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). \r
+ As a result, much of the error checking on the parameters to Stop() has been moved \r
+ into this common boot service. It is legal to call Stop() from other locations, \r
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
+ same driver's Start() function.\r
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
+ Start() function, and the Start() function must have called OpenProtocol() on\r
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
+ \r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must \r
+ support a bus specific I/O protocol for the driver \r
+ to use to stop the device.\r
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL \r
+ if NumberOfChildren is 0.\r
+\r
+ @retval EFI_SUCCESS The device was stopped.\r
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4DriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
+ )\r
+{\r
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
+ DNS_SERVICE *DnsSb;\r
+ EFI_HANDLE NicHandle;\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *List;\r
+ DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
+\r
+ //\r
+ // DNS driver opens UDP child, So, Controller is a UDP\r
+ // child handle. Locate the Nic handle first. Then get the\r
+ // DNS private data back.\r
+ //\r
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);\r
+\r
+ if (NicHandle == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ NicHandle,\r
+ &gEfiDns4ServiceBindingProtocolGuid,\r
+ (VOID **) &ServiceBinding,\r
+ This->DriverBindingHandle,\r
+ NicHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ DnsSb = DNS_SERVICE_FROM_THIS (ServiceBinding);\r
+\r
+ if (!IsListEmpty (&DnsSb->Dns4ChildrenList)) {\r
+ //\r
+ // Destroy the Dns child instance in ChildHandleBuffer.\r
+ //\r
+ List = &DnsSb->Dns4ChildrenList;\r
+ Context.ServiceBinding = ServiceBinding;\r
+ Context.NumberOfChildren = NumberOfChildren;\r
+ Context.ChildHandleBuffer = ChildHandleBuffer;\r
+ Status = NetDestroyLinkList (\r
+ List,\r
+ DnsDestroyChildEntryInHandleBuffer,\r
+ &Context,\r
+ NULL\r
+ );\r
+ }\r
+\r
+ if (NumberOfChildren == 0 && IsListEmpty (&DnsSb->Dns4ChildrenList)) {\r
+ gBS->UninstallProtocolInterface (\r
+ NicHandle,\r
+ &gEfiDns4ServiceBindingProtocolGuid,\r
+ ServiceBinding\r
+ );\r
+\r
+ DnsDestroyService (DnsSb);\r
+ \r
+ if (gDnsControllerNameTable != NULL) {\r
+ FreeUnicodeStringTable (gDnsControllerNameTable);\r
+ gDnsControllerNameTable = NULL;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Tests to see if this driver supports a given controller. If a child device is provided, \r
+ it further tests to see if this driver supports creating a handle for the specified child device.\r
+\r
+ This function checks to see if the driver specified by This supports the device specified by \r
+ ControllerHandle. Drivers will typically use the device path attached to \r
+ ControllerHandle and/or the services from the bus I/O abstraction attached to \r
+ ControllerHandle to determine if the driver supports ControllerHandle. This function \r
+ may be called many times during platform initialization. In order to reduce boot times, the tests \r
+ performed by this function must be very small, and take as little time as possible to execute. This \r
+ function must not change the state of any hardware devices, and this function must be aware that the \r
+ device specified by ControllerHandle may already be managed by the same driver or a \r
+ different driver. This function must match its calls to AllocatePages() with FreePages(), \r
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). \r
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is \r
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required \r
+ to guarantee the state of ControllerHandle is not modified by this function.\r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to test. This handle \r
+ must support a protocol interface that supplies \r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
+ parameter is ignored by device drivers, and is optional for bus \r
+ drivers. For bus drivers, if this parameter is not NULL, then \r
+ the bus driver must determine if the bus controller specified \r
+ by ControllerHandle and the child controller specified \r
+ by RemainingDevicePath are both supported by this \r
+ bus driver.\r
+\r
+ @retval EFI_SUCCESS The device specified by ControllerHandle and\r
+ RemainingDevicePath is supported by the driver specified by This.\r
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by the driver\r
+ specified by This.\r
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by a different\r
+ driver or an application that requires exclusive access.\r
+ Currently not implemented.\r
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
+ RemainingDevicePath is not supported by the driver specified by This.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6DriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Test for the Dns6ServiceBinding Protocol\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiDns6ServiceBindingProtocolGuid,\r
+ NULL,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ return EFI_ALREADY_STARTED;\r
+ }\r
+\r
+ //\r
+ // Test for the Udp6ServiceBinding Protocol\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiUdp6ServiceBindingProtocolGuid,\r
+ NULL,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Starts a device controller or a bus controller.\r
+\r
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
+ As a result, much of the error checking on the parameters to Start() has been moved into this \r
+ common boot service. It is legal to call Start() from other locations, \r
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE.\r
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
+ EFI_DEVICE_PATH_PROTOCOL.\r
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. \r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to start. This handle \r
+ must support a protocol interface that supplies \r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
+ parameter is ignored by device drivers, and is optional for bus \r
+ drivers. For a bus driver, if this parameter is NULL, then handles \r
+ for all the children of Controller are created by this driver. \r
+ If this parameter is not NULL and the first Device Path Node is \r
+ not the End of Device Path Node, then only the handle for the \r
+ child device specified by the first Device Path Node of \r
+ RemainingDevicePath is created by this driver.\r
+ If the first Device Path Node of RemainingDevicePath is \r
+ the End of Device Path Node, no child handle is created by this\r
+ driver.\r
+\r
+ @retval EFI_SUCCESS The device was started.\r
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval Others The driver failded to start the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6DriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ )\r
+{\r
+ DNS_SERVICE *DnsSb;\r
+ EFI_STATUS Status;\r
+\r
+ Status = DnsCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_6, &DnsSb);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ ASSERT (DnsSb != NULL);\r
+ \r
+ Status = gBS->SetTimer (DnsSb->Timer, TimerPeriodic, TICKS_PER_SECOND);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+ \r
+ //\r
+ // Install the Dns6ServiceBinding Protocol onto ControllerHandle\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &ControllerHandle,\r
+ &gEfiDns6ServiceBindingProtocolGuid,\r
+ &DnsSb->ServiceBinding,\r
+ NULL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+ON_ERROR:\r
+ DnsDestroyService (DnsSb);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Stops a device controller or a bus controller.\r
+ \r
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). \r
+ As a result, much of the error checking on the parameters to Stop() has been moved \r
+ into this common boot service. It is legal to call Stop() from other locations, \r
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
+ same driver's Start() function.\r
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
+ Start() function, and the Start() function must have called OpenProtocol() on\r
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
+ \r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must \r
+ support a bus specific I/O protocol for the driver \r
+ to use to stop the device.\r
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL \r
+ if NumberOfChildren is 0.\r
+\r
+ @retval EFI_SUCCESS The device was stopped.\r
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6DriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
+ )\r
+{\r
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
+ DNS_SERVICE *DnsSb;\r
+ EFI_HANDLE NicHandle;\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *List;\r
+ DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
+\r
+ //\r
+ // DNS driver opens UDP child, So, Controller is a UDP\r
+ // child handle. Locate the Nic handle first. Then get the\r
+ // DNS private data back.\r
+ //\r
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp6ProtocolGuid);\r
+\r
+ if (NicHandle == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ NicHandle,\r
+ &gEfiDns6ServiceBindingProtocolGuid,\r
+ (VOID **) &ServiceBinding,\r
+ This->DriverBindingHandle,\r
+ NicHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ DnsSb = DNS_SERVICE_FROM_THIS (ServiceBinding);\r
+\r
+ if (!IsListEmpty (&DnsSb->Dns6ChildrenList)) {\r
+ //\r
+ // Destroy the Dns child instance in ChildHandleBuffer.\r
+ //\r
+ List = &DnsSb->Dns6ChildrenList;\r
+ Context.ServiceBinding = ServiceBinding;\r
+ Context.NumberOfChildren = NumberOfChildren;\r
+ Context.ChildHandleBuffer = ChildHandleBuffer;\r
+ Status = NetDestroyLinkList (\r
+ List,\r
+ DnsDestroyChildEntryInHandleBuffer,\r
+ &Context,\r
+ NULL\r
+ );\r
+ }\r
+\r
+ if (NumberOfChildren == 0 && IsListEmpty (&DnsSb->Dns6ChildrenList)) {\r
+ gBS->UninstallProtocolInterface (\r
+ NicHandle,\r
+ &gEfiDns6ServiceBindingProtocolGuid,\r
+ ServiceBinding\r
+ );\r
+\r
+ DnsDestroyService (DnsSb);\r
+ \r
+ if (gDnsControllerNameTable != NULL) {\r
+ FreeUnicodeStringTable (gDnsControllerNameTable);\r
+ gDnsControllerNameTable = NULL;\r
+ }\r
+ \r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Creates a child handle and installs a protocol.\r
+ \r
+ The CreateChild() function installs a protocol on ChildHandle. \r
+ If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle. \r
+ If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.\r
+\r
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
+ @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,\r
+ then a new handle is created. If it is a pointer to an existing UEFI handle, \r
+ then the protocol is added to the existing UEFI handle.\r
+\r
+ @retval EFI_SUCCES The protocol was added to ChildHandle.\r
+ @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create\r
+ the child\r
+ @retval other The child handle was not created\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4ServiceBindingCreateChild (\r
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE *ChildHandle\r
+ )\r
+{\r
+ DNS_SERVICE *DnsSb;\r
+ DNS_INSTANCE *Instance;\r
+ EFI_STATUS Status;\r
+ EFI_TPL OldTpl;\r
+ VOID *Udp4;\r
+\r
+ if ((This == NULL) || (ChildHandle == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ DnsSb = DNS_SERVICE_FROM_THIS (This);\r
+\r
+ Status = DnsCreateInstance (DnsSb, &Instance);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ ASSERT (Instance != NULL);\r
+\r
+ //\r
+ // Install the DNS protocol onto ChildHandle\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ ChildHandle,\r
+ &gEfiDns4ProtocolGuid,\r
+ &Instance->Dns4,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ Instance->ChildHandle = *ChildHandle;\r
+\r
+ //\r
+ // Open the Udp4 protocol BY_CHILD.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ DnsSb->ConnectUdp->UdpHandle,\r
+ &gEfiUdp4ProtocolGuid,\r
+ (VOID **) &Udp4,\r
+ gDns4DriverBinding.DriverBindingHandle,\r
+ Instance->ChildHandle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->UninstallMultipleProtocolInterfaces (\r
+ Instance->ChildHandle,\r
+ &gEfiDns4ProtocolGuid,\r
+ &Instance->Dns4,\r
+ NULL\r
+ );\r
+ \r
+ goto ON_ERROR;\r
+ }\r
+\r
+ //\r
+ // Open the Udp4 protocol by child.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Instance->UdpIo->UdpHandle,\r
+ &gEfiUdp4ProtocolGuid,\r
+ (VOID **) &Udp4,\r
+ gDns4DriverBinding.DriverBindingHandle,\r
+ Instance->ChildHandle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Close the Udp4 protocol.\r
+ //\r
+ gBS->CloseProtocol (\r
+ DnsSb->ConnectUdp->UdpHandle,\r
+ &gEfiUdp4ProtocolGuid,\r
+ gDns4DriverBinding.DriverBindingHandle,\r
+ ChildHandle\r
+ );\r
+ \r
+ gBS->UninstallMultipleProtocolInterfaces (\r
+ Instance->ChildHandle,\r
+ &gEfiDns4ProtocolGuid,\r
+ &Instance->Dns4,\r
+ NULL\r
+ );\r
+ \r
+ goto ON_ERROR;\r
+ }\r
+\r
+ //\r
+ // Add it to the parent's child list.\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+ InsertTailList (&DnsSb->Dns4ChildrenList, &Instance->Link);\r
+ DnsSb->Dns4ChildrenNum++;\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ return EFI_SUCCESS;\r
+\r
+ON_ERROR:\r
+\r
+ DnsDestroyInstance (Instance);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Destroys a child handle with a protocol installed on it.\r
+ \r
+ The DestroyChild() function does the opposite of CreateChild(). It removes a protocol \r
+ that was installed by CreateChild() from ChildHandle. If the removed protocol is the \r
+ last protocol on ChildHandle, then ChildHandle is destroyed.\r
+\r
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
+ @param[in] ChildHandle Handle of the child to destroy\r
+\r
+ @retval EFI_SUCCES The protocol was removed from ChildHandle.\r
+ @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.\r
+ @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
+ @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle\r
+ because its services are being used.\r
+ @retval other The child handle was not destroyed\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4ServiceBindingDestroyChild (\r
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ChildHandle\r
+ )\r
+{\r
+ DNS_SERVICE *DnsSb;\r
+ DNS_INSTANCE *Instance;\r
+\r
+ EFI_DNS4_PROTOCOL *Dns4;\r
+ EFI_STATUS Status;\r
+ EFI_TPL OldTpl;\r
+\r
+ if ((This == NULL) || (ChildHandle == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Retrieve the private context data structures\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ChildHandle,\r
+ &gEfiDns4ProtocolGuid,\r
+ (VOID **) &Dns4,\r
+ gDns4DriverBinding.DriverBindingHandle,\r
+ ChildHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (Dns4);\r
+ DnsSb = DNS_SERVICE_FROM_THIS (This);\r
+\r
+ if (Instance->Service != DnsSb) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Instance->InDestroy) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+ \r
+ Instance->InDestroy = TRUE;\r
+\r
+ //\r
+ // Close the Udp4 protocol.\r
+ //\r
+ gBS->CloseProtocol (\r
+ DnsSb->ConnectUdp->UdpHandle,\r
+ &gEfiUdp4ProtocolGuid,\r
+ gDns4DriverBinding.DriverBindingHandle,\r
+ ChildHandle\r
+ );\r
+\r
+ gBS->CloseProtocol (\r
+ Instance->UdpIo->UdpHandle,\r
+ &gEfiUdp4ProtocolGuid,\r
+ gDns4DriverBinding.DriverBindingHandle,\r
+ ChildHandle\r
+ );\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ //\r
+ // Uninstall the DNS protocol first to enable a top down destruction.\r
+ //\r
+ Status = gBS->UninstallProtocolInterface (\r
+ ChildHandle,\r
+ &gEfiDns4ProtocolGuid,\r
+ Dns4\r
+ );\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ Instance->InDestroy = FALSE;\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+ }\r
+\r
+ RemoveEntryList (&Instance->Link);\r
+ DnsSb->Dns4ChildrenNum--;\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ DnsDestroyInstance (Instance);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Creates a child handle and installs a protocol.\r
+ \r
+ The CreateChild() function installs a protocol on ChildHandle. \r
+ If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle. \r
+ If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.\r
+\r
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
+ @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,\r
+ then a new handle is created. If it is a pointer to an existing UEFI handle, \r
+ then the protocol is added to the existing UEFI handle.\r
+\r
+ @retval EFI_SUCCES The protocol was added to ChildHandle.\r
+ @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create\r
+ the child\r
+ @retval other The child handle was not created\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6ServiceBindingCreateChild (\r
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE *ChildHandle\r
+ )\r
+{\r
+ DNS_SERVICE *DnsSb;\r
+ DNS_INSTANCE *Instance;\r
+ EFI_STATUS Status;\r
+ EFI_TPL OldTpl;\r
+ VOID *Udp6;\r
+\r
+ if ((This == NULL) || (ChildHandle == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ DnsSb = DNS_SERVICE_FROM_THIS (This);\r
+\r
+ Status = DnsCreateInstance (DnsSb, &Instance);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ ASSERT (Instance != NULL);\r
+\r
+ //\r
+ // Install the DNS protocol onto ChildHandle\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ ChildHandle,\r
+ &gEfiDns6ProtocolGuid,\r
+ &Instance->Dns6,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ Instance->ChildHandle = *ChildHandle;\r
+\r
+ //\r
+ // Open the Udp6 protocol BY_CHILD.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ DnsSb->ConnectUdp->UdpHandle,\r
+ &gEfiUdp6ProtocolGuid,\r
+ (VOID **) &Udp6,\r
+ gDns6DriverBinding.DriverBindingHandle,\r
+ Instance->ChildHandle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->UninstallMultipleProtocolInterfaces (\r
+ Instance->ChildHandle,\r
+ &gEfiDns6ProtocolGuid,\r
+ &Instance->Dns6,\r
+ NULL\r
+ );\r
+ \r
+ goto ON_ERROR;\r
+ }\r
+\r
+ //\r
+ // Open the Udp6 protocol by child.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Instance->UdpIo->UdpHandle,\r
+ &gEfiUdp6ProtocolGuid,\r
+ (VOID **) &Udp6,\r
+ gDns6DriverBinding.DriverBindingHandle,\r
+ Instance->ChildHandle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Close the Udp6 protocol.\r
+ //\r
+ gBS->CloseProtocol (\r
+ DnsSb->ConnectUdp->UdpHandle,\r
+ &gEfiUdp6ProtocolGuid,\r
+ gDns6DriverBinding.DriverBindingHandle,\r
+ ChildHandle\r
+ );\r
+ \r
+ gBS->UninstallMultipleProtocolInterfaces (\r
+ Instance->ChildHandle,\r
+ &gEfiDns6ProtocolGuid,\r
+ &Instance->Dns6,\r
+ NULL\r
+ );\r
+ \r
+ goto ON_ERROR;\r
+ }\r
+\r
+ //\r
+ // Add it to the parent's child list.\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+ InsertTailList (&DnsSb->Dns6ChildrenList, &Instance->Link);\r
+ DnsSb->Dns6ChildrenNum++;\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ return EFI_SUCCESS;\r
+\r
+ON_ERROR:\r
+\r
+ DnsDestroyInstance (Instance);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Destroys a child handle with a protocol installed on it.\r
+ \r
+ The DestroyChild() function does the opposite of CreateChild(). It removes a protocol \r
+ that was installed by CreateChild() from ChildHandle. If the removed protocol is the \r
+ last protocol on ChildHandle, then ChildHandle is destroyed.\r
+\r
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
+ @param[in] ChildHandle Handle of the child to destroy\r
+\r
+ @retval EFI_SUCCES The protocol was removed from ChildHandle.\r
+ @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.\r
+ @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
+ @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle\r
+ because its services are being used.\r
+ @retval other The child handle was not destroyed\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6ServiceBindingDestroyChild (\r
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ChildHandle\r
+ )\r
+{\r
+ DNS_SERVICE *DnsSb;\r
+ DNS_INSTANCE *Instance;\r
+\r
+ EFI_DNS6_PROTOCOL *Dns6;\r
+ EFI_STATUS Status;\r
+ EFI_TPL OldTpl;\r
+\r
+ if ((This == NULL) || (ChildHandle == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Retrieve the private context data structures\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ChildHandle,\r
+ &gEfiDns6ProtocolGuid,\r
+ (VOID **) &Dns6,\r
+ gDns6DriverBinding.DriverBindingHandle,\r
+ ChildHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL6 (Dns6);\r
+ DnsSb = DNS_SERVICE_FROM_THIS (This);\r
+\r
+ if (Instance->Service != DnsSb) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Instance->InDestroy) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+ Instance->InDestroy = TRUE;\r
+\r
+ //\r
+ // Close the Udp6 protocol.\r
+ //\r
+ gBS->CloseProtocol (\r
+ DnsSb->ConnectUdp->UdpHandle,\r
+ &gEfiUdp6ProtocolGuid,\r
+ gDns6DriverBinding.DriverBindingHandle,\r
+ ChildHandle\r
+ );\r
+\r
+ gBS->CloseProtocol (\r
+ Instance->UdpIo->UdpHandle,\r
+ &gEfiUdp6ProtocolGuid,\r
+ gDns6DriverBinding.DriverBindingHandle,\r
+ ChildHandle\r
+ );\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ //\r
+ // Uninstall the DNS protocol first to enable a top down destruction.\r
+ //\r
+ Status = gBS->UninstallProtocolInterface (\r
+ ChildHandle,\r
+ &gEfiDns6ProtocolGuid,\r
+ Dns6\r
+ );\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Instance->InDestroy = FALSE;\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+ }\r
+\r
+ RemoveEntryList (&Instance->Link);\r
+ DnsSb->Dns6ChildrenNum--;\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ DnsDestroyInstance (Instance);\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @file\r
+The header files of the driver binding and service binding protocol for DnsDxe driver.\r
+\r
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _DNS_DRIVER_H_\r
+#define _DNS_DRIVER_H_\r
+\r
+#include <Protocol/DriverBinding.h>\r
+#include <Protocol/ServiceBinding.h>\r
+\r
+///\r
+/// Dns service block\r
+///\r
+typedef struct _DNS_DRIVER_DATA DNS_DRIVER_DATA;\r
+\r
+///\r
+/// Dns service block\r
+///\r
+typedef struct _DNS_SERVICE DNS_SERVICE;\r
+\r
+///\r
+/// Dns instance block\r
+///\r
+typedef struct _DNS_INSTANCE DNS_INSTANCE;\r
+\r
+#define DNS_SERVICE_SIGNATURE SIGNATURE_32 ('D', 'N', 'S', 'S')\r
+\r
+#define DNS_INSTANCE_SIGNATURE SIGNATURE_32 ('D', 'N', 'S', 'I') \r
+\r
+struct _DNS_DRIVER_DATA {\r
+ EFI_EVENT Timer; /// Ticking timer for DNS cache update.\r
+ \r
+ LIST_ENTRY Dns4CacheList;\r
+ LIST_ENTRY Dns4ServerList;\r
+\r
+ LIST_ENTRY Dns6CacheList;\r
+ LIST_ENTRY Dns6ServerList;\r
+};\r
+\r
+struct _DNS_SERVICE {\r
+ UINT32 Signature;\r
+ EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;\r
+\r
+ UINT16 Dns4ChildrenNum;\r
+ LIST_ENTRY Dns4ChildrenList;\r
+\r
+ UINT16 Dns6ChildrenNum;\r
+ LIST_ENTRY Dns6ChildrenList;\r
+\r
+ EFI_HANDLE ControllerHandle;\r
+ EFI_HANDLE ImageHandle;\r
+ \r
+ EFI_EVENT TimerToGetMap;\r
+\r
+ EFI_EVENT Timer; /// Ticking timer for packet retransmission.\r
+\r
+ UINT8 IpVersion;\r
+ UDP_IO *ConnectUdp;\r
+};\r
+\r
+struct _DNS_INSTANCE {\r
+ UINT32 Signature;\r
+ LIST_ENTRY Link;\r
+ \r
+ EFI_DNS4_PROTOCOL Dns4;\r
+ EFI_DNS6_PROTOCOL Dns6;\r
+ \r
+ INTN State;\r
+ BOOLEAN InDestroy;\r
+\r
+ DNS_SERVICE *Service;\r
+ EFI_HANDLE ChildHandle;\r
+\r
+ EFI_DNS4_CONFIG_DATA Dns4CfgData;\r
+ EFI_DNS6_CONFIG_DATA Dns6CfgData;\r
+\r
+ EFI_IP_ADDRESS SessionDnsServer;\r
+\r
+ NET_MAP Dns4TxTokens;\r
+ NET_MAP Dns6TxTokens;\r
+\r
+ UINT32 MaxRetry;\r
+\r
+ UDP_IO *UdpIo;\r
+};\r
+\r
+typedef struct {\r
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
+ UINTN NumberOfChildren;\r
+ EFI_HANDLE *ChildHandleBuffer;\r
+} DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT;\r
+\r
+extern DNS_DRIVER_DATA *mDriverData;\r
+\r
+#define DNS_SERVICE_FROM_THIS(a) \\r
+ CR (a, DNS_SERVICE, ServiceBinding, DNS_SERVICE_SIGNATURE)\r
+\r
+#define DNS_INSTANCE_FROM_THIS_PROTOCOL4(a) \\r
+ CR (a, DNS_INSTANCE, Dns4, DNS_INSTANCE_SIGNATURE)\r
+\r
+#define DNS_INSTANCE_FROM_THIS_PROTOCOL6(a) \\r
+ CR (a, DNS_INSTANCE, Dns6, DNS_INSTANCE_SIGNATURE)\r
+\r
+\r
+/**\r
+ Destroy the DNS instance and recycle the resources.\r
+\r
+ @param[in] Instance The pointer to the DNS instance.\r
+\r
+**/\r
+VOID\r
+DnsDestroyInstance (\r
+ IN DNS_INSTANCE *Instance\r
+ );\r
+\r
+/**\r
+ Create the DNS instance and initialize it.\r
+\r
+ @param[in] Service The pointer to the DNS service.\r
+ @param[out] Instance The pointer to the DNS instance.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
+ @retval EFI_SUCCESS The DNS instance is created.\r
+\r
+**/\r
+EFI_STATUS\r
+DnsCreateInstance (\r
+ IN DNS_SERVICE *Service,\r
+ OUT DNS_INSTANCE **Instance\r
+ );\r
+\r
+/**\r
+ Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
+ \r
+ @param[in] Entry The entry to be removed.\r
+ @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
+\r
+ @retval EFI_SUCCESS The entry has been removed successfully.\r
+ @retval Others Fail to remove the entry.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DnsDestroyChildEntryInHandleBuffer (\r
+ IN LIST_ENTRY *Entry,\r
+ IN VOID *Context\r
+ );\r
+\r
+/**\r
+ Config a NULL UDP that is used to keep the connection between UDP and DNS.\r
+\r
+ Just leave the Udp child unconfigured. When UDP is unloaded,\r
+ DNS will be informed with DriverBinding Stop.\r
+\r
+ @param UdpIo The UDP_IO to configure\r
+ @param Context The opaque parameter to the callback\r
+\r
+ @retval EFI_SUCCESS It always return EFI_SUCCESS directly.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DnsConfigNullUdp (\r
+ IN UDP_IO *UdpIo,\r
+ IN VOID *Context\r
+ );\r
+\r
+/**\r
+ Release all the resource used the DNS service binding instance.\r
+\r
+ @param DnsSb The Dns service binding instance.\r
+\r
+**/\r
+VOID\r
+DnsDestroyService (\r
+ IN DNS_SERVICE *DnsSb\r
+ );\r
+\r
+/**\r
+ Create then initialize a Dns service binding instance.\r
+\r
+ @param Controller The controller to install the DNS service\r
+ binding on\r
+ @param Image The driver binding image of the DNS driver\r
+ @param IpVersion IpVersion for this service\r
+ @param Service The variable to receive the created service\r
+ binding instance.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance.\r
+ @retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep\r
+ connection with UDP.\r
+ @retval EFI_SUCCESS The service instance is created for the\r
+ controller.\r
+\r
+**/\r
+EFI_STATUS\r
+DnsCreateService (\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_HANDLE Image,\r
+ IN UINT8 IpVersion,\r
+ OUT DNS_SERVICE **Service\r
+ );\r
+\r
+/**\r
+ Unloads an image.\r
+\r
+ @param ImageHandle Handle that identifies the image to be unloaded.\r
+\r
+ @retval EFI_SUCCESS The image has been unloaded.\r
+ @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.\r
+\r
+**/\r
+EFI_STATUS \r
+EFIAPI\r
+DnsUnload (\r
+ IN EFI_HANDLE ImageHandle\r
+ );\r
+\r
+/**\r
+ This is the declaration of an EFI image entry point. This entry point is\r
+ the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
+ both device drivers and bus drivers.\r
+\r
+ @param ImageHandle The firmware allocated handle for the UEFI image.\r
+ @param SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval Others An unexpected error occurred.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DnsDriverEntryPoint (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ );\r
+\r
+/**\r
+ Tests to see if this driver supports a given controller. If a child device is provided, \r
+ it further tests to see if this driver supports creating a handle for the specified child device.\r
+\r
+ This function checks to see if the driver specified by This supports the device specified by \r
+ ControllerHandle. Drivers will typically use the device path attached to \r
+ ControllerHandle and/or the services from the bus I/O abstraction attached to \r
+ ControllerHandle to determine if the driver supports ControllerHandle. This function \r
+ may be called many times during platform initialization. In order to reduce boot times, the tests \r
+ performed by this function must be very small, and take as little time as possible to execute. This \r
+ function must not change the state of any hardware devices, and this function must be aware that the \r
+ device specified by ControllerHandle may already be managed by the same driver or a \r
+ different driver. This function must match its calls to AllocatePages() with FreePages(), \r
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). \r
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is \r
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required \r
+ to guarantee the state of ControllerHandle is not modified by this function.\r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to test. This handle \r
+ must support a protocol interface that supplies \r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
+ parameter is ignored by device drivers, and is optional for bus \r
+ drivers. For bus drivers, if this parameter is not NULL, then \r
+ the bus driver must determine if the bus controller specified \r
+ by ControllerHandle and the child controller specified \r
+ by RemainingDevicePath are both supported by this \r
+ bus driver.\r
+\r
+ @retval EFI_SUCCESS The device specified by ControllerHandle and\r
+ RemainingDevicePath is supported by the driver specified by This.\r
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by the driver\r
+ specified by This.\r
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by a different\r
+ driver or an application that requires exclusive access.\r
+ Currently not implemented.\r
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
+ RemainingDevicePath is not supported by the driver specified by This.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4DriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ );\r
+\r
+/**\r
+ Starts a device controller or a bus controller.\r
+\r
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
+ As a result, much of the error checking on the parameters to Start() has been moved into this \r
+ common boot service. It is legal to call Start() from other locations, \r
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE.\r
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
+ EFI_DEVICE_PATH_PROTOCOL.\r
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. \r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to start. This handle \r
+ must support a protocol interface that supplies \r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
+ parameter is ignored by device drivers, and is optional for bus \r
+ drivers. For a bus driver, if this parameter is NULL, then handles \r
+ for all the children of Controller are created by this driver. \r
+ If this parameter is not NULL and the first Device Path Node is \r
+ not the End of Device Path Node, then only the handle for the \r
+ child device specified by the first Device Path Node of \r
+ RemainingDevicePath is created by this driver.\r
+ If the first Device Path Node of RemainingDevicePath is \r
+ the End of Device Path Node, no child handle is created by this\r
+ driver.\r
+\r
+ @retval EFI_SUCCESS The device was started.\r
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval Others The driver failded to start the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4DriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ );\r
+\r
+/**\r
+ Stops a device controller or a bus controller.\r
+ \r
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). \r
+ As a result, much of the error checking on the parameters to Stop() has been moved \r
+ into this common boot service. It is legal to call Stop() from other locations, \r
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
+ same driver's Start() function.\r
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
+ Start() function, and the Start() function must have called OpenProtocol() on\r
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
+ \r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must \r
+ support a bus specific I/O protocol for the driver \r
+ to use to stop the device.\r
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL \r
+ if NumberOfChildren is 0.\r
+\r
+ @retval EFI_SUCCESS The device was stopped.\r
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4DriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
+ );\r
+\r
+/**\r
+ Tests to see if this driver supports a given controller. If a child device is provided, \r
+ it further tests to see if this driver supports creating a handle for the specified child device.\r
+\r
+ This function checks to see if the driver specified by This supports the device specified by \r
+ ControllerHandle. Drivers will typically use the device path attached to \r
+ ControllerHandle and/or the services from the bus I/O abstraction attached to \r
+ ControllerHandle to determine if the driver supports ControllerHandle. This function \r
+ may be called many times during platform initialization. In order to reduce boot times, the tests \r
+ performed by this function must be very small, and take as little time as possible to execute. This \r
+ function must not change the state of any hardware devices, and this function must be aware that the \r
+ device specified by ControllerHandle may already be managed by the same driver or a \r
+ different driver. This function must match its calls to AllocatePages() with FreePages(), \r
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). \r
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is \r
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required \r
+ to guarantee the state of ControllerHandle is not modified by this function.\r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to test. This handle \r
+ must support a protocol interface that supplies \r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
+ parameter is ignored by device drivers, and is optional for bus \r
+ drivers. For bus drivers, if this parameter is not NULL, then \r
+ the bus driver must determine if the bus controller specified \r
+ by ControllerHandle and the child controller specified \r
+ by RemainingDevicePath are both supported by this \r
+ bus driver.\r
+\r
+ @retval EFI_SUCCESS The device specified by ControllerHandle and\r
+ RemainingDevicePath is supported by the driver specified by This.\r
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by the driver\r
+ specified by This.\r
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by a different\r
+ driver or an application that requires exclusive access.\r
+ Currently not implemented.\r
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
+ RemainingDevicePath is not supported by the driver specified by This.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6DriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ );\r
+\r
+/**\r
+ Starts a device controller or a bus controller.\r
+\r
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
+ As a result, much of the error checking on the parameters to Start() has been moved into this \r
+ common boot service. It is legal to call Start() from other locations, \r
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE.\r
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
+ EFI_DEVICE_PATH_PROTOCOL.\r
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. \r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to start. This handle \r
+ must support a protocol interface that supplies \r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
+ parameter is ignored by device drivers, and is optional for bus \r
+ drivers. For a bus driver, if this parameter is NULL, then handles \r
+ for all the children of Controller are created by this driver. \r
+ If this parameter is not NULL and the first Device Path Node is \r
+ not the End of Device Path Node, then only the handle for the \r
+ child device specified by the first Device Path Node of \r
+ RemainingDevicePath is created by this driver.\r
+ If the first Device Path Node of RemainingDevicePath is \r
+ the End of Device Path Node, no child handle is created by this\r
+ driver.\r
+\r
+ @retval EFI_SUCCESS The device was started.\r
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval Others The driver failded to start the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6DriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ );\r
+\r
+/**\r
+ Stops a device controller or a bus controller.\r
+ \r
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). \r
+ As a result, much of the error checking on the parameters to Stop() has been moved \r
+ into this common boot service. It is legal to call Stop() from other locations, \r
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
+ same driver's Start() function.\r
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
+ Start() function, and the Start() function must have called OpenProtocol() on\r
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
+ \r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must \r
+ support a bus specific I/O protocol for the driver \r
+ to use to stop the device.\r
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL \r
+ if NumberOfChildren is 0.\r
+\r
+ @retval EFI_SUCCESS The device was stopped.\r
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6DriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
+ );\r
+\r
+/**\r
+ Creates a child handle and installs a protocol.\r
+ \r
+ The CreateChild() function installs a protocol on ChildHandle. \r
+ If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle. \r
+ If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.\r
+\r
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
+ @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,\r
+ then a new handle is created. If it is a pointer to an existing UEFI handle, \r
+ then the protocol is added to the existing UEFI handle.\r
+\r
+ @retval EFI_SUCCES The protocol was added to ChildHandle.\r
+ @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create\r
+ the child\r
+ @retval other The child handle was not created\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4ServiceBindingCreateChild (\r
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE *ChildHandle\r
+ );\r
+\r
+/**\r
+ Destroys a child handle with a protocol installed on it.\r
+ \r
+ The DestroyChild() function does the opposite of CreateChild(). It removes a protocol \r
+ that was installed by CreateChild() from ChildHandle. If the removed protocol is the \r
+ last protocol on ChildHandle, then ChildHandle is destroyed.\r
+\r
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
+ @param[in] ChildHandle Handle of the child to destroy\r
+\r
+ @retval EFI_SUCCES The protocol was removed from ChildHandle.\r
+ @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.\r
+ @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
+ @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle\r
+ because its services are being used.\r
+ @retval other The child handle was not destroyed\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4ServiceBindingDestroyChild (\r
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ChildHandle\r
+ );\r
+\r
+/**\r
+ Creates a child handle and installs a protocol.\r
+ \r
+ The CreateChild() function installs a protocol on ChildHandle. \r
+ If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle. \r
+ If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.\r
+\r
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
+ @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,\r
+ then a new handle is created. If it is a pointer to an existing UEFI handle, \r
+ then the protocol is added to the existing UEFI handle.\r
+\r
+ @retval EFI_SUCCES The protocol was added to ChildHandle.\r
+ @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create\r
+ the child\r
+ @retval other The child handle was not created\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6ServiceBindingCreateChild (\r
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE *ChildHandle\r
+ );\r
+\r
+/**\r
+ Destroys a child handle with a protocol installed on it.\r
+ \r
+ The DestroyChild() function does the opposite of CreateChild(). It removes a protocol \r
+ that was installed by CreateChild() from ChildHandle. If the removed protocol is the \r
+ last protocol on ChildHandle, then ChildHandle is destroyed.\r
+\r
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
+ @param[in] ChildHandle Handle of the child to destroy\r
+\r
+ @retval EFI_SUCCES The protocol was removed from ChildHandle.\r
+ @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.\r
+ @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
+ @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle\r
+ because its services are being used.\r
+ @retval other The child handle was not destroyed\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6ServiceBindingDestroyChild (\r
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ChildHandle\r
+ );\r
+\r
+\r
+#endif\r
--- /dev/null
+## @file\r
+# Implementation of EFI_DNS4_PROTOCOL and EFI_DNS6_PROTOCOL interfaces.\r
+#\r
+# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = DnsDxe\r
+ FILE_GUID = b219e140-dffc-11e3-b956-0022681e6906\r
+ MODULE_TYPE = UEFI_DRIVER\r
+ VERSION_STRING = 1.0\r
+ ENTRY_POINT = DnsDriverEntryPoint\r
+ UNLOAD_IMAGE = DnsUnload\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+\r
+[Sources]\r
+ ComponentName.c\r
+ DnsDriver.h\r
+ DnsDriver.c\r
+ DnsImpl.h\r
+ DnsImpl.c\r
+ DnsProtocol.c\r
+ DnsDhcp.h\r
+ DnsDhcp.c\r
+ \r
+ \r
+[LibraryClasses]\r
+ BaseLib\r
+ UefiLib\r
+ UefiBootServicesTableLib\r
+ UefiDriverEntryPoint\r
+ UefiRuntimeServicesTableLib\r
+ BaseMemoryLib\r
+ MemoryAllocationLib\r
+ NetLib\r
+ DebugLib\r
+ DpcLib\r
+ PrintLib\r
+ UdpIoLib\r
+ \r
+\r
+[Protocols]\r
+ gEfiDns4ServiceBindingProtocolGuid ## BY_START\r
+ gEfiDns4ProtocolGuid ## BY_START\r
+ gEfiUdp4ServiceBindingProtocolGuid ## TO_START\r
+ gEfiUdp4ProtocolGuid ## BY_START\r
+ gEfiDhcp4ServiceBindingProtocolGuid ## SOMETIMES_CONSUMES\r
+ gEfiDhcp4ProtocolGuid ## SOMETIMES_CONSUMES\r
+ gEfiIp4Config2ProtocolGuid ## SOMETIMES_CONSUMES\r
+ gEfiManagedNetworkServiceBindingProtocolGuid ## SOMETIMES_CONSUMES\r
+ gEfiManagedNetworkProtocolGuid ## SOMETIMES_CONSUMES\r
+ \r
+ gEfiDns6ServiceBindingProtocolGuid ## BY_START\r
+ gEfiDns6ProtocolGuid ## BY_START\r
+ gEfiUdp6ServiceBindingProtocolGuid ## TO_START\r
+ gEfiUdp6ProtocolGuid ## TO_START\r
+ gEfiDhcp6ServiceBindingProtocolGuid ## SOMETIMES_CONSUMES\r
+ gEfiDhcp6ProtocolGuid ## SOMETIMES_CONSUMES\r
+\r
+\r
+[Guids]\r
+\r
--- /dev/null
+/** @file\r
+DnsDxe support functions implementation.\r
+ \r
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "DnsImpl.h"\r
+\r
+/**\r
+ Remove TokenEntry from TokenMap.\r
+\r
+ @param[in] TokenMap All DNSv4 Token entrys.\r
+ @param[in] TokenEntry TokenEntry need to be removed.\r
+\r
+ @retval EFI_SUCCESS Remove TokenEntry from TokenMap sucessfully.\r
+ @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap.\r
+\r
+**/\r
+EFI_STATUS\r
+Dns4RemoveTokenEntry (\r
+ IN NET_MAP *TokenMap,\r
+ IN DNS4_TOKEN_ENTRY *TokenEntry\r
+ )\r
+{\r
+ NET_MAP_ITEM *Item;\r
+\r
+ //\r
+ // Find the TokenEntry first.\r
+ //\r
+ Item = NetMapFindKey (TokenMap, (VOID *) TokenEntry);\r
+\r
+ if (Item != NULL) {\r
+ //\r
+ // Remove the TokenEntry if it's found in the map.\r
+ //\r
+ NetMapRemoveItem (TokenMap, Item, NULL);\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ \r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ Remove TokenEntry from TokenMap.\r
+\r
+ @param[in] TokenMap All DNSv6 Token entrys.\r
+ @param[in] TokenEntry TokenEntry need to be removed.\r
+\r
+ @retval EFI_SUCCESS Remove TokenEntry from TokenMap sucessfully.\r
+ @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap.\r
+ \r
+**/\r
+EFI_STATUS\r
+Dns6RemoveTokenEntry (\r
+ IN NET_MAP *TokenMap,\r
+ IN DNS6_TOKEN_ENTRY *TokenEntry\r
+ )\r
+{\r
+ NET_MAP_ITEM *Item;\r
+\r
+ //\r
+ // Find the TokenEntry first.\r
+ //\r
+ Item = NetMapFindKey (TokenMap, (VOID *) TokenEntry);\r
+\r
+ if (Item != NULL) {\r
+ //\r
+ // Remove the TokenEntry if it's found in the map.\r
+ //\r
+ NetMapRemoveItem (TokenMap, Item, NULL);\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ \r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ This function cancle the token specified by Arg in the Map.\r
+\r
+ @param[in] Map Pointer to the NET_MAP.\r
+ @param[in] Item Pointer to the NET_MAP_ITEM.\r
+ @param[in] Arg Pointer to the token to be cancelled. If NULL, all\r
+ the tokens in this Map will be cancelled.\r
+ This parameter is optional and may be NULL.\r
+\r
+ @retval EFI_SUCCESS The token is cancelled if Arg is NULL, or the token\r
+ is not the same as that in the Item, if Arg is not\r
+ NULL.\r
+ @retval EFI_ABORTED Arg is not NULL, and the token specified by Arg is\r
+ cancelled.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4CancelTokens (\r
+ IN NET_MAP *Map,\r
+ IN NET_MAP_ITEM *Item,\r
+ IN VOID *Arg OPTIONAL\r
+ )\r
+{\r
+ DNS4_TOKEN_ENTRY *TokenEntry;\r
+ NET_BUF *Packet;\r
+ UDP_IO *UdpIo;\r
+\r
+ if ((Arg != NULL) && (Item->Key != Arg)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (Item->Value != NULL) {\r
+ //\r
+ // If the TokenEntry is a transmit TokenEntry, the corresponding Packet is recorded in\r
+ // Item->Value.\r
+ //\r
+ Packet = (NET_BUF *) (Item->Value);\r
+ UdpIo = (UDP_IO *) (*((UINTN *) &Packet->ProtoData[0]));\r
+\r
+ UdpIoCancelSentDatagram (UdpIo, Packet);\r
+ }\r
+\r
+ //\r
+ // Remove TokenEntry from Dns4TxTokens.\r
+ //\r
+ TokenEntry = (DNS4_TOKEN_ENTRY *) Item->Key;\r
+ if (Dns4RemoveTokenEntry (Map, TokenEntry) == EFI_SUCCESS) {\r
+ TokenEntry->Token->Status = EFI_ABORTED;\r
+ gBS->SignalEvent (TokenEntry->Token->Event);\r
+ DispatchDpc ();\r
+ }\r
+\r
+ if (Arg != NULL) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function cancle the token specified by Arg in the Map.\r
+\r
+ @param[in] Map Pointer to the NET_MAP.\r
+ @param[in] Item Pointer to the NET_MAP_ITEM.\r
+ @param[in] Arg Pointer to the token to be cancelled. If NULL, all\r
+ the tokens in this Map will be cancelled.\r
+ This parameter is optional and may be NULL.\r
+\r
+ @retval EFI_SUCCESS The token is cancelled if Arg is NULL, or the token\r
+ is not the same as that in the Item, if Arg is not\r
+ NULL.\r
+ @retval EFI_ABORTED Arg is not NULL, and the token specified by Arg is\r
+ cancelled.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6CancelTokens (\r
+ IN NET_MAP *Map,\r
+ IN NET_MAP_ITEM *Item,\r
+ IN VOID *Arg OPTIONAL\r
+ )\r
+{\r
+ DNS6_TOKEN_ENTRY *TokenEntry;\r
+ NET_BUF *Packet;\r
+ UDP_IO *UdpIo;\r
+\r
+ if ((Arg != NULL) && (Item->Key != Arg)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (Item->Value != NULL) {\r
+ //\r
+ // If the TokenEntry is a transmit TokenEntry, the corresponding Packet is recorded in\r
+ // Item->Value.\r
+ //\r
+ Packet = (NET_BUF *) (Item->Value);\r
+ UdpIo = (UDP_IO *) (*((UINTN *) &Packet->ProtoData[0]));\r
+\r
+ UdpIoCancelSentDatagram (UdpIo, Packet);\r
+ }\r
+\r
+ //\r
+ // Remove TokenEntry from Dns6TxTokens.\r
+ //\r
+ TokenEntry = (DNS6_TOKEN_ENTRY *) Item->Key;\r
+ if (Dns6RemoveTokenEntry (Map, TokenEntry) == EFI_SUCCESS) {\r
+ TokenEntry->Token->Status = EFI_ABORTED;\r
+ gBS->SignalEvent (TokenEntry->Token->Event);\r
+ DispatchDpc ();\r
+ }\r
+\r
+ if (Arg != NULL) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Get the TokenEntry from the TokensMap.\r
+\r
+ @param[in] TokensMap All DNSv4 Token entrys\r
+ @param[in] Token Pointer to the token to be get.\r
+ @param[out] TokenEntry Pointer to TokenEntry corresponding Token.\r
+\r
+ @retval EFI_SUCCESS Get the TokenEntry from the TokensMap sucessfully.\r
+ @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetDns4TokenEntry (\r
+ IN NET_MAP *TokensMap,\r
+ IN EFI_DNS4_COMPLETION_TOKEN *Token, \r
+ OUT DNS4_TOKEN_ENTRY **TokenEntry\r
+ )\r
+{\r
+ LIST_ENTRY *Entry;\r
+ \r
+ NET_MAP_ITEM *Item;\r
+ \r
+ NET_LIST_FOR_EACH (Entry, &TokensMap->Used) {\r
+ Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);\r
+ *TokenEntry = (DNS4_TOKEN_ENTRY *) (Item->Key); \r
+ if ((*TokenEntry)->Token == Token) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ \r
+ *TokenEntry = NULL;\r
+ \r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ Get the TokenEntry from the TokensMap.\r
+\r
+ @param[in] TokensMap All DNSv6 Token entrys\r
+ @param[in] Token Pointer to the token to be get.\r
+ @param[out] TokenEntry Pointer to TokenEntry corresponding Token.\r
+\r
+ @retval EFI_SUCCESS Get the TokenEntry from the TokensMap sucessfully.\r
+ @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetDns6TokenEntry (\r
+ IN NET_MAP *TokensMap,\r
+ IN EFI_DNS6_COMPLETION_TOKEN *Token, \r
+ OUT DNS6_TOKEN_ENTRY **TokenEntry\r
+ )\r
+{\r
+ LIST_ENTRY *Entry;\r
+ \r
+ NET_MAP_ITEM *Item;\r
+ \r
+ NET_LIST_FOR_EACH (Entry, &TokensMap->Used) {\r
+ Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);\r
+ *TokenEntry = (DNS6_TOKEN_ENTRY *) (Item->Key); \r
+ if ((*TokenEntry)->Token == Token) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ \r
+ *TokenEntry =NULL;\r
+ \r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ Cancel DNS4 tokens from the DNS4 instance.\r
+\r
+ @param[in] Instance Pointer to the DNS instance context data.\r
+ @param[in] Token Pointer to the token to be canceled. If NULL, all\r
+ tokens in this instance will be cancelled.\r
+ This parameter is optional and may be NULL.\r
+\r
+ @retval EFI_SUCCESS The Token is cancelled.\r
+ @retval EFI_NOT_FOUND The Token is not found.\r
+\r
+**/\r
+EFI_STATUS\r
+Dns4InstanceCancelToken (\r
+ IN DNS_INSTANCE *Instance,\r
+ IN EFI_DNS4_COMPLETION_TOKEN *Token\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ DNS4_TOKEN_ENTRY *TokenEntry;\r
+\r
+ TokenEntry = NULL;\r
+\r
+ if(Token != NULL ) {\r
+ Status = GetDns4TokenEntry (&Instance->Dns4TxTokens, Token, &TokenEntry);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ } else {\r
+ TokenEntry = NULL;\r
+ }\r
+\r
+ //\r
+ // Cancel this TokenEntry from the Dns4TxTokens map.\r
+ //\r
+ Status = NetMapIterate (&Instance->Dns4TxTokens, Dns4CancelTokens, TokenEntry);\r
+\r
+ if ((TokenEntry != NULL) && (Status == EFI_ABORTED)) {\r
+ //\r
+ // If Token isn't NULL and Status is EFI_ABORTED, the token is cancelled from\r
+ // the Dns4TxTokens and returns success.\r
+ //\r
+ if (NetMapIsEmpty (&Instance->Dns4TxTokens)) {\r
+ Instance->UdpIo->Protocol.Udp4->Cancel (Instance->UdpIo->Protocol.Udp4, &Instance->UdpIo->RecvRequest->Token.Udp4);\r
+ }\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ ASSERT ((TokenEntry != NULL) || (0 == NetMapGetCount (&Instance->Dns4TxTokens)));\r
+ \r
+ if (NetMapIsEmpty (&Instance->Dns4TxTokens)) {\r
+ Instance->UdpIo->Protocol.Udp4->Cancel (Instance->UdpIo->Protocol.Udp4, &Instance->UdpIo->RecvRequest->Token.Udp4);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Cancel DNS6 tokens from the DNS6 instance.\r
+\r
+ @param[in] Instance Pointer to the DNS instance context data.\r
+ @param[in] Token Pointer to the token to be canceled. If NULL, all\r
+ tokens in this instance will be cancelled.\r
+ This parameter is optional and may be NULL.\r
+\r
+ @retval EFI_SUCCESS The Token is cancelled.\r
+ @retval EFI_NOT_FOUND The Token is not found.\r
+\r
+**/\r
+EFI_STATUS\r
+Dns6InstanceCancelToken (\r
+ IN DNS_INSTANCE *Instance,\r
+ IN EFI_DNS6_COMPLETION_TOKEN *Token\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ DNS6_TOKEN_ENTRY *TokenEntry;\r
+\r
+ TokenEntry = NULL;\r
+\r
+ if(Token != NULL ) {\r
+ Status = GetDns6TokenEntry (&Instance->Dns6TxTokens, Token, &TokenEntry);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ } else {\r
+ TokenEntry = NULL;\r
+ }\r
+\r
+ //\r
+ // Cancel this TokenEntry from the Dns6TxTokens map.\r
+ //\r
+ Status = NetMapIterate (&Instance->Dns6TxTokens, Dns6CancelTokens, TokenEntry);\r
+\r
+ if ((TokenEntry != NULL) && (Status == EFI_ABORTED)) {\r
+ //\r
+ // If Token isn't NULL and Status is EFI_ABORTED, the token is cancelled from\r
+ // the Dns6TxTokens and returns success.\r
+ //\r
+ if (NetMapIsEmpty (&Instance->Dns6TxTokens)) {\r
+ Instance->UdpIo->Protocol.Udp6->Cancel (Instance->UdpIo->Protocol.Udp6, &Instance->UdpIo->RecvRequest->Token.Udp6);\r
+ }\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ ASSERT ((TokenEntry != NULL) || (0 == NetMapGetCount (&Instance->Dns6TxTokens)));\r
+ \r
+ if (NetMapIsEmpty (&Instance->Dns6TxTokens)) {\r
+ Instance->UdpIo->Protocol.Udp6->Cancel (Instance->UdpIo->Protocol.Udp6, &Instance->UdpIo->RecvRequest->Token.Udp6);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Free the resource related to the configure parameters.\r
+\r
+ @param Config The DNS configure data\r
+\r
+**/\r
+VOID\r
+Dns4CleanConfigure (\r
+ IN OUT EFI_DNS4_CONFIG_DATA *Config\r
+ )\r
+{\r
+ if (Config->DnsServerList != NULL) {\r
+ FreePool (Config->DnsServerList);\r
+ }\r
+\r
+ ZeroMem (Config, sizeof (EFI_DNS4_CONFIG_DATA));\r
+}\r
+\r
+/**\r
+ Free the resource related to the configure parameters.\r
+\r
+ @param Config The DNS configure data\r
+\r
+**/\r
+VOID\r
+Dns6CleanConfigure (\r
+ IN OUT EFI_DNS6_CONFIG_DATA *Config\r
+ )\r
+{\r
+ if (Config->DnsServerList != NULL) {\r
+ FreePool (Config->DnsServerList);\r
+ }\r
+\r
+ ZeroMem (Config, sizeof (EFI_DNS6_CONFIG_DATA));\r
+}\r
+\r
+/**\r
+ Allocate memory for configure parameter such as timeout value for Dst,\r
+ then copy the configure parameter from Src to Dst.\r
+\r
+ @param[out] Dst The destination DHCP configure data.\r
+ @param[in] Src The source DHCP configure data.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
+ @retval EFI_SUCCESS The configure is copied.\r
+\r
+**/\r
+EFI_STATUS\r
+Dns4CopyConfigure (\r
+ OUT EFI_DNS4_CONFIG_DATA *Dst,\r
+ IN EFI_DNS4_CONFIG_DATA *Src\r
+ )\r
+{\r
+ UINTN Len;\r
+ UINT32 Index;\r
+\r
+ CopyMem (Dst, Src, sizeof (*Dst));\r
+ Dst->DnsServerList = NULL;\r
+\r
+ //\r
+ // Allocate a memory then copy DnsServerList to it\r
+ //\r
+ if (Src->DnsServerList != NULL) {\r
+ Len = Src->DnsServerListCount * sizeof (EFI_IPv4_ADDRESS);\r
+ Dst->DnsServerList = AllocatePool (Len);\r
+ if (Dst->DnsServerList == NULL) {\r
+ Dns4CleanConfigure (Dst);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for (Index = 0; Index < Src->DnsServerListCount; Index++) {\r
+ CopyMem (&Dst->DnsServerList[Index], &Src->DnsServerList[Index], sizeof (EFI_IPv4_ADDRESS));\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Allocate memory for configure parameter such as timeout value for Dst,\r
+ then copy the configure parameter from Src to Dst.\r
+\r
+ @param[out] Dst The destination DHCP configure data.\r
+ @param[in] Src The source DHCP configure data.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
+ @retval EFI_SUCCESS The configure is copied.\r
+\r
+**/\r
+EFI_STATUS\r
+Dns6CopyConfigure (\r
+ OUT EFI_DNS6_CONFIG_DATA *Dst,\r
+ IN EFI_DNS6_CONFIG_DATA *Src\r
+ )\r
+{\r
+ UINTN Len;\r
+ UINT32 Index;\r
+\r
+ CopyMem (Dst, Src, sizeof (*Dst));\r
+ Dst->DnsServerList = NULL;\r
+\r
+ //\r
+ // Allocate a memory then copy DnsServerList to it\r
+ //\r
+ if (Src->DnsServerList != NULL) {\r
+ Len = Src->DnsServerCount * sizeof (EFI_IPv6_ADDRESS);\r
+ Dst->DnsServerList = AllocatePool (Len);\r
+ if (Dst->DnsServerList == NULL) {\r
+ Dns6CleanConfigure (Dst);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for (Index = 0; Index < Src->DnsServerCount; Index++) {\r
+ CopyMem (&Dst->DnsServerList[Index], &Src->DnsServerList[Index], sizeof (EFI_IPv6_ADDRESS));\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Callback of Dns packet. Does nothing.\r
+\r
+ @param Arg The context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DnsDummyExtFree (\r
+ IN VOID *Arg\r
+ )\r
+{\r
+}\r
+\r
+/**\r
+ Poll the UDP to get the IP4 default address, which may be retrieved\r
+ by DHCP. \r
+ \r
+ The default time out value is 5 seconds. If IP has retrieved the default address, \r
+ the UDP is reconfigured.\r
+\r
+ @param Instance The DNS instance\r
+ @param UdpIo The UDP_IO to poll\r
+ @param UdpCfgData The UDP configure data to reconfigure the UDP_IO\r
+\r
+ @retval TRUE The default address is retrieved and UDP is reconfigured.\r
+ @retval FALSE Some error occured.\r
+\r
+**/\r
+BOOLEAN\r
+Dns4GetMapping (\r
+ IN DNS_INSTANCE *Instance,\r
+ IN UDP_IO *UdpIo,\r
+ IN EFI_UDP4_CONFIG_DATA *UdpCfgData\r
+ )\r
+{\r
+ DNS_SERVICE *Service;\r
+ EFI_IP4_MODE_DATA Ip4Mode;\r
+ EFI_UDP4_PROTOCOL *Udp;\r
+ EFI_STATUS Status;\r
+\r
+ ASSERT (Instance->Dns4CfgData.UseDefaultSetting);\r
+\r
+ Service = Instance->Service;\r
+ Udp = UdpIo->Protocol.Udp4;\r
+\r
+ Status = gBS->SetTimer (\r
+ Service->TimerToGetMap,\r
+ TimerRelative,\r
+ DNS_TIME_TO_GETMAP * TICKS_PER_SECOND\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ while (!EFI_ERROR (gBS->CheckEvent (Service->TimerToGetMap))) {\r
+ Udp->Poll (Udp);\r
+\r
+ if (!EFI_ERROR (Udp->GetModeData (Udp, NULL, &Ip4Mode, NULL, NULL)) &&\r
+ Ip4Mode.IsConfigured) {\r
+\r
+ Udp->Configure (Udp, NULL);\r
+ return (BOOLEAN) (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS);\r
+ }\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Configure the opened Udp6 instance until the corresponding Ip6 instance\r
+ has been configured.\r
+\r
+ @param Instance The DNS instance\r
+ @param UdpIo The UDP_IO to poll\r
+ @param UdpCfgData The UDP configure data to reconfigure the UDP_IO\r
+\r
+ @retval TRUE Configure the Udp6 instance successfully.\r
+ @retval FALSE Some error occured.\r
+\r
+**/\r
+BOOLEAN\r
+Dns6GetMapping (\r
+ IN DNS_INSTANCE *Instance,\r
+ IN UDP_IO *UdpIo,\r
+ IN EFI_UDP6_CONFIG_DATA *UdpCfgData\r
+ )\r
+{\r
+ DNS_SERVICE *Service;\r
+ EFI_IP6_MODE_DATA Ip6Mode;\r
+ EFI_UDP6_PROTOCOL *Udp;\r
+ EFI_STATUS Status;\r
+\r
+ Service = Instance->Service;\r
+ Udp = UdpIo->Protocol.Udp6;\r
+\r
+ Status = gBS->SetTimer (\r
+ Service->TimerToGetMap,\r
+ TimerRelative,\r
+ DNS_TIME_TO_GETMAP * TICKS_PER_SECOND\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ while (!EFI_ERROR (gBS->CheckEvent (Service->TimerToGetMap))) {\r
+ Udp->Poll (Udp);\r
+\r
+ if (!EFI_ERROR (Udp->GetModeData (Udp, NULL, &Ip6Mode, NULL, NULL)) &&\r
+ Ip6Mode.IsConfigured) {\r
+\r
+ Udp->Configure (Udp, NULL);\r
+ return (BOOLEAN) (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS);\r
+ }\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Configure the UDP.\r
+ \r
+ @param Instance The DNS session\r
+ @param UdpIo The UDP_IO instance\r
+ \r
+ @retval EFI_SUCCESS The UDP is successfully configured for the\r
+ session.\r
+\r
+**/\r
+EFI_STATUS\r
+Dns4ConfigUdp (\r
+ IN DNS_INSTANCE *Instance,\r
+ IN UDP_IO *UdpIo\r
+ )\r
+{\r
+ EFI_DNS4_CONFIG_DATA *Config;\r
+ EFI_UDP4_CONFIG_DATA UdpConfig;\r
+ EFI_STATUS Status;\r
+\r
+ Config = &Instance->Dns4CfgData;\r
+\r
+ UdpConfig.AcceptBroadcast = FALSE;\r
+ UdpConfig.AcceptPromiscuous = FALSE;\r
+ UdpConfig.AcceptAnyPort = FALSE;\r
+ UdpConfig.AllowDuplicatePort = FALSE;\r
+ UdpConfig.TypeOfService = 0;\r
+ UdpConfig.TimeToLive = 128;\r
+ UdpConfig.DoNotFragment = FALSE;\r
+ UdpConfig.ReceiveTimeout = 0;\r
+ UdpConfig.TransmitTimeout = 0;\r
+ UdpConfig.UseDefaultAddress = Config->UseDefaultSetting;\r
+ UdpConfig.SubnetMask = Config->SubnetMask;\r
+ UdpConfig.StationPort = Config->LocalPort;\r
+ UdpConfig.RemotePort = DNS_SERVER_PORT;\r
+\r
+ CopyMem (&UdpConfig.StationAddress, &Config->StationIp, sizeof (EFI_IPv4_ADDRESS));\r
+ CopyMem (&UdpConfig.RemoteAddress, &Instance->SessionDnsServer.v4, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+ Status = UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfig);\r
+\r
+ if ((Status == EFI_NO_MAPPING) && Dns4GetMapping (Instance, UdpIo, &UdpConfig)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ \r
+ return Status;\r
+}\r
+\r
+/**\r
+ Configure the UDP.\r
+ \r
+ @param Instance The DNS session\r
+ @param UdpIo The UDP_IO instance\r
+\r
+ @retval EFI_SUCCESS The UDP is successfully configured for the\r
+ session.\r
+\r
+**/\r
+EFI_STATUS\r
+Dns6ConfigUdp (\r
+ IN DNS_INSTANCE *Instance,\r
+ IN UDP_IO *UdpIo\r
+ )\r
+{\r
+ EFI_DNS6_CONFIG_DATA *Config;\r
+ EFI_UDP6_CONFIG_DATA UdpConfig;\r
+ EFI_STATUS Status;\r
+\r
+ Config = &Instance->Dns6CfgData;\r
+\r
+ UdpConfig.AcceptPromiscuous = FALSE;\r
+ UdpConfig.AcceptAnyPort = FALSE;\r
+ UdpConfig.AllowDuplicatePort = FALSE;\r
+ UdpConfig.TrafficClass = 0;\r
+ UdpConfig.HopLimit = 128;\r
+ UdpConfig.ReceiveTimeout = 0;\r
+ UdpConfig.TransmitTimeout = 0;\r
+ UdpConfig.StationPort = Config->LocalPort;\r
+ UdpConfig.RemotePort = DNS_SERVER_PORT;\r
+ CopyMem (&UdpConfig.StationAddress, &Config->StationIp, sizeof (EFI_IPv6_ADDRESS));\r
+ CopyMem (&UdpConfig.RemoteAddress, &Instance->SessionDnsServer.v6, sizeof (EFI_IPv6_ADDRESS));\r
+\r
+ Status = UdpIo->Protocol.Udp6->Configure (UdpIo->Protocol.Udp6, &UdpConfig);\r
+\r
+ if ((Status == EFI_NO_MAPPING) && Dns6GetMapping (Instance, UdpIo, &UdpConfig)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ \r
+ return Status;\r
+}\r
+\r
+/**\r
+ Update Dns4 cache to shared list of caches of all DNSv4 instances.\r
+ \r
+ @param Dns4CacheList All Dns4 cache list.\r
+ @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache. \r
+ If TRUE, this function will delete matching DNS Cache entry. \r
+ @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter. \r
+ If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.\r
+ @param DnsCacheEntry Entry Pointer to DNS Cache entry.\r
+\r
+ @retval EFI_SUCCESS Update Dns4 cache successfully.\r
+ @retval Others Failed to update Dns4 cache. \r
+ \r
+**/ \r
+EFI_STATUS\r
+EFIAPI\r
+UpdateDns4Cache (\r
+ IN LIST_ENTRY *Dns4CacheList,\r
+ IN BOOLEAN DeleteFlag,\r
+ IN BOOLEAN Override,\r
+ IN EFI_DNS4_CACHE_ENTRY DnsCacheEntry\r
+ )\r
+{\r
+ DNS4_CACHE *NewDnsCache; \r
+ DNS4_CACHE *Item;\r
+ LIST_ENTRY *Entry;\r
+ LIST_ENTRY *Next;\r
+\r
+ NewDnsCache = NULL;\r
+ Item = NULL;\r
+ \r
+ //\r
+ // Search the database for the matching EFI_DNS_CACHE_ENTRY\r
+ //\r
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns4CacheList) {\r
+ Item = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);\r
+ if (StrCmp (DnsCacheEntry.HostName, Item->DnsCache.HostName) == 0 && \\r
+ CompareMem (DnsCacheEntry.IpAddress, Item->DnsCache.IpAddress, sizeof (EFI_IPv4_ADDRESS)) == 0) {\r
+ //\r
+ // This is the Dns cache entry\r
+ //\r
+ if (DeleteFlag) {\r
+ //\r
+ // Delete matching DNS Cache entry\r
+ //\r
+ RemoveEntryList (&Item->AllCacheLink);\r
+ \r
+ return EFI_SUCCESS;\r
+ } else if (Override) {\r
+ //\r
+ // Update this one\r
+ //\r
+ Item->DnsCache.Timeout = DnsCacheEntry.Timeout;\r
+ \r
+ return EFI_SUCCESS;\r
+ }else {\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Add new one\r
+ //\r
+ NewDnsCache = AllocatePool (sizeof (DNS4_CACHE));\r
+ if (NewDnsCache == NULL) { \r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ \r
+ InitializeListHead (&NewDnsCache->AllCacheLink);\r
+ \r
+ NewDnsCache->DnsCache.HostName = AllocatePool (StrSize (DnsCacheEntry.HostName));\r
+ if (NewDnsCache->DnsCache.HostName == NULL) { \r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ \r
+ CopyMem (NewDnsCache->DnsCache.HostName, DnsCacheEntry.HostName, StrSize (DnsCacheEntry.HostName));\r
+\r
+ NewDnsCache->DnsCache.IpAddress = AllocatePool (sizeof (EFI_IPv4_ADDRESS));\r
+ if (NewDnsCache->DnsCache.IpAddress == NULL) { \r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ CopyMem (NewDnsCache->DnsCache.IpAddress, DnsCacheEntry.IpAddress, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+ NewDnsCache->DnsCache.Timeout = DnsCacheEntry.Timeout;\r
+ \r
+ InsertTailList (Dns4CacheList, &NewDnsCache->AllCacheLink);\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Update Dns6 cache to shared list of caches of all DNSv6 instances. \r
+\r
+ @param Dns6CacheList All Dns6 cache list.\r
+ @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache. \r
+ If TRUE, this function will delete matching DNS Cache entry. \r
+ @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter. \r
+ If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.\r
+ @param DnsCacheEntry Entry Pointer to DNS Cache entry.\r
+ \r
+ @retval EFI_SUCCESS Update Dns6 cache successfully.\r
+ @retval Others Failed to update Dns6 cache.\r
+**/ \r
+EFI_STATUS\r
+EFIAPI\r
+UpdateDns6Cache (\r
+ IN LIST_ENTRY *Dns6CacheList,\r
+ IN BOOLEAN DeleteFlag,\r
+ IN BOOLEAN Override,\r
+ IN EFI_DNS6_CACHE_ENTRY DnsCacheEntry\r
+ )\r
+{\r
+ DNS6_CACHE *NewDnsCache; \r
+ DNS6_CACHE *Item;\r
+ LIST_ENTRY *Entry;\r
+ LIST_ENTRY *Next;\r
+\r
+ NewDnsCache = NULL;\r
+ Item = NULL;\r
+ \r
+ //\r
+ // Search the database for the matching EFI_DNS_CACHE_ENTRY\r
+ //\r
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns6CacheList) {\r
+ Item = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);\r
+ if (StrCmp (DnsCacheEntry.HostName, Item->DnsCache.HostName) == 0 && \\r
+ CompareMem (DnsCacheEntry.IpAddress, Item->DnsCache.IpAddress, sizeof (EFI_IPv6_ADDRESS)) == 0) {\r
+ //\r
+ // This is the Dns cache entry\r
+ //\r
+ if (DeleteFlag) {\r
+ //\r
+ // Delete matching DNS Cache entry\r
+ //\r
+ RemoveEntryList (&Item->AllCacheLink);\r
+ \r
+ return EFI_SUCCESS;\r
+ } else if (Override) {\r
+ //\r
+ // Update this one\r
+ //\r
+ Item->DnsCache.Timeout = DnsCacheEntry.Timeout;\r
+ \r
+ return EFI_SUCCESS;\r
+ }else {\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Add new one\r
+ //\r
+ NewDnsCache = AllocatePool (sizeof (DNS6_CACHE));\r
+ if (NewDnsCache == NULL) { \r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ \r
+ InitializeListHead (&NewDnsCache->AllCacheLink);\r
+ \r
+ NewDnsCache->DnsCache.HostName = AllocatePool (StrSize (DnsCacheEntry.HostName));\r
+ if (NewDnsCache->DnsCache.HostName == NULL) { \r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ \r
+ CopyMem (NewDnsCache->DnsCache.HostName, DnsCacheEntry.HostName, StrSize (DnsCacheEntry.HostName));\r
+\r
+ NewDnsCache->DnsCache.IpAddress = AllocatePool (sizeof (EFI_IPv6_ADDRESS));\r
+ if (NewDnsCache->DnsCache.IpAddress == NULL) { \r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ \r
+ CopyMem (NewDnsCache->DnsCache.IpAddress, DnsCacheEntry.IpAddress, sizeof (EFI_IPv6_ADDRESS));\r
+\r
+ NewDnsCache->DnsCache.Timeout = DnsCacheEntry.Timeout;\r
+ \r
+ InsertTailList (Dns6CacheList, &NewDnsCache->AllCacheLink);\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Add Dns4 ServerIp to common list of addresses of all configured DNSv4 server. \r
+\r
+ @param Dns4ServerList Common list of addresses of all configured DNSv4 server. \r
+ @param ServerIp DNS server Ip. \r
+\r
+ @retval EFI_SUCCESS Add Dns4 ServerIp to common list successfully.\r
+ @retval Others Failed to add Dns4 ServerIp to common list.\r
+ \r
+**/ \r
+EFI_STATUS\r
+EFIAPI\r
+AddDns4ServerIp (\r
+ IN LIST_ENTRY *Dns4ServerList,\r
+ IN EFI_IPv4_ADDRESS ServerIp\r
+ )\r
+{\r
+ DNS4_SERVER_IP *NewServerIp; \r
+ DNS4_SERVER_IP *Item;\r
+ LIST_ENTRY *Entry;\r
+ LIST_ENTRY *Next;\r
+\r
+ NewServerIp = NULL;\r
+ Item = NULL;\r
+ \r
+ //\r
+ // Search the database for the matching ServerIp\r
+ //\r
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns4ServerList) {\r
+ Item = NET_LIST_USER_STRUCT (Entry, DNS4_SERVER_IP, AllServerLink);\r
+ if (CompareMem (&Item->Dns4ServerIp, &ServerIp, sizeof (EFI_IPv4_ADDRESS)) == 0) {\r
+ //\r
+ // Already done.\r
+ // \r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Add new one\r
+ //\r
+ NewServerIp = AllocatePool (sizeof (DNS4_SERVER_IP));\r
+ if (NewServerIp == NULL) { \r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ \r
+ InitializeListHead (&NewServerIp->AllServerLink);\r
+ \r
+ CopyMem (&NewServerIp->Dns4ServerIp, &ServerIp, sizeof (EFI_IPv4_ADDRESS));\r
+ \r
+ InsertTailList (Dns4ServerList, &NewServerIp->AllServerLink);\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Add Dns6 ServerIp to common list of addresses of all configured DNSv6 server. \r
+\r
+ @param Dns6ServerList Common list of addresses of all configured DNSv6 server. \r
+ @param ServerIp DNS server Ip. \r
+\r
+ @retval EFI_SUCCESS Add Dns6 ServerIp to common list successfully.\r
+ @retval Others Failed to add Dns6 ServerIp to common list.\r
+ \r
+**/ \r
+EFI_STATUS\r
+EFIAPI\r
+AddDns6ServerIp (\r
+ IN LIST_ENTRY *Dns6ServerList,\r
+ IN EFI_IPv6_ADDRESS ServerIp\r
+ )\r
+{\r
+ DNS6_SERVER_IP *NewServerIp; \r
+ DNS6_SERVER_IP *Item;\r
+ LIST_ENTRY *Entry;\r
+ LIST_ENTRY *Next;\r
+\r
+ NewServerIp = NULL;\r
+ Item = NULL;\r
+ \r
+ //\r
+ // Search the database for the matching ServerIp\r
+ //\r
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns6ServerList) {\r
+ Item = NET_LIST_USER_STRUCT (Entry, DNS6_SERVER_IP, AllServerLink);\r
+ if (CompareMem (&Item->Dns6ServerIp, &ServerIp, sizeof (EFI_IPv6_ADDRESS)) == 0) {\r
+ //\r
+ // Already done.\r
+ // \r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Add new one\r
+ //\r
+ NewServerIp = AllocatePool (sizeof (DNS6_SERVER_IP));\r
+ if (NewServerIp == NULL) { \r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ \r
+ InitializeListHead (&NewServerIp->AllServerLink);\r
+ \r
+ CopyMem (&NewServerIp->Dns6ServerIp, &ServerIp, sizeof (EFI_IPv6_ADDRESS));\r
+ \r
+ InsertTailList (Dns6ServerList, &NewServerIp->AllServerLink);\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Find out whether the response is valid or invalid.\r
+\r
+ @param TokensMap All DNS transmittal Tokens entry. \r
+ @param Identification Identification for queried packet. \r
+ @param Type Type for queried packet.\r
+ @param Item Return corresponding Token entry.\r
+\r
+ @retval TRUE The response is valid.\r
+ @retval FALSE The response is invalid.\r
+ \r
+**/ \r
+BOOLEAN\r
+IsValidDnsResponse (\r
+ IN NET_MAP *TokensMap,\r
+ IN UINT16 Identification,\r
+ IN UINT16 Type,\r
+ OUT NET_MAP_ITEM **Item\r
+ )\r
+{\r
+ LIST_ENTRY *Entry;\r
+\r
+ NET_BUF *Packet;\r
+ UINT8 *TxString;\r
+ DNS_HEADER *DnsHeader;\r
+ CHAR8 *QueryName;\r
+ DNS_QUERY_SECTION *QuerySection;\r
+\r
+ NET_LIST_FOR_EACH (Entry, &TokensMap->Used) {\r
+ *Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);\r
+ Packet = (NET_BUF *) ((*Item)->Value);\r
+ if (Packet == NULL){\r
+ \r
+ continue;\r
+ } else {\r
+ TxString = NetbufGetByte (Packet, 0, NULL);\r
+ DnsHeader = (DNS_HEADER *) TxString;\r
+ QueryName = (CHAR8 *) (TxString + sizeof (*DnsHeader));\r
+ QuerySection = (DNS_QUERY_SECTION *) (QueryName + AsciiStrLen (QueryName) + 1);\r
+\r
+ DnsHeader->Identification = NTOHS (DnsHeader->Identification);\r
+ QuerySection->Type = NTOHS (QuerySection->Type);\r
+ \r
+ if (DnsHeader->Identification == Identification && QuerySection->Type == Type) {\r
+ return TRUE;\r
+ }\r
+ } \r
+ }\r
+ \r
+ *Item =NULL;\r
+ \r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Parse Dns Response.\r
+\r
+ @param Instance The DNS instance\r
+ @param RxString Received buffer.\r
+ @param Completed Flag to indicate that Dns response is valid. \r
+ \r
+ @retval EFI_SUCCESS Parse Dns Response successfully.\r
+ @retval Others Failed to parse Dns Response.\r
+ \r
+**/ \r
+EFI_STATUS\r
+ParseDnsResponse (\r
+ IN OUT DNS_INSTANCE *Instance,\r
+ IN UINT8 *RxString,\r
+ OUT BOOLEAN *Completed\r
+ )\r
+{\r
+ DNS_HEADER *DnsHeader;\r
+ \r
+ CHAR8 *QueryName;\r
+ DNS_QUERY_SECTION *QuerySection;\r
+ \r
+ CHAR8 *AnswerName;\r
+ DNS_ANSWER_SECTION *AnswerSection;\r
+ UINT8 *AnswerData;\r
+\r
+ NET_MAP_ITEM *Item;\r
+ DNS4_TOKEN_ENTRY *Dns4TokenEntry;\r
+ DNS6_TOKEN_ENTRY *Dns6TokenEntry;\r
+ \r
+ UINT32 IpCount;\r
+ UINT32 AnswerSectionNum;\r
+ \r
+ EFI_IPv4_ADDRESS *HostAddr4;\r
+ EFI_IPv6_ADDRESS *HostAddr6;\r
+\r
+ EFI_DNS4_CACHE_ENTRY *Dns4CacheEntry;\r
+ EFI_DNS6_CACHE_ENTRY *Dns6CacheEntry;\r
+\r
+ EFI_STATUS Status;\r
+\r
+ EFI_TPL OldTpl;\r
+ \r
+ Item = NULL;\r
+ Dns4TokenEntry = NULL;\r
+ Dns6TokenEntry = NULL;\r
+ \r
+ IpCount = 0;\r
+ AnswerSectionNum = 0;\r
+ \r
+ HostAddr4 = NULL;\r
+ HostAddr6 = NULL;\r
+ \r
+ Dns4CacheEntry = NULL;\r
+ Dns6CacheEntry = NULL;\r
+\r
+ *Completed = TRUE;\r
+ Status = EFI_SUCCESS;\r
+ \r
+ //\r
+ // Get header\r
+ //\r
+ DnsHeader = (DNS_HEADER *) RxString;\r
+ \r
+ DnsHeader->Identification = NTOHS (DnsHeader->Identification);\r
+ DnsHeader->Flags.Uint16 = NTOHS (DnsHeader->Flags.Uint16);\r
+ DnsHeader->QuestionsNum = NTOHS (DnsHeader->QuestionsNum);\r
+ DnsHeader->AnswersNum = NTOHS (DnsHeader->AnswersNum);\r
+ DnsHeader->AuthorityNum = NTOHS (DnsHeader->AuthorityNum);\r
+ DnsHeader->AditionalNum = NTOHS (DnsHeader->AditionalNum);\r
+\r
+ //\r
+ // Get Query name\r
+ //\r
+ QueryName = (CHAR8 *) (RxString + sizeof (*DnsHeader));\r
+\r
+ //\r
+ // Get query section\r
+ //\r
+ QuerySection = (DNS_QUERY_SECTION *) (QueryName + AsciiStrLen (QueryName) + 1);\r
+ QuerySection->Type = NTOHS (QuerySection->Type);\r
+ QuerySection->Class = NTOHS (QuerySection->Class);\r
+\r
+ //\r
+ // Get Answer name\r
+ //\r
+ AnswerName = (CHAR8 *) QuerySection + sizeof (*QuerySection);\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+ //\r
+ // Check DnsResponse Validity, if so, also get a valid NET_MAP_ITEM.\r
+ //\r
+ if (Instance->Service->IpVersion == IP_VERSION_4) {\r
+ if (!IsValidDnsResponse (&Instance->Dns4TxTokens, DnsHeader->Identification, QuerySection->Type, &Item)) {\r
+ *Completed = FALSE;\r
+ Status = EFI_ABORTED;\r
+ goto ON_EXIT;\r
+ }\r
+ ASSERT (Item != NULL);\r
+ Dns4TokenEntry = (DNS4_TOKEN_ENTRY *) (Item->Key);\r
+ } else {\r
+ if (!IsValidDnsResponse (&Instance->Dns6TxTokens, DnsHeader->Identification, QuerySection->Type, &Item)) {\r
+ *Completed = FALSE;\r
+ Status = EFI_ABORTED;\r
+ goto ON_EXIT;\r
+ }\r
+ ASSERT (Item != NULL);\r
+ Dns6TokenEntry = (DNS6_TOKEN_ENTRY *) (Item->Key);\r
+ }\r
+ \r
+ //\r
+ // Continue Check Some Errors.\r
+ //\r
+ if (DnsHeader->Flags.Bits.RCode != DNS_FLAGS_RCODE_NO_ERROR || DnsHeader->AnswersNum < 1 || \\r
+ DnsHeader->Flags.Bits.QR != DNS_FLAGS_QR_RESPONSE || QuerySection->Class != DNS_CLASS_INET) {\r
+ Status = EFI_ABORTED;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Free the sending packet.\r
+ //\r
+ if (Item->Value != NULL) {\r
+ NetbufFree ((NET_BUF *) (Item->Value));\r
+ }\r
+ \r
+ //\r
+ // Check the Query type, do some buffer allocations.\r
+ //\r
+ if (QuerySection->Type == DNS_TYPE_A) {\r
+ Dns4TokenEntry->Token->RspData.H2AData = AllocatePool (sizeof (DNS_HOST_TO_ADDR_DATA));\r
+ ASSERT (Dns4TokenEntry->Token->RspData.H2AData != NULL);\r
+ Dns4TokenEntry->Token->RspData.H2AData->IpList = AllocatePool (DnsHeader->AnswersNum * sizeof (EFI_IPv4_ADDRESS));\r
+ ASSERT (Dns4TokenEntry->Token->RspData.H2AData->IpList != NULL);\r
+ } else if (QuerySection->Type == DNS_TYPE_AAAA) {\r
+ Dns6TokenEntry->Token->RspData.H2AData = AllocatePool (sizeof (DNS6_HOST_TO_ADDR_DATA));\r
+ ASSERT (Dns6TokenEntry->Token->RspData.H2AData != NULL);\r
+ Dns6TokenEntry->Token->RspData.H2AData->IpList = AllocatePool (DnsHeader->AnswersNum * sizeof (EFI_IPv6_ADDRESS));\r
+ ASSERT (Dns6TokenEntry->Token->RspData.H2AData->IpList != NULL);\r
+ } else {\r
+ Status = EFI_UNSUPPORTED;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Processing AnswerSection.\r
+ //\r
+ while (AnswerSectionNum < DnsHeader->AnswersNum) {\r
+ //\r
+ // Answer name should be PTR.\r
+ //\r
+ ASSERT ((*(UINT8 *) AnswerName & 0xC0) == 0xC0);\r
+ \r
+ //\r
+ // Get Answer section.\r
+ //\r
+ AnswerSection = (DNS_ANSWER_SECTION *) (AnswerName + sizeof (UINT16));\r
+ AnswerSection->Type = NTOHS (AnswerSection->Type);\r
+ AnswerSection->Class = NTOHS (AnswerSection->Class);\r
+ AnswerSection->Ttl = NTOHL (AnswerSection->Ttl);\r
+ AnswerSection->DataLength = NTOHS (AnswerSection->DataLength);\r
+\r
+ ASSERT (AnswerSection->Class == DNS_CLASS_INET);\r
+\r
+ if (AnswerSection->Type == QuerySection->Type) {\r
+ switch (AnswerSection->Type) {\r
+ case DNS_TYPE_A:\r
+ //\r
+ // This is address entry, get Data.\r
+ //\r
+ ASSERT (AnswerSection->DataLength == 4);\r
+ \r
+ HostAddr4 = Dns4TokenEntry->Token->RspData.H2AData->IpList;\r
+ AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);\r
+ CopyMem (&HostAddr4[IpCount], AnswerData, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+ //\r
+ // Update DNS cache dynamically.\r
+ //\r
+ if (Dns4CacheEntry != NULL) {\r
+ if (Dns4CacheEntry->HostName != NULL) {\r
+ FreePool (Dns4CacheEntry->HostName);\r
+ }\r
+\r
+ if (Dns4CacheEntry->IpAddress != NULL) {\r
+ FreePool (Dns4CacheEntry->IpAddress);\r
+ }\r
+ \r
+ FreePool (Dns4CacheEntry);\r
+ }\r
+\r
+ // \r
+ // Allocate new CacheEntry pool.\r
+ //\r
+ Dns4CacheEntry = AllocateZeroPool (sizeof (EFI_DNS4_CACHE_ENTRY));\r
+ ASSERT (Dns4CacheEntry != NULL);\r
+ Dns4CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1));\r
+ ASSERT (Dns4CacheEntry->HostName != NULL);\r
+ CopyMem (Dns4CacheEntry->HostName, Dns4TokenEntry->QueryHostName, 2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1));\r
+ Dns4CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv4_ADDRESS));\r
+ ASSERT (Dns4CacheEntry->IpAddress != NULL);\r
+ CopyMem (Dns4CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv4_ADDRESS));\r
+ Dns4CacheEntry->Timeout = AnswerSection->Ttl;\r
+ \r
+ UpdateDns4Cache (&mDriverData->Dns4CacheList, FALSE, TRUE, *Dns4CacheEntry); \r
+\r
+ IpCount ++; \r
+ break;\r
+ case DNS_TYPE_AAAA:\r
+ //\r
+ // This is address entry, get Data.\r
+ //\r
+ ASSERT (AnswerSection->DataLength == 16);\r
+ \r
+ HostAddr6 = Dns6TokenEntry->Token->RspData.H2AData->IpList;\r
+ AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);\r
+ CopyMem (&HostAddr6[IpCount], AnswerData, sizeof (EFI_IPv6_ADDRESS));\r
+\r
+ //\r
+ // Update DNS cache dynamically.\r
+ //\r
+ if (Dns6CacheEntry != NULL) {\r
+ if (Dns6CacheEntry->HostName != NULL) {\r
+ FreePool (Dns6CacheEntry->HostName);\r
+ }\r
+\r
+ if (Dns6CacheEntry->IpAddress != NULL) {\r
+ FreePool (Dns6CacheEntry->IpAddress);\r
+ }\r
+ \r
+ FreePool (Dns6CacheEntry);\r
+ }\r
+\r
+ // \r
+ // Allocate new CacheEntry pool.\r
+ //\r
+ Dns6CacheEntry = AllocateZeroPool (sizeof (EFI_DNS6_CACHE_ENTRY));\r
+ ASSERT (Dns6CacheEntry != NULL);\r
+ Dns6CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1));\r
+ ASSERT (Dns6CacheEntry->HostName != NULL);\r
+ CopyMem (Dns6CacheEntry->HostName, Dns6TokenEntry->QueryHostName, 2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1));\r
+ Dns6CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS));\r
+ ASSERT (Dns6CacheEntry->IpAddress != NULL);\r
+ CopyMem (Dns6CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv6_ADDRESS));\r
+ Dns6CacheEntry->Timeout = AnswerSection->Ttl;\r
+ \r
+ UpdateDns6Cache (&mDriverData->Dns6CacheList, FALSE, TRUE, *Dns6CacheEntry); \r
+ \r
+ IpCount ++;\r
+ break;\r
+ default:\r
+ Status = EFI_UNSUPPORTED;\r
+ goto ON_EXIT;\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Find next one\r
+ //\r
+ AnswerName = (CHAR8 *) AnswerSection + sizeof (*AnswerSection) + AnswerSection->DataLength;\r
+ AnswerSectionNum ++;\r
+ }\r
+\r
+ if (QuerySection->Type == DNS_TYPE_A) {\r
+ Dns4TokenEntry->Token->RspData.H2AData->IpCount = IpCount;\r
+ } else if (QuerySection->Type == DNS_TYPE_AAAA) {\r
+ Dns6TokenEntry->Token->RspData.H2AData->IpCount = IpCount;\r
+ }\r
+\r
+ //\r
+ // Parsing is complete, SignalEvent here.\r
+ //\r
+ if (Instance->Service->IpVersion == IP_VERSION_4) {\r
+ Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry);\r
+ Dns4TokenEntry->Token->Status = EFI_SUCCESS;\r
+ if (Dns4TokenEntry->Token->Event != NULL) {\r
+ gBS->SignalEvent (Dns4TokenEntry->Token->Event);\r
+ DispatchDpc ();\r
+ }\r
+ } else {\r
+ Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry);\r
+ Dns6TokenEntry->Token->Status = EFI_SUCCESS;\r
+ if (Dns6TokenEntry->Token->Event != NULL) {\r
+ gBS->SignalEvent (Dns6TokenEntry->Token->Event);\r
+ DispatchDpc ();\r
+ }\r
+ }\r
+\r
+ // \r
+ // Free allocated CacheEntry pool.\r
+ //\r
+ if (Dns4CacheEntry != NULL) {\r
+ if (Dns4CacheEntry->HostName != NULL) {\r
+ FreePool (Dns4CacheEntry->HostName);\r
+ }\r
+\r
+ if (Dns4CacheEntry->IpAddress != NULL) {\r
+ FreePool (Dns4CacheEntry->IpAddress);\r
+ }\r
+\r
+ FreePool (Dns4CacheEntry);\r
+ }\r
+ \r
+ if (Dns6CacheEntry != NULL) {\r
+ if (Dns6CacheEntry->HostName != NULL) {\r
+ FreePool (Dns6CacheEntry->HostName);\r
+ }\r
+\r
+ if (Dns6CacheEntry->IpAddress != NULL) {\r
+ FreePool (Dns6CacheEntry->IpAddress);\r
+ }\r
+ \r
+ FreePool (Dns6CacheEntry);\r
+ }\r
+\r
+ON_EXIT:\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Parse response packet.\r
+\r
+ @param Packet The packets received.\r
+ @param EndPoint The local/remote UDP access point\r
+ @param IoStatus The status of the UDP receive\r
+ @param Context The opaque parameter to the function.\r
+\r
+**/ \r
+VOID\r
+EFIAPI\r
+DnsOnPacketReceived (\r
+ NET_BUF *Packet,\r
+ UDP_END_POINT *EndPoint,\r
+ EFI_STATUS IoStatus,\r
+ VOID *Context\r
+ )\r
+{\r
+ DNS_INSTANCE *Instance;\r
+\r
+ UINT8 *RcvString;\r
+\r
+ BOOLEAN Completed;\r
+ \r
+ Instance = (DNS_INSTANCE *) Context;\r
+ NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE);\r
+\r
+ RcvString = NULL;\r
+ Completed = FALSE;\r
+\r
+ if (EFI_ERROR (IoStatus)) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ ASSERT (Packet != NULL);\r
+ \r
+ RcvString = NetbufGetByte (Packet, 0, NULL);\r
+\r
+ //\r
+ // Parse Dns Response\r
+ //\r
+ ParseDnsResponse (Instance, RcvString, &Completed);\r
+\r
+ ON_EXIT:\r
+\r
+ if (Packet != NULL) {\r
+ NetbufFree (Packet);\r
+ }\r
+\r
+ if (!Completed) {\r
+ UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);\r
+ }\r
+}\r
+\r
+/**\r
+ Release the net buffer when packet is sent.\r
+\r
+ @param Packet The packets received.\r
+ @param EndPoint The local/remote UDP access point\r
+ @param IoStatus The status of the UDP receive\r
+ @param Context The opaque parameter to the function.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DnsOnPacketSent (\r
+ NET_BUF *Packet,\r
+ UDP_END_POINT *EndPoint,\r
+ EFI_STATUS IoStatus,\r
+ VOID *Context\r
+ )\r
+{\r
+ DNS_INSTANCE *Instance;\r
+ LIST_ENTRY *Entry;\r
+ NET_MAP_ITEM *Item;\r
+ DNS4_TOKEN_ENTRY *Dns4TokenEntry;\r
+ DNS6_TOKEN_ENTRY *Dns6TokenEntry;\r
+\r
+ Dns4TokenEntry = NULL;\r
+ Dns6TokenEntry = NULL;\r
+\r
+ Instance = (DNS_INSTANCE *) Context;\r
+ NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE);\r
+\r
+ if (Instance->Service->IpVersion == IP_VERSION_4) {\r
+ NET_LIST_FOR_EACH (Entry, &Instance->Dns4TxTokens.Used) {\r
+ Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);\r
+ if (Packet == (NET_BUF *)(Item->Value)) {\r
+ Dns4TokenEntry = ((DNS4_TOKEN_ENTRY *)Item->Key);\r
+ Dns4TokenEntry->PacketToLive = Dns4TokenEntry->Token->RetryInterval;\r
+ break;\r
+ }\r
+ }\r
+ } else {\r
+ NET_LIST_FOR_EACH (Entry, &Instance->Dns6TxTokens.Used) {\r
+ Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);\r
+ if (Packet == (NET_BUF *)(Item->Value)) {\r
+ Dns6TokenEntry = ((DNS6_TOKEN_ENTRY *)Item->Key);\r
+ Dns6TokenEntry->PacketToLive = Dns6TokenEntry->Token->RetryInterval;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ \r
+ NetbufFree (Packet);\r
+}\r
+\r
+/**\r
+ Query request information.\r
+\r
+ @param Instance The DNS instance\r
+ @param Packet The packet for querying request information.\r
+\r
+ @retval EFI_SUCCESS Query request information successfully.\r
+ @retval Others Failed to query request information.\r
+\r
+**/\r
+EFI_STATUS\r
+DoDnsQuery (\r
+ IN DNS_INSTANCE *Instance,\r
+ IN NET_BUF *Packet\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Ready to receive the DNS response.\r
+ //\r
+ if (Instance->UdpIo->RecvRequest == NULL) {\r
+ Status = UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Transmit the DNS packet.\r
+ //\r
+ NET_GET_REF (Packet);\r
+\r
+ Status = UdpIoSendDatagram (Instance->UdpIo, Packet, NULL, NULL, DnsOnPacketSent, Instance);\r
+ \r
+ return Status;\r
+}\r
+\r
+/**\r
+ Construct the Packet to query Ip.\r
+\r
+ @param Instance The DNS instance\r
+ @param HostName Queried HostName \r
+ @param Type DNS query Type\r
+ @param Packet The packet for querying Ip\r
+\r
+ @retval EFI_SUCCESS The packet is constructed.\r
+ @retval Others Failed to construct the Packet.\r
+\r
+**/\r
+EFI_STATUS\r
+ConstructDNSQueryIp (\r
+ IN DNS_INSTANCE *Instance,\r
+ IN CHAR16 *HostName,\r
+ IN UINT16 Type,\r
+ OUT NET_BUF **Packet\r
+ )\r
+{\r
+ NET_FRAGMENT Frag;\r
+ DNS_HEADER *DnsHeader;\r
+ CHAR8 *QueryName;\r
+ DNS_QUERY_SECTION *QuerySection;\r
+ CHAR8 *Header;\r
+ CHAR8 *Tail;\r
+ UINTN Len;\r
+ UINTN Index;\r
+ \r
+\r
+ Frag.Bulk = AllocatePool (DNS_DEFAULT_BLKSIZE * sizeof (UINT8));\r
+ if (Frag.Bulk == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Fill header\r
+ //\r
+ DnsHeader = (DNS_HEADER *)Frag.Bulk; \r
+ DnsHeader->Identification = (UINT16)AsmReadTsc ();\r
+ DnsHeader->Flags.Uint16 = 0x0000;\r
+ DnsHeader->Flags.Bits.RD = 1;\r
+ DnsHeader->Flags.Bits.OpCode = DNS_FLAGS_OPCODE_STANDARD;\r
+ DnsHeader->Flags.Bits.QR = DNS_FLAGS_QR_QUERY;\r
+ DnsHeader->QuestionsNum = 1;\r
+ DnsHeader->AnswersNum = 0;\r
+ DnsHeader->AuthorityNum = 0;\r
+ DnsHeader->AditionalNum = 0;\r
+\r
+ DnsHeader->Identification = HTONS(DnsHeader->Identification);\r
+ DnsHeader->Flags.Uint16 = HTONS(DnsHeader->Flags.Uint16);\r
+ DnsHeader->QuestionsNum = HTONS(DnsHeader->QuestionsNum);\r
+ DnsHeader->AnswersNum = HTONS(DnsHeader->AnswersNum);\r
+ DnsHeader->AuthorityNum = HTONS(DnsHeader->AuthorityNum);\r
+ DnsHeader->AditionalNum = HTONS(DnsHeader->AditionalNum);\r
+\r
+ Frag.Len = sizeof (*DnsHeader);\r
+\r
+ //\r
+ // Fill Query name\r
+ //\r
+ QueryName = (CHAR8 *) (Frag.Bulk + Frag.Len);\r
+ Header = QueryName;\r
+ Tail = Header + 1;\r
+ Len = 0;\r
+ for (Index = 0; HostName[Index] != 0; Index++) {\r
+ *Tail = (CHAR8) HostName[Index];\r
+ if (*Tail == '.') {\r
+ *Header = (CHAR8) Len;\r
+ Header = Tail;\r
+ Tail ++;\r
+ Len = 0;\r
+ } else {\r
+ Tail++;\r
+ Len++;\r
+ }\r
+ }\r
+ *Header = (CHAR8) Len;\r
+ *Tail = 0;\r
+ Frag.Len = (UINT32) (Frag.Len + StrLen (HostName) + 2); /// 1 for header, 1 for tail.\r
+\r
+ //\r
+ // Rest query section\r
+ //\r
+ QuerySection = (DNS_QUERY_SECTION *) (Frag.Bulk + Frag.Len);\r
+ QuerySection->Type = Type;\r
+ QuerySection->Class = DNS_CLASS_INET;\r
+\r
+ QuerySection->Type = HTONS (QuerySection->Type);\r
+ QuerySection->Class = HTONS (QuerySection->Class);\r
+\r
+ Frag.Len += sizeof (*QuerySection);\r
+\r
+ //\r
+ // Wrap the Frag in a net buffer.\r
+ //\r
+ *Packet = NetbufFromExt (&Frag, 1, 0, 0, DnsDummyExtFree, NULL);\r
+ if (*Packet == NULL) {\r
+ FreePool (Frag.Bulk);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ \r
+ //\r
+ // Store the UdpIo in ProtoData.\r
+ //\r
+ *((UINTN *) &((*Packet)->ProtoData[0])) = (UINTN) (Instance->UdpIo);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Retransmit the packet.\r
+\r
+ @param Instance The DNS instance\r
+ @param Packet Retransmit the packet \r
+\r
+ @retval EFI_SUCCESS The packet is retransmitted.\r
+ @retval Others Failed to retransmit.\r
+\r
+**/\r
+EFI_STATUS\r
+DnsRetransmit (\r
+ IN DNS_INSTANCE *Instance,\r
+ IN NET_BUF *Packet\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ \r
+ UINT8 *Buffer;\r
+\r
+ ASSERT (Packet != NULL);\r
+\r
+ //\r
+ // Set the requests to the listening port, other packets to the connected port\r
+ //\r
+ Buffer = NetbufGetByte (Packet, 0, NULL);\r
+ ASSERT (Buffer != NULL);\r
+\r
+ NET_GET_REF (Packet);\r
+\r
+ Status = UdpIoSendDatagram (\r
+ Instance->UdpIo,\r
+ Packet,\r
+ NULL,\r
+ NULL,\r
+ DnsOnPacketSent,\r
+ Instance\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ NET_PUT_REF (Packet);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ The timer ticking function for the DNS services.\r
+\r
+ @param Event The ticking event\r
+ @param Context The DNS service instance\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DnsOnTimerRetransmit (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ DNS_SERVICE *Service;\r
+\r
+ LIST_ENTRY *Entry;\r
+ LIST_ENTRY *Next;\r
+\r
+ DNS_INSTANCE *Instance;\r
+ LIST_ENTRY *EntryNetMap;\r
+ NET_MAP_ITEM *ItemNetMap;\r
+ DNS4_TOKEN_ENTRY *Dns4TokenEntry;\r
+ DNS6_TOKEN_ENTRY *Dns6TokenEntry;\r
+\r
+ Dns4TokenEntry = NULL;\r
+ Dns6TokenEntry = NULL;\r
+\r
+ Service = (DNS_SERVICE *) Context;\r
+\r
+\r
+ if (Service->IpVersion == IP_VERSION_4) {\r
+ //\r
+ // Iterate through all the children of the DNS service instance. Time\r
+ // out the packet. If maximum retries reached, clean the Token up.\r
+ //\r
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, &Service->Dns4ChildrenList) {\r
+ Instance = NET_LIST_USER_STRUCT (Entry, DNS_INSTANCE, Link);\r
+\r
+ EntryNetMap = Instance->Dns4TxTokens.Used.ForwardLink;\r
+ while (EntryNetMap != &Instance->Dns4TxTokens.Used) {\r
+ ItemNetMap = NET_LIST_USER_STRUCT (EntryNetMap, NET_MAP_ITEM, Link);\r
+ Dns4TokenEntry = (DNS4_TOKEN_ENTRY *)(ItemNetMap->Key);\r
+ if (Dns4TokenEntry->PacketToLive == 0 || (--Dns4TokenEntry->PacketToLive > 0)) {\r
+ EntryNetMap = EntryNetMap->ForwardLink;\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Retransmit the packet if haven't reach the maxmium retry count,\r
+ // otherwise exit the transfer.\r
+ //\r
+ if (++Dns4TokenEntry->Token->RetryCount < Instance->MaxRetry) {\r
+ DnsRetransmit (Instance, (NET_BUF *)ItemNetMap->Value);\r
+ EntryNetMap = EntryNetMap->ForwardLink;\r
+ } else {\r
+ //\r
+ // Maximum retries reached, clean the Token up.\r
+ //\r
+ Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry);\r
+ Dns4TokenEntry->Token->Status = EFI_TIMEOUT;\r
+ gBS->SignalEvent (Dns4TokenEntry->Token->Event);\r
+ DispatchDpc ();\r
+ \r
+ //\r
+ // Free the sending packet.\r
+ //\r
+ if (ItemNetMap->Value != NULL) {\r
+ NetbufFree ((NET_BUF *)(ItemNetMap->Value));\r
+ }\r
+\r
+ EntryNetMap = Instance->Dns4TxTokens.Used.ForwardLink;\r
+ }\r
+ }\r
+ } \r
+ }else {\r
+ //\r
+ // Iterate through all the children of the DNS service instance. Time\r
+ // out the packet. If maximum retries reached, clean the Token up.\r
+ //\r
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, &Service->Dns6ChildrenList) {\r
+ Instance = NET_LIST_USER_STRUCT (Entry, DNS_INSTANCE, Link);\r
+ \r
+ EntryNetMap = Instance->Dns6TxTokens.Used.ForwardLink;\r
+ while (EntryNetMap != &Instance->Dns6TxTokens.Used) {\r
+ ItemNetMap = NET_LIST_USER_STRUCT (EntryNetMap, NET_MAP_ITEM, Link);\r
+ Dns6TokenEntry = (DNS6_TOKEN_ENTRY *) (ItemNetMap->Key);\r
+ if (Dns6TokenEntry->PacketToLive == 0 || (--Dns6TokenEntry->PacketToLive > 0)) {\r
+ EntryNetMap = EntryNetMap->ForwardLink;\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Retransmit the packet if haven't reach the maxmium retry count,\r
+ // otherwise exit the transfer.\r
+ //\r
+ if (++Dns6TokenEntry->Token->RetryCount < Instance->MaxRetry) {\r
+ DnsRetransmit (Instance, (NET_BUF *) ItemNetMap->Value);\r
+ EntryNetMap = EntryNetMap->ForwardLink;\r
+ } else {\r
+ //\r
+ // Maximum retries reached, clean the Token up.\r
+ //\r
+ Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry);\r
+ Dns6TokenEntry->Token->Status = EFI_TIMEOUT;\r
+ gBS->SignalEvent (Dns6TokenEntry->Token->Event);\r
+ DispatchDpc ();\r
+ \r
+ //\r
+ // Free the sending packet.\r
+ //\r
+ if (ItemNetMap->Value != NULL) {\r
+ NetbufFree ((NET_BUF *) (ItemNetMap->Value));\r
+ }\r
+\r
+ EntryNetMap = Instance->Dns6TxTokens.Used.ForwardLink;\r
+ } \r
+ }\r
+ }\r
+ } \r
+}\r
+\r
+/**\r
+ The timer ticking function for the DNS driver.\r
+\r
+ @param Event The ticking event\r
+ @param Context NULL\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DnsOnTimerUpdate (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ LIST_ENTRY *Entry;\r
+ LIST_ENTRY *Next;\r
+ DNS4_CACHE *Item4;\r
+ DNS6_CACHE *Item6;\r
+\r
+ Item4 = NULL;\r
+ Item6 = NULL;\r
+\r
+ //\r
+ // Iterate through all the DNS4 cache list.\r
+ //\r
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) {\r
+ Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);\r
+ Item4->DnsCache.Timeout--;\r
+ }\r
+ \r
+ Entry = mDriverData->Dns4CacheList.ForwardLink;\r
+ while (Entry != &mDriverData->Dns4CacheList) {\r
+ Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);\r
+ if (Item4->DnsCache.Timeout<=0) {\r
+ RemoveEntryList (&Item4->AllCacheLink);\r
+ Entry = mDriverData->Dns4CacheList.ForwardLink;\r
+ } else {\r
+ Entry = Entry->ForwardLink;\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Iterate through all the DNS6 cache list.\r
+ //\r
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6CacheList) {\r
+ Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);\r
+ Item6->DnsCache.Timeout--;\r
+ }\r
+ \r
+ Entry = mDriverData->Dns6CacheList.ForwardLink;\r
+ while (Entry != &mDriverData->Dns6CacheList) {\r
+ Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);\r
+ if (Item6->DnsCache.Timeout<=0) {\r
+ RemoveEntryList (&Item6->AllCacheLink);\r
+ Entry = mDriverData->Dns6CacheList.ForwardLink;\r
+ } else {\r
+ Entry = Entry->ForwardLink;\r
+ }\r
+ }\r
+}\r
+\r
--- /dev/null
+/** @file\r
+DnsDxe support functions implementation.\r
+ \r
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __EFI_DNS_IMPL_H_\r
+#define __EFI_DNS_IMPL_H_\r
+\r
+#include <Uefi.h>\r
+\r
+//\r
+// Libraries classes\r
+//\r
+#include <Library/BaseLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/NetLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/DpcLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/UdpIoLib.h>\r
+\r
+//\r
+// UEFI Driver Model Protocols\r
+//\r
+#include <Protocol/DriverBinding.h>\r
+#include <Protocol/ComponentName2.h>\r
+#include <Protocol/ComponentName.h>\r
+\r
+#include <Protocol/Udp4.h>\r
+#include <Protocol/Dhcp4.h>\r
+#include <Protocol/Dns4.h>\r
+\r
+#include <Protocol/Udp6.h>\r
+#include <Protocol/Dhcp6.h>\r
+#include <Protocol/Dns6.h>\r
+\r
+#include <Protocol/Ip4Config2.h>\r
+\r
+#include "DnsDriver.h"\r
+#include "DnsDhcp.h"\r
+\r
+//\r
+// Driver Version\r
+//\r
+#define DNS_VERSION 0x00000000\r
+\r
+//\r
+// Protocol instances\r
+//\r
+extern EFI_COMPONENT_NAME_PROTOCOL gDnsComponentName;\r
+extern EFI_COMPONENT_NAME2_PROTOCOL gDnsComponentName2;\r
+extern EFI_UNICODE_STRING_TABLE *gDnsControllerNameTable;\r
+\r
+extern EFI_DRIVER_BINDING_PROTOCOL gDns4DriverBinding;\r
+extern EFI_SERVICE_BINDING_PROTOCOL mDns4ServiceBinding;\r
+extern EFI_DNS4_PROTOCOL mDns4Protocol;\r
+\r
+extern EFI_DRIVER_BINDING_PROTOCOL gDns6DriverBinding;\r
+extern EFI_SERVICE_BINDING_PROTOCOL mDns6ServiceBinding;\r
+extern EFI_DNS6_PROTOCOL mDns6Protocol;\r
+\r
+//\r
+// DNS related\r
+//\r
+#define DNS_SERVER_PORT 53\r
+\r
+#define DNS_PROTOCOL_UDP EFI_IP_PROTO_UDP\r
+#define DNS_PROTOCOL_TCP EFI_IP_PROTO_TCP\r
+\r
+#define DNS_STATE_UNCONFIGED 0\r
+#define DNS_STATE_CONFIGED 1\r
+#define DNS_STATE_DESTROY 2\r
+\r
+#define DNS_DEFAULT_TIMEOUT 2\r
+#define DNS_DEFAULT_RETRY 3\r
+#define DNS_DEFAULT_BLKSIZE 512\r
+\r
+#define DNS_TIME_TO_GETMAP 5\r
+\r
+#pragma pack(1)\r
+\r
+typedef union _DNS_FLAGS DNS_FLAGS;\r
+\r
+typedef struct {\r
+ LIST_ENTRY AllCacheLink;\r
+ EFI_DNS4_CACHE_ENTRY DnsCache; \r
+} DNS4_CACHE;\r
+\r
+typedef struct {\r
+ LIST_ENTRY AllCacheLink;\r
+ EFI_DNS6_CACHE_ENTRY DnsCache; \r
+} DNS6_CACHE;\r
+\r
+typedef struct {\r
+ LIST_ENTRY AllServerLink;\r
+ EFI_IPv4_ADDRESS Dns4ServerIp; \r
+} DNS4_SERVER_IP;\r
+\r
+typedef struct {\r
+ LIST_ENTRY AllServerLink;\r
+ EFI_IPv6_ADDRESS Dns6ServerIp; \r
+} DNS6_SERVER_IP;\r
+\r
+typedef struct {\r
+ UINT32 PacketToLive;\r
+ CHAR16 *QueryHostName;\r
+ EFI_IPv4_ADDRESS QueryIpAddress;\r
+ EFI_DNS4_COMPLETION_TOKEN *Token;\r
+} DNS4_TOKEN_ENTRY;\r
+\r
+typedef struct {\r
+ UINT32 PacketToLive;\r
+ CHAR16 *QueryHostName;\r
+ EFI_IPv6_ADDRESS QueryIpAddress;\r
+ EFI_DNS6_COMPLETION_TOKEN *Token;\r
+} DNS6_TOKEN_ENTRY;\r
+\r
+union _DNS_FLAGS{\r
+ struct {\r
+ UINT16 RCode:4;\r
+ UINT16 Zero:3;\r
+ UINT16 RA:1;\r
+ UINT16 RD:1;\r
+ UINT16 TC:1;\r
+ UINT16 AA:1;\r
+ UINT16 OpCode:4;\r
+ UINT16 QR:1;\r
+ } Bits;\r
+ UINT16 Uint16;\r
+};\r
+\r
+#define DNS_FLAGS_QR_QUERY 0\r
+#define DNS_FLAGS_QR_RESPONSE 1\r
+\r
+#define DNS_FLAGS_OPCODE_STANDARD 0\r
+#define DNS_FLAGS_OPCODE_INVERSE 1\r
+#define DNS_FLAGS_OPCODE_SERVER_STATE 2\r
+\r
+#define DNS_FLAGS_RCODE_NO_ERROR 0\r
+#define DNS_FLAGS_RCODE_NAME_ERROR 3\r
+\r
+typedef struct {\r
+ UINT16 Identification;\r
+ DNS_FLAGS Flags;\r
+ UINT16 QuestionsNum;\r
+ UINT16 AnswersNum;\r
+ UINT16 AuthorityNum;\r
+ UINT16 AditionalNum;\r
+} DNS_HEADER;\r
+\r
+typedef struct {\r
+ UINT16 Type;\r
+ UINT16 Class;\r
+} DNS_QUERY_SECTION;\r
+\r
+typedef struct {\r
+ UINT16 Type;\r
+ UINT16 Class;\r
+ UINT32 Ttl;\r
+ UINT16 DataLength;\r
+} DNS_ANSWER_SECTION;\r
+\r
+#define DNS_TYPE_A 1\r
+#define DNS_TYPE_NS 2\r
+#define DNS_TYPE_CNAME 5\r
+#define DNS_TYPE_PTR 12\r
+#define DNS_TYPE_HINFO 13\r
+#define DNS_TYPE_MX 15\r
+#define DNS_TYPE_AAAA 28\r
+#define DNS_TYPE_SRV_RR 33\r
+#define DNS_TYPE_AXFR 252\r
+#define DNS_TYPE_ANY 255\r
+\r
+#define DNS_CLASS_INET 1\r
+\r
+#define DNS4_DOMAIN L"in-addr.arpa"\r
+#define DNS6_DOMAIN L"IP6.ARPA"\r
+\r
+\r
+#pragma pack()\r
+\r
+/**\r
+ Remove TokenEntry from TokenMap.\r
+\r
+ @param[in] TokenMap All DNSv4 Token entrys.\r
+ @param[in] TokenEntry TokenEntry need to be removed.\r
+\r
+ @retval EFI_SUCCESS Remove TokenEntry from TokenMap sucessfully.\r
+ @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap.\r
+\r
+**/\r
+EFI_STATUS\r
+Dns4RemoveTokenEntry (\r
+ IN NET_MAP *TokenMap,\r
+ IN DNS4_TOKEN_ENTRY *TokenEntry\r
+ );\r
+\r
+/**\r
+ Remove TokenEntry from TokenMap.\r
+\r
+ @param[in] TokenMap All DNSv6 Token entrys.\r
+ @param[in] TokenEntry TokenEntry need to be removed.\r
+\r
+ @retval EFI_SUCCESS Remove TokenEntry from TokenMap sucessfully.\r
+ @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap.\r
+ \r
+**/\r
+EFI_STATUS\r
+Dns6RemoveTokenEntry (\r
+ IN NET_MAP *TokenMap,\r
+ IN DNS6_TOKEN_ENTRY *TokenEntry\r
+ );\r
+\r
+/**\r
+ This function cancle the token specified by Arg in the Map.\r
+\r
+ @param[in] Map Pointer to the NET_MAP.\r
+ @param[in] Item Pointer to the NET_MAP_ITEM.\r
+ @param[in] Arg Pointer to the token to be cancelled. If NULL, all\r
+ the tokens in this Map will be cancelled.\r
+ This parameter is optional and may be NULL.\r
+\r
+ @retval EFI_SUCCESS The token is cancelled if Arg is NULL, or the token\r
+ is not the same as that in the Item, if Arg is not\r
+ NULL.\r
+ @retval EFI_ABORTED Arg is not NULL, and the token specified by Arg is\r
+ cancelled.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4CancelTokens (\r
+ IN NET_MAP *Map,\r
+ IN NET_MAP_ITEM *Item,\r
+ IN VOID *Arg OPTIONAL\r
+ );\r
+\r
+/**\r
+ This function cancle the token specified by Arg in the Map.\r
+\r
+ @param[in] Map Pointer to the NET_MAP.\r
+ @param[in] Item Pointer to the NET_MAP_ITEM.\r
+ @param[in] Arg Pointer to the token to be cancelled. If NULL, all\r
+ the tokens in this Map will be cancelled.\r
+ This parameter is optional and may be NULL.\r
+\r
+ @retval EFI_SUCCESS The token is cancelled if Arg is NULL, or the token\r
+ is not the same as that in the Item, if Arg is not\r
+ NULL.\r
+ @retval EFI_ABORTED Arg is not NULL, and the token specified by Arg is\r
+ cancelled.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6CancelTokens (\r
+ IN NET_MAP *Map,\r
+ IN NET_MAP_ITEM *Item,\r
+ IN VOID *Arg OPTIONAL\r
+ );\r
+\r
+/**\r
+ Get the TokenEntry from the TokensMap.\r
+\r
+ @param[in] TokensMap All DNSv4 Token entrys\r
+ @param[in] Token Pointer to the token to be get.\r
+ @param[out] TokenEntry Pointer to TokenEntry corresponding Token.\r
+\r
+ @retval EFI_SUCCESS Get the TokenEntry from the TokensMap sucessfully.\r
+ @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetDns4TokenEntry (\r
+ IN NET_MAP *TokensMap,\r
+ IN EFI_DNS4_COMPLETION_TOKEN *Token, \r
+ OUT DNS4_TOKEN_ENTRY **TokenEntry\r
+ );\r
+\r
+/**\r
+ Get the TokenEntry from the TokensMap.\r
+\r
+ @param[in] TokensMap All DNSv6 Token entrys\r
+ @param[in] Token Pointer to the token to be get.\r
+ @param[out] TokenEntry Pointer to TokenEntry corresponding Token.\r
+\r
+ @retval EFI_SUCCESS Get the TokenEntry from the TokensMap sucessfully.\r
+ @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetDns6TokenEntry (\r
+ IN NET_MAP *TokensMap,\r
+ IN EFI_DNS6_COMPLETION_TOKEN *Token, \r
+ OUT DNS6_TOKEN_ENTRY **TokenEntry\r
+ );\r
+\r
+/**\r
+ Cancel DNS4 tokens from the DNS4 instance.\r
+\r
+ @param[in] Instance Pointer to the DNS instance context data.\r
+ @param[in] Token Pointer to the token to be canceled. If NULL, all\r
+ tokens in this instance will be cancelled.\r
+ This parameter is optional and may be NULL.\r
+\r
+ @retval EFI_SUCCESS The Token is cancelled.\r
+ @retval EFI_NOT_FOUND The Token is not found.\r
+\r
+**/\r
+EFI_STATUS\r
+Dns4InstanceCancelToken (\r
+ IN DNS_INSTANCE *Instance,\r
+ IN EFI_DNS4_COMPLETION_TOKEN *Token\r
+ );\r
+\r
+/**\r
+ Cancel DNS6 tokens from the DNS6 instance.\r
+\r
+ @param[in] Instance Pointer to the DNS instance context data.\r
+ @param[in] Token Pointer to the token to be canceled. If NULL, all\r
+ tokens in this instance will be cancelled.\r
+ This parameter is optional and may be NULL.\r
+\r
+ @retval EFI_SUCCESS The Token is cancelled.\r
+ @retval EFI_NOT_FOUND The Token is not found.\r
+\r
+**/\r
+EFI_STATUS\r
+Dns6InstanceCancelToken (\r
+ IN DNS_INSTANCE *Instance,\r
+ IN EFI_DNS6_COMPLETION_TOKEN *Token\r
+ );\r
+\r
+/**\r
+ Free the resource related to the configure parameters.\r
+\r
+ @param Config The DNS configure data\r
+\r
+**/\r
+VOID\r
+Dns4CleanConfigure (\r
+ IN OUT EFI_DNS4_CONFIG_DATA *Config\r
+ );\r
+\r
+/**\r
+ Free the resource related to the configure parameters.\r
+\r
+ @param Config The DNS configure data\r
+\r
+**/\r
+VOID\r
+Dns6CleanConfigure (\r
+ IN OUT EFI_DNS6_CONFIG_DATA *Config\r
+ );\r
+\r
+/**\r
+ Allocate memory for configure parameter such as timeout value for Dst,\r
+ then copy the configure parameter from Src to Dst.\r
+\r
+ @param[out] Dst The destination DHCP configure data.\r
+ @param[in] Src The source DHCP configure data.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
+ @retval EFI_SUCCESS The configure is copied.\r
+\r
+**/\r
+EFI_STATUS\r
+Dns4CopyConfigure (\r
+ OUT EFI_DNS4_CONFIG_DATA *Dst,\r
+ IN EFI_DNS4_CONFIG_DATA *Src\r
+ );\r
+\r
+/**\r
+ Allocate memory for configure parameter such as timeout value for Dst,\r
+ then copy the configure parameter from Src to Dst.\r
+\r
+ @param[out] Dst The destination DHCP configure data.\r
+ @param[in] Src The source DHCP configure data.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
+ @retval EFI_SUCCESS The configure is copied.\r
+\r
+**/\r
+EFI_STATUS\r
+Dns6CopyConfigure (\r
+ OUT EFI_DNS6_CONFIG_DATA *Dst,\r
+ IN EFI_DNS6_CONFIG_DATA *Src\r
+ );\r
+\r
+/**\r
+ Callback of Dns packet. Does nothing.\r
+\r
+ @param Arg The context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DnsDummyExtFree (\r
+ IN VOID *Arg\r
+ );\r
+\r
+/**\r
+ Poll the UDP to get the IP4 default address, which may be retrieved\r
+ by DHCP. \r
+ \r
+ The default time out value is 5 seconds. If IP has retrieved the default address, \r
+ the UDP is reconfigured.\r
+\r
+ @param Instance The DNS instance\r
+ @param UdpIo The UDP_IO to poll\r
+ @param UdpCfgData The UDP configure data to reconfigure the UDP_IO\r
+\r
+ @retval TRUE The default address is retrieved and UDP is reconfigured.\r
+ @retval FALSE Some error occured.\r
+\r
+**/\r
+BOOLEAN\r
+Dns4GetMapping (\r
+ IN DNS_INSTANCE *Instance,\r
+ IN UDP_IO *UdpIo,\r
+ IN EFI_UDP4_CONFIG_DATA *UdpCfgData\r
+ );\r
+\r
+/**\r
+ Configure the opened Udp6 instance until the corresponding Ip6 instance\r
+ has been configured.\r
+\r
+ @param Instance The DNS instance\r
+ @param UdpIo The UDP_IO to poll\r
+ @param UdpCfgData The UDP configure data to reconfigure the UDP_IO\r
+\r
+ @retval TRUE Configure the Udp6 instance successfully.\r
+ @retval FALSE Some error occured.\r
+\r
+**/\r
+BOOLEAN\r
+Dns6GetMapping (\r
+ IN DNS_INSTANCE *Instance,\r
+ IN UDP_IO *UdpIo,\r
+ IN EFI_UDP6_CONFIG_DATA *UdpCfgData\r
+ );\r
+\r
+/**\r
+ Configure the UDP.\r
+ \r
+ @param Instance The DNS session\r
+ @param UdpIo The UDP_IO instance\r
+ \r
+ @retval EFI_SUCCESS The UDP is successfully configured for the\r
+ session.\r
+\r
+**/\r
+EFI_STATUS\r
+Dns4ConfigUdp (\r
+ IN DNS_INSTANCE *Instance,\r
+ IN UDP_IO *UdpIo\r
+ );\r
+\r
+/**\r
+ Configure the UDP.\r
+ \r
+ @param Instance The DNS session\r
+ @param UdpIo The UDP_IO instance\r
+\r
+ @retval EFI_SUCCESS The UDP is successfully configured for the\r
+ session.\r
+\r
+**/\r
+EFI_STATUS\r
+Dns6ConfigUdp (\r
+ IN DNS_INSTANCE *Instance,\r
+ IN UDP_IO *UdpIo\r
+ );\r
+\r
+/**\r
+ Update Dns4 cache to shared list of caches of all DNSv4 instances.\r
+ \r
+ @param Dns4CacheList All Dns4 cache list.\r
+ @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache. \r
+ If TRUE, this function will delete matching DNS Cache entry. \r
+ @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter. \r
+ If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.\r
+ @param DnsCacheEntry Entry Pointer to DNS Cache entry.\r
+\r
+ @retval EFI_SUCCESS Update Dns4 cache successfully.\r
+ @retval Others Failed to update Dns4 cache. \r
+ \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UpdateDns4Cache (\r
+ IN LIST_ENTRY *Dns4CacheList,\r
+ IN BOOLEAN DeleteFlag,\r
+ IN BOOLEAN Override,\r
+ IN EFI_DNS4_CACHE_ENTRY DnsCacheEntry\r
+ );\r
+\r
+/**\r
+ Update Dns6 cache to shared list of caches of all DNSv6 instances. \r
+\r
+ @param Dns6CacheList All Dns6 cache list.\r
+ @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache. \r
+ If TRUE, this function will delete matching DNS Cache entry. \r
+ @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter. \r
+ If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.\r
+ @param DnsCacheEntry Entry Pointer to DNS Cache entry.\r
+ \r
+ @retval EFI_SUCCESS Update Dns6 cache successfully.\r
+ @retval Others Failed to update Dns6 cache.\r
+**/ \r
+EFI_STATUS\r
+EFIAPI\r
+UpdateDns6Cache (\r
+ IN LIST_ENTRY *Dns6CacheList,\r
+ IN BOOLEAN DeleteFlag,\r
+ IN BOOLEAN Override,\r
+ IN EFI_DNS6_CACHE_ENTRY DnsCacheEntry\r
+ );\r
+\r
+/**\r
+ Add Dns4 ServerIp to common list of addresses of all configured DNSv4 server. \r
+\r
+ @param Dns4ServerList Common list of addresses of all configured DNSv4 server. \r
+ @param ServerIp DNS server Ip. \r
+\r
+ @retval EFI_SUCCESS Add Dns4 ServerIp to common list successfully.\r
+ @retval Others Failed to add Dns4 ServerIp to common list.\r
+ \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AddDns4ServerIp (\r
+ IN LIST_ENTRY *Dns4ServerList,\r
+ IN EFI_IPv4_ADDRESS ServerIp\r
+ );\r
+\r
+/**\r
+ Add Dns6 ServerIp to common list of addresses of all configured DNSv6 server. \r
+\r
+ @param Dns6ServerList Common list of addresses of all configured DNSv6 server. \r
+ @param ServerIp DNS server Ip. \r
+\r
+ @retval EFI_SUCCESS Add Dns6 ServerIp to common list successfully.\r
+ @retval Others Failed to add Dns6 ServerIp to common list.\r
+ \r
+**/ \r
+EFI_STATUS\r
+EFIAPI\r
+AddDns6ServerIp (\r
+ IN LIST_ENTRY *Dns6ServerList,\r
+ IN EFI_IPv6_ADDRESS ServerIp\r
+ );\r
+\r
+/**\r
+ Find out whether the response is valid or invalid.\r
+\r
+ @param TokensMap All DNS transmittal Tokens entry. \r
+ @param Identification Identification for queried packet. \r
+ @param Type Type for queried packet.\r
+ @param Item Return corresponding Token entry.\r
+\r
+ @retval TRUE The response is valid.\r
+ @retval FALSE The response is invalid.\r
+ \r
+**/ \r
+BOOLEAN\r
+IsValidDnsResponse (\r
+ IN NET_MAP *TokensMap,\r
+ IN UINT16 Identification,\r
+ IN UINT16 Type,\r
+ OUT NET_MAP_ITEM **Item\r
+ );\r
+\r
+/**\r
+ Parse Dns Response.\r
+\r
+ @param Instance The DNS instance\r
+ @param RxString Received buffer.\r
+ @param Completed Flag to indicate that Dns response is valid. \r
+ \r
+ @retval EFI_SUCCESS Parse Dns Response successfully.\r
+ @retval Others Failed to parse Dns Response.\r
+ \r
+**/ \r
+EFI_STATUS\r
+ParseDnsResponse (\r
+ IN OUT DNS_INSTANCE *Instance,\r
+ IN UINT8 *RxString,\r
+ OUT BOOLEAN *Completed\r
+ );\r
+\r
+/**\r
+ Parse response packet.\r
+\r
+ @param Packet The packets received.\r
+ @param EndPoint The local/remote UDP access point\r
+ @param IoStatus The status of the UDP receive\r
+ @param Context The opaque parameter to the function.\r
+\r
+**/ \r
+VOID\r
+EFIAPI\r
+DnsOnPacketReceived (\r
+ NET_BUF *Packet,\r
+ UDP_END_POINT *EndPoint,\r
+ EFI_STATUS IoStatus,\r
+ VOID *Context\r
+ );\r
+\r
+/**\r
+ Release the net buffer when packet is sent.\r
+\r
+ @param Packet The packets received.\r
+ @param EndPoint The local/remote UDP access point\r
+ @param IoStatus The status of the UDP receive\r
+ @param Context The opaque parameter to the function.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DnsOnPacketSent (\r
+ NET_BUF *Packet,\r
+ UDP_END_POINT *EndPoint,\r
+ EFI_STATUS IoStatus,\r
+ VOID *Context\r
+ );\r
+\r
+/**\r
+ Query request information.\r
+\r
+ @param Instance The DNS instance\r
+ @param Packet The packet for querying request information.\r
+\r
+ @retval EFI_SUCCESS Query request information successfully.\r
+ @retval Others Failed to query request information.\r
+\r
+**/\r
+EFI_STATUS\r
+DoDnsQuery (\r
+ IN DNS_INSTANCE *Instance,\r
+ IN NET_BUF *Packet\r
+ );\r
+\r
+/**\r
+ Construct the Packet to query Ip.\r
+\r
+ @param Instance The DNS instance\r
+ @param HostName Queried HostName \r
+ @param Type DNS query Type\r
+ @param Packet The packet for querying Ip\r
+\r
+ @retval EFI_SUCCESS The packet is constructed.\r
+ @retval Others Failed to construct the Packet.\r
+\r
+**/\r
+EFI_STATUS\r
+ConstructDNSQueryIp (\r
+ IN DNS_INSTANCE *Instance,\r
+ IN CHAR16 *HostName,\r
+ IN UINT16 Type,\r
+ OUT NET_BUF **Packet\r
+ );\r
+\r
+/**\r
+ Retransmit the packet.\r
+\r
+ @param Instance The DNS instance\r
+ @param Packet Retransmit the packet \r
+\r
+ @retval EFI_SUCCESS The packet is retransmitted.\r
+ @retval Others Failed to retransmit.\r
+\r
+**/\r
+EFI_STATUS\r
+DnsRetransmit (\r
+ IN DNS_INSTANCE *Instance,\r
+ IN NET_BUF *Packet\r
+ );\r
+\r
+/**\r
+ The timer ticking function for the DNS service.\r
+\r
+ @param Event The ticking event\r
+ @param Context The DNS service instance\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DnsOnTimerRetransmit (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ );\r
+\r
+/**\r
+ The timer ticking function for the DNS driver.\r
+\r
+ @param Event The ticking event\r
+ @param Context NULL\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DnsOnTimerUpdate (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ );\r
+\r
+\r
+/**\r
+ This function is used to retrieve DNS mode data for this DNS instance.\r
+\r
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.\r
+ @param[out] DnsModeData Pointer to the caller-allocated storage for the EFI_DNS4_MODE_DATA structure.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_NOT_STARTED When DnsConfigData is queried, no configuration data is \r
+ available because this instance has not been configured.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
+ @retval EFI_INVALID_PARAMETER This is NULL or DnsModeData is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4GetModeData (\r
+ IN EFI_DNS4_PROTOCOL *This,\r
+ OUT EFI_DNS4_MODE_DATA *DnsModeData\r
+ );\r
+\r
+/**\r
+ This function is used to configure DNS configuration data for this DNS instance.\r
+\r
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.\r
+ @param[in] DnsConfigData Pointer to caller-allocated buffer containing EFI_DNS4_CONFIG_DATA structure. \r
+ If NULL, the driver will reinitialize the protocol instance to the unconfigured state.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_UNSUPPORTED The designated protocol is not supported.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
+ @retval EFI_INVALID_PARAMETER This is NULL.\r
+ The StationIp address provided in DnsConfigData is not a valid unicast.\r
+ DnsServerList is NULL while DnsServerListCount is not equal to Zero.\r
+ DnsServerListCount is Zero while DnsServerListCount is not equal to NULL.\r
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI DNSv4 Protocol instance is not configured.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4Configure (\r
+ IN EFI_DNS4_PROTOCOL *This,\r
+ IN EFI_DNS4_CONFIG_DATA *DnsConfigData\r
+ );\r
+\r
+/**\r
+ The function is used to translate the host name to host IP address. \r
+ A type A query is used to get the one or more IP addresses for this host. \r
+\r
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.\r
+ @param[in] HostName Pointer to caller-supplied buffer containing Host name to be translated. \r
+ This buffer contains 16 bit characters but these are translated to ASCII for use with \r
+ DNSv4 server and there is no requirement for driver to support non-ASCII Unicode characters.\r
+ @param[in] Token Pointer to the caller-allocated completion token to return at the completion of the process to translate host name to host address. \r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
+ @retval EFI_INVALID_PARAMETER This is NULL.\r
+ Token is NULL.\r
+ Token.Event is.NULL\r
+ HostName is NULL\r
+ @retval EFI_NO_MAPPING There's no source address is available for use.\r
+ @retval EFI_NOT_STARTED This instance has not been started.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4HostNameToIp (\r
+ IN EFI_DNS4_PROTOCOL *This,\r
+ IN CHAR16 *HostName,\r
+ IN EFI_DNS4_COMPLETION_TOKEN *Token\r
+ );\r
+\r
+/**\r
+ The function is used to translate the host address to host name. \r
+ A type PTR query is used to get the primary name of the host. \r
+\r
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.\r
+ @param[in] IpAddress IP address.\r
+ @param[in] Token Pointer to the caller-allocated completion used token to translate host address to host name.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
+ @retval EFI_INVALID_PARAMETER This is NULL.\r
+ Token is NULL.\r
+ Token.Event is NULL.\r
+ IpAddress is not valid IP address.\r
+ @retval EFI_NO_MAPPING There's no source address is available for use.\r
+ @retval EFI_NOT_STARTED This instance has not been started.\r
+ @retval EFI_UNSUPPORTED This function is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4IpToHostName (\r
+ IN EFI_DNS4_PROTOCOL *This,\r
+ IN EFI_IPv4_ADDRESS IpAddress,\r
+ IN EFI_DNS4_COMPLETION_TOKEN *Token\r
+ );\r
+\r
+/**\r
+ This function retrieves arbitrary information from the DNS. \r
+ The caller supplies a QNAME, QTYPE, and QCLASS, and all of the matching RRs are returned. \r
+ All RR content (e.g., Ttl) was returned. \r
+ The caller need parse the returned RR to get required information. This function is optional.\r
+\r
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.\r
+ @param[in] QName Pointer to Query Name.\r
+ @param[in] QType Query Type.\r
+ @param[in] QClass Query Name.\r
+ @param[in] Token Point to the caller-allocated completion token to retrieve arbitrary information.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
+ @retval EFI_INVALID_PARAMETER This is NULL.\r
+ Token is NULL.\r
+ Token.Event is NULL.\r
+ QName is NULL.\r
+ @retval EFI_NO_MAPPING There's no source address is available for use.\r
+ @retval EFI_ALREADY_STARTED This Token is being used in another DNS session.\r
+ @retval EFI_UNSUPPORTED This function is not supported. Or the requested QType is not supported\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4GeneralLookUp (\r
+ IN EFI_DNS4_PROTOCOL *This,\r
+ IN CHAR8 *QName,\r
+ IN UINT16 QType, \r
+ IN UINT16 QClass,\r
+ IN EFI_DNS4_COMPLETION_TOKEN *Token\r
+ );\r
+\r
+/**\r
+ This function is used to add/delete/modify DNS cache entry. \r
+ DNS cache can be normally dynamically updated after the DNS resolve succeeds. \r
+ This function provided capability to manually add/delete/modify the DNS cache.\r
+\r
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.\r
+ @param[in] DeleteFlag If FALSE, this function is to add one entry to the DNS Cache. \r
+ If TRUE, this function will delete matching DNS Cache entry. \r
+ @param[in] Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter. \r
+ If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.\r
+ @param[in] DnsCacheEntry Pointer to DNS Cache entry.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_INVALID_PARAMETER This is NULL. \r
+ DnsCacheEntry.HostName is NULL.\r
+ DnsCacheEntry.IpAddress is NULL.\r
+ DnsCacheEntry.Timeout is zero.\r
+ @retval EFI_ACCESS_DENIED The DNS cache entry already exists and Override is not TRUE. \r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4UpdateDnsCache (\r
+ IN EFI_DNS4_PROTOCOL *This,\r
+ IN BOOLEAN DeleteFlag,\r
+ IN BOOLEAN Override,\r
+ IN EFI_DNS4_CACHE_ENTRY DnsCacheEntry\r
+ );\r
+\r
+/**\r
+ This function can be used by network drivers and applications to increase the rate that data packets are moved between \r
+ the communications device and the transmit and receive queues. In some systems, the periodic timer event in the managed \r
+ network driver may not poll the underlying communications device fast enough to transmit and/or receive all data packets \r
+ without missing incoming packets or dropping outgoing packets.\r
+\r
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.\r
+\r
+ @retval EFI_SUCCESS Incoming or outgoing data was processed.\r
+ @retval EFI_INVALID_PARAMETER This is NULL. \r
+ @retval EFI_NOT_STARTED This EFI DNS Protocol instance has not been started. \r
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. \r
+ @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue. \r
+ Consider increasing the polling rate.\r
+ \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4Poll (\r
+ IN EFI_DNS4_PROTOCOL *This\r
+ );\r
+\r
+/**\r
+ This function is used to abort a pending resolution request. \r
+ After calling this function, Token.Status will be set to EFI_ABORTED and then Token.\r
+\r
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.\r
+ @param[in] Token Pointer to a token that has been issued by EFI_DNS4_PROTOCOL.HostNameToIp(), \r
+ EFI_DNS4_PROTOCOL.IpToHostName() or EFI_DNS4_PROTOCOL.GeneralLookup(). \r
+ If NULL, all pending tokens are aborted.\r
+\r
+ @retval EFI_SUCCESS Incoming or outgoing data was processed.\r
+ @retval EFI_INVALID_PARAMETER This is NULL. \r
+ @retval EFI_NOT_STARTED This EFI DNS Protocol instance has not been started. \r
+ @retval EFI_NOT_FOUND When Token is not NULL, and the asynchronous DNS operation was not found in the transmit queue. \r
+ It was either completed or was not issued by HostNameToIp(), IpToHostName() or GeneralLookup().\r
+ \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4Cancel (\r
+ IN EFI_DNS4_PROTOCOL *This,\r
+ IN EFI_DNS4_COMPLETION_TOKEN *Token\r
+ );\r
+\r
+\r
+/**\r
+ This function is used to retrieve DNS mode data for this DNS instance.\r
+\r
+ @param[in] This Pointer to EFI_DNS6_PROTOCOL instance.\r
+ @param[out] DnsModeData Pointer to the caller-allocated storage for the EFI_DNS6_MODE_DATA structure.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_NOT_STARTED When DnsConfigData is queried, no configuration data is \r
+ available because this instance has not been configured.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
+ @retval EFI_INVALID_PARAMETER This is NULL or DnsModeData is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6GetModeData (\r
+ IN EFI_DNS6_PROTOCOL *This,\r
+ OUT EFI_DNS6_MODE_DATA *DnsModeData\r
+ );\r
+\r
+/**\r
+ The function is used to set and change the configuration data for this EFI DNSv6 Protocol driver instance. \r
+ Reset the DNS instance if DnsConfigData is NULL.\r
+\r
+ @param[in] This Pointer to EFI_DNS6_PROTOCOL instance.\r
+ @param[in] DnsConfigData Pointer to the configuration data structure. \r
+ All associated storage to be allocated and released by caller.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_UNSUPPORTED The designated protocol is not supported.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
+ @retval EFI_INVALID_PARAMETER This is NULL.\r
+ The StationIp address provided in DnsConfigData is not a valid unicast.\r
+ DnsServerList is NULL while DnsServerListCount is not equal to Zero.\r
+ DnsServerListCount is Zero while DnsServerList is not equal to NULL.\r
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI DNSv6 Protocol instance is not configured.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6Configure (\r
+ IN EFI_DNS6_PROTOCOL *This,\r
+ IN EFI_DNS6_CONFIG_DATA *DnsConfigData\r
+ );\r
+\r
+/**\r
+ The function is used to translate the host name to host IP address. \r
+ A type AAAA query is used to get the one or more IPv6 addresses for this host. \r
+\r
+ @param[in] This Pointer to EFI_DNS6_PROTOCOL instance.\r
+ @param[in] HostName Pointer to caller-supplied buffer containing Host name to be translated. \r
+ This buffer contains 16 bit characters but these are translated to ASCII for use with \r
+ DNSv4 server and there is no requirement for driver to support non-ASCII Unicode characters.\r
+ @param[in] Token Pointer to the caller-allocated completion token to return at the completion of the process to translate host name to host address. \r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
+ @retval EFI_INVALID_PARAMETER This is NULL.\r
+ Token is NULL.\r
+ Token.Event is.NULL\r
+ HostName is NULL\r
+ @retval EFI_NO_MAPPING There's no source address is available for use.\r
+ @retval EFI_NOT_STARTED This instance has not been started.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6HostNameToIp (\r
+ IN EFI_DNS6_PROTOCOL *This,\r
+ IN CHAR16 *HostName,\r
+ IN EFI_DNS6_COMPLETION_TOKEN *Token\r
+ );\r
+\r
+/**\r
+ The function is used to translate the host address to host name. \r
+ A type PTR query is used to get the primary name of the host. \r
+\r
+ @param[in] This Pointer to EFI_DNS6_PROTOCOL instance.\r
+ @param[in] IpAddress IP address.\r
+ @param[in] Token Pointer to the caller-allocated completion used token to translate host address to host name.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
+ @retval EFI_INVALID_PARAMETER This is NULL.\r
+ Token is NULL.\r
+ Token.Event is NULL.\r
+ IpAddress is not valid IP address.\r
+ @retval EFI_NO_MAPPING There's no source address is available for use.\r
+ @retval EFI_NOT_STARTED This instance has not been started.\r
+ @retval EFI_UNSUPPORTED This function is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6IpToHostName (\r
+ IN EFI_DNS6_PROTOCOL *This,\r
+ IN EFI_IPv6_ADDRESS IpAddress,\r
+ IN EFI_DNS6_COMPLETION_TOKEN *Token\r
+ );\r
+\r
+/**\r
+ This function retrieves arbitrary information from the DNS. \r
+ The caller supplies a QNAME, QTYPE, and QCLASS, and all of the matching RRs are returned. \r
+ All RR content (e.g., Ttl) was returned. \r
+ The caller need parse the returned RR to get required information. This function is optional.\r
+\r
+ @param[in] This Pointer to EFI_DNS6_PROTOCOL instance.\r
+ @param[in] QName Pointer to Query Name.\r
+ @param[in] QType Query Type.\r
+ @param[in] QClass Query Name.\r
+ @param[in] Token Point to the caller-allocated completion token to retrieve arbitrary information.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
+ @retval EFI_INVALID_PARAMETER This is NULL.\r
+ Token is NULL.\r
+ Token.Event is NULL.\r
+ QName is NULL.\r
+ @retval EFI_NO_MAPPING There's no source address is available for use.\r
+ @retval EFI_NOT_STARTED This instance has not been started.\r
+ @retval EFI_UNSUPPORTED This function is not supported. Or the requested QType is not supported\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6GeneralLookUp (\r
+ IN EFI_DNS6_PROTOCOL *This,\r
+ IN CHAR8 *QName,\r
+ IN UINT16 QType, \r
+ IN UINT16 QClass,\r
+ IN EFI_DNS6_COMPLETION_TOKEN *Token\r
+ );\r
+\r
+/**\r
+ This function is used to add/delete/modify DNS cache entry. \r
+ DNS cache can be normally dynamically updated after the DNS resolve succeeds. \r
+ This function provided capability to manually add/delete/modify the DNS cache.\r
+\r
+ @param[in] This Pointer to EFI_DNS6_PROTOCOL instance.\r
+ @param[in] DeleteFlag If FALSE, this function is to add one entry to the DNS Cache. \r
+ If TRUE, this function will delete matching DNS Cache entry. \r
+ @param[in] Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter. \r
+ If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.\r
+ @param[in] DnsCacheEntry Pointer to DNS Cache entry.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_INVALID_PARAMETER This is NULL. \r
+ DnsCacheEntry.HostName is NULL.\r
+ DnsCacheEntry.IpAddress is NULL.\r
+ DnsCacheEntry.Timeout is zero.\r
+ @retval EFI_ACCESS_DENIED The DNS cache entry already exists and Override is not TRUE. \r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6UpdateDnsCache (\r
+ IN EFI_DNS6_PROTOCOL *This,\r
+ IN BOOLEAN DeleteFlag,\r
+ IN BOOLEAN Override,\r
+ IN EFI_DNS6_CACHE_ENTRY DnsCacheEntry\r
+ );\r
+\r
+/**\r
+ This function can be used by network drivers and applications to increase the rate that data packets are moved between \r
+ the communications device and the transmit and receive queues. In some systems, the periodic timer event in the managed \r
+ network driver may not poll the underlying communications device fast enough to transmit and/or receive all data packets \r
+ without missing incoming packets or dropping outgoing packets.\r
+\r
+ @param[in] This Pointer to EFI_DNS6_PROTOCOL instance.\r
+\r
+ @retval EFI_SUCCESS Incoming or outgoing data was processed.\r
+ @retval EFI_INVALID_PARAMETER This is NULL. \r
+ @retval EFI_NOT_STARTED This EFI DNS Protocol instance has not been started. \r
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. \r
+ @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue. \r
+ Consider increasing the polling rate.\r
+ \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6Poll (\r
+ IN EFI_DNS6_PROTOCOL *This\r
+ );\r
+\r
+/**\r
+ This function is used to abort a pending resolution request. \r
+ After calling this function, Token.Status will be set to EFI_ABORTED and then Token.\r
+\r
+ @param[in] This Pointer to EFI_DNS6_PROTOCOL instance.\r
+ @param[in] Token Pointer to a token that has been issued by EFI_DNS6_PROTOCOL.HostNameToIp(), \r
+ EFI_DNS6_PROTOCOL.IpToHostName() or EFI_DNS6_PROTOCOL.GeneralLookup(). \r
+ If NULL, all pending tokens are aborted.\r
+\r
+ @retval EFI_SUCCESS Incoming or outgoing data was processed.\r
+ @retval EFI_INVALID_PARAMETER This is NULL. \r
+ @retval EFI_NOT_STARTED This EFI DNS Protocol instance has not been started. \r
+ @retval EFI_NOT_FOUND When Token is not NULL, and the asynchronous DNS operation was not found in the transmit queue. \r
+ It was either completed or was not issued by HostNameToIp(), IpToHostName() or GeneralLookup().\r
+ \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6Cancel (\r
+ IN EFI_DNS6_PROTOCOL *This,\r
+ IN EFI_DNS6_COMPLETION_TOKEN *Token\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+Implementation of EFI_DNS4_PROTOCOL and EFI_DNS6_PROTOCOL interfaces.\r
+\r
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "DnsImpl.h"\r
+\r
+EFI_DNS4_PROTOCOL mDns4Protocol = {\r
+ Dns4GetModeData,\r
+ Dns4Configure,\r
+ Dns4HostNameToIp,\r
+ Dns4IpToHostName,\r
+ Dns4GeneralLookUp,\r
+ Dns4UpdateDnsCache,\r
+ Dns4Poll,\r
+ Dns4Cancel\r
+};\r
+\r
+EFI_DNS6_PROTOCOL mDns6Protocol = {\r
+ Dns6GetModeData,\r
+ Dns6Configure,\r
+ Dns6HostNameToIp,\r
+ Dns6IpToHostName,\r
+ Dns6GeneralLookUp,\r
+ Dns6UpdateDnsCache,\r
+ Dns6Poll,\r
+ Dns6Cancel\r
+};\r
+\r
+/**\r
+ This function is used to retrieve DNS mode data for this DNS instance.\r
+\r
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.\r
+ @param[out] DnsModeData Pointer to the caller-allocated storage for the EFI_DNS4_MODE_DATA structure.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_NOT_STARTED When DnsConfigData is queried, no configuration data is \r
+ available because this instance has not been configured.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
+ @retval EFI_INVALID_PARAMETER This is NULL or DnsModeData is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4GetModeData (\r
+ IN EFI_DNS4_PROTOCOL *This,\r
+ OUT EFI_DNS4_MODE_DATA *DnsModeData\r
+ )\r
+{\r
+ DNS_INSTANCE *Instance;\r
+ \r
+ EFI_TPL OldTpl;\r
+\r
+ UINTN Index;\r
+ \r
+ LIST_ENTRY *Entry;\r
+ LIST_ENTRY *Next;\r
+ \r
+ DNS4_SERVER_IP *ServerItem;\r
+ EFI_IPv4_ADDRESS *ServerList;\r
+ DNS4_CACHE *CacheItem;\r
+ EFI_DNS4_CACHE_ENTRY *CacheList;\r
+ EFI_STATUS Status;\r
+\r
+ ServerItem = NULL;\r
+ ServerList = NULL;\r
+ CacheItem = NULL;\r
+ CacheList = NULL;\r
+ Status = EFI_SUCCESS;\r
+ \r
+ \r
+ if ((This == NULL) || (DnsModeData == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+ \r
+ Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (This);\r
+ if (Instance->State == DNS_STATE_UNCONFIGED) {\r
+ gBS->RestoreTPL (OldTpl);\r
+ return EFI_NOT_STARTED;\r
+ }\r
+ \r
+ ZeroMem (DnsModeData, sizeof (EFI_DNS4_MODE_DATA));\r
+\r
+ //\r
+ // Get the current configuration data of this instance. \r
+ //\r
+ Status = Dns4CopyConfigure (&DnsModeData->DnsConfigData, &Instance->Dns4CfgData);\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get the DnsServerCount and DnsServerList\r
+ //\r
+ Index = 0;\r
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4ServerList) {\r
+ Index++;\r
+ }\r
+ DnsModeData->DnsServerCount = (UINT32) Index;\r
+ ServerList = AllocatePool (sizeof (EFI_IPv4_ADDRESS) * DnsModeData->DnsServerCount);\r
+ ASSERT (ServerList != NULL);\r
+ Index = 0;\r
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4ServerList) {\r
+ ServerItem = NET_LIST_USER_STRUCT (Entry, DNS4_SERVER_IP, AllServerLink);\r
+ CopyMem (ServerList + Index, &ServerItem->Dns4ServerIp, sizeof (EFI_IPv4_ADDRESS));\r
+ Index++;\r
+ }\r
+ DnsModeData->DnsServerList = ServerList;\r
+\r
+ //\r
+ // Get the DnsCacheCount and DnsCacheList\r
+ //\r
+ Index =0;\r
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) {\r
+ Index++;\r
+ }\r
+ DnsModeData->DnsCacheCount = (UINT32) Index;\r
+ CacheList = AllocatePool (sizeof (EFI_DNS4_CACHE_ENTRY) * DnsModeData->DnsCacheCount);\r
+ ASSERT (CacheList != NULL);\r
+ Index =0;\r
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) {\r
+ CacheItem = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);\r
+ CopyMem (CacheList + Index, &CacheItem->DnsCache, sizeof (EFI_DNS4_CACHE_ENTRY));\r
+ Index++;\r
+ }\r
+ DnsModeData->DnsCacheList = CacheList;\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function is used to configure DNS configuration data for this DNS instance.\r
+\r
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.\r
+ @param[in] DnsConfigData Pointer to caller-allocated buffer containing EFI_DNS4_CONFIG_DATA structure. \r
+ If NULL, the driver will reinitialize the protocol instance to the unconfigured state.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_UNSUPPORTED The designated protocol is not supported.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
+ @retval EFI_INVALID_PARAMETER This is NULL.\r
+ The StationIp address provided in DnsConfigData is not a valid unicast.\r
+ DnsServerList is NULL while DnsServerListCount is not equal to Zero.\r
+ DnsServerListCount is Zero while DnsServerListCount is not equal to NULL.\r
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI DNSv4 Protocol instance is not configured.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4Configure (\r
+ IN EFI_DNS4_PROTOCOL *This,\r
+ IN EFI_DNS4_CONFIG_DATA *DnsConfigData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ DNS_INSTANCE *Instance;\r
+ \r
+ EFI_TPL OldTpl;\r
+ IP4_ADDR Ip;\r
+ IP4_ADDR Netmask;\r
+\r
+ UINT32 ServerListCount;\r
+ EFI_IPv4_ADDRESS *ServerList; \r
+\r
+ Status = EFI_SUCCESS;\r
+ ServerList = NULL;\r
+ \r
+ if (This == NULL || \r
+ (DnsConfigData != NULL && ((DnsConfigData->DnsServerListCount != 0 && DnsConfigData->DnsServerList == NULL) || \r
+ (DnsConfigData->DnsServerListCount == 0 && DnsConfigData->DnsServerList != NULL)))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (DnsConfigData != NULL && DnsConfigData->Protocol != DNS_PROTOCOL_UDP) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+ Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (This);\r
+\r
+ if (DnsConfigData == NULL) {\r
+ ZeroMem (&Instance->SessionDnsServer, sizeof (EFI_IP_ADDRESS));\r
+ \r
+ //\r
+ // Reset the Instance if ConfigData is NULL\r
+ //\r
+ if (!NetMapIsEmpty(&Instance->Dns4TxTokens)) {\r
+ Dns4InstanceCancelToken(Instance, NULL);\r
+ }\r
+\r
+ Instance->MaxRetry = 0;\r
+\r
+ if (Instance->UdpIo != NULL){\r
+ UdpIoCleanIo (Instance->UdpIo);\r
+ }\r
+ \r
+ if (Instance->Dns4CfgData.DnsServerList != NULL) {\r
+ FreePool (Instance->Dns4CfgData.DnsServerList);\r
+ }\r
+ ZeroMem (&Instance->Dns4CfgData, sizeof (EFI_DNS4_CONFIG_DATA));\r
+ \r
+ Instance->State = DNS_STATE_UNCONFIGED;\r
+ } else {\r
+ //\r
+ // Configure the parameters for new operation.\r
+ //\r
+ CopyMem (&Ip, &DnsConfigData->StationIp, sizeof (IP4_ADDR));\r
+ CopyMem (&Netmask, &DnsConfigData->SubnetMask, sizeof (IP4_ADDR));\r
+\r
+ Ip = NTOHL (Ip);\r
+ Netmask = NTOHL (Netmask);\r
+\r
+ if (!DnsConfigData->UseDefaultSetting &&\r
+ ((!IP4_IS_VALID_NETMASK (Netmask) || !NetIp4IsUnicast (Ip, Netmask)))) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Status = Dns4CopyConfigure (&Instance->Dns4CfgData, DnsConfigData);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ if (DnsConfigData->DnsServerListCount == 0 || DnsConfigData->DnsServerList == NULL) {\r
+ gBS->RestoreTPL (OldTpl); \r
+ \r
+ //\r
+ // The DNS instance will retrieve DNS server from DHCP Server\r
+ //\r
+ Status = GetDns4ServerFromDhcp4 (\r
+ Instance,\r
+ &ServerListCount, \r
+ &ServerList\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ ASSERT(ServerList != NULL);\r
+ \r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+ CopyMem (&Instance->SessionDnsServer.v4, &ServerList[0], sizeof (EFI_IPv4_ADDRESS));\r
+ } else {\r
+ CopyMem (&Instance->SessionDnsServer.v4, &DnsConfigData->DnsServerList[0], sizeof (EFI_IPv4_ADDRESS));\r
+ }\r
+\r
+ //\r
+ // Config UDP\r
+ //\r
+ Status = Dns4ConfigUdp (Instance, Instance->UdpIo);\r
+ if (EFI_ERROR (Status)) {\r
+ if (Instance->Dns4CfgData.DnsServerList != NULL) {\r
+ FreePool (Instance->Dns4CfgData.DnsServerList);\r
+ }\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Add configured DNS server used by this instance to ServerList.\r
+ //\r
+ Status = AddDns4ServerIp (&mDriverData->Dns4ServerList, Instance->SessionDnsServer.v4);\r
+ if (EFI_ERROR (Status)) {\r
+ if (Instance->Dns4CfgData.DnsServerList != NULL) {\r
+ FreePool (Instance->Dns4CfgData.DnsServerList);\r
+ }\r
+ goto ON_EXIT;\r
+ }\r
+ \r
+ Instance->State = DNS_STATE_CONFIGED;\r
+ }\r
+\r
+ON_EXIT:\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ The function is used to translate the host name to host IP address. \r
+ A type A query is used to get the one or more IP addresses for this host. \r
+\r
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.\r
+ @param[in] HostName Pointer to caller-supplied buffer containing Host name to be translated. \r
+ This buffer contains 16 bit characters but these are translated to ASCII for use with \r
+ DNSv4 server and there is no requirement for driver to support non-ASCII Unicode characters.\r
+ @param[in] Token Pointer to the caller-allocated completion token to return at the completion of the process to translate host name to host address. \r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
+ @retval EFI_INVALID_PARAMETER This is NULL.\r
+ Token is NULL.\r
+ Token.Event is.NULL\r
+ HostName is NULL\r
+ @retval EFI_NO_MAPPING There's no source address is available for use.\r
+ @retval EFI_NOT_STARTED This instance has not been started.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4HostNameToIp (\r
+ IN EFI_DNS4_PROTOCOL *This,\r
+ IN CHAR16 *HostName,\r
+ IN EFI_DNS4_COMPLETION_TOKEN *Token\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ \r
+ DNS_INSTANCE *Instance;\r
+ \r
+ EFI_DNS4_CONFIG_DATA *ConfigData;\r
+ \r
+ UINTN Index;\r
+ DNS4_CACHE *Item;\r
+ LIST_ENTRY *Entry;\r
+ LIST_ENTRY *Next;\r
+ \r
+ DNS4_TOKEN_ENTRY *TokenEntry;\r
+ NET_BUF *Packet;\r
+ \r
+ EFI_TPL OldTpl;\r
+ \r
+ Status = EFI_SUCCESS;\r
+ Item = NULL;\r
+ TokenEntry = NULL;\r
+ Packet = NULL;\r
+ \r
+ //\r
+ // Validate the parameters\r
+ //\r
+ if ((This == NULL) || (HostName == NULL) || Token == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+ \r
+ Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (This);\r
+ \r
+ ConfigData = &(Instance->Dns4CfgData);\r
+ \r
+ Instance->MaxRetry = ConfigData->RetryCount;\r
+ \r
+ Token->Status = EFI_NOT_READY;\r
+ Token->RetryCount = 0;\r
+ Token->RetryInterval = ConfigData->RetryInterval;\r
+\r
+ if (Instance->State != DNS_STATE_CONFIGED) {\r
+ Status = EFI_NOT_STARTED;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Check the MaxRetry and RetryInterval values.\r
+ //\r
+ if (Instance->MaxRetry == 0) {\r
+ Instance->MaxRetry = DNS_DEFAULT_RETRY;\r
+ }\r
+\r
+ if (Token->RetryInterval < DNS_DEFAULT_TIMEOUT) {\r
+ Token->RetryInterval = DNS_DEFAULT_TIMEOUT;\r
+ }\r
+\r
+ //\r
+ // Check cache\r
+ //\r
+ if (ConfigData->EnableDnsCache) {\r
+ Index = 0;\r
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) {\r
+ Item = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);\r
+ if (StrCmp (HostName, Item->DnsCache.HostName) == 0) {\r
+ Index++;\r
+ }\r
+ }\r
+\r
+ if (Index != 0) {\r
+ Token->RspData.H2AData = AllocatePool (sizeof (DNS_HOST_TO_ADDR_DATA));\r
+ if (Token->RspData.H2AData == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Token->RspData.H2AData->IpCount = (UINT32)Index;\r
+ Token->RspData.H2AData->IpList = AllocatePool (sizeof (EFI_IPv4_ADDRESS) * Index);\r
+ if (Token->RspData.H2AData->IpList == NULL) {\r
+ if (Token->RspData.H2AData != NULL) {\r
+ FreePool (Token->RspData.H2AData);\r
+ }\r
+ \r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Index = 0;\r
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) {\r
+ Item = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);\r
+ if ((UINT32)Index < Token->RspData.H2AData->IpCount && StrCmp (HostName, Item->DnsCache.HostName) == 0) {\r
+ CopyMem ((Token->RspData.H2AData->IpList) + Index, Item->DnsCache.IpAddress, sizeof (EFI_IPv4_ADDRESS));\r
+ Index++; \r
+ }\r
+ }\r
+ \r
+ Token->Status = EFI_SUCCESS;\r
+ \r
+ if (Token->Event != NULL) {\r
+ gBS->SignalEvent (Token->Event);\r
+ DispatchDpc ();\r
+ }\r
+\r
+ Status = Token->Status;\r
+ goto ON_EXIT;\r
+ } \r
+ }\r
+\r
+ //\r
+ // Construct DNS TokenEntry.\r
+ //\r
+ TokenEntry = AllocateZeroPool (sizeof(DNS4_TOKEN_ENTRY));\r
+ if (TokenEntry == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ }\r
+ \r
+ TokenEntry->PacketToLive = Token->RetryInterval;\r
+ TokenEntry->QueryHostName = HostName;\r
+ TokenEntry->Token = Token;\r
+\r
+ //\r
+ // Construct DNS Query Packet.\r
+ //\r
+ Status = ConstructDNSQueryIp (Instance, TokenEntry->QueryHostName, DNS_TYPE_A, &Packet);\r
+ if (EFI_ERROR (Status)) {\r
+ if (TokenEntry != NULL) {\r
+ FreePool (TokenEntry);\r
+ }\r
+ \r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Save the token into the Dns4TxTokens map.\r
+ //\r
+ Status = NetMapInsertTail (&Instance->Dns4TxTokens, TokenEntry, Packet);\r
+ if (EFI_ERROR (Status)) {\r
+ if (TokenEntry != NULL) {\r
+ FreePool (TokenEntry);\r
+ }\r
+ \r
+ NetbufFree (Packet);\r
+ \r
+ goto ON_EXIT;\r
+ }\r
+ \r
+ //\r
+ // Dns Query Ip\r
+ //\r
+ Status = DoDnsQuery (Instance, Packet);\r
+ if (EFI_ERROR (Status)) {\r
+ if (TokenEntry != NULL) {\r
+ FreePool (TokenEntry);\r
+ }\r
+ \r
+ NetbufFree (Packet);\r
+ }\r
+ \r
+ON_EXIT:\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ The function is used to translate the host address to host name. \r
+ A type PTR query is used to get the primary name of the host. \r
+\r
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.\r
+ @param[in] IpAddress IP address.\r
+ @param[in] Token Pointer to the caller-allocated completion used token to translate host address to host name.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
+ @retval EFI_INVALID_PARAMETER This is NULL.\r
+ Token is NULL.\r
+ Token.Event is NULL.\r
+ IpAddress is not valid IP address.\r
+ @retval EFI_NO_MAPPING There's no source address is available for use.\r
+ @retval EFI_NOT_STARTED This instance has not been started.\r
+ @retval EFI_UNSUPPORTED This function is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4IpToHostName (\r
+ IN EFI_DNS4_PROTOCOL *This,\r
+ IN EFI_IPv4_ADDRESS IpAddress,\r
+ IN EFI_DNS4_COMPLETION_TOKEN *Token\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ This function retrieves arbitrary information from the DNS. \r
+ The caller supplies a QNAME, QTYPE, and QCLASS, and all of the matching RRs are returned. \r
+ All RR content (e.g., Ttl) was returned. \r
+ The caller need parse the returned RR to get required information. This function is optional.\r
+\r
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.\r
+ @param[in] QName Pointer to Query Name.\r
+ @param[in] QType Query Type.\r
+ @param[in] QClass Query Name.\r
+ @param[in] Token Point to the caller-allocated completion token to retrieve arbitrary information.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
+ @retval EFI_INVALID_PARAMETER This is NULL.\r
+ Token is NULL.\r
+ Token.Event is NULL.\r
+ QName is NULL.\r
+ @retval EFI_NO_MAPPING There's no source address is available for use.\r
+ @retval EFI_ALREADY_STARTED This Token is being used in another DNS session.\r
+ @retval EFI_UNSUPPORTED This function is not supported. Or the requested QType is not supported\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4GeneralLookUp (\r
+ IN EFI_DNS4_PROTOCOL *This,\r
+ IN CHAR8 *QName,\r
+ IN UINT16 QType, \r
+ IN UINT16 QClass,\r
+ IN EFI_DNS4_COMPLETION_TOKEN *Token\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ This function is used to add/delete/modify DNS cache entry. \r
+ DNS cache can be normally dynamically updated after the DNS resolve succeeds. \r
+ This function provided capability to manually add/delete/modify the DNS cache.\r
+\r
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.\r
+ @param[in] DeleteFlag If FALSE, this function is to add one entry to the DNS Cache. \r
+ If TRUE, this function will delete matching DNS Cache entry. \r
+ @param[in] Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter. \r
+ If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.\r
+ @param[in] DnsCacheEntry Pointer to DNS Cache entry.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_INVALID_PARAMETER This is NULL. \r
+ DnsCacheEntry.HostName is NULL.\r
+ DnsCacheEntry.IpAddress is NULL.\r
+ DnsCacheEntry.Timeout is zero.\r
+ @retval EFI_ACCESS_DENIED The DNS cache entry already exists and Override is not TRUE. \r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4UpdateDnsCache (\r
+ IN EFI_DNS4_PROTOCOL *This,\r
+ IN BOOLEAN DeleteFlag,\r
+ IN BOOLEAN Override,\r
+ IN EFI_DNS4_CACHE_ENTRY DnsCacheEntry\r
+ )\r
+{\r
+ EFI_STATUS Status; \r
+ EFI_TPL OldTpl;\r
+\r
+ Status = EFI_SUCCESS;\r
+ \r
+ if (DnsCacheEntry.HostName == NULL || DnsCacheEntry.IpAddress == NULL || DnsCacheEntry.Timeout == 0) {\r
+ return EFI_INVALID_PARAMETER; \r
+ }\r
+ \r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+ //\r
+ // Update Dns4Cache here.\r
+ //\r
+ Status = UpdateDns4Cache (&mDriverData->Dns4CacheList, DeleteFlag, Override, DnsCacheEntry);\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+ \r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function can be used by network drivers and applications to increase the rate that data packets are moved between \r
+ the communications device and the transmit and receive queues. In some systems, the periodic timer event in the managed \r
+ network driver may not poll the underlying communications device fast enough to transmit and/or receive all data packets \r
+ without missing incoming packets or dropping outgoing packets.\r
+\r
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.\r
+\r
+ @retval EFI_SUCCESS Incoming or outgoing data was processed.\r
+ @retval EFI_INVALID_PARAMETER This is NULL. \r
+ @retval EFI_NOT_STARTED This EFI DNS Protocol instance has not been started. \r
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. \r
+ @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue. \r
+ Consider increasing the polling rate.\r
+ \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4Poll (\r
+ IN EFI_DNS4_PROTOCOL *This\r
+ )\r
+{\r
+ DNS_INSTANCE *Instance;\r
+ EFI_UDP4_PROTOCOL *Udp;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (This);\r
+\r
+ if (Instance->State == DNS_STATE_UNCONFIGED) {\r
+ return EFI_NOT_STARTED;\r
+ } else if (Instance->State == DNS_STATE_DESTROY) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Udp = Instance->UdpIo->Protocol.Udp4;\r
+ \r
+ return Udp->Poll (Udp);\r
+}\r
+\r
+/**\r
+ This function is used to abort a pending resolution request. \r
+ After calling this function, Token.Status will be set to EFI_ABORTED and then Token.\r
+\r
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.\r
+ @param[in] Token Pointer to a token that has been issued by EFI_DNS4_PROTOCOL.HostNameToIp(), \r
+ EFI_DNS4_PROTOCOL.IpToHostName() or EFI_DNS4_PROTOCOL.GeneralLookup(). \r
+ If NULL, all pending tokens are aborted.\r
+\r
+ @retval EFI_SUCCESS Incoming or outgoing data was processed.\r
+ @retval EFI_INVALID_PARAMETER This is NULL. \r
+ @retval EFI_NOT_STARTED This EFI DNS Protocol instance has not been started. \r
+ @retval EFI_NOT_FOUND When Token is not NULL, and the asynchronous DNS operation was not found in the transmit queue. \r
+ It was either completed or was not issued by HostNameToIp(), IpToHostName() or GeneralLookup().\r
+ \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns4Cancel (\r
+ IN EFI_DNS4_PROTOCOL *This,\r
+ IN EFI_DNS4_COMPLETION_TOKEN *Token\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ DNS_INSTANCE *Instance;\r
+ EFI_TPL OldTpl;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (This);\r
+\r
+ if (Instance->State == DNS_STATE_UNCONFIGED) {\r
+ return EFI_NOT_STARTED;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+ //\r
+ // Cancle the tokens specified by Token for this instance.\r
+ //\r
+ Status = Dns4InstanceCancelToken (Instance, Token);\r
+\r
+ //\r
+ // Dispatch the DPC queued by the NotifyFunction of the canceled token's events.\r
+ //\r
+ DispatchDpc ();\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function is used to retrieve DNS mode data for this DNS instance.\r
+\r
+ @param[in] This Pointer to EFI_DNS6_PROTOCOL instance.\r
+ @param[out] DnsModeData Pointer to the caller-allocated storage for the EFI_DNS6_MODE_DATA structure.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_NOT_STARTED When DnsConfigData is queried, no configuration data is \r
+ available because this instance has not been configured.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
+ @retval EFI_INVALID_PARAMETER This is NULL or DnsModeData is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6GetModeData (\r
+ IN EFI_DNS6_PROTOCOL *This,\r
+ OUT EFI_DNS6_MODE_DATA *DnsModeData\r
+ )\r
+{\r
+ DNS_INSTANCE *Instance;\r
+ \r
+ EFI_TPL OldTpl;\r
+\r
+ UINTN Index;\r
+ \r
+ LIST_ENTRY *Entry;\r
+ LIST_ENTRY *Next;\r
+\r
+ DNS6_SERVER_IP *ServerItem;\r
+ EFI_IPv6_ADDRESS *ServerList;\r
+ DNS6_CACHE *CacheItem;\r
+ EFI_DNS6_CACHE_ENTRY *CacheList;\r
+ EFI_STATUS Status;\r
+\r
+ ServerItem = NULL;\r
+ ServerList = NULL;\r
+ CacheItem = NULL;\r
+ CacheList = NULL;\r
+ Status = EFI_SUCCESS;\r
+\r
+ if ((This == NULL) || (DnsModeData == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+ \r
+ Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL6 (This);\r
+ if (Instance->State == DNS_STATE_UNCONFIGED) {\r
+ gBS->RestoreTPL (OldTpl);\r
+ return EFI_NOT_STARTED;\r
+ }\r
+\r
+ ZeroMem (DnsModeData, sizeof (EFI_DNS6_MODE_DATA));\r
+\r
+ //\r
+ // Get the current configuration data of this instance. \r
+ //\r
+ Status = Dns6CopyConfigure(&DnsModeData->DnsConfigData, &Instance->Dns6CfgData);\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+ }\r
+ \r
+ //\r
+ // Get the DnsServerCount and DnsServerList\r
+ //\r
+ Index = 0;\r
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6ServerList) {\r
+ Index++;\r
+ }\r
+ DnsModeData->DnsServerCount = (UINT32) Index;\r
+ ServerList = AllocatePool (sizeof(EFI_IPv6_ADDRESS) * DnsModeData->DnsServerCount);\r
+ ASSERT (ServerList != NULL);\r
+ Index = 0;\r
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6ServerList) {\r
+ ServerItem = NET_LIST_USER_STRUCT (Entry, DNS6_SERVER_IP, AllServerLink);\r
+ CopyMem (ServerList + Index, &ServerItem->Dns6ServerIp, sizeof (EFI_IPv6_ADDRESS));\r
+ Index++;\r
+ }\r
+ DnsModeData->DnsServerList = ServerList;\r
+\r
+ //\r
+ // Get the DnsCacheCount and DnsCacheList\r
+ //\r
+ Index =0;\r
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6CacheList) {\r
+ Index++;\r
+ }\r
+ DnsModeData->DnsCacheCount = (UINT32) Index;\r
+ CacheList = AllocatePool (sizeof(EFI_DNS6_CACHE_ENTRY) * DnsModeData->DnsCacheCount);\r
+ ASSERT (CacheList != NULL);\r
+ Index =0;\r
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6CacheList) {\r
+ CacheItem = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);\r
+ CopyMem (CacheList + Index, &CacheItem->DnsCache, sizeof (EFI_DNS6_CACHE_ENTRY));\r
+ Index++;\r
+ }\r
+ DnsModeData->DnsCacheList = CacheList;\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ The function is used to set and change the configuration data for this EFI DNSv6 Protocol driver instance. \r
+ Reset the DNS instance if DnsConfigData is NULL.\r
+\r
+ @param[in] This Pointer to EFI_DNS6_PROTOCOL instance.\r
+ @param[in] DnsConfigData Pointer to the configuration data structure. \r
+ All associated storage to be allocated and released by caller.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_UNSUPPORTED The designated protocol is not supported.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
+ @retval EFI_INVALID_PARAMETER This is NULL.\r
+ The StationIp address provided in DnsConfigData is not a valid unicast.\r
+ DnsServerList is NULL while DnsServerListCount is not equal to Zero.\r
+ DnsServerListCount is Zero while DnsServerList is not equal to NULL.\r
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI DNSv6 Protocol instance is not configured.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6Configure (\r
+ IN EFI_DNS6_PROTOCOL *This,\r
+ IN EFI_DNS6_CONFIG_DATA *DnsConfigData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ DNS_INSTANCE *Instance;\r
+ \r
+ EFI_TPL OldTpl;\r
+\r
+ UINT32 ServerListCount;\r
+ EFI_IPv6_ADDRESS *ServerList; \r
+\r
+ Status = EFI_SUCCESS;\r
+ ServerList = NULL;\r
+\r
+ if (This == NULL || \r
+ (DnsConfigData != NULL && ((DnsConfigData->DnsServerCount != 0 && DnsConfigData->DnsServerList == NULL) || \r
+ (DnsConfigData->DnsServerCount == 0 && DnsConfigData->DnsServerList != NULL)))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (DnsConfigData != NULL && DnsConfigData->Protocol != DNS_PROTOCOL_UDP) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+ Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL6 (This);\r
+\r
+ if (DnsConfigData == NULL) {\r
+ ZeroMem (&Instance->SessionDnsServer, sizeof (EFI_IP_ADDRESS));\r
+\r
+ //\r
+ // Reset the Instance if ConfigData is NULL\r
+ //\r
+ if (!NetMapIsEmpty(&Instance->Dns6TxTokens)) {\r
+ Dns6InstanceCancelToken(Instance, NULL);\r
+ }\r
+\r
+ Instance->MaxRetry = 0;\r
+\r
+ if (Instance->UdpIo != NULL){\r
+ UdpIoCleanIo (Instance->UdpIo);\r
+ }\r
+\r
+ if (Instance->Dns6CfgData.DnsServerList != NULL) {\r
+ FreePool (Instance->Dns6CfgData.DnsServerList);\r
+ }\r
+ ZeroMem (&Instance->Dns6CfgData, sizeof (EFI_DNS6_CONFIG_DATA));\r
+ \r
+ Instance->State = DNS_STATE_UNCONFIGED;\r
+ } else {\r
+ //\r
+ // Configure the parameters for new operation.\r
+ //\r
+ if (!NetIp6IsValidUnicast (&DnsConfigData->StationIp)) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Status = Dns6CopyConfigure (&Instance->Dns6CfgData, DnsConfigData);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ if (DnsConfigData->DnsServerCount == 0 || DnsConfigData->DnsServerList == NULL) {\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ //\r
+ //The DNS instance will retrieve DNS server from DHCP Server.\r
+ //\r
+ Status = GetDns6ServerFromDhcp6 (\r
+ Instance->Service->ImageHandle,\r
+ Instance->Service->ControllerHandle, \r
+ &ServerListCount, \r
+ &ServerList\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+ \r
+ ASSERT(ServerList != NULL);\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+ CopyMem (&Instance->SessionDnsServer.v6, &ServerList[0], sizeof (EFI_IPv6_ADDRESS));\r
+ } else {\r
+ CopyMem (&Instance->SessionDnsServer.v6, &DnsConfigData->DnsServerList[0], sizeof (EFI_IPv6_ADDRESS));\r
+ }\r
+\r
+ //\r
+ // Config UDP\r
+ //\r
+ Status = Dns6ConfigUdp (Instance, Instance->UdpIo);\r
+ if (EFI_ERROR (Status)) {\r
+ if (Instance->Dns6CfgData.DnsServerList != NULL) {\r
+ FreePool (Instance->Dns6CfgData.DnsServerList);\r
+ }\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Add configured DNS server used by this instance to ServerList.\r
+ //\r
+ Status = AddDns6ServerIp (&mDriverData->Dns6ServerList, Instance->SessionDnsServer.v6);\r
+ if (EFI_ERROR (Status)) {\r
+ if (Instance->Dns6CfgData.DnsServerList != NULL) {\r
+ FreePool (Instance->Dns6CfgData.DnsServerList);\r
+ }\r
+ goto ON_EXIT;\r
+ }\r
+ \r
+ Instance->State = DNS_STATE_CONFIGED;\r
+ }\r
+\r
+ON_EXIT:\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ The function is used to translate the host name to host IP address. \r
+ A type AAAA query is used to get the one or more IPv6 addresses for this host. \r
+\r
+ @param[in] This Pointer to EFI_DNS6_PROTOCOL instance.\r
+ @param[in] HostName Pointer to caller-supplied buffer containing Host name to be translated. \r
+ This buffer contains 16 bit characters but these are translated to ASCII for use with \r
+ DNSv4 server and there is no requirement for driver to support non-ASCII Unicode characters.\r
+ @param[in] Token Pointer to the caller-allocated completion token to return at the completion of the process to translate host name to host address. \r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
+ @retval EFI_INVALID_PARAMETER This is NULL.\r
+ Token is NULL.\r
+ Token.Event is.NULL\r
+ HostName is NULL\r
+ @retval EFI_NO_MAPPING There's no source address is available for use.\r
+ @retval EFI_NOT_STARTED This instance has not been started.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dns6HostNameToIp (\r
+ IN EFI_DNS6_PROTOCOL *This,\r
+ IN CHAR16 *HostName,\r
+ IN EFI_DNS6_COMPLETION_TOKEN *Token\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ \r
+ DNS_INSTANCE *Instance;\r
+\r
+ EFI_DNS6_CONFIG_DATA *ConfigData;\r
+ \r
+ UINTN Index; \r
+ DNS6_CACHE *Item;\r
+ LIST_ENTRY *Entry;\r
+ LIST_ENTRY *Next;\r
+ \r
+ DNS6_TOKEN_ENTRY *TokenEntry;\r
+ NET_BUF *Packet;\r
+ \r
+ EFI_TPL OldTpl;\r
+ \r
+ Status = EFI_SUCCESS;\r
+ Item = NULL;\r
+ TokenEntry = NULL;\r
+ Packet = NULL;\r
+\r
+ //\r
+ // Validate the parameters\r
+ //\r
+ if ((This == NULL) || (HostName == NULL) || Token == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+ \r
+ Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL6 (This);\r
+ \r
+ ConfigData = &(Instance->Dns6CfgData);\r
+ \r
+ Instance->MaxRetry = ConfigData->RetryCount;\r
+\r
+ Token->Status = EFI_NOT_READY;\r
+ Token->RetryCount = 0;\r
+ Token->RetryInterval = ConfigData->RetryInterval;\r
+\r
+ if (Instance->State != DNS_STATE_CONFIGED) {\r
+ Status = EFI_NOT_STARTED;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Check the MaxRetry and RetryInterval values.\r
+ //\r
+ if (Instance->MaxRetry == 0) {\r
+ Instance->MaxRetry = DNS_DEFAULT_RETRY;\r
+ }\r
+\r
+ if (Token->RetryInterval < DNS_DEFAULT_TIMEOUT) {\r
+ Token->RetryInterval = DNS_DEFAULT_TIMEOUT;\r
+ } \r
+\r
+ //\r
+ // Check cache\r
+ //\r
+ if (ConfigData->EnableDnsCache) {\r
+ Index = 0;\r
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6CacheList) {\r
+ Item = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);\r
+ if (StrCmp (HostName, Item->DnsCache.HostName) == 0) {\r
+ Index++;\r
+ }\r
+ }