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