VirtualBox

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

最後變更 在這個檔案從77662是 77662,由 vboxsync 提交於 6 年 前

EFI: First step in UDK2018 merge. Does not build yet.

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

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