]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/DnsDxe/DnsDhcp.c
NetworkPkg: Apply uncrustify changes
[mirror_edk2.git] / NetworkPkg / DnsDxe / DnsDhcp.c
CommitLineData
99c048ef 1/** @file\r
2Functions implementation related with DHCPv4/v6 for DNS driver.\r
3\r
f75a7f56 4Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
ecf98fbc 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
99c048ef 6\r
7**/\r
8\r
9#include "DnsImpl.h"\r
10\r
11/**\r
12 This function initialize the DHCP4 message instance.\r
13\r
14 This function will pad each item of dhcp4 message packet.\r
15\r
16 @param Seed Pointer to the message instance of the DHCP4 packet.\r
17 @param InterfaceInfo Pointer to the EFI_IP4_CONFIG2_INTERFACE_INFO instance.\r
18\r
19**/\r
20VOID\r
21DnsInitSeedPacket (\r
d1050b9d
MK
22 OUT EFI_DHCP4_PACKET *Seed,\r
23 IN EFI_IP4_CONFIG2_INTERFACE_INFO *InterfaceInfo\r
99c048ef 24 )\r
25{\r
d1050b9d 26 EFI_DHCP4_HEADER *Header;\r
99c048ef 27\r
28 //\r
29 // Get IfType and HwAddressSize from SNP mode data.\r
30 //\r
d1050b9d
MK
31 Seed->Size = sizeof (EFI_DHCP4_PACKET);\r
32 Seed->Length = sizeof (Seed->Dhcp4);\r
33 Header = &Seed->Dhcp4.Header;\r
99c048ef 34 ZeroMem (Header, sizeof (EFI_DHCP4_HEADER));\r
d1050b9d
MK
35 Header->OpCode = DHCP4_OPCODE_REQUEST;\r
36 Header->HwType = InterfaceInfo->IfType;\r
37 Header->HwAddrLen = (UINT8)InterfaceInfo->HwAddressSize;\r
99c048ef 38 CopyMem (Header->ClientHwAddr, &(InterfaceInfo->HwAddress), Header->HwAddrLen);\r
39\r
40 Seed->Dhcp4.Magik = DHCP4_MAGIC;\r
41 Seed->Dhcp4.Option[0] = DHCP4_TAG_EOP;\r
42}\r
43\r
44/**\r
f75a7f56 45 The common notify function.\r
99c048ef 46\r
47 @param[in] Event The event signaled.\r
48 @param[in] Context The context.\r
49\r
50**/\r
51VOID\r
52EFIAPI\r
53DhcpCommonNotify (\r
54 IN EFI_EVENT Event,\r
55 IN VOID *Context\r
56 )\r
57{\r
58 if ((Event == NULL) || (Context == NULL)) {\r
d1050b9d 59 return;\r
99c048ef 60 }\r
61\r
d1050b9d 62 *((BOOLEAN *)Context) = TRUE;\r
99c048ef 63}\r
64\r
65/**\r
66 Parse the ACK to get required information\r
67\r
68 @param Dhcp4 The DHCP4 protocol.\r
69 @param Packet Packet waiting for parse.\r
70 @param DnsServerInfor The required Dns4 server information.\r
71\r
72 @retval EFI_SUCCESS The DNS information is got from the DHCP ACK.\r
73 @retval EFI_NO_MAPPING DHCP failed to acquire address and other information.\r
74 @retval EFI_DEVICE_ERROR Other errors as indicated.\r
75 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
76\r
77**/\r
78EFI_STATUS\r
79ParseDhcp4Ack (\r
d1050b9d
MK
80 IN EFI_DHCP4_PROTOCOL *Dhcp4,\r
81 IN EFI_DHCP4_PACKET *Packet,\r
82 IN DNS4_SERVER_INFOR *DnsServerInfor\r
99c048ef 83 )\r
84{\r
d1050b9d
MK
85 EFI_STATUS Status;\r
86 UINT32 OptionCount;\r
87 EFI_DHCP4_PACKET_OPTION **OptionList;\r
88 UINT32 ServerCount;\r
89 EFI_IPv4_ADDRESS *ServerList;\r
90 UINT32 Index;\r
91 UINT32 Count;\r
99c048ef 92\r
93 ServerCount = 0;\r
d1050b9d 94 ServerList = NULL;\r
99c048ef 95\r
96 OptionCount = 0;\r
97 OptionList = NULL;\r
98\r
d1050b9d 99 Status = Dhcp4->Parse (Dhcp4, Packet, &OptionCount, OptionList);\r
99c048ef 100 if (Status != EFI_BUFFER_TOO_SMALL) {\r
101 return EFI_DEVICE_ERROR;\r
102 }\r
103\r
104 OptionList = AllocatePool (OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));\r
105 if (OptionList == NULL) {\r
106 return EFI_OUT_OF_RESOURCES;\r
107 }\r
108\r
109 Status = Dhcp4->Parse (Dhcp4, Packet, &OptionCount, OptionList);\r
110 if (EFI_ERROR (Status)) {\r
111 gBS->FreePool (OptionList);\r
112 return EFI_DEVICE_ERROR;\r
113 }\r
114\r
115 Status = EFI_NOT_FOUND;\r
116\r
117 for (Index = 0; Index < OptionCount; Index++) {\r
118 //\r
119 // Get DNS server addresses\r
120 //\r
121 if (OptionList[Index]->OpCode == DHCP4_TAG_DNS_SERVER) {\r
99c048ef 122 if (((OptionList[Index]->Length & 0x3) != 0) || (OptionList[Index]->Length == 0)) {\r
123 Status = EFI_DEVICE_ERROR;\r
124 break;\r
125 }\r
126\r
127 ServerCount = OptionList[Index]->Length/4;\r
d1050b9d 128 ServerList = AllocatePool (ServerCount * sizeof (EFI_IPv4_ADDRESS));\r
99c048ef 129 if (ServerList == NULL) {\r
130 return EFI_OUT_OF_RESOURCES;\r
131 }\r
132\r
d1050b9d 133 for (Count = 0; Count < ServerCount; Count++) {\r
99c048ef 134 CopyMem (ServerList + Count, &OptionList[Index]->Data[4 * Count], sizeof (EFI_IPv4_ADDRESS));\r
135 }\r
136\r
137 *(DnsServerInfor->ServerCount) = ServerCount;\r
138 DnsServerInfor->ServerList = ServerList;\r
139\r
140 Status = EFI_SUCCESS;\r
141 }\r
142 }\r
143\r
144 gBS->FreePool (OptionList);\r
f75a7f56 145\r
99c048ef 146 return Status;\r
147}\r
148\r
149/**\r
f75a7f56 150 EFI_DHCP6_INFO_CALLBACK is provided by the consumer of the EFI DHCPv6 Protocol\r
99c048ef 151 instance to intercept events that occurs in the DHCPv6 Information Request\r
152 exchange process.\r
153\r
f75a7f56 154 @param This Pointer to the EFI_DHCP6_PROTOCOL instance that\r
99c048ef 155 is used to configure this callback function.\r
156 @param Context Pointer to the context that is initialized in\r
157 the EFI_DHCP6_PROTOCOL.InfoRequest().\r
158 @param Packet Pointer to Reply packet that has been received.\r
159 The EFI DHCPv6 Protocol instance is responsible\r
160 for freeing the buffer.\r
161\r
162 @retval EFI_SUCCESS The DNS information is got from the DHCP ACK.\r
163 @retval EFI_DEVICE_ERROR Other errors as indicated.\r
164 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
165**/\r
166EFI_STATUS\r
167EFIAPI\r
168ParseDhcp6Ack (\r
d1050b9d
MK
169 IN EFI_DHCP6_PROTOCOL *This,\r
170 IN VOID *Context,\r
171 IN EFI_DHCP6_PACKET *Packet\r
99c048ef 172 )\r
173{\r
d1050b9d
MK
174 EFI_STATUS Status;\r
175 UINT32 OptionCount;\r
176 EFI_DHCP6_PACKET_OPTION **OptionList;\r
177 DNS6_SERVER_INFOR *DnsServerInfor;\r
178 UINT32 ServerCount;\r
179 EFI_IPv6_ADDRESS *ServerList;\r
180 UINT32 Index;\r
181 UINT32 Count;\r
f75a7f56 182\r
99c048ef 183 OptionCount = 0;\r
184 ServerCount = 0;\r
185 ServerList = NULL;\r
f75a7f56 186\r
d1050b9d 187 Status = This->Parse (This, Packet, &OptionCount, NULL);\r
99c048ef 188 if (Status != EFI_BUFFER_TOO_SMALL) {\r
189 return EFI_DEVICE_ERROR;\r
190 }\r
191\r
192 OptionList = AllocateZeroPool (OptionCount * sizeof (EFI_DHCP6_PACKET_OPTION *));\r
193 if (OptionList == NULL) {\r
194 return EFI_OUT_OF_RESOURCES;\r
195 }\r
196\r
197 Status = This->Parse (This, Packet, &OptionCount, OptionList);\r
198 if (EFI_ERROR (Status)) {\r
199 gBS->FreePool (OptionList);\r
200 return EFI_DEVICE_ERROR;\r
201 }\r
f75a7f56 202\r
d1050b9d 203 DnsServerInfor = (DNS6_SERVER_INFOR *)Context;\r
99c048ef 204\r
205 for (Index = 0; Index < OptionCount; Index++) {\r
206 OptionList[Index]->OpCode = NTOHS (OptionList[Index]->OpCode);\r
207 OptionList[Index]->OpLen = NTOHS (OptionList[Index]->OpLen);\r
208\r
209 //\r
210 // Get DNS server addresses from this reply packet.\r
211 //\r
212 if (OptionList[Index]->OpCode == DHCP6_TAG_DNS_SERVER) {\r
99c048ef 213 if (((OptionList[Index]->OpLen & 0xf) != 0) || (OptionList[Index]->OpLen == 0)) {\r
214 Status = EFI_DEVICE_ERROR;\r
215 gBS->FreePool (OptionList);\r
216 return Status;\r
217 }\r
f75a7f56 218\r
99c048ef 219 ServerCount = OptionList[Index]->OpLen/16;\r
d1050b9d 220 ServerList = AllocatePool (ServerCount * sizeof (EFI_IPv6_ADDRESS));\r
99c048ef 221 if (ServerList == NULL) {\r
222 gBS->FreePool (OptionList);\r
223 return EFI_OUT_OF_RESOURCES;\r
224 }\r
225\r
d1050b9d 226 for (Count = 0; Count < ServerCount; Count++) {\r
99c048ef 227 CopyMem (ServerList + Count, &OptionList[Index]->Data[16 * Count], sizeof (EFI_IPv6_ADDRESS));\r
228 }\r
229\r
230 *(DnsServerInfor->ServerCount) = ServerCount;\r
231 DnsServerInfor->ServerList = ServerList;\r
232 }\r
233 }\r
234\r
235 gBS->FreePool (OptionList);\r
f75a7f56 236\r
99c048ef 237 return Status;\r
99c048ef 238}\r
239\r
240/**\r
241 Parse the DHCP ACK to get Dns4 server information.\r
242\r
243 @param Instance The DNS instance.\r
244 @param DnsServerCount Retrieved Dns4 server Ip count.\r
245 @param DnsServerList Retrieved Dns4 server Ip list.\r
246\r
247 @retval EFI_SUCCESS The Dns4 information is got from the DHCP ACK.\r
248 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
249 @retval EFI_NO_MEDIA There was a media error.\r
250 @retval Others Other errors as indicated.\r
251\r
252**/\r
253EFI_STATUS\r
254GetDns4ServerFromDhcp4 (\r
d1050b9d
MK
255 IN DNS_INSTANCE *Instance,\r
256 OUT UINT32 *DnsServerCount,\r
257 OUT EFI_IPv4_ADDRESS **DnsServerList\r
99c048ef 258 )\r
259{\r
d1050b9d
MK
260 EFI_STATUS Status;\r
261 EFI_HANDLE Image;\r
262 EFI_HANDLE Controller;\r
263 EFI_STATUS MediaStatus;\r
264 EFI_HANDLE MnpChildHandle;\r
265 EFI_MANAGED_NETWORK_PROTOCOL *Mnp;\r
266 EFI_MANAGED_NETWORK_CONFIG_DATA MnpConfigData;\r
267 EFI_HANDLE Dhcp4Handle;\r
268 EFI_DHCP4_PROTOCOL *Dhcp4;\r
269 EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2;\r
270 UINTN DataSize;\r
271 VOID *Data;\r
272 EFI_IP4_CONFIG2_INTERFACE_INFO *InterfaceInfo;\r
273 EFI_DHCP4_PACKET SeedPacket;\r
274 EFI_DHCP4_PACKET_OPTION *ParaList[2];\r
275 DNS4_SERVER_INFOR DnsServerInfor;\r
276\r
277 EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN Token;\r
278 BOOLEAN IsDone;\r
279 UINTN Index;\r
280\r
281 Image = Instance->Service->ImageHandle;\r
282 Controller = Instance->Service->ControllerHandle;\r
283\r
284 MnpChildHandle = NULL;\r
285 Mnp = NULL;\r
286\r
287 Dhcp4Handle = NULL;\r
288 Dhcp4 = NULL;\r
289\r
290 Ip4Config2 = NULL;\r
291 DataSize = 0;\r
292 Data = NULL;\r
293 InterfaceInfo = NULL;\r
294\r
295 ZeroMem ((UINT8 *)ParaList, sizeof (ParaList));\r
3fd7bd08 296\r
99c048ef 297 ZeroMem (&MnpConfigData, sizeof (EFI_MANAGED_NETWORK_CONFIG_DATA));\r
f75a7f56 298\r
99c048ef 299 ZeroMem (&DnsServerInfor, sizeof (DNS4_SERVER_INFOR));\r
f75a7f56 300\r
99c048ef 301 ZeroMem (&Token, sizeof (EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN));\r
f75a7f56 302\r
99c048ef 303 DnsServerInfor.ServerCount = DnsServerCount;\r
304\r
305 IsDone = FALSE;\r
306\r
307 //\r
308 // Check media.\r
309 //\r
152f2d5e 310 MediaStatus = EFI_SUCCESS;\r
311 NetLibDetectMediaWaitTimeout (Controller, DNS_CHECK_MEDIA_GET_DHCP_WAITING_TIME, &MediaStatus);\r
312 if (MediaStatus != EFI_SUCCESS) {\r
99c048ef 313 return EFI_NO_MEDIA;\r
314 }\r
315\r
316 //\r
317 // Create a Mnp child instance, get the protocol and config for it.\r
318 //\r
319 Status = NetLibCreateServiceChild (\r
320 Controller,\r
321 Image,\r
322 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
323 &MnpChildHandle\r
324 );\r
325 if (EFI_ERROR (Status)) {\r
326 return Status;\r
327 }\r
328\r
329 Status = gBS->OpenProtocol (\r
330 MnpChildHandle,\r
331 &gEfiManagedNetworkProtocolGuid,\r
d1050b9d 332 (VOID **)&Mnp,\r
99c048ef 333 Image,\r
334 Controller,\r
335 EFI_OPEN_PROTOCOL_BY_DRIVER\r
336 );\r
337 if (EFI_ERROR (Status)) {\r
338 goto ON_EXIT;\r
339 }\r
f75a7f56 340\r
99c048ef 341 MnpConfigData.ReceivedQueueTimeoutValue = 0;\r
342 MnpConfigData.TransmitQueueTimeoutValue = 0;\r
343 MnpConfigData.ProtocolTypeFilter = IP4_ETHER_PROTO;\r
344 MnpConfigData.EnableUnicastReceive = TRUE;\r
345 MnpConfigData.EnableMulticastReceive = TRUE;\r
346 MnpConfigData.EnableBroadcastReceive = TRUE;\r
347 MnpConfigData.EnablePromiscuousReceive = FALSE;\r
348 MnpConfigData.FlushQueuesOnReset = TRUE;\r
349 MnpConfigData.EnableReceiveTimestamps = FALSE;\r
350 MnpConfigData.DisableBackgroundPolling = FALSE;\r
351\r
d1050b9d 352 Status = Mnp->Configure (Mnp, &MnpConfigData);\r
99c048ef 353 if (EFI_ERROR (Status)) {\r
354 goto ON_EXIT;\r
355 }\r
f75a7f56 356\r
99c048ef 357 //\r
358 // Create a DHCP4 child instance and get the protocol.\r
359 //\r
360 Status = NetLibCreateServiceChild (\r
361 Controller,\r
362 Image,\r
363 &gEfiDhcp4ServiceBindingProtocolGuid,\r
364 &Dhcp4Handle\r
365 );\r
366 if (EFI_ERROR (Status)) {\r
367 goto ON_EXIT;\r
368 }\r
369\r
370 Status = gBS->OpenProtocol (\r
371 Dhcp4Handle,\r
372 &gEfiDhcp4ProtocolGuid,\r
d1050b9d 373 (VOID **)&Dhcp4,\r
99c048ef 374 Image,\r
375 Controller,\r
376 EFI_OPEN_PROTOCOL_BY_DRIVER\r
377 );\r
378 if (EFI_ERROR (Status)) {\r
379 goto ON_EXIT;\r
380 }\r
381\r
382 //\r
383 // Get Ip4Config2 instance info.\r
384 //\r
d1050b9d 385 Status = gBS->HandleProtocol (Controller, &gEfiIp4Config2ProtocolGuid, (VOID **)&Ip4Config2);\r
99c048ef 386 if (EFI_ERROR (Status)) {\r
387 goto ON_EXIT;\r
388 }\r
f75a7f56 389\r
99c048ef 390 Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeInterfaceInfo, &DataSize, Data);\r
d1050b9d 391 if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {\r
99c048ef 392 goto ON_EXIT;\r
393 }\r
394\r
395 Data = AllocateZeroPool (DataSize);\r
396 if (Data == NULL) {\r
397 Status = EFI_OUT_OF_RESOURCES;\r
398 goto ON_EXIT;\r
399 }\r
400\r
401 Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeInterfaceInfo, &DataSize, Data);\r
402 if (EFI_ERROR (Status)) {\r
403 goto ON_EXIT;\r
404 }\r
405\r
406 InterfaceInfo = (EFI_IP4_CONFIG2_INTERFACE_INFO *)Data;\r
f75a7f56 407\r
99c048ef 408 //\r
409 // Build required Token.\r
410 //\r
411 Status = gBS->CreateEvent (\r
412 EVT_NOTIFY_SIGNAL,\r
413 TPL_NOTIFY,\r
414 DhcpCommonNotify,\r
415 &IsDone,\r
416 &Token.CompletionEvent\r
417 );\r
418 if (EFI_ERROR (Status)) {\r
419 goto ON_EXIT;\r
420 }\r
f75a7f56 421\r
99c048ef 422 SetMem (&Token.RemoteAddress, sizeof (EFI_IPv4_ADDRESS), 0xff);\r
f75a7f56 423\r
99c048ef 424 Token.RemotePort = 67;\r
425\r
426 Token.ListenPointCount = 1;\r
f75a7f56 427\r
99c048ef 428 Token.ListenPoints = AllocateZeroPool (Token.ListenPointCount * sizeof (EFI_DHCP4_LISTEN_POINT));\r
429 if (Token.ListenPoints == NULL) {\r
430 Status = EFI_OUT_OF_RESOURCES;\r
431 goto ON_EXIT;\r
432 }\r
433\r
434 if (Instance->Dns4CfgData.UseDefaultSetting) {\r
435 CopyMem (&(Token.ListenPoints[0].ListenAddress), &(InterfaceInfo->StationAddress), sizeof (EFI_IPv4_ADDRESS));\r
436 CopyMem (&(Token.ListenPoints[0].SubnetMask), &(InterfaceInfo->SubnetMask), sizeof (EFI_IPv4_ADDRESS));\r
437 } else {\r
438 CopyMem (&(Token.ListenPoints[0].ListenAddress), &(Instance->Dns4CfgData.StationIp), sizeof (EFI_IPv4_ADDRESS));\r
439 CopyMem (&(Token.ListenPoints[0].SubnetMask), &(Instance->Dns4CfgData.SubnetMask), sizeof (EFI_IPv4_ADDRESS));\r
440 }\r
f75a7f56 441\r
99c048ef 442 Token.ListenPoints[0].ListenPort = 68;\r
f75a7f56 443\r
99c048ef 444 Token.TimeoutValue = DNS_TIME_TO_GETMAP;\r
445\r
446 DnsInitSeedPacket (&SeedPacket, InterfaceInfo);\r
447\r
448 ParaList[0] = AllocateZeroPool (sizeof (EFI_DHCP4_PACKET_OPTION));\r
449 if (ParaList[0] == NULL) {\r
450 Status = EFI_OUT_OF_RESOURCES;\r
451 goto ON_EXIT;\r
452 }\r
f75a7f56 453\r
99c048ef 454 ParaList[0]->OpCode = DHCP4_TAG_TYPE;\r
455 ParaList[0]->Length = 1;\r
b61fda11 456 ParaList[0]->Data[0] = DHCP4_MSG_REQUEST;\r
f75a7f56 457\r
99c048ef 458 ParaList[1] = AllocateZeroPool (sizeof (EFI_DHCP4_PACKET_OPTION));\r
459 if (ParaList[1] == NULL) {\r
460 Status = EFI_OUT_OF_RESOURCES;\r
461 goto ON_EXIT;\r
462 }\r
f75a7f56 463\r
99c048ef 464 ParaList[1]->OpCode = DHCP4_TAG_PARA_LIST;\r
465 ParaList[1]->Length = 1;\r
466 ParaList[1]->Data[0] = DHCP4_TAG_DNS_SERVER;\r
467\r
f75a7f56 468 Status = Dhcp4->Build (Dhcp4, &SeedPacket, 0, NULL, 2, ParaList, &Token.Packet);\r
99c048ef 469\r
d1050b9d 470 Token.Packet->Dhcp4.Header.Xid = HTONL (NET_RANDOM (NetRandomInitSeed ()));\r
f75a7f56 471\r
99c048ef 472 Token.Packet->Dhcp4.Header.Reserved = HTONS ((UINT16)0x8000);\r
f75a7f56 473\r
99c048ef 474 if (Instance->Dns4CfgData.UseDefaultSetting) {\r
475 CopyMem (&(Token.Packet->Dhcp4.Header.ClientAddr), &(InterfaceInfo->StationAddress), sizeof (EFI_IPv4_ADDRESS));\r
476 } else {\r
477 CopyMem (&(Token.Packet->Dhcp4.Header.ClientAddr), &(Instance->Dns4CfgData.StationIp), sizeof (EFI_IPv4_ADDRESS));\r
478 }\r
f75a7f56
LG
479\r
480 CopyMem (Token.Packet->Dhcp4.Header.ClientHwAddr, &(InterfaceInfo->HwAddress), InterfaceInfo->HwAddressSize);\r
481\r
99c048ef 482 Token.Packet->Dhcp4.Header.HwAddrLen = (UINT8)(InterfaceInfo->HwAddressSize);\r
483\r
484 //\r
485 // TransmitReceive Token\r
486 //\r
487 Status = Dhcp4->TransmitReceive (Dhcp4, &Token);\r
488 if (EFI_ERROR (Status)) {\r
489 goto ON_EXIT;\r
490 }\r
491\r
492 //\r
493 // Poll the packet\r
494 //\r
495 do {\r
496 Status = Mnp->Poll (Mnp);\r
497 } while (!IsDone);\r
f75a7f56 498\r
99c048ef 499 //\r
500 // Parse the ACK to get required information if received done.\r
501 //\r
502 if (IsDone && !EFI_ERROR (Token.Status)) {\r
503 for (Index = 0; Index < Token.ResponseCount; Index++) {\r
504 Status = ParseDhcp4Ack (Dhcp4, &Token.ResponseList[Index], &DnsServerInfor);\r
505 if (!EFI_ERROR (Status)) {\r
506 break;\r
507 }\r
508 }\r
509\r
510 *DnsServerList = DnsServerInfor.ServerList;\r
511 } else {\r
512 Status = Token.Status;\r
513 }\r
f75a7f56 514\r
99c048ef 515ON_EXIT:\r
516\r
517 if (Data != NULL) {\r
518 FreePool (Data);\r
519 }\r
520\r
521 for (Index = 0; Index < 2; Index++) {\r
522 if (ParaList[Index] != NULL) {\r
523 FreePool (ParaList[Index]);\r
524 }\r
525 }\r
526\r
527 if (Token.ListenPoints) {\r
528 FreePool (Token.ListenPoints);\r
529 }\r
530\r
531 if (Token.Packet) {\r
532 FreePool (Token.Packet);\r
533 }\r
f75a7f56 534\r
99c048ef 535 if (Token.ResponseList != NULL) {\r
536 FreePool (Token.ResponseList);\r
537 }\r
f75a7f56 538\r
99c048ef 539 if (Token.CompletionEvent != NULL) {\r
540 gBS->CloseEvent (Token.CompletionEvent);\r
541 }\r
f75a7f56 542\r
99c048ef 543 if (Dhcp4 != NULL) {\r
544 Dhcp4->Stop (Dhcp4);\r
545 Dhcp4->Configure (Dhcp4, NULL);\r
546\r
547 gBS->CloseProtocol (\r
548 Dhcp4Handle,\r
549 &gEfiDhcp4ProtocolGuid,\r
550 Image,\r
551 Controller\r
552 );\r
553 }\r
f75a7f56 554\r
99c048ef 555 if (Dhcp4Handle != NULL) {\r
556 NetLibDestroyServiceChild (\r
557 Controller,\r
558 Image,\r
559 &gEfiDhcp4ServiceBindingProtocolGuid,\r
560 Dhcp4Handle\r
561 );\r
562 }\r
563\r
564 if (Mnp != NULL) {\r
565 Mnp->Configure (Mnp, NULL);\r
566\r
567 gBS->CloseProtocol (\r
568 MnpChildHandle,\r
569 &gEfiManagedNetworkProtocolGuid,\r
570 Image,\r
571 Controller\r
572 );\r
573 }\r
f75a7f56 574\r
99c048ef 575 NetLibDestroyServiceChild (\r
576 Controller,\r
577 Image,\r
578 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
579 MnpChildHandle\r
580 );\r
f75a7f56 581\r
99c048ef 582 return Status;\r
583}\r
584\r
585/**\r
586 Parse the DHCP ACK to get Dns6 server information.\r
587\r
588 @param Image The handle of the driver image.\r
589 @param Controller The handle of the controller.\r
590 @param DnsServerCount Retrieved Dns6 server Ip count.\r
591 @param DnsServerList Retrieved Dns6 server Ip list.\r
592\r
593 @retval EFI_SUCCESS The Dns6 information is got from the DHCP ACK.\r
594 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
595 @retval EFI_NO_MEDIA There was a media error.\r
596 @retval Others Other errors as indicated.\r
597\r
598**/\r
599EFI_STATUS\r
600GetDns6ServerFromDhcp6 (\r
d1050b9d
MK
601 IN EFI_HANDLE Image,\r
602 IN EFI_HANDLE Controller,\r
603 OUT UINT32 *DnsServerCount,\r
604 OUT EFI_IPv6_ADDRESS **DnsServerList\r
99c048ef 605 )\r
606{\r
607 EFI_HANDLE Dhcp6Handle;\r
608 EFI_DHCP6_PROTOCOL *Dhcp6;\r
609 EFI_STATUS Status;\r
610 EFI_STATUS TimerStatus;\r
611 EFI_DHCP6_PACKET_OPTION *Oro;\r
612 EFI_DHCP6_RETRANSMISSION InfoReqReXmit;\r
613 EFI_EVENT Timer;\r
152f2d5e 614 EFI_STATUS MediaStatus;\r
99c048ef 615 DNS6_SERVER_INFOR DnsServerInfor;\r
616\r
617 Dhcp6Handle = NULL;\r
618 Dhcp6 = NULL;\r
619 Oro = NULL;\r
620 Timer = NULL;\r
621\r
622 ZeroMem (&DnsServerInfor, sizeof (DNS6_SERVER_INFOR));\r
623\r
624 DnsServerInfor.ServerCount = DnsServerCount;\r
625\r
626 //\r
627 // Check media status before doing DHCP.\r
628 //\r
152f2d5e 629 MediaStatus = EFI_SUCCESS;\r
630 NetLibDetectMediaWaitTimeout (Controller, DNS_CHECK_MEDIA_GET_DHCP_WAITING_TIME, &MediaStatus);\r
631 if (MediaStatus != EFI_SUCCESS) {\r
99c048ef 632 return EFI_NO_MEDIA;\r
633 }\r
634\r
635 //\r
636 // Create a DHCP6 child instance and get the protocol.\r
637 //\r
638 Status = NetLibCreateServiceChild (\r
639 Controller,\r
640 Image,\r
641 &gEfiDhcp6ServiceBindingProtocolGuid,\r
642 &Dhcp6Handle\r
643 );\r
644 if (EFI_ERROR (Status)) {\r
645 return Status;\r
646 }\r
647\r
648 Status = gBS->OpenProtocol (\r
649 Dhcp6Handle,\r
650 &gEfiDhcp6ProtocolGuid,\r
d1050b9d 651 (VOID **)&Dhcp6,\r
99c048ef 652 Image,\r
653 Controller,\r
654 EFI_OPEN_PROTOCOL_BY_DRIVER\r
655 );\r
656 if (EFI_ERROR (Status)) {\r
657 goto ON_EXIT;\r
658 }\r
659\r
660 Oro = AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + 1);\r
661 if (Oro == NULL) {\r
662 Status = EFI_OUT_OF_RESOURCES;\r
663 goto ON_EXIT;\r
664 }\r
665\r
666 //\r
667 // Ask the server to reply with DNS options.\r
668 // All members in EFI_DHCP6_PACKET_OPTION are in network order.\r
669 //\r
670 Oro->OpCode = HTONS (DHCP6_TAG_DNS_REQUEST);\r
671 Oro->OpLen = HTONS (2);\r
672 Oro->Data[1] = DHCP6_TAG_DNS_SERVER;\r
673\r
674 InfoReqReXmit.Irt = 4;\r
675 InfoReqReXmit.Mrc = 1;\r
676 InfoReqReXmit.Mrt = 10;\r
677 InfoReqReXmit.Mrd = 30;\r
678\r
679 Status = Dhcp6->InfoRequest (\r
680 Dhcp6,\r
681 TRUE,\r
682 Oro,\r
683 0,\r
684 NULL,\r
685 &InfoReqReXmit,\r
686 NULL,\r
687 ParseDhcp6Ack,\r
688 &DnsServerInfor\r
689 );\r
690 if (Status == EFI_NO_MAPPING) {\r
691 Status = gBS->CreateEvent (EVT_TIMER, TPL_CALLBACK, NULL, NULL, &Timer);\r
692 if (EFI_ERROR (Status)) {\r
693 goto ON_EXIT;\r
694 }\r
695\r
696 Status = gBS->SetTimer (\r
697 Timer,\r
698 TimerRelative,\r
699 DNS_TIME_TO_GETMAP * TICKS_PER_SECOND\r
700 );\r
701\r
702 if (EFI_ERROR (Status)) {\r
703 goto ON_EXIT;\r
704 }\r
705\r
706 do {\r
707 TimerStatus = gBS->CheckEvent (Timer);\r
708 if (!EFI_ERROR (TimerStatus)) {\r
709 Status = Dhcp6->InfoRequest (\r
710 Dhcp6,\r
711 TRUE,\r
712 Oro,\r
713 0,\r
714 NULL,\r
715 &InfoReqReXmit,\r
716 NULL,\r
717 ParseDhcp6Ack,\r
718 &DnsServerInfor\r
719 );\r
720 }\r
721 } while (TimerStatus == EFI_NOT_READY);\r
722 }\r
f75a7f56 723\r
d1050b9d 724 *DnsServerList = DnsServerInfor.ServerList;\r
99c048ef 725\r
726ON_EXIT:\r
727\r
728 if (Oro != NULL) {\r
729 FreePool (Oro);\r
f75a7f56 730 }\r
99c048ef 731\r
732 if (Timer != NULL) {\r
733 gBS->CloseEvent (Timer);\r
734 }\r
735\r
736 if (Dhcp6 != NULL) {\r
737 gBS->CloseProtocol (\r
738 Dhcp6Handle,\r
739 &gEfiDhcp6ProtocolGuid,\r
740 Image,\r
741 Controller\r
742 );\r
743 }\r
744\r
745 NetLibDestroyServiceChild (\r
746 Controller,\r
747 Image,\r
748 &gEfiDhcp6ServiceBindingProtocolGuid,\r
749 Dhcp6Handle\r
750 );\r
751\r
752 return Status;\r
99c048ef 753}\r