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