123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420 |
- /** @file
- Routines for HttpDxe driver to perform DNS resolution based on UEFI DNS protocols.
- Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #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->Ip4DriverBindingHandle,
- &gEfiDns4ServiceBindingProtocolGuid,
- &Dns4Handle
- );
- if (EFI_ERROR (Status)) {
- goto Exit;
- }
- Status = gBS->OpenProtocol (
- Dns4Handle,
- &gEfiDns4ProtocolGuid,
- (VOID **)&Dns4,
- Service->Ip4DriverBindingHandle,
- 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;
- Dns4CfgData.RetryInterval = PcdGet32 (PcdHttpDnsRetryInterval);
- Dns4CfgData.RetryCount = PcdGet32 (PcdHttpDnsRetryCount);
- 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->Ip4DriverBindingHandle,
- Service->ControllerHandle
- );
- }
- if (Dns4Handle != NULL) {
- NetLibDestroyServiceChild (
- Service->ControllerHandle,
- Service->Ip4DriverBindingHandle,
- &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->Ip6DriverBindingHandle,
- &gEfiDns6ServiceBindingProtocolGuid,
- &Dns6Handle
- );
- if (EFI_ERROR (Status)) {
- goto Exit;
- }
- Status = gBS->OpenProtocol (
- Dns6Handle,
- &gEfiDns6ProtocolGuid,
- (VOID **)&Dns6,
- Service->Ip6DriverBindingHandle,
- 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;
- Dns6ConfigData.RetryInterval = PcdGet32 (PcdHttpDnsRetryInterval);
- Dns6ConfigData.RetryCount = PcdGet32 (PcdHttpDnsRetryCount);
- 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->Ip6DriverBindingHandle,
- Service->ControllerHandle
- );
- }
- if (Dns6Handle != NULL) {
- NetLibDestroyServiceChild (
- Service->ControllerHandle,
- Service->Ip6DriverBindingHandle,
- &gEfiDns6ServiceBindingProtocolGuid,
- Dns6Handle
- );
- }
- if (DnsServerList != NULL) {
- FreePool (DnsServerList);
- }
- return Status;
- }
|