1 /** @file 2 Functions implementation related with DHCPv4/v6 for DNS driver. 3 4 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT 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 **/ 26 VOID 27 DnsInitSeedPacket ( 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 **/ 57 VOID 58 EFIAPI 59 DhcpCommonNotify ( 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 **/ 84 EFI_STATUS 85 ParseDhcp4Ack ( 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 **/ 173 EFI_STATUS 174 EFIAPI 175 ParseDhcp6Ack ( 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 **/ 262 EFI_STATUS 263 GetDns4ServerFromDhcp4 ( 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 BOOLEAN MediaPresent; 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 MediaPresent = TRUE; 320 NetLibDetectMedia (Controller, &MediaPresent); 321 if (!MediaPresent) { 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_INFORM; 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 524 ON_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 **/ 608 EFI_STATUS 609 GetDns6ServerFromDhcp6 ( 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 BOOLEAN MediaPresent; 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 MediaPresent = TRUE; 639 NetLibDetectMedia (Controller, &MediaPresent); 640 if (!MediaPresent) { 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 735 ON_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 765