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