summaryrefslogtreecommitdiff
path: root/Core/NetworkPkg/HttpDxe/HttpDns.c
diff options
context:
space:
mode:
Diffstat (limited to 'Core/NetworkPkg/HttpDxe/HttpDns.c')
-rw-r--r--Core/NetworkPkg/HttpDxe/HttpDns.c415
1 files changed, 415 insertions, 0 deletions
diff --git a/Core/NetworkPkg/HttpDxe/HttpDns.c b/Core/NetworkPkg/HttpDxe/HttpDns.c
new file mode 100644
index 0000000000..0f5fe18072
--- /dev/null
+++ b/Core/NetworkPkg/HttpDxe/HttpDns.c
@@ -0,0 +1,415 @@
+/** @file
+ Routines for HttpDxe driver to perform DNS resolution based on UEFI DNS protocols.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HttpDriver.h"
+
+/**
+ Retrieve the host address using the EFI_DNS4_PROTOCOL.
+
+ @param[in] HttpInstance Pointer to HTTP_PROTOCOL instance.
+ @param[in] HostName Pointer to buffer containing hostname.
+ @param[out] IpAddress On output, pointer to buffer containing IPv4 address.
+
+ @retval EFI_SUCCESS Operation succeeded.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
+ @retval EFI_DEVICE_ERROR An unexpected network error occurred.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+HttpDns4 (
+ IN HTTP_PROTOCOL *HttpInstance,
+ IN CHAR16 *HostName,
+ OUT EFI_IPv4_ADDRESS *IpAddress
+ )
+{
+ EFI_STATUS Status;
+ EFI_DNS4_PROTOCOL *Dns4;
+ EFI_DNS4_CONFIG_DATA Dns4CfgData;
+ EFI_DNS4_COMPLETION_TOKEN Token;
+ BOOLEAN IsDone;
+ HTTP_SERVICE *Service;
+ EFI_HANDLE Dns4Handle;
+ EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2;
+ UINTN DnsServerListCount;
+ EFI_IPv4_ADDRESS *DnsServerList;
+ UINTN DataSize;
+
+
+ Service = HttpInstance->Service;
+ ASSERT (Service != NULL);
+
+ DnsServerList = NULL;
+ DnsServerListCount = 0;
+ ZeroMem (&Token, sizeof (EFI_DNS4_COMPLETION_TOKEN));
+
+ //
+ // Get DNS server list from EFI IPv4 Configuration II protocol.
+ //
+ Status = gBS->HandleProtocol (Service->ControllerHandle, &gEfiIp4Config2ProtocolGuid, (VOID **) &Ip4Config2);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Get the required size.
+ //
+ DataSize = 0;
+ Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeDnsServer, &DataSize, NULL);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ DnsServerList = AllocatePool (DataSize);
+ if (DnsServerList == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeDnsServer, &DataSize, DnsServerList);
+ if (EFI_ERROR (Status)) {
+ FreePool (DnsServerList);
+ DnsServerList = NULL;
+ } else {
+ DnsServerListCount = DataSize / sizeof (EFI_IPv4_ADDRESS);
+ }
+ }
+ }
+
+ Dns4Handle = NULL;
+ Dns4 = NULL;
+
+ //
+ // Create a DNS child instance and get the protocol.
+ //
+ Status = NetLibCreateServiceChild (
+ Service->ControllerHandle,
+ Service->ImageHandle,
+ &gEfiDns4ServiceBindingProtocolGuid,
+ &Dns4Handle
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ Status = gBS->OpenProtocol (
+ Dns4Handle,
+ &gEfiDns4ProtocolGuid,
+ (VOID **) &Dns4,
+ Service->ImageHandle,
+ Service->ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ //
+ // Configure DNS4 instance for the DNS server address and protocol.
+ //
+ ZeroMem (&Dns4CfgData, sizeof (Dns4CfgData));
+ Dns4CfgData.DnsServerListCount = DnsServerListCount;
+ Dns4CfgData.DnsServerList = DnsServerList;
+ Dns4CfgData.UseDefaultSetting = HttpInstance->IPv4Node.UseDefaultAddress;
+ if (!Dns4CfgData.UseDefaultSetting) {
+ IP4_COPY_ADDRESS (&Dns4CfgData.StationIp, &HttpInstance->IPv4Node.LocalAddress);
+ IP4_COPY_ADDRESS (&Dns4CfgData.SubnetMask, &HttpInstance->IPv4Node.LocalSubnet);
+ }
+ Dns4CfgData.EnableDnsCache = TRUE;
+ Dns4CfgData.Protocol = EFI_IP_PROTO_UDP;
+ Status = Dns4->Configure (
+ Dns4,
+ &Dns4CfgData
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ //
+ // Create event to set the is done flag when name resolution is finished.
+ //
+ ZeroMem (&Token, sizeof (Token));
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ HttpCommonNotify,
+ &IsDone,
+ &Token.Event
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ //
+ // Start asynchronous name resolution.
+ //
+ Token.Status = EFI_NOT_READY;
+ IsDone = FALSE;
+ Status = Dns4->HostNameToIp (Dns4, HostName, &Token);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ while (!IsDone) {
+ Dns4->Poll (Dns4);
+ }
+
+ //
+ // Name resolution is done, check result.
+ //
+ Status = Token.Status;
+ if (!EFI_ERROR (Status)) {
+ if (Token.RspData.H2AData == NULL) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ //
+ // We just return the first IP address from DNS protocol.
+ //
+ IP4_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);
+ Status = EFI_SUCCESS;
+ }
+
+Exit:
+
+ if (Token.Event != NULL) {
+ gBS->CloseEvent (Token.Event);
+ }
+ if (Token.RspData.H2AData != NULL) {
+ if (Token.RspData.H2AData->IpList != NULL) {
+ FreePool (Token.RspData.H2AData->IpList);
+ }
+ FreePool (Token.RspData.H2AData);
+ }
+
+ if (Dns4 != NULL) {
+ Dns4->Configure (Dns4, NULL);
+
+ gBS->CloseProtocol (
+ Dns4Handle,
+ &gEfiDns4ProtocolGuid,
+ Service->ImageHandle,
+ Service->ControllerHandle
+ );
+ }
+
+ if (Dns4Handle != NULL) {
+ NetLibDestroyServiceChild (
+ Service->ControllerHandle,
+ Service->ImageHandle,
+ &gEfiDns4ServiceBindingProtocolGuid,
+ Dns4Handle
+ );
+ }
+
+ if (DnsServerList != NULL) {
+ FreePool (DnsServerList);
+ }
+
+ return Status;
+}
+
+/**
+ Retrieve the host address using the EFI_DNS6_PROTOCOL.
+
+ @param[in] HttpInstance Pointer to HTTP_PROTOCOL instance.
+ @param[in] HostName Pointer to buffer containing hostname.
+ @param[out] IpAddress On output, pointer to buffer containing IPv6 address.
+
+ @retval EFI_SUCCESS Operation succeeded.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
+ @retval EFI_DEVICE_ERROR An unexpected network error occurred.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+HttpDns6 (
+ IN HTTP_PROTOCOL *HttpInstance,
+ IN CHAR16 *HostName,
+ OUT EFI_IPv6_ADDRESS *IpAddress
+ )
+{
+ EFI_STATUS Status;
+ HTTP_SERVICE *Service;
+ EFI_DNS6_PROTOCOL *Dns6;
+ EFI_DNS6_CONFIG_DATA Dns6ConfigData;
+ EFI_DNS6_COMPLETION_TOKEN Token;
+ EFI_HANDLE Dns6Handle;
+ EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
+ EFI_IPv6_ADDRESS *DnsServerList;
+ UINTN DnsServerListCount;
+ UINTN DataSize;
+ BOOLEAN IsDone;
+
+
+ Service = HttpInstance->Service;
+ ASSERT (Service != NULL);
+
+ DnsServerList = NULL;
+ DnsServerListCount = 0;
+ Dns6 = NULL;
+ Dns6Handle = NULL;
+ ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN));
+
+ //
+ // Get DNS server list from EFI IPv6 Configuration protocol.
+ //
+ Status = gBS->HandleProtocol (Service->ControllerHandle, &gEfiIp6ConfigProtocolGuid, (VOID **) &Ip6Config);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Get the required size.
+ //
+ DataSize = 0;
+ Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, NULL);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ DnsServerList = AllocatePool (DataSize);
+ if (DnsServerList == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, DnsServerList);
+ if (EFI_ERROR (Status)) {
+ FreePool (DnsServerList);
+ DnsServerList = NULL;
+ } else {
+ DnsServerListCount = DataSize / sizeof (EFI_IPv6_ADDRESS);
+ }
+ }
+ }
+
+ //
+ // Create a DNSv6 child instance and get the protocol.
+ //
+ Status = NetLibCreateServiceChild (
+ Service->ControllerHandle,
+ Service->ImageHandle,
+ &gEfiDns6ServiceBindingProtocolGuid,
+ &Dns6Handle
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ Status = gBS->OpenProtocol (
+ Dns6Handle,
+ &gEfiDns6ProtocolGuid,
+ (VOID **) &Dns6,
+ Service->ImageHandle,
+ Service->ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ //
+ // Configure DNS6 instance for the DNS server address and protocol.
+ //
+ ZeroMem (&Dns6ConfigData, sizeof (EFI_DNS6_CONFIG_DATA));
+ Dns6ConfigData.DnsServerCount = (UINT32)DnsServerListCount;
+ Dns6ConfigData.DnsServerList = DnsServerList;
+ Dns6ConfigData.EnableDnsCache = TRUE;
+ Dns6ConfigData.Protocol = EFI_IP_PROTO_UDP;
+ IP6_COPY_ADDRESS (&Dns6ConfigData.StationIp, &HttpInstance->Ipv6Node.LocalAddress);
+ Status = Dns6->Configure (
+ Dns6,
+ &Dns6ConfigData
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ Token.Status = EFI_NOT_READY;
+ IsDone = FALSE;
+ //
+ // Create event to set the IsDone flag when name resolution is finished.
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ HttpCommonNotify,
+ &IsDone,
+ &Token.Event
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ //
+ // Start asynchronous name resolution.
+ //
+ Status = Dns6->HostNameToIp (Dns6, HostName, &Token);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ while (!IsDone) {
+ Dns6->Poll (Dns6);
+ }
+
+ //
+ // Name resolution is done, check result.
+ //
+ Status = Token.Status;
+ if (!EFI_ERROR (Status)) {
+ if (Token.RspData.H2AData == NULL) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ //
+ // We just return the first IPv6 address from DNS protocol.
+ //
+ IP6_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);
+ Status = EFI_SUCCESS;
+ }
+
+Exit:
+
+ if (Token.Event != NULL) {
+ gBS->CloseEvent (Token.Event);
+ }
+ if (Token.RspData.H2AData != NULL) {
+ if (Token.RspData.H2AData->IpList != NULL) {
+ FreePool (Token.RspData.H2AData->IpList);
+ }
+ FreePool (Token.RspData.H2AData);
+ }
+
+ if (Dns6 != NULL) {
+ Dns6->Configure (Dns6, NULL);
+
+ gBS->CloseProtocol (
+ Dns6Handle,
+ &gEfiDns6ProtocolGuid,
+ Service->ImageHandle,
+ Service->ControllerHandle
+ );
+ }
+
+ if (Dns6Handle != NULL) {
+ NetLibDestroyServiceChild (
+ Service->ControllerHandle,
+ Service->ImageHandle,
+ &gEfiDns6ServiceBindingProtocolGuid,
+ Dns6Handle
+ );
+ }
+
+ if (DnsServerList != NULL) {
+ FreePool (DnsServerList);
+ }
+
+ return Status;
+}