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
;
44 Service
= HttpInstance
->Service
;
45 ASSERT (Service
!= NULL
);
48 DnsServerListCount
= 0;
49 ZeroMem (&Token
, sizeof (EFI_DNS4_COMPLETION_TOKEN
));
52 // Get DNS server list from EFI IPv4 Configuration II protocol.
54 Status
= gBS
->HandleProtocol (Service
->ControllerHandle
, &gEfiIp4Config2ProtocolGuid
, (VOID
**) &Ip4Config2
);
55 if (!EFI_ERROR (Status
)) {
57 // Get the required size.
60 Status
= Ip4Config2
->GetData (Ip4Config2
, Ip4Config2DataTypeDnsServer
, &DataSize
, NULL
);
61 if (Status
== EFI_BUFFER_TOO_SMALL
) {
62 DnsServerList
= AllocatePool (DataSize
);
63 if (DnsServerList
== NULL
) {
64 return EFI_OUT_OF_RESOURCES
;
67 Status
= Ip4Config2
->GetData (Ip4Config2
, Ip4Config2DataTypeDnsServer
, &DataSize
, DnsServerList
);
68 if (EFI_ERROR (Status
)) {
69 FreePool (DnsServerList
);
72 DnsServerListCount
= DataSize
/ sizeof (EFI_IPv4_ADDRESS
);
81 // Create a DNS child instance and get the protocol.
83 Status
= NetLibCreateServiceChild (
84 Service
->ControllerHandle
,
85 Service
->Ip4DriverBindingHandle
,
86 &gEfiDns4ServiceBindingProtocolGuid
,
89 if (EFI_ERROR (Status
)) {
93 Status
= gBS
->OpenProtocol (
95 &gEfiDns4ProtocolGuid
,
97 Service
->Ip4DriverBindingHandle
,
98 Service
->ControllerHandle
,
99 EFI_OPEN_PROTOCOL_BY_DRIVER
101 if (EFI_ERROR (Status
)) {
106 // Configure DNS4 instance for the DNS server address and protocol.
108 ZeroMem (&Dns4CfgData
, sizeof (Dns4CfgData
));
109 Dns4CfgData
.DnsServerListCount
= DnsServerListCount
;
110 Dns4CfgData
.DnsServerList
= DnsServerList
;
111 Dns4CfgData
.UseDefaultSetting
= HttpInstance
->IPv4Node
.UseDefaultAddress
;
112 if (!Dns4CfgData
.UseDefaultSetting
) {
113 IP4_COPY_ADDRESS (&Dns4CfgData
.StationIp
, &HttpInstance
->IPv4Node
.LocalAddress
);
114 IP4_COPY_ADDRESS (&Dns4CfgData
.SubnetMask
, &HttpInstance
->IPv4Node
.LocalSubnet
);
116 Dns4CfgData
.EnableDnsCache
= TRUE
;
117 Dns4CfgData
.Protocol
= EFI_IP_PROTO_UDP
;
118 Status
= Dns4
->Configure (
122 if (EFI_ERROR (Status
)) {
127 // Create event to set the is done flag when name resolution is finished.
129 ZeroMem (&Token
, sizeof (Token
));
130 Status
= gBS
->CreateEvent (
137 if (EFI_ERROR (Status
)) {
142 // Start asynchronous name resolution.
144 Token
.Status
= EFI_NOT_READY
;
146 Status
= Dns4
->HostNameToIp (Dns4
, HostName
, &Token
);
147 if (EFI_ERROR (Status
)) {
156 // Name resolution is done, check result.
158 Status
= Token
.Status
;
159 if (!EFI_ERROR (Status
)) {
160 if (Token
.RspData
.H2AData
== NULL
) {
161 Status
= EFI_DEVICE_ERROR
;
164 if (Token
.RspData
.H2AData
->IpCount
== 0 || Token
.RspData
.H2AData
->IpList
== NULL
) {
165 Status
= EFI_DEVICE_ERROR
;
169 // We just return the first IP address from DNS protocol.
171 IP4_COPY_ADDRESS (IpAddress
, Token
.RspData
.H2AData
->IpList
);
172 Status
= EFI_SUCCESS
;
177 if (Token
.Event
!= NULL
) {
178 gBS
->CloseEvent (Token
.Event
);
180 if (Token
.RspData
.H2AData
!= NULL
) {
181 if (Token
.RspData
.H2AData
->IpList
!= NULL
) {
182 FreePool (Token
.RspData
.H2AData
->IpList
);
184 FreePool (Token
.RspData
.H2AData
);
188 Dns4
->Configure (Dns4
, NULL
);
192 &gEfiDns4ProtocolGuid
,
193 Service
->Ip4DriverBindingHandle
,
194 Service
->ControllerHandle
198 if (Dns4Handle
!= NULL
) {
199 NetLibDestroyServiceChild (
200 Service
->ControllerHandle
,
201 Service
->Ip4DriverBindingHandle
,
202 &gEfiDns4ServiceBindingProtocolGuid
,
207 if (DnsServerList
!= NULL
) {
208 FreePool (DnsServerList
);
215 Retrieve the host address using the EFI_DNS6_PROTOCOL.
217 @param[in] HttpInstance Pointer to HTTP_PROTOCOL instance.
218 @param[in] HostName Pointer to buffer containing hostname.
219 @param[out] IpAddress On output, pointer to buffer containing IPv6 address.
221 @retval EFI_SUCCESS Operation succeeded.
222 @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
223 @retval EFI_DEVICE_ERROR An unexpected network error occurred.
224 @retval Others Other errors as indicated.
229 IN HTTP_PROTOCOL
*HttpInstance
,
231 OUT EFI_IPv6_ADDRESS
*IpAddress
235 HTTP_SERVICE
*Service
;
236 EFI_DNS6_PROTOCOL
*Dns6
;
237 EFI_DNS6_CONFIG_DATA Dns6ConfigData
;
238 EFI_DNS6_COMPLETION_TOKEN Token
;
239 EFI_HANDLE Dns6Handle
;
240 EFI_IP6_CONFIG_PROTOCOL
*Ip6Config
;
241 EFI_IPv6_ADDRESS
*DnsServerList
;
242 UINTN DnsServerListCount
;
247 Service
= HttpInstance
->Service
;
248 ASSERT (Service
!= NULL
);
250 DnsServerList
= NULL
;
251 DnsServerListCount
= 0;
254 ZeroMem (&Token
, sizeof (EFI_DNS6_COMPLETION_TOKEN
));
257 // Get DNS server list from EFI IPv6 Configuration protocol.
259 Status
= gBS
->HandleProtocol (Service
->ControllerHandle
, &gEfiIp6ConfigProtocolGuid
, (VOID
**) &Ip6Config
);
260 if (!EFI_ERROR (Status
)) {
262 // Get the required size.
265 Status
= Ip6Config
->GetData (Ip6Config
, Ip6ConfigDataTypeDnsServer
, &DataSize
, NULL
);
266 if (Status
== EFI_BUFFER_TOO_SMALL
) {
267 DnsServerList
= AllocatePool (DataSize
);
268 if (DnsServerList
== NULL
) {
269 return EFI_OUT_OF_RESOURCES
;
272 Status
= Ip6Config
->GetData (Ip6Config
, Ip6ConfigDataTypeDnsServer
, &DataSize
, DnsServerList
);
273 if (EFI_ERROR (Status
)) {
274 FreePool (DnsServerList
);
275 DnsServerList
= NULL
;
277 DnsServerListCount
= DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
283 // Create a DNSv6 child instance and get the protocol.
285 Status
= NetLibCreateServiceChild (
286 Service
->ControllerHandle
,
287 Service
->Ip6DriverBindingHandle
,
288 &gEfiDns6ServiceBindingProtocolGuid
,
291 if (EFI_ERROR (Status
)) {
295 Status
= gBS
->OpenProtocol (
297 &gEfiDns6ProtocolGuid
,
299 Service
->Ip6DriverBindingHandle
,
300 Service
->ControllerHandle
,
301 EFI_OPEN_PROTOCOL_BY_DRIVER
303 if (EFI_ERROR (Status
)) {
308 // Configure DNS6 instance for the DNS server address and protocol.
310 ZeroMem (&Dns6ConfigData
, sizeof (EFI_DNS6_CONFIG_DATA
));
311 Dns6ConfigData
.DnsServerCount
= (UINT32
)DnsServerListCount
;
312 Dns6ConfigData
.DnsServerList
= DnsServerList
;
313 Dns6ConfigData
.EnableDnsCache
= TRUE
;
314 Dns6ConfigData
.Protocol
= EFI_IP_PROTO_UDP
;
315 IP6_COPY_ADDRESS (&Dns6ConfigData
.StationIp
, &HttpInstance
->Ipv6Node
.LocalAddress
);
316 Status
= Dns6
->Configure (
320 if (EFI_ERROR (Status
)) {
324 Token
.Status
= EFI_NOT_READY
;
327 // Create event to set the IsDone flag when name resolution is finished.
329 Status
= gBS
->CreateEvent (
336 if (EFI_ERROR (Status
)) {
341 // Start asynchronous name resolution.
343 Status
= Dns6
->HostNameToIp (Dns6
, HostName
, &Token
);
344 if (EFI_ERROR (Status
)) {
353 // Name resolution is done, check result.
355 Status
= Token
.Status
;
356 if (!EFI_ERROR (Status
)) {
357 if (Token
.RspData
.H2AData
== NULL
) {
358 Status
= EFI_DEVICE_ERROR
;
361 if (Token
.RspData
.H2AData
->IpCount
== 0 || Token
.RspData
.H2AData
->IpList
== NULL
) {
362 Status
= EFI_DEVICE_ERROR
;
366 // We just return the first IPv6 address from DNS protocol.
368 IP6_COPY_ADDRESS (IpAddress
, Token
.RspData
.H2AData
->IpList
);
369 Status
= EFI_SUCCESS
;
374 if (Token
.Event
!= NULL
) {
375 gBS
->CloseEvent (Token
.Event
);
377 if (Token
.RspData
.H2AData
!= NULL
) {
378 if (Token
.RspData
.H2AData
->IpList
!= NULL
) {
379 FreePool (Token
.RspData
.H2AData
->IpList
);
381 FreePool (Token
.RspData
.H2AData
);
385 Dns6
->Configure (Dns6
, NULL
);
389 &gEfiDns6ProtocolGuid
,
390 Service
->Ip6DriverBindingHandle
,
391 Service
->ControllerHandle
395 if (Dns6Handle
!= NULL
) {
396 NetLibDestroyServiceChild (
397 Service
->ControllerHandle
,
398 Service
->Ip6DriverBindingHandle
,
399 &gEfiDns6ServiceBindingProtocolGuid
,
404 if (DnsServerList
!= NULL
) {
405 FreePool (DnsServerList
);