VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/NetworkPkg/IScsiDxe/IScsiDns.c@ 77662

Last change on this file since 77662 was 77662, checked in by vboxsync, 6 years ago

EFI: First step in UDK2018 merge. Does not build yet.

  • Property svn:eol-style set to native
File size: 11.4 KB
Line 
1/** @file
2 Perform DNS resolution based on UEFI DNS protocols.
3
4Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
5This program and the accompanying materials
6are licensed and made available under the terms and conditions of the BSD License
7which accompanies this distribution. The full text of the license may be found at
8http://opensource.org/licenses/bsd-license.php
9
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13**/
14
15#include "IScsiImpl.h"
16
17/**
18 Notify the callback function when an event is triggered.
19
20 @param[in] Event The triggered event.
21 @param[in] Context The opaque parameter to the function.
22
23**/
24VOID
25EFIAPI
26IScsiCommonNotify (
27 IN EFI_EVENT Event,
28 IN VOID *Context
29 )
30{
31 *((BOOLEAN *) Context) = TRUE;
32}
33
34/**
35 Retrieve the host address using the EFI_DNS4_PROTOCOL.
36
37 @param[in] Image The handle of the driver image.
38 @param[in] Controller The handle of the controller.
39 @param[in, out] NvData The Session config data structure.
40
41 @retval EFI_SUCCESS Operation succeeded.
42 @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
43 @retval EFI_DEVICE_ERROR An unexpected network error occurred.
44 @retval Others Other errors as indicated.
45
46**/
47EFI_STATUS
48IScsiDns4 (
49 IN EFI_HANDLE Image,
50 IN EFI_HANDLE Controller,
51 IN OUT ISCSI_SESSION_CONFIG_NVDATA *NvData
52 )
53{
54 EFI_STATUS Status;
55 EFI_DNS4_PROTOCOL *Dns4;
56 EFI_DNS4_CONFIG_DATA Dns4CfgData;
57 EFI_DNS4_COMPLETION_TOKEN Token;
58 BOOLEAN IsDone;
59 EFI_HANDLE Dns4Handle;
60 EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2;
61 EFI_IPv4_ADDRESS *DnsServerList;
62 UINTN DnsServerListCount;
63 UINTN DataSize;
64 CHAR16 *HostName;
65
66 DnsServerList = NULL;
67 DnsServerListCount = 0;
68 Dns4Handle = NULL;
69 Dns4 = NULL;
70 ZeroMem (&Token, sizeof (EFI_DNS4_COMPLETION_TOKEN));
71
72 //
73 // Get DNS server list from EFI IPv4 Configuration II protocol.
74 //
75 Status = gBS->HandleProtocol (Controller, &gEfiIp4Config2ProtocolGuid, (VOID **) &Ip4Config2);
76 if (!EFI_ERROR (Status)) {
77 //
78 // Get the required size.
79 //
80 DataSize = 0;
81 Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeDnsServer, &DataSize, NULL);
82 if (Status == EFI_BUFFER_TOO_SMALL) {
83 DnsServerList = AllocatePool (DataSize);
84 if (DnsServerList == NULL) {
85 return EFI_OUT_OF_RESOURCES;
86 }
87
88 Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeDnsServer, &DataSize, DnsServerList);
89 if (EFI_ERROR (Status)) {
90 FreePool (DnsServerList);
91 DnsServerList = NULL;
92 } else {
93 DnsServerListCount = DataSize / sizeof (EFI_IPv4_ADDRESS);
94 }
95 }
96 }
97
98
99 //
100 // Create a DNS child instance and get the protocol.
101 //
102 Status = NetLibCreateServiceChild (
103 Controller,
104 Image,
105 &gEfiDns4ServiceBindingProtocolGuid,
106 &Dns4Handle
107 );
108 if (EFI_ERROR (Status)) {
109 goto Exit;
110 }
111
112 Status = gBS->OpenProtocol (
113 Dns4Handle,
114 &gEfiDns4ProtocolGuid,
115 (VOID **) &Dns4,
116 Image,
117 Controller,
118 EFI_OPEN_PROTOCOL_BY_DRIVER
119 );
120 if (EFI_ERROR (Status)) {
121 goto Exit;
122 }
123
124 //
125 // Configure DNS4 instance for the DNS server address and protocol.
126 //
127 ZeroMem (&Dns4CfgData, sizeof (Dns4CfgData));
128 Dns4CfgData.DnsServerListCount = DnsServerListCount;
129 Dns4CfgData.DnsServerList = DnsServerList;
130 Dns4CfgData.EnableDnsCache = TRUE;
131 IP4_COPY_ADDRESS (&Dns4CfgData.StationIp, &NvData->LocalIp);
132 IP4_COPY_ADDRESS (&Dns4CfgData.SubnetMask, &NvData->SubnetMask);
133 Dns4CfgData.Protocol = EFI_IP_PROTO_UDP;
134 Status = Dns4->Configure (
135 Dns4,
136 &Dns4CfgData
137 );
138 if (EFI_ERROR (Status)) {
139 goto Exit;
140 }
141
142 //
143 // Create event to set the is done flag when name resolution is finished.
144 //
145 ZeroMem (&Token, sizeof (Token));
146 Status = gBS->CreateEvent (
147 EVT_NOTIFY_SIGNAL,
148 TPL_NOTIFY,
149 IScsiCommonNotify,
150 &IsDone,
151 &Token.Event
152 );
153 if (EFI_ERROR (Status)) {
154 goto Exit;
155 }
156
157 //
158 // Start asynchronous name resolution.
159 //
160 Token.Status = EFI_NOT_READY;
161 IsDone = FALSE;
162
163 HostName = (CHAR16 *) AllocateZeroPool (ISCSI_NAME_MAX_SIZE);
164 if (HostName == NULL) {
165 return EFI_OUT_OF_RESOURCES;
166 }
167
168 AsciiStrToUnicodeStrS (
169 NvData->TargetUrl,
170 HostName,
171 ISCSI_NAME_MAX_SIZE
172 );
173
174 Status = Dns4->HostNameToIp (Dns4, HostName, &Token);
175 if (EFI_ERROR (Status)) {
176 goto Exit;
177 }
178
179 while (!IsDone) {
180 Dns4->Poll (Dns4);
181 }
182
183 //
184 // Name resolution is done, check result.
185 //
186 Status = Token.Status;
187 if (!EFI_ERROR (Status)) {
188 if (Token.RspData.H2AData == NULL) {
189 Status = EFI_DEVICE_ERROR;
190 goto Exit;
191 }
192 if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) {
193 Status = EFI_DEVICE_ERROR;
194 goto Exit;
195 }
196 //
197 // We just return the first IP address from DNS protocol.
198 //
199 IP4_COPY_ADDRESS (&NvData->TargetIp.v4, Token.RspData.H2AData->IpList);
200 Status = EFI_SUCCESS;
201 }
202
203Exit:
204
205 if (Token.Event != NULL) {
206 gBS->CloseEvent (Token.Event);
207 }
208 if (Token.RspData.H2AData != NULL) {
209 if (Token.RspData.H2AData->IpList != NULL) {
210 FreePool (Token.RspData.H2AData->IpList);
211 }
212 FreePool (Token.RspData.H2AData);
213 }
214
215 if (Dns4 != NULL) {
216 Dns4->Configure (Dns4, NULL);
217
218 gBS->CloseProtocol (
219 Dns4Handle,
220 &gEfiDns4ProtocolGuid,
221 Image,
222 Controller
223 );
224 }
225
226 if (Dns4Handle != NULL) {
227 NetLibDestroyServiceChild (
228 Controller,
229 Image,
230 &gEfiDns4ServiceBindingProtocolGuid,
231 Dns4Handle
232 );
233 }
234
235 return Status;
236}
237
238/**
239 Retrieve the host address using the EFI_DNS6_PROTOCOL.
240
241 @param[in] Image The handle of the driver image.
242 @param[in] Controller The handle of the controller.
243 @param[in, out] NvData The Session config data structure.
244
245 @retval EFI_SUCCESS Operation succeeded.
246 @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
247 @retval EFI_DEVICE_ERROR An unexpected network error occurred.
248 @retval Others Other errors as indicated.
249
250**/
251EFI_STATUS
252IScsiDns6 (
253 IN EFI_HANDLE Image,
254 IN EFI_HANDLE Controller,
255 IN OUT ISCSI_SESSION_CONFIG_NVDATA *NvData
256 )
257{
258 EFI_STATUS Status;
259 EFI_DNS6_PROTOCOL *Dns6;
260 EFI_DNS6_CONFIG_DATA Dns6ConfigData;
261 EFI_DNS6_COMPLETION_TOKEN Token;
262 EFI_HANDLE Dns6Handle;
263 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
264 EFI_IPv6_ADDRESS *DnsServerList;
265 UINTN DnsServerListCount;
266 UINTN DataSize;
267 BOOLEAN IsDone;
268 CHAR16 *HostName;
269
270 DnsServerList = NULL;
271 DnsServerListCount = 0;
272 Dns6 = NULL;
273 Dns6Handle = NULL;
274 ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN));
275
276 //
277 // Get DNS server list from EFI IPv6 Configuration protocol.
278 //
279 Status = gBS->HandleProtocol (Controller, &gEfiIp6ConfigProtocolGuid, (VOID **) &Ip6Config);
280 if (!EFI_ERROR (Status)) {
281 //
282 // Get the required size.
283 //
284 DataSize = 0;
285 Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, NULL);
286 if (Status == EFI_BUFFER_TOO_SMALL) {
287 DnsServerList = AllocatePool (DataSize);
288 if (DnsServerList == NULL) {
289 return EFI_OUT_OF_RESOURCES;
290 }
291
292 Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, DnsServerList);
293 if (EFI_ERROR (Status)) {
294 FreePool (DnsServerList);
295 DnsServerList = NULL;
296 } else {
297 DnsServerListCount = DataSize / sizeof (EFI_IPv6_ADDRESS);
298 }
299 }
300 }
301
302 //
303 // Create a DNSv6 child instance and get the protocol.
304 //
305 Status = NetLibCreateServiceChild (
306 Controller,
307 Image,
308 &gEfiDns6ServiceBindingProtocolGuid,
309 &Dns6Handle
310 );
311 if (EFI_ERROR (Status)) {
312 goto Exit;
313 }
314
315 Status = gBS->OpenProtocol (
316 Dns6Handle,
317 &gEfiDns6ProtocolGuid,
318 (VOID **) &Dns6,
319 Image,
320 Controller,
321 EFI_OPEN_PROTOCOL_BY_DRIVER
322 );
323 if (EFI_ERROR (Status)) {
324 goto Exit;
325 }
326
327 //
328 // Configure DNS6 instance for the DNS server address and protocol.
329 //
330 ZeroMem (&Dns6ConfigData, sizeof (EFI_DNS6_CONFIG_DATA));
331 Dns6ConfigData.DnsServerCount = (UINT32)DnsServerListCount;
332 Dns6ConfigData.DnsServerList = DnsServerList;
333 Dns6ConfigData.EnableDnsCache = TRUE;
334 Dns6ConfigData.Protocol = EFI_IP_PROTO_UDP;
335 Status = Dns6->Configure (
336 Dns6,
337 &Dns6ConfigData
338 );
339 if (EFI_ERROR (Status)) {
340 goto Exit;
341 }
342
343 Token.Status = EFI_NOT_READY;
344 IsDone = FALSE;
345 //
346 // Create event to set the IsDone flag when name resolution is finished.
347 //
348 Status = gBS->CreateEvent (
349 EVT_NOTIFY_SIGNAL,
350 TPL_NOTIFY,
351 IScsiCommonNotify,
352 &IsDone,
353 &Token.Event
354 );
355 if (EFI_ERROR (Status)) {
356 goto Exit;
357 }
358
359 //
360 // Start asynchronous name resolution.
361 //
362 HostName = (CHAR16 *) AllocateZeroPool (ISCSI_NAME_MAX_SIZE);
363 if (HostName == NULL) {
364 return EFI_OUT_OF_RESOURCES;
365 }
366
367 AsciiStrToUnicodeStrS (
368 NvData->TargetUrl,
369 HostName,
370 ISCSI_NAME_MAX_SIZE
371 );
372 Status = Dns6->HostNameToIp (Dns6, HostName, &Token);
373 if (EFI_ERROR (Status)) {
374 goto Exit;
375 }
376
377 while (!IsDone) {
378 Dns6->Poll (Dns6);
379 }
380
381 //
382 // Name resolution is done, check result.
383 //
384 Status = Token.Status;
385 if (!EFI_ERROR (Status)) {
386 if (Token.RspData.H2AData == NULL) {
387 Status = EFI_DEVICE_ERROR;
388 goto Exit;
389 }
390 if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) {
391 Status = EFI_DEVICE_ERROR;
392 goto Exit;
393 }
394 //
395 // We just return the first IPv6 address from DNS protocol.
396 //
397 IP6_COPY_ADDRESS (&NvData->TargetIp.v6, Token.RspData.H2AData->IpList);
398 Status = EFI_SUCCESS;
399 }
400
401Exit:
402
403 if (Token.Event != NULL) {
404 gBS->CloseEvent (Token.Event);
405 }
406 if (Token.RspData.H2AData != NULL) {
407 if (Token.RspData.H2AData->IpList != NULL) {
408 FreePool (Token.RspData.H2AData->IpList);
409 }
410 FreePool (Token.RspData.H2AData);
411 }
412
413 if (Dns6 != NULL) {
414 Dns6->Configure (Dns6, NULL);
415
416 gBS->CloseProtocol (
417 Dns6Handle,
418 &gEfiDns6ProtocolGuid,
419 Image,
420 Controller
421 );
422 }
423
424 if (Dns6Handle != NULL) {
425 NetLibDestroyServiceChild (
426 Controller,
427 Image,
428 &gEfiDns6ServiceBindingProtocolGuid,
429 Dns6Handle
430 );
431 }
432
433 return Status;
434}
435
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette