]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/HttpDxe/HttpDns.c
BaseTools: Add HOST_APPLICATION module type.
[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
44 Service = HttpInstance->Service;
45 ASSERT (Service != NULL);
46
47 DnsServerList = NULL;
48 DnsServerListCount = 0;
49 ZeroMem (&Token, sizeof (EFI_DNS4_COMPLETION_TOKEN));
50
51 //
52 // Get DNS server list from EFI IPv4 Configuration II protocol.
53 //
54 Status = gBS->HandleProtocol (Service->ControllerHandle, &gEfiIp4Config2ProtocolGuid, (VOID **) &Ip4Config2);
55 if (!EFI_ERROR (Status)) {
56 //
57 // Get the required size.
58 //
59 DataSize = 0;
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;
65 }
66
67 Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeDnsServer, &DataSize, DnsServerList);
68 if (EFI_ERROR (Status)) {
69 FreePool (DnsServerList);
70 DnsServerList = NULL;
71 } else {
72 DnsServerListCount = DataSize / sizeof (EFI_IPv4_ADDRESS);
73 }
74 }
75 }
76
77 Dns4Handle = NULL;
78 Dns4 = NULL;
79
80 //
81 // Create a DNS child instance and get the protocol.
82 //
83 Status = NetLibCreateServiceChild (
84 Service->ControllerHandle,
85 Service->Ip4DriverBindingHandle,
86 &gEfiDns4ServiceBindingProtocolGuid,
87 &Dns4Handle
88 );
89 if (EFI_ERROR (Status)) {
90 goto Exit;
91 }
92
93 Status = gBS->OpenProtocol (
94 Dns4Handle,
95 &gEfiDns4ProtocolGuid,
96 (VOID **) &Dns4,
97 Service->Ip4DriverBindingHandle,
98 Service->ControllerHandle,
99 EFI_OPEN_PROTOCOL_BY_DRIVER
100 );
101 if (EFI_ERROR (Status)) {
102 goto Exit;
103 }
104
105 //
106 // Configure DNS4 instance for the DNS server address and protocol.
107 //
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);
115 }
116 Dns4CfgData.EnableDnsCache = TRUE;
117 Dns4CfgData.Protocol = EFI_IP_PROTO_UDP;
118 Status = Dns4->Configure (
119 Dns4,
120 &Dns4CfgData
121 );
122 if (EFI_ERROR (Status)) {
123 goto Exit;
124 }
125
126 //
127 // Create event to set the is done flag when name resolution is finished.
128 //
129 ZeroMem (&Token, sizeof (Token));
130 Status = gBS->CreateEvent (
131 EVT_NOTIFY_SIGNAL,
132 TPL_NOTIFY,
133 HttpCommonNotify,
134 &IsDone,
135 &Token.Event
136 );
137 if (EFI_ERROR (Status)) {
138 goto Exit;
139 }
140
141 //
142 // Start asynchronous name resolution.
143 //
144 Token.Status = EFI_NOT_READY;
145 IsDone = FALSE;
146 Status = Dns4->HostNameToIp (Dns4, HostName, &Token);
147 if (EFI_ERROR (Status)) {
148 goto Exit;
149 }
150
151 while (!IsDone) {
152 Dns4->Poll (Dns4);
153 }
154
155 //
156 // Name resolution is done, check result.
157 //
158 Status = Token.Status;
159 if (!EFI_ERROR (Status)) {
160 if (Token.RspData.H2AData == NULL) {
161 Status = EFI_DEVICE_ERROR;
162 goto Exit;
163 }
164 if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) {
165 Status = EFI_DEVICE_ERROR;
166 goto Exit;
167 }
168 //
169 // We just return the first IP address from DNS protocol.
170 //
171 IP4_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);
172 Status = EFI_SUCCESS;
173 }
174
175 Exit:
176
177 if (Token.Event != NULL) {
178 gBS->CloseEvent (Token.Event);
179 }
180 if (Token.RspData.H2AData != NULL) {
181 if (Token.RspData.H2AData->IpList != NULL) {
182 FreePool (Token.RspData.H2AData->IpList);
183 }
184 FreePool (Token.RspData.H2AData);
185 }
186
187 if (Dns4 != NULL) {
188 Dns4->Configure (Dns4, NULL);
189
190 gBS->CloseProtocol (
191 Dns4Handle,
192 &gEfiDns4ProtocolGuid,
193 Service->Ip4DriverBindingHandle,
194 Service->ControllerHandle
195 );
196 }
197
198 if (Dns4Handle != NULL) {
199 NetLibDestroyServiceChild (
200 Service->ControllerHandle,
201 Service->Ip4DriverBindingHandle,
202 &gEfiDns4ServiceBindingProtocolGuid,
203 Dns4Handle
204 );
205 }
206
207 if (DnsServerList != NULL) {
208 FreePool (DnsServerList);
209 }
210
211 return Status;
212 }
213
214 /**
215 Retrieve the host address using the EFI_DNS6_PROTOCOL.
216
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.
220
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.
225
226 **/
227 EFI_STATUS
228 HttpDns6 (
229 IN HTTP_PROTOCOL *HttpInstance,
230 IN CHAR16 *HostName,
231 OUT EFI_IPv6_ADDRESS *IpAddress
232 )
233 {
234 EFI_STATUS Status;
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;
243 UINTN DataSize;
244 BOOLEAN IsDone;
245
246
247 Service = HttpInstance->Service;
248 ASSERT (Service != NULL);
249
250 DnsServerList = NULL;
251 DnsServerListCount = 0;
252 Dns6 = NULL;
253 Dns6Handle = NULL;
254 ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN));
255
256 //
257 // Get DNS server list from EFI IPv6 Configuration protocol.
258 //
259 Status = gBS->HandleProtocol (Service->ControllerHandle, &gEfiIp6ConfigProtocolGuid, (VOID **) &Ip6Config);
260 if (!EFI_ERROR (Status)) {
261 //
262 // Get the required size.
263 //
264 DataSize = 0;
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;
270 }
271
272 Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, DnsServerList);
273 if (EFI_ERROR (Status)) {
274 FreePool (DnsServerList);
275 DnsServerList = NULL;
276 } else {
277 DnsServerListCount = DataSize / sizeof (EFI_IPv6_ADDRESS);
278 }
279 }
280 }
281
282 //
283 // Create a DNSv6 child instance and get the protocol.
284 //
285 Status = NetLibCreateServiceChild (
286 Service->ControllerHandle,
287 Service->Ip6DriverBindingHandle,
288 &gEfiDns6ServiceBindingProtocolGuid,
289 &Dns6Handle
290 );
291 if (EFI_ERROR (Status)) {
292 goto Exit;
293 }
294
295 Status = gBS->OpenProtocol (
296 Dns6Handle,
297 &gEfiDns6ProtocolGuid,
298 (VOID **) &Dns6,
299 Service->Ip6DriverBindingHandle,
300 Service->ControllerHandle,
301 EFI_OPEN_PROTOCOL_BY_DRIVER
302 );
303 if (EFI_ERROR (Status)) {
304 goto Exit;
305 }
306
307 //
308 // Configure DNS6 instance for the DNS server address and protocol.
309 //
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 (
317 Dns6,
318 &Dns6ConfigData
319 );
320 if (EFI_ERROR (Status)) {
321 goto Exit;
322 }
323
324 Token.Status = EFI_NOT_READY;
325 IsDone = FALSE;
326 //
327 // Create event to set the IsDone flag when name resolution is finished.
328 //
329 Status = gBS->CreateEvent (
330 EVT_NOTIFY_SIGNAL,
331 TPL_NOTIFY,
332 HttpCommonNotify,
333 &IsDone,
334 &Token.Event
335 );
336 if (EFI_ERROR (Status)) {
337 goto Exit;
338 }
339
340 //
341 // Start asynchronous name resolution.
342 //
343 Status = Dns6->HostNameToIp (Dns6, HostName, &Token);
344 if (EFI_ERROR (Status)) {
345 goto Exit;
346 }
347
348 while (!IsDone) {
349 Dns6->Poll (Dns6);
350 }
351
352 //
353 // Name resolution is done, check result.
354 //
355 Status = Token.Status;
356 if (!EFI_ERROR (Status)) {
357 if (Token.RspData.H2AData == NULL) {
358 Status = EFI_DEVICE_ERROR;
359 goto Exit;
360 }
361 if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) {
362 Status = EFI_DEVICE_ERROR;
363 goto Exit;
364 }
365 //
366 // We just return the first IPv6 address from DNS protocol.
367 //
368 IP6_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);
369 Status = EFI_SUCCESS;
370 }
371
372 Exit:
373
374 if (Token.Event != NULL) {
375 gBS->CloseEvent (Token.Event);
376 }
377 if (Token.RspData.H2AData != NULL) {
378 if (Token.RspData.H2AData->IpList != NULL) {
379 FreePool (Token.RspData.H2AData->IpList);
380 }
381 FreePool (Token.RspData.H2AData);
382 }
383
384 if (Dns6 != NULL) {
385 Dns6->Configure (Dns6, NULL);
386
387 gBS->CloseProtocol (
388 Dns6Handle,
389 &gEfiDns6ProtocolGuid,
390 Service->Ip6DriverBindingHandle,
391 Service->ControllerHandle
392 );
393 }
394
395 if (Dns6Handle != NULL) {
396 NetLibDestroyServiceChild (
397 Service->ControllerHandle,
398 Service->Ip6DriverBindingHandle,
399 &gEfiDns6ServiceBindingProtocolGuid,
400 Dns6Handle
401 );
402 }
403
404 if (DnsServerList != NULL) {
405 FreePool (DnsServerList);
406 }
407
408 return Status;
409 }