VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/NetworkPkg/DnsDxe/DnsDhcp.c@ 109193

Last change on this file since 109193 was 105670, checked in by vboxsync, 10 months ago

Devices/EFI/FirmwareNew: Merge edk2-stable-202405 and make it build on aarch64, bugref:4643

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette