2 Routines for HttpDxe driver to perform DNS resolution based on UEFI DNS protocols.
4 Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "HttpDriver.h"
12 Retrieve the host address using the EFI_DNS4_PROTOCOL.
14 @param[in] HttpInstance Pointer to HTTP_PROTOCOL instance.
15 @param[in] HostName Pointer to buffer containing hostname.
16 @param[out] IpAddress On output, pointer to buffer containing IPv4 address.
18 @retval EFI_SUCCESS Operation succeeded.
19 @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
20 @retval EFI_DEVICE_ERROR An unexpected network error occurred.
21 @retval Others Other errors as indicated.
26 IN HTTP_PROTOCOL
*HttpInstance
,
28 OUT EFI_IPv4_ADDRESS
*IpAddress
32 EFI_DNS4_PROTOCOL
*Dns4
;
33 EFI_DNS4_CONFIG_DATA Dns4CfgData
;
34 EFI_DNS4_COMPLETION_TOKEN Token
;
36 HTTP_SERVICE
*Service
;
37 EFI_HANDLE Dns4Handle
;
38 EFI_IP4_CONFIG2_PROTOCOL
*Ip4Config2
;
39 UINTN DnsServerListCount
;
40 EFI_IPv4_ADDRESS
*DnsServerList
;
43 Service
= HttpInstance
->Service
;
44 ASSERT (Service
!= NULL
);
47 DnsServerListCount
= 0;
48 ZeroMem (&Token
, sizeof (EFI_DNS4_COMPLETION_TOKEN
));
51 // Get DNS server list from EFI IPv4 Configuration II protocol.
53 Status
= gBS
->HandleProtocol (Service
->ControllerHandle
, &gEfiIp4Config2ProtocolGuid
, (VOID
**)&Ip4Config2
);
54 if (!EFI_ERROR (Status
)) {
56 // Get the required size.
59 Status
= Ip4Config2
->GetData (Ip4Config2
, Ip4Config2DataTypeDnsServer
, &DataSize
, NULL
);
60 if (Status
== EFI_BUFFER_TOO_SMALL
) {
61 DnsServerList
= AllocatePool (DataSize
);
62 if (DnsServerList
== NULL
) {
63 return EFI_OUT_OF_RESOURCES
;
66 Status
= Ip4Config2
->GetData (Ip4Config2
, Ip4Config2DataTypeDnsServer
, &DataSize
, DnsServerList
);
67 if (EFI_ERROR (Status
)) {
68 FreePool (DnsServerList
);
71 DnsServerListCount
= DataSize
/ sizeof (EFI_IPv4_ADDRESS
);
80 // Create a DNS child instance and get the protocol.
82 Status
= NetLibCreateServiceChild (
83 Service
->ControllerHandle
,
84 Service
->Ip4DriverBindingHandle
,
85 &gEfiDns4ServiceBindingProtocolGuid
,
88 if (EFI_ERROR (Status
)) {
92 Status
= gBS
->OpenProtocol (
94 &gEfiDns4ProtocolGuid
,
96 Service
->Ip4DriverBindingHandle
,
97 Service
->ControllerHandle
,
98 EFI_OPEN_PROTOCOL_BY_DRIVER
100 if (EFI_ERROR (Status
)) {
105 // Configure DNS4 instance for the DNS server address and protocol.
107 ZeroMem (&Dns4CfgData
, sizeof (Dns4CfgData
));
108 Dns4CfgData
.DnsServerListCount
= DnsServerListCount
;
109 Dns4CfgData
.DnsServerList
= DnsServerList
;
110 Dns4CfgData
.UseDefaultSetting
= HttpInstance
->IPv4Node
.UseDefaultAddress
;
111 Dns4CfgData
.RetryInterval
= PcdGet32 (PcdHttpDnsRetryInterval
);
112 Dns4CfgData
.RetryCount
= PcdGet32 (PcdHttpDnsRetryCount
);
113 if (!Dns4CfgData
.UseDefaultSetting
) {
114 IP4_COPY_ADDRESS (&Dns4CfgData
.StationIp
, &HttpInstance
->IPv4Node
.LocalAddress
);
115 IP4_COPY_ADDRESS (&Dns4CfgData
.SubnetMask
, &HttpInstance
->IPv4Node
.LocalSubnet
);
118 Dns4CfgData
.EnableDnsCache
= TRUE
;
119 Dns4CfgData
.Protocol
= EFI_IP_PROTO_UDP
;
120 Status
= Dns4
->Configure (
124 if (EFI_ERROR (Status
)) {
129 // Create event to set the is done flag when name resolution is finished.
131 ZeroMem (&Token
, sizeof (Token
));
132 Status
= gBS
->CreateEvent (
139 if (EFI_ERROR (Status
)) {
144 // Start asynchronous name resolution.
146 Token
.Status
= EFI_NOT_READY
;
148 Status
= Dns4
->HostNameToIp (Dns4
, HostName
, &Token
);
149 if (EFI_ERROR (Status
)) {
158 // Name resolution is done, check result.
160 Status
= Token
.Status
;
161 if (!EFI_ERROR (Status
)) {
162 if (Token
.RspData
.H2AData
== NULL
) {
163 Status
= EFI_DEVICE_ERROR
;
167 if ((Token
.RspData
.H2AData
->IpCount
== 0) || (Token
.RspData
.H2AData
->IpList
== NULL
)) {
168 Status
= EFI_DEVICE_ERROR
;
173 // We just return the first IP address from DNS protocol.
175 IP4_COPY_ADDRESS (IpAddress
, Token
.RspData
.H2AData
->IpList
);
176 Status
= EFI_SUCCESS
;
181 if (Token
.Event
!= NULL
) {
182 gBS
->CloseEvent (Token
.Event
);
185 if (Token
.RspData
.H2AData
!= NULL
) {
186 if (Token
.RspData
.H2AData
->IpList
!= NULL
) {
187 FreePool (Token
.RspData
.H2AData
->IpList
);
190 FreePool (Token
.RspData
.H2AData
);
194 Dns4
->Configure (Dns4
, NULL
);
198 &gEfiDns4ProtocolGuid
,
199 Service
->Ip4DriverBindingHandle
,
200 Service
->ControllerHandle
204 if (Dns4Handle
!= NULL
) {
205 NetLibDestroyServiceChild (
206 Service
->ControllerHandle
,
207 Service
->Ip4DriverBindingHandle
,
208 &gEfiDns4ServiceBindingProtocolGuid
,
213 if (DnsServerList
!= NULL
) {
214 FreePool (DnsServerList
);
221 Retrieve the host address using the EFI_DNS6_PROTOCOL.
223 @param[in] HttpInstance Pointer to HTTP_PROTOCOL instance.
224 @param[in] HostName Pointer to buffer containing hostname.
225 @param[out] IpAddress On output, pointer to buffer containing IPv6 address.
227 @retval EFI_SUCCESS Operation succeeded.
228 @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
229 @retval EFI_DEVICE_ERROR An unexpected network error occurred.
230 @retval Others Other errors as indicated.
235 IN HTTP_PROTOCOL
*HttpInstance
,
237 OUT EFI_IPv6_ADDRESS
*IpAddress
241 HTTP_SERVICE
*Service
;
242 EFI_DNS6_PROTOCOL
*Dns6
;
243 EFI_DNS6_CONFIG_DATA Dns6ConfigData
;
244 EFI_DNS6_COMPLETION_TOKEN Token
;
245 EFI_HANDLE Dns6Handle
;
246 EFI_IP6_CONFIG_PROTOCOL
*Ip6Config
;
247 EFI_IPv6_ADDRESS
*DnsServerList
;
248 UINTN DnsServerListCount
;
252 Service
= HttpInstance
->Service
;
253 ASSERT (Service
!= NULL
);
255 DnsServerList
= NULL
;
256 DnsServerListCount
= 0;
259 ZeroMem (&Token
, sizeof (EFI_DNS6_COMPLETION_TOKEN
));
262 // Get DNS server list from EFI IPv6 Configuration protocol.
264 Status
= gBS
->HandleProtocol (Service
->ControllerHandle
, &gEfiIp6ConfigProtocolGuid
, (VOID
**)&Ip6Config
);
265 if (!EFI_ERROR (Status
)) {
267 // Get the required size.
270 Status
= Ip6Config
->GetData (Ip6Config
, Ip6ConfigDataTypeDnsServer
, &DataSize
, NULL
);
271 if (Status
== EFI_BUFFER_TOO_SMALL
) {
272 DnsServerList
= AllocatePool (DataSize
);
273 if (DnsServerList
== NULL
) {
274 return EFI_OUT_OF_RESOURCES
;
277 Status
= Ip6Config
->GetData (Ip6Config
, Ip6ConfigDataTypeDnsServer
, &DataSize
, DnsServerList
);
278 if (EFI_ERROR (Status
)) {
279 FreePool (DnsServerList
);
280 DnsServerList
= NULL
;
282 DnsServerListCount
= DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
288 // Create a DNSv6 child instance and get the protocol.
290 Status
= NetLibCreateServiceChild (
291 Service
->ControllerHandle
,
292 Service
->Ip6DriverBindingHandle
,
293 &gEfiDns6ServiceBindingProtocolGuid
,
296 if (EFI_ERROR (Status
)) {
300 Status
= gBS
->OpenProtocol (
302 &gEfiDns6ProtocolGuid
,
304 Service
->Ip6DriverBindingHandle
,
305 Service
->ControllerHandle
,
306 EFI_OPEN_PROTOCOL_BY_DRIVER
308 if (EFI_ERROR (Status
)) {
313 // Configure DNS6 instance for the DNS server address and protocol.
315 ZeroMem (&Dns6ConfigData
, sizeof (EFI_DNS6_CONFIG_DATA
));
316 Dns6ConfigData
.DnsServerCount
= (UINT32
)DnsServerListCount
;
317 Dns6ConfigData
.DnsServerList
= DnsServerList
;
318 Dns6ConfigData
.EnableDnsCache
= TRUE
;
319 Dns6ConfigData
.Protocol
= EFI_IP_PROTO_UDP
;
320 Dns6ConfigData
.RetryInterval
= PcdGet32 (PcdHttpDnsRetryInterval
);
321 Dns6ConfigData
.RetryCount
= PcdGet32 (PcdHttpDnsRetryCount
);
322 IP6_COPY_ADDRESS (&Dns6ConfigData
.StationIp
, &HttpInstance
->Ipv6Node
.LocalAddress
);
323 Status
= Dns6
->Configure (
327 if (EFI_ERROR (Status
)) {
331 Token
.Status
= EFI_NOT_READY
;
334 // Create event to set the IsDone flag when name resolution is finished.
336 Status
= gBS
->CreateEvent (
343 if (EFI_ERROR (Status
)) {
348 // Start asynchronous name resolution.
350 Status
= Dns6
->HostNameToIp (Dns6
, HostName
, &Token
);
351 if (EFI_ERROR (Status
)) {
360 // Name resolution is done, check result.
362 Status
= Token
.Status
;
363 if (!EFI_ERROR (Status
)) {
364 if (Token
.RspData
.H2AData
== NULL
) {
365 Status
= EFI_DEVICE_ERROR
;
369 if ((Token
.RspData
.H2AData
->IpCount
== 0) || (Token
.RspData
.H2AData
->IpList
== NULL
)) {
370 Status
= EFI_DEVICE_ERROR
;
375 // We just return the first IPv6 address from DNS protocol.
377 IP6_COPY_ADDRESS (IpAddress
, Token
.RspData
.H2AData
->IpList
);
378 Status
= EFI_SUCCESS
;
383 if (Token
.Event
!= NULL
) {
384 gBS
->CloseEvent (Token
.Event
);
387 if (Token
.RspData
.H2AData
!= NULL
) {
388 if (Token
.RspData
.H2AData
->IpList
!= NULL
) {
389 FreePool (Token
.RspData
.H2AData
->IpList
);
392 FreePool (Token
.RspData
.H2AData
);
396 Dns6
->Configure (Dns6
, NULL
);
400 &gEfiDns6ProtocolGuid
,
401 Service
->Ip6DriverBindingHandle
,
402 Service
->ControllerHandle
406 if (Dns6Handle
!= NULL
) {
407 NetLibDestroyServiceChild (
408 Service
->ControllerHandle
,
409 Service
->Ip6DriverBindingHandle
,
410 &gEfiDns6ServiceBindingProtocolGuid
,
415 if (DnsServerList
!= NULL
) {
416 FreePool (DnsServerList
);