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