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