]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/HttpDxe/HttpDns.c
NetworkPkg: Apply uncrustify changes
[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 if (!Dns4CfgData.UseDefaultSetting) {
112 IP4_COPY_ADDRESS (&Dns4CfgData.StationIp, &HttpInstance->IPv4Node.LocalAddress);
113 IP4_COPY_ADDRESS (&Dns4CfgData.SubnetMask, &HttpInstance->IPv4Node.LocalSubnet);
114 }
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
165 if ((Token.RspData.H2AData->IpCount == 0) || (Token.RspData.H2AData->IpList == NULL)) {
166 Status = EFI_DEVICE_ERROR;
167 goto Exit;
168 }
169
170 //
171 // We just return the first IP address from DNS protocol.
172 //
173 IP4_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);
174 Status = EFI_SUCCESS;
175 }
176
177 Exit:
178
179 if (Token.Event != NULL) {
180 gBS->CloseEvent (Token.Event);
181 }
182
183 if (Token.RspData.H2AData != NULL) {
184 if (Token.RspData.H2AData->IpList != NULL) {
185 FreePool (Token.RspData.H2AData->IpList);
186 }
187
188 FreePool (Token.RspData.H2AData);
189 }
190
191 if (Dns4 != NULL) {
192 Dns4->Configure (Dns4, NULL);
193
194 gBS->CloseProtocol (
195 Dns4Handle,
196 &gEfiDns4ProtocolGuid,
197 Service->Ip4DriverBindingHandle,
198 Service->ControllerHandle
199 );
200 }
201
202 if (Dns4Handle != NULL) {
203 NetLibDestroyServiceChild (
204 Service->ControllerHandle,
205 Service->Ip4DriverBindingHandle,
206 &gEfiDns4ServiceBindingProtocolGuid,
207 Dns4Handle
208 );
209 }
210
211 if (DnsServerList != NULL) {
212 FreePool (DnsServerList);
213 }
214
215 return Status;
216 }
217
218 /**
219 Retrieve the host address using the EFI_DNS6_PROTOCOL.
220
221 @param[in] HttpInstance Pointer to HTTP_PROTOCOL instance.
222 @param[in] HostName Pointer to buffer containing hostname.
223 @param[out] IpAddress On output, pointer to buffer containing IPv6 address.
224
225 @retval EFI_SUCCESS Operation succeeded.
226 @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
227 @retval EFI_DEVICE_ERROR An unexpected network error occurred.
228 @retval Others Other errors as indicated.
229
230 **/
231 EFI_STATUS
232 HttpDns6 (
233 IN HTTP_PROTOCOL *HttpInstance,
234 IN CHAR16 *HostName,
235 OUT EFI_IPv6_ADDRESS *IpAddress
236 )
237 {
238 EFI_STATUS Status;
239 HTTP_SERVICE *Service;
240 EFI_DNS6_PROTOCOL *Dns6;
241 EFI_DNS6_CONFIG_DATA Dns6ConfigData;
242 EFI_DNS6_COMPLETION_TOKEN Token;
243 EFI_HANDLE Dns6Handle;
244 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
245 EFI_IPv6_ADDRESS *DnsServerList;
246 UINTN DnsServerListCount;
247 UINTN DataSize;
248 BOOLEAN IsDone;
249
250 Service = HttpInstance->Service;
251 ASSERT (Service != NULL);
252
253 DnsServerList = NULL;
254 DnsServerListCount = 0;
255 Dns6 = NULL;
256 Dns6Handle = NULL;
257 ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN));
258
259 //
260 // Get DNS server list from EFI IPv6 Configuration protocol.
261 //
262 Status = gBS->HandleProtocol (Service->ControllerHandle, &gEfiIp6ConfigProtocolGuid, (VOID **)&Ip6Config);
263 if (!EFI_ERROR (Status)) {
264 //
265 // Get the required size.
266 //
267 DataSize = 0;
268 Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, NULL);
269 if (Status == EFI_BUFFER_TOO_SMALL) {
270 DnsServerList = AllocatePool (DataSize);
271 if (DnsServerList == NULL) {
272 return EFI_OUT_OF_RESOURCES;
273 }
274
275 Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, DnsServerList);
276 if (EFI_ERROR (Status)) {
277 FreePool (DnsServerList);
278 DnsServerList = NULL;
279 } else {
280 DnsServerListCount = DataSize / sizeof (EFI_IPv6_ADDRESS);
281 }
282 }
283 }
284
285 //
286 // Create a DNSv6 child instance and get the protocol.
287 //
288 Status = NetLibCreateServiceChild (
289 Service->ControllerHandle,
290 Service->Ip6DriverBindingHandle,
291 &gEfiDns6ServiceBindingProtocolGuid,
292 &Dns6Handle
293 );
294 if (EFI_ERROR (Status)) {
295 goto Exit;
296 }
297
298 Status = gBS->OpenProtocol (
299 Dns6Handle,
300 &gEfiDns6ProtocolGuid,
301 (VOID **)&Dns6,
302 Service->Ip6DriverBindingHandle,
303 Service->ControllerHandle,
304 EFI_OPEN_PROTOCOL_BY_DRIVER
305 );
306 if (EFI_ERROR (Status)) {
307 goto Exit;
308 }
309
310 //
311 // Configure DNS6 instance for the DNS server address and protocol.
312 //
313 ZeroMem (&Dns6ConfigData, sizeof (EFI_DNS6_CONFIG_DATA));
314 Dns6ConfigData.DnsServerCount = (UINT32)DnsServerListCount;
315 Dns6ConfigData.DnsServerList = DnsServerList;
316 Dns6ConfigData.EnableDnsCache = TRUE;
317 Dns6ConfigData.Protocol = EFI_IP_PROTO_UDP;
318 IP6_COPY_ADDRESS (&Dns6ConfigData.StationIp, &HttpInstance->Ipv6Node.LocalAddress);
319 Status = Dns6->Configure (
320 Dns6,
321 &Dns6ConfigData
322 );
323 if (EFI_ERROR (Status)) {
324 goto Exit;
325 }
326
327 Token.Status = EFI_NOT_READY;
328 IsDone = FALSE;
329 //
330 // Create event to set the IsDone flag when name resolution is finished.
331 //
332 Status = gBS->CreateEvent (
333 EVT_NOTIFY_SIGNAL,
334 TPL_NOTIFY,
335 HttpCommonNotify,
336 &IsDone,
337 &Token.Event
338 );
339 if (EFI_ERROR (Status)) {
340 goto Exit;
341 }
342
343 //
344 // Start asynchronous name resolution.
345 //
346 Status = Dns6->HostNameToIp (Dns6, HostName, &Token);
347 if (EFI_ERROR (Status)) {
348 goto Exit;
349 }
350
351 while (!IsDone) {
352 Dns6->Poll (Dns6);
353 }
354
355 //
356 // Name resolution is done, check result.
357 //
358 Status = Token.Status;
359 if (!EFI_ERROR (Status)) {
360 if (Token.RspData.H2AData == NULL) {
361 Status = EFI_DEVICE_ERROR;
362 goto Exit;
363 }
364
365 if ((Token.RspData.H2AData->IpCount == 0) || (Token.RspData.H2AData->IpList == NULL)) {
366 Status = EFI_DEVICE_ERROR;
367 goto Exit;
368 }
369
370 //
371 // We just return the first IPv6 address from DNS protocol.
372 //
373 IP6_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);
374 Status = EFI_SUCCESS;
375 }
376
377 Exit:
378
379 if (Token.Event != NULL) {
380 gBS->CloseEvent (Token.Event);
381 }
382
383 if (Token.RspData.H2AData != NULL) {
384 if (Token.RspData.H2AData->IpList != NULL) {
385 FreePool (Token.RspData.H2AData->IpList);
386 }
387
388 FreePool (Token.RspData.H2AData);
389 }
390
391 if (Dns6 != NULL) {
392 Dns6->Configure (Dns6, NULL);
393
394 gBS->CloseProtocol (
395 Dns6Handle,
396 &gEfiDns6ProtocolGuid,
397 Service->Ip6DriverBindingHandle,
398 Service->ControllerHandle
399 );
400 }
401
402 if (Dns6Handle != NULL) {
403 NetLibDestroyServiceChild (
404 Service->ControllerHandle,
405 Service->Ip6DriverBindingHandle,
406 &gEfiDns6ServiceBindingProtocolGuid,
407 Dns6Handle
408 );
409 }
410
411 if (DnsServerList != NULL) {
412 FreePool (DnsServerList);
413 }
414
415 return Status;
416 }