]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/DnsDxe/DnsDhcp.c
MdeModulePkg: Fix a bug that return type differs from the left one when assigned.
[mirror_edk2.git] / NetworkPkg / DnsDxe / DnsDhcp.c
CommitLineData
99c048ef 1/** @file\r
2Functions implementation related with DHCPv4/v6 for DNS driver.\r
3\r
4Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
5This software and associated documentation (if any) is furnished\r
6under a license and may only be used or copied in accordance\r
7with the terms of the license. Except as permitted by such\r
8license, no part of this software or documentation may be\r
9reproduced, stored in a retrieval system, or transmitted in any\r
10form or by any means without the express written consent of\r
11Intel Corporation.\r
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
51 The common notify function. \r
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
152 \r
153 return Status;\r
154}\r
155\r
156/**\r
157 EFI_DHCP6_INFO_CALLBACK is provided by the consumer of the EFI DHCPv6 Protocol \r
158 instance to intercept events that occurs in the DHCPv6 Information Request\r
159 exchange process.\r
160\r
161 @param This Pointer to the EFI_DHCP6_PROTOCOL instance that \r
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
189 \r
190 OptionCount = 0;\r
191 ServerCount = 0;\r
192 ServerList = NULL;\r
193 \r
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
209 \r
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
226 \r
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
244 \r
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
272 BOOLEAN MediaPresent;\r
273 EFI_HANDLE MnpChildHandle; \r
274 EFI_MANAGED_NETWORK_PROTOCOL *Mnp;\r
275 EFI_MANAGED_NETWORK_CONFIG_DATA MnpConfigData;\r
276 EFI_HANDLE Dhcp4Handle; \r
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
289 \r
290 Image = Instance->Service->ImageHandle;\r
291 Controller = Instance->Service->ControllerHandle;\r
292\r
293 MnpChildHandle = NULL;\r
294 Mnp = NULL;\r
295 \r
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
304 ZeroMem (&MnpConfigData, sizeof (EFI_MANAGED_NETWORK_CONFIG_DATA));\r
305 \r
306 ZeroMem (&DnsServerInfor, sizeof (DNS4_SERVER_INFOR));\r
307 \r
308 ZeroMem (&Token, sizeof (EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN));\r
309 \r
310 DnsServerInfor.ServerCount = DnsServerCount;\r
311\r
312 IsDone = FALSE;\r
313\r
314 //\r
315 // Check media.\r
316 //\r
317 MediaPresent = TRUE;\r
318 NetLibDetectMedia (Controller, &MediaPresent);\r
319 if (!MediaPresent) {\r
320 return EFI_NO_MEDIA;\r
321 }\r
322\r
323 //\r
324 // Create a Mnp child instance, get the protocol and config for it.\r
325 //\r
326 Status = NetLibCreateServiceChild (\r
327 Controller,\r
328 Image,\r
329 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
330 &MnpChildHandle\r
331 );\r
332 if (EFI_ERROR (Status)) {\r
333 return Status;\r
334 }\r
335\r
336 Status = gBS->OpenProtocol (\r
337 MnpChildHandle,\r
338 &gEfiManagedNetworkProtocolGuid,\r
339 (VOID **) &Mnp,\r
340 Image,\r
341 Controller,\r
342 EFI_OPEN_PROTOCOL_BY_DRIVER\r
343 );\r
344 if (EFI_ERROR (Status)) {\r
345 goto ON_EXIT;\r
346 }\r
347 \r
348 MnpConfigData.ReceivedQueueTimeoutValue = 0;\r
349 MnpConfigData.TransmitQueueTimeoutValue = 0;\r
350 MnpConfigData.ProtocolTypeFilter = IP4_ETHER_PROTO;\r
351 MnpConfigData.EnableUnicastReceive = TRUE;\r
352 MnpConfigData.EnableMulticastReceive = TRUE;\r
353 MnpConfigData.EnableBroadcastReceive = TRUE;\r
354 MnpConfigData.EnablePromiscuousReceive = FALSE;\r
355 MnpConfigData.FlushQueuesOnReset = TRUE;\r
356 MnpConfigData.EnableReceiveTimestamps = FALSE;\r
357 MnpConfigData.DisableBackgroundPolling = FALSE;\r
358\r
359 Status = Mnp->Configure(Mnp, &MnpConfigData);\r
360 if (EFI_ERROR (Status)) {\r
361 goto ON_EXIT;\r
362 }\r
363 \r
364 //\r
365 // Create a DHCP4 child instance and get the protocol.\r
366 //\r
367 Status = NetLibCreateServiceChild (\r
368 Controller,\r
369 Image,\r
370 &gEfiDhcp4ServiceBindingProtocolGuid,\r
371 &Dhcp4Handle\r
372 );\r
373 if (EFI_ERROR (Status)) {\r
374 goto ON_EXIT;\r
375 }\r
376\r
377 Status = gBS->OpenProtocol (\r
378 Dhcp4Handle,\r
379 &gEfiDhcp4ProtocolGuid,\r
380 (VOID **) &Dhcp4,\r
381 Image,\r
382 Controller,\r
383 EFI_OPEN_PROTOCOL_BY_DRIVER\r
384 );\r
385 if (EFI_ERROR (Status)) {\r
386 goto ON_EXIT;\r
387 }\r
388\r
389 //\r
390 // Get Ip4Config2 instance info.\r
391 //\r
392 Status = gBS->HandleProtocol (Controller, &gEfiIp4Config2ProtocolGuid, (VOID **) &Ip4Config2);\r
393 if (EFI_ERROR (Status)) {\r
394 goto ON_EXIT;\r
395 }\r
396 \r
397 Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeInterfaceInfo, &DataSize, Data);\r
398 if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
399 goto ON_EXIT;\r
400 }\r
401\r
402 Data = AllocateZeroPool (DataSize);\r
403 if (Data == NULL) {\r
404 Status = EFI_OUT_OF_RESOURCES;\r
405 goto ON_EXIT;\r
406 }\r
407\r
408 Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeInterfaceInfo, &DataSize, Data);\r
409 if (EFI_ERROR (Status)) {\r
410 goto ON_EXIT;\r
411 }\r
412\r
413 InterfaceInfo = (EFI_IP4_CONFIG2_INTERFACE_INFO *)Data;\r
414 \r
415 //\r
416 // Build required Token.\r
417 //\r
418 Status = gBS->CreateEvent (\r
419 EVT_NOTIFY_SIGNAL,\r
420 TPL_NOTIFY,\r
421 DhcpCommonNotify,\r
422 &IsDone,\r
423 &Token.CompletionEvent\r
424 );\r
425 if (EFI_ERROR (Status)) {\r
426 goto ON_EXIT;\r
427 }\r
428 \r
429 SetMem (&Token.RemoteAddress, sizeof (EFI_IPv4_ADDRESS), 0xff);\r
430 \r
431 Token.RemotePort = 67;\r
432\r
433 Token.ListenPointCount = 1;\r
434 \r
435 Token.ListenPoints = AllocateZeroPool (Token.ListenPointCount * sizeof (EFI_DHCP4_LISTEN_POINT));\r
436 if (Token.ListenPoints == NULL) {\r
437 Status = EFI_OUT_OF_RESOURCES;\r
438 goto ON_EXIT;\r
439 }\r
440\r
441 if (Instance->Dns4CfgData.UseDefaultSetting) {\r
442 CopyMem (&(Token.ListenPoints[0].ListenAddress), &(InterfaceInfo->StationAddress), sizeof (EFI_IPv4_ADDRESS));\r
443 CopyMem (&(Token.ListenPoints[0].SubnetMask), &(InterfaceInfo->SubnetMask), sizeof (EFI_IPv4_ADDRESS));\r
444 } else {\r
445 CopyMem (&(Token.ListenPoints[0].ListenAddress), &(Instance->Dns4CfgData.StationIp), sizeof (EFI_IPv4_ADDRESS));\r
446 CopyMem (&(Token.ListenPoints[0].SubnetMask), &(Instance->Dns4CfgData.SubnetMask), sizeof (EFI_IPv4_ADDRESS));\r
447 }\r
448 \r
449 Token.ListenPoints[0].ListenPort = 68;\r
450 \r
451 Token.TimeoutValue = DNS_TIME_TO_GETMAP;\r
452\r
453 DnsInitSeedPacket (&SeedPacket, InterfaceInfo);\r
454\r
455 ParaList[0] = AllocateZeroPool (sizeof (EFI_DHCP4_PACKET_OPTION));\r
456 if (ParaList[0] == NULL) {\r
457 Status = EFI_OUT_OF_RESOURCES;\r
458 goto ON_EXIT;\r
459 }\r
460 \r
461 ParaList[0]->OpCode = DHCP4_TAG_TYPE;\r
462 ParaList[0]->Length = 1;\r
463 ParaList[0]->Data[0] = DHCP4_MSG_INFORM;\r
464 \r
465 ParaList[1] = AllocateZeroPool (sizeof (EFI_DHCP4_PACKET_OPTION));\r
466 if (ParaList[1] == NULL) {\r
467 Status = EFI_OUT_OF_RESOURCES;\r
468 goto ON_EXIT;\r
469 }\r
470 \r
471 ParaList[1]->OpCode = DHCP4_TAG_PARA_LIST;\r
472 ParaList[1]->Length = 1;\r
473 ParaList[1]->Data[0] = DHCP4_TAG_DNS_SERVER;\r
474\r
475 Status = Dhcp4->Build (Dhcp4, &SeedPacket, 0, NULL, 2, ParaList, &Token.Packet); \r
476\r
477 Token.Packet->Dhcp4.Header.Xid = HTONL(NET_RANDOM (NetRandomInitSeed ()));\r
478 \r
479 Token.Packet->Dhcp4.Header.Reserved = HTONS ((UINT16)0x8000);\r
480 \r
481 if (Instance->Dns4CfgData.UseDefaultSetting) {\r
482 CopyMem (&(Token.Packet->Dhcp4.Header.ClientAddr), &(InterfaceInfo->StationAddress), sizeof (EFI_IPv4_ADDRESS));\r
483 } else {\r
484 CopyMem (&(Token.Packet->Dhcp4.Header.ClientAddr), &(Instance->Dns4CfgData.StationIp), sizeof (EFI_IPv4_ADDRESS));\r
485 }\r
486 \r
487 CopyMem (Token.Packet->Dhcp4.Header.ClientHwAddr, &(InterfaceInfo->HwAddress), InterfaceInfo->HwAddressSize); \r
488 \r
489 Token.Packet->Dhcp4.Header.HwAddrLen = (UINT8)(InterfaceInfo->HwAddressSize);\r
490\r
491 //\r
492 // TransmitReceive Token\r
493 //\r
494 Status = Dhcp4->TransmitReceive (Dhcp4, &Token);\r
495 if (EFI_ERROR (Status)) {\r
496 goto ON_EXIT;\r
497 }\r
498\r
499 //\r
500 // Poll the packet\r
501 //\r
502 do {\r
503 Status = Mnp->Poll (Mnp);\r
504 } while (!IsDone);\r
505 \r
506 //\r
507 // Parse the ACK to get required information if received done.\r
508 //\r
509 if (IsDone && !EFI_ERROR (Token.Status)) {\r
510 for (Index = 0; Index < Token.ResponseCount; Index++) {\r
511 Status = ParseDhcp4Ack (Dhcp4, &Token.ResponseList[Index], &DnsServerInfor);\r
512 if (!EFI_ERROR (Status)) {\r
513 break;\r
514 }\r
515 }\r
516\r
517 *DnsServerList = DnsServerInfor.ServerList;\r
518 } else {\r
519 Status = Token.Status;\r
520 }\r
521 \r
522ON_EXIT:\r
523\r
524 if (Data != NULL) {\r
525 FreePool (Data);\r
526 }\r
527\r
528 for (Index = 0; Index < 2; Index++) {\r
529 if (ParaList[Index] != NULL) {\r
530 FreePool (ParaList[Index]);\r
531 }\r
532 }\r
533\r
534 if (Token.ListenPoints) {\r
535 FreePool (Token.ListenPoints);\r
536 }\r
537\r
538 if (Token.Packet) {\r
539 FreePool (Token.Packet);\r
540 }\r
541 \r
542 if (Token.ResponseList != NULL) {\r
543 FreePool (Token.ResponseList);\r
544 }\r
545 \r
546 if (Token.CompletionEvent != NULL) {\r
547 gBS->CloseEvent (Token.CompletionEvent);\r
548 }\r
549 \r
550 if (Dhcp4 != NULL) {\r
551 Dhcp4->Stop (Dhcp4);\r
552 Dhcp4->Configure (Dhcp4, NULL);\r
553\r
554 gBS->CloseProtocol (\r
555 Dhcp4Handle,\r
556 &gEfiDhcp4ProtocolGuid,\r
557 Image,\r
558 Controller\r
559 );\r
560 }\r
561 \r
562 if (Dhcp4Handle != NULL) {\r
563 NetLibDestroyServiceChild (\r
564 Controller,\r
565 Image,\r
566 &gEfiDhcp4ServiceBindingProtocolGuid,\r
567 Dhcp4Handle\r
568 );\r
569 }\r
570\r
571 if (Mnp != NULL) {\r
572 Mnp->Configure (Mnp, NULL);\r
573\r
574 gBS->CloseProtocol (\r
575 MnpChildHandle,\r
576 &gEfiManagedNetworkProtocolGuid,\r
577 Image,\r
578 Controller\r
579 );\r
580 }\r
581 \r
582 NetLibDestroyServiceChild (\r
583 Controller,\r
584 Image,\r
585 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
586 MnpChildHandle\r
587 );\r
588 \r
589 return Status;\r
590}\r
591\r
592/**\r
593 Parse the DHCP ACK to get Dns6 server information.\r
594\r
595 @param Image The handle of the driver image.\r
596 @param Controller The handle of the controller.\r
597 @param DnsServerCount Retrieved Dns6 server Ip count.\r
598 @param DnsServerList Retrieved Dns6 server Ip list.\r
599\r
600 @retval EFI_SUCCESS The Dns6 information is got from the DHCP ACK.\r
601 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
602 @retval EFI_NO_MEDIA There was a media error.\r
603 @retval Others Other errors as indicated.\r
604\r
605**/\r
606EFI_STATUS\r
607GetDns6ServerFromDhcp6 (\r
608 IN EFI_HANDLE Image,\r
609 IN EFI_HANDLE Controller,\r
610 OUT UINT32 *DnsServerCount,\r
611 OUT EFI_IPv6_ADDRESS **DnsServerList\r
612 )\r
613{\r
614 EFI_HANDLE Dhcp6Handle;\r
615 EFI_DHCP6_PROTOCOL *Dhcp6;\r
616 EFI_STATUS Status;\r
617 EFI_STATUS TimerStatus;\r
618 EFI_DHCP6_PACKET_OPTION *Oro;\r
619 EFI_DHCP6_RETRANSMISSION InfoReqReXmit;\r
620 EFI_EVENT Timer;\r
621 BOOLEAN MediaPresent;\r
622 DNS6_SERVER_INFOR DnsServerInfor;\r
623\r
624 Dhcp6Handle = NULL;\r
625 Dhcp6 = NULL;\r
626 Oro = NULL;\r
627 Timer = NULL;\r
628\r
629 ZeroMem (&DnsServerInfor, sizeof (DNS6_SERVER_INFOR));\r
630\r
631 DnsServerInfor.ServerCount = DnsServerCount;\r
632\r
633 //\r
634 // Check media status before doing DHCP.\r
635 //\r
636 MediaPresent = TRUE;\r
637 NetLibDetectMedia (Controller, &MediaPresent);\r
638 if (!MediaPresent) {\r
639 return EFI_NO_MEDIA;\r
640 }\r
641\r
642 //\r
643 // Create a DHCP6 child instance and get the protocol.\r
644 //\r
645 Status = NetLibCreateServiceChild (\r
646 Controller,\r
647 Image,\r
648 &gEfiDhcp6ServiceBindingProtocolGuid,\r
649 &Dhcp6Handle\r
650 );\r
651 if (EFI_ERROR (Status)) {\r
652 return Status;\r
653 }\r
654\r
655 Status = gBS->OpenProtocol (\r
656 Dhcp6Handle,\r
657 &gEfiDhcp6ProtocolGuid,\r
658 (VOID **) &Dhcp6,\r
659 Image,\r
660 Controller,\r
661 EFI_OPEN_PROTOCOL_BY_DRIVER\r
662 );\r
663 if (EFI_ERROR (Status)) {\r
664 goto ON_EXIT;\r
665 }\r
666\r
667 Oro = AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + 1);\r
668 if (Oro == NULL) {\r
669 Status = EFI_OUT_OF_RESOURCES;\r
670 goto ON_EXIT;\r
671 }\r
672\r
673 //\r
674 // Ask the server to reply with DNS options.\r
675 // All members in EFI_DHCP6_PACKET_OPTION are in network order.\r
676 //\r
677 Oro->OpCode = HTONS (DHCP6_TAG_DNS_REQUEST);\r
678 Oro->OpLen = HTONS (2);\r
679 Oro->Data[1] = DHCP6_TAG_DNS_SERVER;\r
680\r
681 InfoReqReXmit.Irt = 4;\r
682 InfoReqReXmit.Mrc = 1;\r
683 InfoReqReXmit.Mrt = 10;\r
684 InfoReqReXmit.Mrd = 30;\r
685\r
686 Status = Dhcp6->InfoRequest (\r
687 Dhcp6,\r
688 TRUE,\r
689 Oro,\r
690 0,\r
691 NULL,\r
692 &InfoReqReXmit,\r
693 NULL,\r
694 ParseDhcp6Ack,\r
695 &DnsServerInfor\r
696 );\r
697 if (Status == EFI_NO_MAPPING) {\r
698 Status = gBS->CreateEvent (EVT_TIMER, TPL_CALLBACK, NULL, NULL, &Timer);\r
699 if (EFI_ERROR (Status)) {\r
700 goto ON_EXIT;\r
701 }\r
702\r
703 Status = gBS->SetTimer (\r
704 Timer,\r
705 TimerRelative,\r
706 DNS_TIME_TO_GETMAP * TICKS_PER_SECOND\r
707 );\r
708\r
709 if (EFI_ERROR (Status)) {\r
710 goto ON_EXIT;\r
711 }\r
712\r
713 do {\r
714 TimerStatus = gBS->CheckEvent (Timer);\r
715 if (!EFI_ERROR (TimerStatus)) {\r
716 Status = Dhcp6->InfoRequest (\r
717 Dhcp6,\r
718 TRUE,\r
719 Oro,\r
720 0,\r
721 NULL,\r
722 &InfoReqReXmit,\r
723 NULL,\r
724 ParseDhcp6Ack,\r
725 &DnsServerInfor\r
726 );\r
727 }\r
728 } while (TimerStatus == EFI_NOT_READY);\r
729 }\r
730 \r
731 *DnsServerList = DnsServerInfor.ServerList;\r
732\r
733ON_EXIT:\r
734\r
735 if (Oro != NULL) {\r
736 FreePool (Oro);\r
737 } \r
738\r
739 if (Timer != NULL) {\r
740 gBS->CloseEvent (Timer);\r
741 }\r
742\r
743 if (Dhcp6 != NULL) {\r
744 gBS->CloseProtocol (\r
745 Dhcp6Handle,\r
746 &gEfiDhcp6ProtocolGuid,\r
747 Image,\r
748 Controller\r
749 );\r
750 }\r
751\r
752 NetLibDestroyServiceChild (\r
753 Controller,\r
754 Image,\r
755 &gEfiDhcp6ServiceBindingProtocolGuid,\r
756 Dhcp6Handle\r
757 );\r
758\r
759 return Status;\r
760 \r
761}\r
762\r