]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/HttpDxe/HttpDns.c
NetworkPkg: Add PCDs for HTTP DNS RetryCount and RetryInterval
[mirror_edk2.git] / NetworkPkg / HttpDxe / HttpDns.c
CommitLineData
47f51a06
YT
1/** @file\r
2 Routines for HttpDxe driver to perform DNS resolution based on UEFI DNS protocols.\r
3\r
f75a7f56 4Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>\r
ecf98fbc 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
47f51a06
YT
6\r
7**/\r
8\r
9#include "HttpDriver.h"\r
10\r
11/**\r
12 Retrieve the host address using the EFI_DNS4_PROTOCOL.\r
13\r
14 @param[in] HttpInstance Pointer to HTTP_PROTOCOL instance.\r
15 @param[in] HostName Pointer to buffer containing hostname.\r
16 @param[out] IpAddress On output, pointer to buffer containing IPv4 address.\r
17\r
18 @retval EFI_SUCCESS Operation succeeded.\r
19 @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
20 @retval EFI_DEVICE_ERROR An unexpected network error occurred.\r
21 @retval Others Other errors as indicated.\r
f75a7f56 22\r
47f51a06
YT
23**/\r
24EFI_STATUS\r
25HttpDns4 (\r
d1050b9d
MK
26 IN HTTP_PROTOCOL *HttpInstance,\r
27 IN CHAR16 *HostName,\r
28 OUT EFI_IPv4_ADDRESS *IpAddress\r
47f51a06
YT
29 )\r
30{\r
d1050b9d
MK
31 EFI_STATUS Status;\r
32 EFI_DNS4_PROTOCOL *Dns4;\r
33 EFI_DNS4_CONFIG_DATA Dns4CfgData;\r
34 EFI_DNS4_COMPLETION_TOKEN Token;\r
35 BOOLEAN IsDone;\r
36 HTTP_SERVICE *Service;\r
37 EFI_HANDLE Dns4Handle;\r
38 EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2;\r
39 UINTN DnsServerListCount;\r
40 EFI_IPv4_ADDRESS *DnsServerList;\r
41 UINTN DataSize;\r
47f51a06
YT
42\r
43 Service = HttpInstance->Service;\r
44 ASSERT (Service != NULL);\r
45\r
46 DnsServerList = NULL;\r
47 DnsServerListCount = 0;\r
48 ZeroMem (&Token, sizeof (EFI_DNS4_COMPLETION_TOKEN));\r
49\r
50 //\r
51 // Get DNS server list from EFI IPv4 Configuration II protocol.\r
52 //\r
d1050b9d 53 Status = gBS->HandleProtocol (Service->ControllerHandle, &gEfiIp4Config2ProtocolGuid, (VOID **)&Ip4Config2);\r
47f51a06
YT
54 if (!EFI_ERROR (Status)) {\r
55 //\r
56 // Get the required size.\r
57 //\r
58 DataSize = 0;\r
59 Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeDnsServer, &DataSize, NULL);\r
60 if (Status == EFI_BUFFER_TOO_SMALL) {\r
61 DnsServerList = AllocatePool (DataSize);\r
62 if (DnsServerList == NULL) {\r
63 return EFI_OUT_OF_RESOURCES;\r
64 }\r
65\r
d1050b9d 66 Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeDnsServer, &DataSize, DnsServerList);\r
47f51a06
YT
67 if (EFI_ERROR (Status)) {\r
68 FreePool (DnsServerList);\r
69 DnsServerList = NULL;\r
70 } else {\r
71 DnsServerListCount = DataSize / sizeof (EFI_IPv4_ADDRESS);\r
72 }\r
73 }\r
74 }\r
75\r
76 Dns4Handle = NULL;\r
77 Dns4 = NULL;\r
f75a7f56 78\r
47f51a06
YT
79 //\r
80 // Create a DNS child instance and get the protocol.\r
81 //\r
82 Status = NetLibCreateServiceChild (\r
83 Service->ControllerHandle,\r
7cf59c85 84 Service->Ip4DriverBindingHandle,\r
47f51a06
YT
85 &gEfiDns4ServiceBindingProtocolGuid,\r
86 &Dns4Handle\r
87 );\r
88 if (EFI_ERROR (Status)) {\r
89 goto Exit;\r
f75a7f56 90 }\r
47f51a06
YT
91\r
92 Status = gBS->OpenProtocol (\r
93 Dns4Handle,\r
94 &gEfiDns4ProtocolGuid,\r
d1050b9d 95 (VOID **)&Dns4,\r
7cf59c85 96 Service->Ip4DriverBindingHandle,\r
47f51a06
YT
97 Service->ControllerHandle,\r
98 EFI_OPEN_PROTOCOL_BY_DRIVER\r
99 );\r
100 if (EFI_ERROR (Status)) {\r
101 goto Exit;\r
102 }\r
103\r
104 //\r
105 // Configure DNS4 instance for the DNS server address and protocol.\r
106 //\r
107 ZeroMem (&Dns4CfgData, sizeof (Dns4CfgData));\r
108 Dns4CfgData.DnsServerListCount = DnsServerListCount;\r
109 Dns4CfgData.DnsServerList = DnsServerList;\r
110 Dns4CfgData.UseDefaultSetting = HttpInstance->IPv4Node.UseDefaultAddress;\r
35a4b632
HL
111 Dns4CfgData.RetryInterval = PcdGet32 (PcdHttpDnsRetryInterval);\r
112 Dns4CfgData.RetryCount = PcdGet32 (PcdHttpDnsRetryCount);\r
47f51a06
YT
113 if (!Dns4CfgData.UseDefaultSetting) {\r
114 IP4_COPY_ADDRESS (&Dns4CfgData.StationIp, &HttpInstance->IPv4Node.LocalAddress);\r
115 IP4_COPY_ADDRESS (&Dns4CfgData.SubnetMask, &HttpInstance->IPv4Node.LocalSubnet);\r
116 }\r
d1050b9d
MK
117\r
118 Dns4CfgData.EnableDnsCache = TRUE;\r
119 Dns4CfgData.Protocol = EFI_IP_PROTO_UDP;\r
120 Status = Dns4->Configure (\r
121 Dns4,\r
122 &Dns4CfgData\r
123 );\r
47f51a06
YT
124 if (EFI_ERROR (Status)) {\r
125 goto Exit;\r
126 }\r
f75a7f56 127\r
47f51a06
YT
128 //\r
129 // Create event to set the is done flag when name resolution is finished.\r
130 //\r
131 ZeroMem (&Token, sizeof (Token));\r
132 Status = gBS->CreateEvent (\r
133 EVT_NOTIFY_SIGNAL,\r
134 TPL_NOTIFY,\r
135 HttpCommonNotify,\r
136 &IsDone,\r
137 &Token.Event\r
138 );\r
139 if (EFI_ERROR (Status)) {\r
140 goto Exit;\r
141 }\r
142\r
143 //\r
144 // Start asynchronous name resolution.\r
145 //\r
146 Token.Status = EFI_NOT_READY;\r
147 IsDone = FALSE;\r
d1050b9d 148 Status = Dns4->HostNameToIp (Dns4, HostName, &Token);\r
47f51a06
YT
149 if (EFI_ERROR (Status)) {\r
150 goto Exit;\r
151 }\r
152\r
153 while (!IsDone) {\r
154 Dns4->Poll (Dns4);\r
155 }\r
156\r
157 //\r
158 // Name resolution is done, check result.\r
159 //\r
f75a7f56 160 Status = Token.Status;\r
47f51a06
YT
161 if (!EFI_ERROR (Status)) {\r
162 if (Token.RspData.H2AData == NULL) {\r
163 Status = EFI_DEVICE_ERROR;\r
164 goto Exit;\r
165 }\r
d1050b9d
MK
166\r
167 if ((Token.RspData.H2AData->IpCount == 0) || (Token.RspData.H2AData->IpList == NULL)) {\r
47f51a06
YT
168 Status = EFI_DEVICE_ERROR;\r
169 goto Exit;\r
170 }\r
d1050b9d 171\r
47f51a06
YT
172 //\r
173 // We just return the first IP address from DNS protocol.\r
174 //\r
175 IP4_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);\r
176 Status = EFI_SUCCESS;\r
177 }\r
178\r
179Exit:\r
f75a7f56 180\r
47f51a06
YT
181 if (Token.Event != NULL) {\r
182 gBS->CloseEvent (Token.Event);\r
183 }\r
d1050b9d 184\r
47f51a06
YT
185 if (Token.RspData.H2AData != NULL) {\r
186 if (Token.RspData.H2AData->IpList != NULL) {\r
187 FreePool (Token.RspData.H2AData->IpList);\r
188 }\r
d1050b9d 189\r
47f51a06
YT
190 FreePool (Token.RspData.H2AData);\r
191 }\r
192\r
193 if (Dns4 != NULL) {\r
194 Dns4->Configure (Dns4, NULL);\r
f75a7f56 195\r
47f51a06 196 gBS->CloseProtocol (\r
b659408b
ZL
197 Dns4Handle,\r
198 &gEfiDns4ProtocolGuid,\r
7cf59c85 199 Service->Ip4DriverBindingHandle,\r
b659408b
ZL
200 Service->ControllerHandle\r
201 );\r
47f51a06
YT
202 }\r
203\r
204 if (Dns4Handle != NULL) {\r
205 NetLibDestroyServiceChild (\r
206 Service->ControllerHandle,\r
7cf59c85 207 Service->Ip4DriverBindingHandle,\r
47f51a06
YT
208 &gEfiDns4ServiceBindingProtocolGuid,\r
209 Dns4Handle\r
210 );\r
211 }\r
212\r
213 if (DnsServerList != NULL) {\r
214 FreePool (DnsServerList);\r
215 }\r
f75a7f56 216\r
47f51a06
YT
217 return Status;\r
218}\r
b659408b
ZL
219\r
220/**\r
221 Retrieve the host address using the EFI_DNS6_PROTOCOL.\r
222\r
223 @param[in] HttpInstance Pointer to HTTP_PROTOCOL instance.\r
224 @param[in] HostName Pointer to buffer containing hostname.\r
225 @param[out] IpAddress On output, pointer to buffer containing IPv6 address.\r
226\r
227 @retval EFI_SUCCESS Operation succeeded.\r
228 @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
229 @retval EFI_DEVICE_ERROR An unexpected network error occurred.\r
230 @retval Others Other errors as indicated.\r
f75a7f56 231\r
b659408b
ZL
232**/\r
233EFI_STATUS\r
234HttpDns6 (\r
d1050b9d
MK
235 IN HTTP_PROTOCOL *HttpInstance,\r
236 IN CHAR16 *HostName,\r
237 OUT EFI_IPv6_ADDRESS *IpAddress\r
b659408b
ZL
238 )\r
239{\r
d1050b9d
MK
240 EFI_STATUS Status;\r
241 HTTP_SERVICE *Service;\r
242 EFI_DNS6_PROTOCOL *Dns6;\r
243 EFI_DNS6_CONFIG_DATA Dns6ConfigData;\r
244 EFI_DNS6_COMPLETION_TOKEN Token;\r
245 EFI_HANDLE Dns6Handle;\r
246 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;\r
247 EFI_IPv6_ADDRESS *DnsServerList;\r
248 UINTN DnsServerListCount;\r
249 UINTN DataSize;\r
250 BOOLEAN IsDone;\r
b659408b
ZL
251\r
252 Service = HttpInstance->Service;\r
253 ASSERT (Service != NULL);\r
254\r
d1050b9d
MK
255 DnsServerList = NULL;\r
256 DnsServerListCount = 0;\r
257 Dns6 = NULL;\r
258 Dns6Handle = NULL;\r
b659408b 259 ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN));\r
f75a7f56 260\r
b659408b
ZL
261 //\r
262 // Get DNS server list from EFI IPv6 Configuration protocol.\r
263 //\r
d1050b9d 264 Status = gBS->HandleProtocol (Service->ControllerHandle, &gEfiIp6ConfigProtocolGuid, (VOID **)&Ip6Config);\r
b659408b
ZL
265 if (!EFI_ERROR (Status)) {\r
266 //\r
267 // Get the required size.\r
268 //\r
269 DataSize = 0;\r
d1050b9d 270 Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, NULL);\r
b659408b
ZL
271 if (Status == EFI_BUFFER_TOO_SMALL) {\r
272 DnsServerList = AllocatePool (DataSize);\r
273 if (DnsServerList == NULL) {\r
274 return EFI_OUT_OF_RESOURCES;\r
f75a7f56 275 }\r
b659408b
ZL
276\r
277 Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, DnsServerList);\r
278 if (EFI_ERROR (Status)) {\r
279 FreePool (DnsServerList);\r
280 DnsServerList = NULL;\r
281 } else {\r
282 DnsServerListCount = DataSize / sizeof (EFI_IPv6_ADDRESS);\r
283 }\r
284 }\r
285 }\r
286\r
287 //\r
288 // Create a DNSv6 child instance and get the protocol.\r
289 //\r
290 Status = NetLibCreateServiceChild (\r
291 Service->ControllerHandle,\r
7cf59c85 292 Service->Ip6DriverBindingHandle,\r
b659408b
ZL
293 &gEfiDns6ServiceBindingProtocolGuid,\r
294 &Dns6Handle\r
295 );\r
296 if (EFI_ERROR (Status)) {\r
297 goto Exit;\r
f75a7f56
LG
298 }\r
299\r
b659408b
ZL
300 Status = gBS->OpenProtocol (\r
301 Dns6Handle,\r
302 &gEfiDns6ProtocolGuid,\r
d1050b9d 303 (VOID **)&Dns6,\r
7cf59c85 304 Service->Ip6DriverBindingHandle,\r
b659408b
ZL
305 Service->ControllerHandle,\r
306 EFI_OPEN_PROTOCOL_BY_DRIVER\r
307 );\r
308 if (EFI_ERROR (Status)) {\r
309 goto Exit;\r
310 }\r
311\r
312 //\r
313 // Configure DNS6 instance for the DNS server address and protocol.\r
314 //\r
315 ZeroMem (&Dns6ConfigData, sizeof (EFI_DNS6_CONFIG_DATA));\r
316 Dns6ConfigData.DnsServerCount = (UINT32)DnsServerListCount;\r
317 Dns6ConfigData.DnsServerList = DnsServerList;\r
318 Dns6ConfigData.EnableDnsCache = TRUE;\r
319 Dns6ConfigData.Protocol = EFI_IP_PROTO_UDP;\r
35a4b632
HL
320 Dns6ConfigData.RetryInterval = PcdGet32 (PcdHttpDnsRetryInterval);\r
321 Dns6ConfigData.RetryCount = PcdGet32 (PcdHttpDnsRetryCount);\r
b659408b
ZL
322 IP6_COPY_ADDRESS (&Dns6ConfigData.StationIp, &HttpInstance->Ipv6Node.LocalAddress);\r
323 Status = Dns6->Configure (\r
324 Dns6,\r
325 &Dns6ConfigData\r
326 );\r
327 if (EFI_ERROR (Status)) {\r
328 goto Exit;\r
329 }\r
330\r
331 Token.Status = EFI_NOT_READY;\r
332 IsDone = FALSE;\r
333 //\r
334 // Create event to set the IsDone flag when name resolution is finished.\r
335 //\r
336 Status = gBS->CreateEvent (\r
337 EVT_NOTIFY_SIGNAL,\r
338 TPL_NOTIFY,\r
339 HttpCommonNotify,\r
340 &IsDone,\r
341 &Token.Event\r
342 );\r
343 if (EFI_ERROR (Status)) {\r
344 goto Exit;\r
345 }\r
346\r
347 //\r
348 // Start asynchronous name resolution.\r
349 //\r
350 Status = Dns6->HostNameToIp (Dns6, HostName, &Token);\r
351 if (EFI_ERROR (Status)) {\r
352 goto Exit;\r
353 }\r
354\r
355 while (!IsDone) {\r
356 Dns6->Poll (Dns6);\r
357 }\r
358\r
359 //\r
360 // Name resolution is done, check result.\r
361 //\r
f75a7f56 362 Status = Token.Status;\r
b659408b
ZL
363 if (!EFI_ERROR (Status)) {\r
364 if (Token.RspData.H2AData == NULL) {\r
365 Status = EFI_DEVICE_ERROR;\r
366 goto Exit;\r
367 }\r
d1050b9d
MK
368\r
369 if ((Token.RspData.H2AData->IpCount == 0) || (Token.RspData.H2AData->IpList == NULL)) {\r
b659408b
ZL
370 Status = EFI_DEVICE_ERROR;\r
371 goto Exit;\r
372 }\r
d1050b9d 373\r
b659408b
ZL
374 //\r
375 // We just return the first IPv6 address from DNS protocol.\r
376 //\r
377 IP6_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);\r
378 Status = EFI_SUCCESS;\r
379 }\r
f75a7f56 380\r
b659408b
ZL
381Exit:\r
382\r
383 if (Token.Event != NULL) {\r
384 gBS->CloseEvent (Token.Event);\r
385 }\r
d1050b9d 386\r
b659408b
ZL
387 if (Token.RspData.H2AData != NULL) {\r
388 if (Token.RspData.H2AData->IpList != NULL) {\r
389 FreePool (Token.RspData.H2AData->IpList);\r
390 }\r
d1050b9d 391\r
b659408b
ZL
392 FreePool (Token.RspData.H2AData);\r
393 }\r
394\r
395 if (Dns6 != NULL) {\r
396 Dns6->Configure (Dns6, NULL);\r
f75a7f56 397\r
b659408b
ZL
398 gBS->CloseProtocol (\r
399 Dns6Handle,\r
400 &gEfiDns6ProtocolGuid,\r
7cf59c85 401 Service->Ip6DriverBindingHandle,\r
b659408b
ZL
402 Service->ControllerHandle\r
403 );\r
404 }\r
405\r
406 if (Dns6Handle != NULL) {\r
407 NetLibDestroyServiceChild (\r
408 Service->ControllerHandle,\r
7cf59c85 409 Service->Ip6DriverBindingHandle,\r
b659408b
ZL
410 &gEfiDns6ServiceBindingProtocolGuid,\r
411 Dns6Handle\r
412 );\r
413 }\r
414\r
415 if (DnsServerList != NULL) {\r
416 FreePool (DnsServerList);\r
417 }\r
f75a7f56
LG
418\r
419 return Status;\r
b659408b 420}\r