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