1 /** @file 2 DnsDxe support functions implementation. 3 4 Copyright (c) 2016, 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 Remove TokenEntry from TokenMap. 19 20 @param[in] TokenMap All DNSv4 Token entrys. 21 @param[in] TokenEntry TokenEntry need to be removed. 22 23 @retval EFI_SUCCESS Remove TokenEntry from TokenMap sucessfully. 24 @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap. 25 26 **/ 27 EFI_STATUS 28 Dns4RemoveTokenEntry ( 29 IN NET_MAP *TokenMap, 30 IN DNS4_TOKEN_ENTRY *TokenEntry 31 ) 32 { 33 NET_MAP_ITEM *Item; 34 35 // 36 // Find the TokenEntry first. 37 // 38 Item = NetMapFindKey (TokenMap, (VOID *) TokenEntry); 39 40 if (Item != NULL) { 41 // 42 // Remove the TokenEntry if it's found in the map. 43 // 44 NetMapRemoveItem (TokenMap, Item, NULL); 45 46 return EFI_SUCCESS; 47 } 48 49 return EFI_NOT_FOUND; 50 } 51 52 /** 53 Remove TokenEntry from TokenMap. 54 55 @param[in] TokenMap All DNSv6 Token entrys. 56 @param[in] TokenEntry TokenEntry need to be removed. 57 58 @retval EFI_SUCCESS Remove TokenEntry from TokenMap sucessfully. 59 @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap. 60 61 **/ 62 EFI_STATUS 63 Dns6RemoveTokenEntry ( 64 IN NET_MAP *TokenMap, 65 IN DNS6_TOKEN_ENTRY *TokenEntry 66 ) 67 { 68 NET_MAP_ITEM *Item; 69 70 // 71 // Find the TokenEntry first. 72 // 73 Item = NetMapFindKey (TokenMap, (VOID *) TokenEntry); 74 75 if (Item != NULL) { 76 // 77 // Remove the TokenEntry if it's found in the map. 78 // 79 NetMapRemoveItem (TokenMap, Item, NULL); 80 81 return EFI_SUCCESS; 82 } 83 84 return EFI_NOT_FOUND; 85 } 86 87 /** 88 This function cancle the token specified by Arg in the Map. 89 90 @param[in] Map Pointer to the NET_MAP. 91 @param[in] Item Pointer to the NET_MAP_ITEM. 92 @param[in] Arg Pointer to the token to be cancelled. If NULL, all 93 the tokens in this Map will be cancelled. 94 This parameter is optional and may be NULL. 95 96 @retval EFI_SUCCESS The token is cancelled if Arg is NULL, or the token 97 is not the same as that in the Item, if Arg is not 98 NULL. 99 @retval EFI_ABORTED Arg is not NULL, and the token specified by Arg is 100 cancelled. 101 102 **/ 103 EFI_STATUS 104 EFIAPI 105 Dns4CancelTokens ( 106 IN NET_MAP *Map, 107 IN NET_MAP_ITEM *Item, 108 IN VOID *Arg OPTIONAL 109 ) 110 { 111 DNS4_TOKEN_ENTRY *TokenEntry; 112 NET_BUF *Packet; 113 UDP_IO *UdpIo; 114 115 if ((Arg != NULL) && (Item->Key != Arg)) { 116 return EFI_SUCCESS; 117 } 118 119 if (Item->Value != NULL) { 120 // 121 // If the TokenEntry is a transmit TokenEntry, the corresponding Packet is recorded in 122 // Item->Value. 123 // 124 Packet = (NET_BUF *) (Item->Value); 125 UdpIo = (UDP_IO *) (*((UINTN *) &Packet->ProtoData[0])); 126 127 UdpIoCancelSentDatagram (UdpIo, Packet); 128 } 129 130 // 131 // Remove TokenEntry from Dns4TxTokens. 132 // 133 TokenEntry = (DNS4_TOKEN_ENTRY *) Item->Key; 134 if (Dns4RemoveTokenEntry (Map, TokenEntry) == EFI_SUCCESS) { 135 TokenEntry->Token->Status = EFI_ABORTED; 136 gBS->SignalEvent (TokenEntry->Token->Event); 137 DispatchDpc (); 138 } 139 140 if (Arg != NULL) { 141 return EFI_ABORTED; 142 } 143 144 return EFI_SUCCESS; 145 } 146 147 /** 148 This function cancle the token specified by Arg in the Map. 149 150 @param[in] Map Pointer to the NET_MAP. 151 @param[in] Item Pointer to the NET_MAP_ITEM. 152 @param[in] Arg Pointer to the token to be cancelled. If NULL, all 153 the tokens in this Map will be cancelled. 154 This parameter is optional and may be NULL. 155 156 @retval EFI_SUCCESS The token is cancelled if Arg is NULL, or the token 157 is not the same as that in the Item, if Arg is not 158 NULL. 159 @retval EFI_ABORTED Arg is not NULL, and the token specified by Arg is 160 cancelled. 161 162 **/ 163 EFI_STATUS 164 EFIAPI 165 Dns6CancelTokens ( 166 IN NET_MAP *Map, 167 IN NET_MAP_ITEM *Item, 168 IN VOID *Arg OPTIONAL 169 ) 170 { 171 DNS6_TOKEN_ENTRY *TokenEntry; 172 NET_BUF *Packet; 173 UDP_IO *UdpIo; 174 175 if ((Arg != NULL) && (Item->Key != Arg)) { 176 return EFI_SUCCESS; 177 } 178 179 if (Item->Value != NULL) { 180 // 181 // If the TokenEntry is a transmit TokenEntry, the corresponding Packet is recorded in 182 // Item->Value. 183 // 184 Packet = (NET_BUF *) (Item->Value); 185 UdpIo = (UDP_IO *) (*((UINTN *) &Packet->ProtoData[0])); 186 187 UdpIoCancelSentDatagram (UdpIo, Packet); 188 } 189 190 // 191 // Remove TokenEntry from Dns6TxTokens. 192 // 193 TokenEntry = (DNS6_TOKEN_ENTRY *) Item->Key; 194 if (Dns6RemoveTokenEntry (Map, TokenEntry) == EFI_SUCCESS) { 195 TokenEntry->Token->Status = EFI_ABORTED; 196 gBS->SignalEvent (TokenEntry->Token->Event); 197 DispatchDpc (); 198 } 199 200 if (Arg != NULL) { 201 return EFI_ABORTED; 202 } 203 204 return EFI_SUCCESS; 205 } 206 207 /** 208 Get the TokenEntry from the TokensMap. 209 210 @param[in] TokensMap All DNSv4 Token entrys 211 @param[in] Token Pointer to the token to be get. 212 @param[out] TokenEntry Pointer to TokenEntry corresponding Token. 213 214 @retval EFI_SUCCESS Get the TokenEntry from the TokensMap sucessfully. 215 @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap. 216 217 **/ 218 EFI_STATUS 219 EFIAPI 220 GetDns4TokenEntry ( 221 IN NET_MAP *TokensMap, 222 IN EFI_DNS4_COMPLETION_TOKEN *Token, 223 OUT DNS4_TOKEN_ENTRY **TokenEntry 224 ) 225 { 226 LIST_ENTRY *Entry; 227 228 NET_MAP_ITEM *Item; 229 230 NET_LIST_FOR_EACH (Entry, &TokensMap->Used) { 231 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link); 232 *TokenEntry = (DNS4_TOKEN_ENTRY *) (Item->Key); 233 if ((*TokenEntry)->Token == Token) { 234 return EFI_SUCCESS; 235 } 236 } 237 238 *TokenEntry = NULL; 239 240 return EFI_NOT_FOUND; 241 } 242 243 /** 244 Get the TokenEntry from the TokensMap. 245 246 @param[in] TokensMap All DNSv6 Token entrys 247 @param[in] Token Pointer to the token to be get. 248 @param[out] TokenEntry Pointer to TokenEntry corresponding Token. 249 250 @retval EFI_SUCCESS Get the TokenEntry from the TokensMap sucessfully. 251 @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap. 252 253 **/ 254 EFI_STATUS 255 EFIAPI 256 GetDns6TokenEntry ( 257 IN NET_MAP *TokensMap, 258 IN EFI_DNS6_COMPLETION_TOKEN *Token, 259 OUT DNS6_TOKEN_ENTRY **TokenEntry 260 ) 261 { 262 LIST_ENTRY *Entry; 263 264 NET_MAP_ITEM *Item; 265 266 NET_LIST_FOR_EACH (Entry, &TokensMap->Used) { 267 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link); 268 *TokenEntry = (DNS6_TOKEN_ENTRY *) (Item->Key); 269 if ((*TokenEntry)->Token == Token) { 270 return EFI_SUCCESS; 271 } 272 } 273 274 *TokenEntry =NULL; 275 276 return EFI_NOT_FOUND; 277 } 278 279 /** 280 Cancel DNS4 tokens from the DNS4 instance. 281 282 @param[in] Instance Pointer to the DNS instance context data. 283 @param[in] Token Pointer to the token to be canceled. If NULL, all 284 tokens in this instance will be cancelled. 285 This parameter is optional and may be NULL. 286 287 @retval EFI_SUCCESS The Token is cancelled. 288 @retval EFI_NOT_FOUND The Token is not found. 289 290 **/ 291 EFI_STATUS 292 Dns4InstanceCancelToken ( 293 IN DNS_INSTANCE *Instance, 294 IN EFI_DNS4_COMPLETION_TOKEN *Token 295 ) 296 { 297 EFI_STATUS Status; 298 DNS4_TOKEN_ENTRY *TokenEntry; 299 300 TokenEntry = NULL; 301 302 if(Token != NULL ) { 303 Status = GetDns4TokenEntry (&Instance->Dns4TxTokens, Token, &TokenEntry); 304 if (EFI_ERROR (Status)) { 305 return Status; 306 } 307 } else { 308 TokenEntry = NULL; 309 } 310 311 // 312 // Cancel this TokenEntry from the Dns4TxTokens map. 313 // 314 Status = NetMapIterate (&Instance->Dns4TxTokens, Dns4CancelTokens, TokenEntry); 315 316 if ((TokenEntry != NULL) && (Status == EFI_ABORTED)) { 317 // 318 // If Token isn't NULL and Status is EFI_ABORTED, the token is cancelled from 319 // the Dns4TxTokens and returns success. 320 // 321 if (NetMapIsEmpty (&Instance->Dns4TxTokens)) { 322 Instance->UdpIo->Protocol.Udp4->Cancel (Instance->UdpIo->Protocol.Udp4, &Instance->UdpIo->RecvRequest->Token.Udp4); 323 } 324 return EFI_SUCCESS; 325 } 326 327 ASSERT ((TokenEntry != NULL) || (0 == NetMapGetCount (&Instance->Dns4TxTokens))); 328 329 if (NetMapIsEmpty (&Instance->Dns4TxTokens)) { 330 Instance->UdpIo->Protocol.Udp4->Cancel (Instance->UdpIo->Protocol.Udp4, &Instance->UdpIo->RecvRequest->Token.Udp4); 331 } 332 333 return EFI_SUCCESS; 334 } 335 336 /** 337 Cancel DNS6 tokens from the DNS6 instance. 338 339 @param[in] Instance Pointer to the DNS instance context data. 340 @param[in] Token Pointer to the token to be canceled. If NULL, all 341 tokens in this instance will be cancelled. 342 This parameter is optional and may be NULL. 343 344 @retval EFI_SUCCESS The Token is cancelled. 345 @retval EFI_NOT_FOUND The Token is not found. 346 347 **/ 348 EFI_STATUS 349 Dns6InstanceCancelToken ( 350 IN DNS_INSTANCE *Instance, 351 IN EFI_DNS6_COMPLETION_TOKEN *Token 352 ) 353 { 354 EFI_STATUS Status; 355 DNS6_TOKEN_ENTRY *TokenEntry; 356 357 TokenEntry = NULL; 358 359 if(Token != NULL ) { 360 Status = GetDns6TokenEntry (&Instance->Dns6TxTokens, Token, &TokenEntry); 361 if (EFI_ERROR (Status)) { 362 return Status; 363 } 364 } else { 365 TokenEntry = NULL; 366 } 367 368 // 369 // Cancel this TokenEntry from the Dns6TxTokens map. 370 // 371 Status = NetMapIterate (&Instance->Dns6TxTokens, Dns6CancelTokens, TokenEntry); 372 373 if ((TokenEntry != NULL) && (Status == EFI_ABORTED)) { 374 // 375 // If Token isn't NULL and Status is EFI_ABORTED, the token is cancelled from 376 // the Dns6TxTokens and returns success. 377 // 378 if (NetMapIsEmpty (&Instance->Dns6TxTokens)) { 379 Instance->UdpIo->Protocol.Udp6->Cancel (Instance->UdpIo->Protocol.Udp6, &Instance->UdpIo->RecvRequest->Token.Udp6); 380 } 381 return EFI_SUCCESS; 382 } 383 384 ASSERT ((TokenEntry != NULL) || (0 == NetMapGetCount (&Instance->Dns6TxTokens))); 385 386 if (NetMapIsEmpty (&Instance->Dns6TxTokens)) { 387 Instance->UdpIo->Protocol.Udp6->Cancel (Instance->UdpIo->Protocol.Udp6, &Instance->UdpIo->RecvRequest->Token.Udp6); 388 } 389 390 return EFI_SUCCESS; 391 } 392 393 /** 394 Free the resource related to the configure parameters. 395 396 @param Config The DNS configure data 397 398 **/ 399 VOID 400 Dns4CleanConfigure ( 401 IN OUT EFI_DNS4_CONFIG_DATA *Config 402 ) 403 { 404 if (Config->DnsServerList != NULL) { 405 FreePool (Config->DnsServerList); 406 } 407 408 ZeroMem (Config, sizeof (EFI_DNS4_CONFIG_DATA)); 409 } 410 411 /** 412 Free the resource related to the configure parameters. 413 414 @param Config The DNS configure data 415 416 **/ 417 VOID 418 Dns6CleanConfigure ( 419 IN OUT EFI_DNS6_CONFIG_DATA *Config 420 ) 421 { 422 if (Config->DnsServerList != NULL) { 423 FreePool (Config->DnsServerList); 424 } 425 426 ZeroMem (Config, sizeof (EFI_DNS6_CONFIG_DATA)); 427 } 428 429 /** 430 Allocate memory for configure parameter such as timeout value for Dst, 431 then copy the configure parameter from Src to Dst. 432 433 @param[out] Dst The destination DHCP configure data. 434 @param[in] Src The source DHCP configure data. 435 436 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. 437 @retval EFI_SUCCESS The configure is copied. 438 439 **/ 440 EFI_STATUS 441 Dns4CopyConfigure ( 442 OUT EFI_DNS4_CONFIG_DATA *Dst, 443 IN EFI_DNS4_CONFIG_DATA *Src 444 ) 445 { 446 UINTN Len; 447 UINT32 Index; 448 449 CopyMem (Dst, Src, sizeof (*Dst)); 450 Dst->DnsServerList = NULL; 451 452 // 453 // Allocate a memory then copy DnsServerList to it 454 // 455 if (Src->DnsServerList != NULL) { 456 Len = Src->DnsServerListCount * sizeof (EFI_IPv4_ADDRESS); 457 Dst->DnsServerList = AllocatePool (Len); 458 if (Dst->DnsServerList == NULL) { 459 Dns4CleanConfigure (Dst); 460 return EFI_OUT_OF_RESOURCES; 461 } 462 463 for (Index = 0; Index < Src->DnsServerListCount; Index++) { 464 CopyMem (&Dst->DnsServerList[Index], &Src->DnsServerList[Index], sizeof (EFI_IPv4_ADDRESS)); 465 } 466 } 467 468 return EFI_SUCCESS; 469 } 470 471 /** 472 Allocate memory for configure parameter such as timeout value for Dst, 473 then copy the configure parameter from Src to Dst. 474 475 @param[out] Dst The destination DHCP configure data. 476 @param[in] Src The source DHCP configure data. 477 478 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. 479 @retval EFI_SUCCESS The configure is copied. 480 481 **/ 482 EFI_STATUS 483 Dns6CopyConfigure ( 484 OUT EFI_DNS6_CONFIG_DATA *Dst, 485 IN EFI_DNS6_CONFIG_DATA *Src 486 ) 487 { 488 UINTN Len; 489 UINT32 Index; 490 491 CopyMem (Dst, Src, sizeof (*Dst)); 492 Dst->DnsServerList = NULL; 493 494 // 495 // Allocate a memory then copy DnsServerList to it 496 // 497 if (Src->DnsServerList != NULL) { 498 Len = Src->DnsServerCount * sizeof (EFI_IPv6_ADDRESS); 499 Dst->DnsServerList = AllocatePool (Len); 500 if (Dst->DnsServerList == NULL) { 501 Dns6CleanConfigure (Dst); 502 return EFI_OUT_OF_RESOURCES; 503 } 504 505 for (Index = 0; Index < Src->DnsServerCount; Index++) { 506 CopyMem (&Dst->DnsServerList[Index], &Src->DnsServerList[Index], sizeof (EFI_IPv6_ADDRESS)); 507 } 508 } 509 510 return EFI_SUCCESS; 511 } 512 513 /** 514 Callback of Dns packet. Does nothing. 515 516 @param Arg The context. 517 518 **/ 519 VOID 520 EFIAPI 521 DnsDummyExtFree ( 522 IN VOID *Arg 523 ) 524 { 525 } 526 527 /** 528 Poll the UDP to get the IP4 default address, which may be retrieved 529 by DHCP. 530 531 The default time out value is 5 seconds. If IP has retrieved the default address, 532 the UDP is reconfigured. 533 534 @param Instance The DNS instance 535 @param UdpIo The UDP_IO to poll 536 @param UdpCfgData The UDP configure data to reconfigure the UDP_IO 537 538 @retval TRUE The default address is retrieved and UDP is reconfigured. 539 @retval FALSE Some error occured. 540 541 **/ 542 BOOLEAN 543 Dns4GetMapping ( 544 IN DNS_INSTANCE *Instance, 545 IN UDP_IO *UdpIo, 546 IN EFI_UDP4_CONFIG_DATA *UdpCfgData 547 ) 548 { 549 DNS_SERVICE *Service; 550 EFI_IP4_MODE_DATA Ip4Mode; 551 EFI_UDP4_PROTOCOL *Udp; 552 EFI_STATUS Status; 553 554 ASSERT (Instance->Dns4CfgData.UseDefaultSetting); 555 556 Service = Instance->Service; 557 Udp = UdpIo->Protocol.Udp4; 558 559 Status = gBS->SetTimer ( 560 Service->TimerToGetMap, 561 TimerRelative, 562 DNS_TIME_TO_GETMAP * TICKS_PER_SECOND 563 ); 564 if (EFI_ERROR (Status)) { 565 return FALSE; 566 } 567 568 while (EFI_ERROR (gBS->CheckEvent (Service->TimerToGetMap))) { 569 Udp->Poll (Udp); 570 571 if (!EFI_ERROR (Udp->GetModeData (Udp, NULL, &Ip4Mode, NULL, NULL)) && 572 Ip4Mode.IsConfigured) { 573 574 Udp->Configure (Udp, NULL); 575 return (BOOLEAN) (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS); 576 } 577 } 578 579 return FALSE; 580 } 581 582 /** 583 Configure the opened Udp6 instance until the corresponding Ip6 instance 584 has been configured. 585 586 @param Instance The DNS instance 587 @param UdpIo The UDP_IO to poll 588 @param UdpCfgData The UDP configure data to reconfigure the UDP_IO 589 590 @retval TRUE Configure the Udp6 instance successfully. 591 @retval FALSE Some error occured. 592 593 **/ 594 BOOLEAN 595 Dns6GetMapping ( 596 IN DNS_INSTANCE *Instance, 597 IN UDP_IO *UdpIo, 598 IN EFI_UDP6_CONFIG_DATA *UdpCfgData 599 ) 600 { 601 DNS_SERVICE *Service; 602 EFI_IP6_MODE_DATA Ip6Mode; 603 EFI_UDP6_PROTOCOL *Udp; 604 EFI_STATUS Status; 605 606 Service = Instance->Service; 607 Udp = UdpIo->Protocol.Udp6; 608 609 Status = gBS->SetTimer ( 610 Service->TimerToGetMap, 611 TimerRelative, 612 DNS_TIME_TO_GETMAP * TICKS_PER_SECOND 613 ); 614 if (EFI_ERROR (Status)) { 615 return FALSE; 616 } 617 618 while (EFI_ERROR (gBS->CheckEvent (Service->TimerToGetMap))) { 619 Udp->Poll (Udp); 620 621 if (!EFI_ERROR (Udp->GetModeData (Udp, NULL, &Ip6Mode, NULL, NULL))) { 622 if (Ip6Mode.AddressList != NULL) { 623 FreePool (Ip6Mode.AddressList); 624 } 625 626 if (Ip6Mode.GroupTable != NULL) { 627 FreePool (Ip6Mode.GroupTable); 628 } 629 630 if (Ip6Mode.RouteTable != NULL) { 631 FreePool (Ip6Mode.RouteTable); 632 } 633 634 if (Ip6Mode.NeighborCache != NULL) { 635 FreePool (Ip6Mode.NeighborCache); 636 } 637 638 if (Ip6Mode.PrefixTable != NULL) { 639 FreePool (Ip6Mode.PrefixTable); 640 } 641 642 if (Ip6Mode.IcmpTypeList != NULL) { 643 FreePool (Ip6Mode.IcmpTypeList); 644 } 645 646 if (Ip6Mode.IsConfigured) { 647 Udp->Configure (Udp, NULL); 648 return (BOOLEAN) (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS); 649 } 650 } 651 } 652 653 return FALSE; 654 } 655 656 /** 657 Configure the UDP. 658 659 @param Instance The DNS session 660 @param UdpIo The UDP_IO instance 661 662 @retval EFI_SUCCESS The UDP is successfully configured for the 663 session. 664 665 **/ 666 EFI_STATUS 667 Dns4ConfigUdp ( 668 IN DNS_INSTANCE *Instance, 669 IN UDP_IO *UdpIo 670 ) 671 { 672 EFI_DNS4_CONFIG_DATA *Config; 673 EFI_UDP4_CONFIG_DATA UdpConfig; 674 EFI_STATUS Status; 675 676 Config = &Instance->Dns4CfgData; 677 678 UdpConfig.AcceptBroadcast = FALSE; 679 UdpConfig.AcceptPromiscuous = FALSE; 680 UdpConfig.AcceptAnyPort = FALSE; 681 UdpConfig.AllowDuplicatePort = FALSE; 682 UdpConfig.TypeOfService = 0; 683 UdpConfig.TimeToLive = 128; 684 UdpConfig.DoNotFragment = FALSE; 685 UdpConfig.ReceiveTimeout = 0; 686 UdpConfig.TransmitTimeout = 0; 687 UdpConfig.UseDefaultAddress = Config->UseDefaultSetting; 688 UdpConfig.SubnetMask = Config->SubnetMask; 689 UdpConfig.StationPort = Config->LocalPort; 690 UdpConfig.RemotePort = DNS_SERVER_PORT; 691 692 CopyMem (&UdpConfig.StationAddress, &Config->StationIp, sizeof (EFI_IPv4_ADDRESS)); 693 CopyMem (&UdpConfig.RemoteAddress, &Instance->SessionDnsServer.v4, sizeof (EFI_IPv4_ADDRESS)); 694 695 Status = UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfig); 696 697 if ((Status == EFI_NO_MAPPING) && Dns4GetMapping (Instance, UdpIo, &UdpConfig)) { 698 return EFI_SUCCESS; 699 } 700 701 return Status; 702 } 703 704 /** 705 Configure the UDP. 706 707 @param Instance The DNS session 708 @param UdpIo The UDP_IO instance 709 710 @retval EFI_SUCCESS The UDP is successfully configured for the 711 session. 712 713 **/ 714 EFI_STATUS 715 Dns6ConfigUdp ( 716 IN DNS_INSTANCE *Instance, 717 IN UDP_IO *UdpIo 718 ) 719 { 720 EFI_DNS6_CONFIG_DATA *Config; 721 EFI_UDP6_CONFIG_DATA UdpConfig; 722 EFI_STATUS Status; 723 724 Config = &Instance->Dns6CfgData; 725 726 UdpConfig.AcceptPromiscuous = FALSE; 727 UdpConfig.AcceptAnyPort = FALSE; 728 UdpConfig.AllowDuplicatePort = FALSE; 729 UdpConfig.TrafficClass = 0; 730 UdpConfig.HopLimit = 128; 731 UdpConfig.ReceiveTimeout = 0; 732 UdpConfig.TransmitTimeout = 0; 733 UdpConfig.StationPort = Config->LocalPort; 734 UdpConfig.RemotePort = DNS_SERVER_PORT; 735 CopyMem (&UdpConfig.StationAddress, &Config->StationIp, sizeof (EFI_IPv6_ADDRESS)); 736 CopyMem (&UdpConfig.RemoteAddress, &Instance->SessionDnsServer.v6, sizeof (EFI_IPv6_ADDRESS)); 737 738 Status = UdpIo->Protocol.Udp6->Configure (UdpIo->Protocol.Udp6, &UdpConfig); 739 740 if ((Status == EFI_NO_MAPPING) && Dns6GetMapping (Instance, UdpIo, &UdpConfig)) { 741 return EFI_SUCCESS; 742 } 743 744 return Status; 745 } 746 747 /** 748 Update Dns4 cache to shared list of caches of all DNSv4 instances. 749 750 @param Dns4CacheList All Dns4 cache list. 751 @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache. 752 If TRUE, this function will delete matching DNS Cache entry. 753 @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter. 754 If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists. 755 @param DnsCacheEntry Entry Pointer to DNS Cache entry. 756 757 @retval EFI_SUCCESS Update Dns4 cache successfully. 758 @retval Others Failed to update Dns4 cache. 759 760 **/ 761 EFI_STATUS 762 EFIAPI 763 UpdateDns4Cache ( 764 IN LIST_ENTRY *Dns4CacheList, 765 IN BOOLEAN DeleteFlag, 766 IN BOOLEAN Override, 767 IN EFI_DNS4_CACHE_ENTRY DnsCacheEntry 768 ) 769 { 770 DNS4_CACHE *NewDnsCache; 771 DNS4_CACHE *Item; 772 LIST_ENTRY *Entry; 773 LIST_ENTRY *Next; 774 775 NewDnsCache = NULL; 776 Item = NULL; 777 778 // 779 // Search the database for the matching EFI_DNS_CACHE_ENTRY 780 // 781 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns4CacheList) { 782 Item = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink); 783 if (StrCmp (DnsCacheEntry.HostName, Item->DnsCache.HostName) == 0 && \ 784 CompareMem (DnsCacheEntry.IpAddress, Item->DnsCache.IpAddress, sizeof (EFI_IPv4_ADDRESS)) == 0) { 785 // 786 // This is the Dns cache entry 787 // 788 if (DeleteFlag) { 789 // 790 // Delete matching DNS Cache entry 791 // 792 RemoveEntryList (&Item->AllCacheLink); 793 794 return EFI_SUCCESS; 795 } else if (Override) { 796 // 797 // Update this one 798 // 799 Item->DnsCache.Timeout = DnsCacheEntry.Timeout; 800 801 return EFI_SUCCESS; 802 }else { 803 return EFI_ACCESS_DENIED; 804 } 805 } 806 } 807 808 // 809 // Add new one 810 // 811 NewDnsCache = AllocatePool (sizeof (DNS4_CACHE)); 812 if (NewDnsCache == NULL) { 813 return EFI_OUT_OF_RESOURCES; 814 } 815 816 InitializeListHead (&NewDnsCache->AllCacheLink); 817 818 NewDnsCache->DnsCache.HostName = AllocatePool (StrSize (DnsCacheEntry.HostName)); 819 if (NewDnsCache->DnsCache.HostName == NULL) { 820 return EFI_OUT_OF_RESOURCES; 821 } 822 823 CopyMem (NewDnsCache->DnsCache.HostName, DnsCacheEntry.HostName, StrSize (DnsCacheEntry.HostName)); 824 825 NewDnsCache->DnsCache.IpAddress = AllocatePool (sizeof (EFI_IPv4_ADDRESS)); 826 if (NewDnsCache->DnsCache.IpAddress == NULL) { 827 return EFI_OUT_OF_RESOURCES; 828 } 829 830 CopyMem (NewDnsCache->DnsCache.IpAddress, DnsCacheEntry.IpAddress, sizeof (EFI_IPv4_ADDRESS)); 831 832 NewDnsCache->DnsCache.Timeout = DnsCacheEntry.Timeout; 833 834 InsertTailList (Dns4CacheList, &NewDnsCache->AllCacheLink); 835 836 return EFI_SUCCESS; 837 } 838 839 /** 840 Update Dns6 cache to shared list of caches of all DNSv6 instances. 841 842 @param Dns6CacheList All Dns6 cache list. 843 @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache. 844 If TRUE, this function will delete matching DNS Cache entry. 845 @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter. 846 If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists. 847 @param DnsCacheEntry Entry Pointer to DNS Cache entry. 848 849 @retval EFI_SUCCESS Update Dns6 cache successfully. 850 @retval Others Failed to update Dns6 cache. 851 **/ 852 EFI_STATUS 853 EFIAPI 854 UpdateDns6Cache ( 855 IN LIST_ENTRY *Dns6CacheList, 856 IN BOOLEAN DeleteFlag, 857 IN BOOLEAN Override, 858 IN EFI_DNS6_CACHE_ENTRY DnsCacheEntry 859 ) 860 { 861 DNS6_CACHE *NewDnsCache; 862 DNS6_CACHE *Item; 863 LIST_ENTRY *Entry; 864 LIST_ENTRY *Next; 865 866 NewDnsCache = NULL; 867 Item = NULL; 868 869 // 870 // Search the database for the matching EFI_DNS_CACHE_ENTRY 871 // 872 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns6CacheList) { 873 Item = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink); 874 if (StrCmp (DnsCacheEntry.HostName, Item->DnsCache.HostName) == 0 && \ 875 CompareMem (DnsCacheEntry.IpAddress, Item->DnsCache.IpAddress, sizeof (EFI_IPv6_ADDRESS)) == 0) { 876 // 877 // This is the Dns cache entry 878 // 879 if (DeleteFlag) { 880 // 881 // Delete matching DNS Cache entry 882 // 883 RemoveEntryList (&Item->AllCacheLink); 884 885 return EFI_SUCCESS; 886 } else if (Override) { 887 // 888 // Update this one 889 // 890 Item->DnsCache.Timeout = DnsCacheEntry.Timeout; 891 892 return EFI_SUCCESS; 893 }else { 894 return EFI_ACCESS_DENIED; 895 } 896 } 897 } 898 899 // 900 // Add new one 901 // 902 NewDnsCache = AllocatePool (sizeof (DNS6_CACHE)); 903 if (NewDnsCache == NULL) { 904 return EFI_OUT_OF_RESOURCES; 905 } 906 907 InitializeListHead (&NewDnsCache->AllCacheLink); 908 909 NewDnsCache->DnsCache.HostName = AllocatePool (StrSize (DnsCacheEntry.HostName)); 910 if (NewDnsCache->DnsCache.HostName == NULL) { 911 return EFI_OUT_OF_RESOURCES; 912 } 913 914 CopyMem (NewDnsCache->DnsCache.HostName, DnsCacheEntry.HostName, StrSize (DnsCacheEntry.HostName)); 915 916 NewDnsCache->DnsCache.IpAddress = AllocatePool (sizeof (EFI_IPv6_ADDRESS)); 917 if (NewDnsCache->DnsCache.IpAddress == NULL) { 918 return EFI_OUT_OF_RESOURCES; 919 } 920 921 CopyMem (NewDnsCache->DnsCache.IpAddress, DnsCacheEntry.IpAddress, sizeof (EFI_IPv6_ADDRESS)); 922 923 NewDnsCache->DnsCache.Timeout = DnsCacheEntry.Timeout; 924 925 InsertTailList (Dns6CacheList, &NewDnsCache->AllCacheLink); 926 927 return EFI_SUCCESS; 928 } 929 930 /** 931 Add Dns4 ServerIp to common list of addresses of all configured DNSv4 server. 932 933 @param Dns4ServerList Common list of addresses of all configured DNSv4 server. 934 @param ServerIp DNS server Ip. 935 936 @retval EFI_SUCCESS Add Dns4 ServerIp to common list successfully. 937 @retval Others Failed to add Dns4 ServerIp to common list. 938 939 **/ 940 EFI_STATUS 941 EFIAPI 942 AddDns4ServerIp ( 943 IN LIST_ENTRY *Dns4ServerList, 944 IN EFI_IPv4_ADDRESS ServerIp 945 ) 946 { 947 DNS4_SERVER_IP *NewServerIp; 948 DNS4_SERVER_IP *Item; 949 LIST_ENTRY *Entry; 950 LIST_ENTRY *Next; 951 952 NewServerIp = NULL; 953 Item = NULL; 954 955 // 956 // Search the database for the matching ServerIp 957 // 958 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns4ServerList) { 959 Item = NET_LIST_USER_STRUCT (Entry, DNS4_SERVER_IP, AllServerLink); 960 if (CompareMem (&Item->Dns4ServerIp, &ServerIp, sizeof (EFI_IPv4_ADDRESS)) == 0) { 961 // 962 // Already done. 963 // 964 return EFI_SUCCESS; 965 } 966 } 967 968 // 969 // Add new one 970 // 971 NewServerIp = AllocatePool (sizeof (DNS4_SERVER_IP)); 972 if (NewServerIp == NULL) { 973 return EFI_OUT_OF_RESOURCES; 974 } 975 976 InitializeListHead (&NewServerIp->AllServerLink); 977 978 CopyMem (&NewServerIp->Dns4ServerIp, &ServerIp, sizeof (EFI_IPv4_ADDRESS)); 979 980 InsertTailList (Dns4ServerList, &NewServerIp->AllServerLink); 981 982 return EFI_SUCCESS; 983 } 984 985 /** 986 Add Dns6 ServerIp to common list of addresses of all configured DNSv6 server. 987 988 @param Dns6ServerList Common list of addresses of all configured DNSv6 server. 989 @param ServerIp DNS server Ip. 990 991 @retval EFI_SUCCESS Add Dns6 ServerIp to common list successfully. 992 @retval Others Failed to add Dns6 ServerIp to common list. 993 994 **/ 995 EFI_STATUS 996 EFIAPI 997 AddDns6ServerIp ( 998 IN LIST_ENTRY *Dns6ServerList, 999 IN EFI_IPv6_ADDRESS ServerIp 1000 ) 1001 { 1002 DNS6_SERVER_IP *NewServerIp; 1003 DNS6_SERVER_IP *Item; 1004 LIST_ENTRY *Entry; 1005 LIST_ENTRY *Next; 1006 1007 NewServerIp = NULL; 1008 Item = NULL; 1009 1010 // 1011 // Search the database for the matching ServerIp 1012 // 1013 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns6ServerList) { 1014 Item = NET_LIST_USER_STRUCT (Entry, DNS6_SERVER_IP, AllServerLink); 1015 if (CompareMem (&Item->Dns6ServerIp, &ServerIp, sizeof (EFI_IPv6_ADDRESS)) == 0) { 1016 // 1017 // Already done. 1018 // 1019 return EFI_SUCCESS; 1020 } 1021 } 1022 1023 // 1024 // Add new one 1025 // 1026 NewServerIp = AllocatePool (sizeof (DNS6_SERVER_IP)); 1027 if (NewServerIp == NULL) { 1028 return EFI_OUT_OF_RESOURCES; 1029 } 1030 1031 InitializeListHead (&NewServerIp->AllServerLink); 1032 1033 CopyMem (&NewServerIp->Dns6ServerIp, &ServerIp, sizeof (EFI_IPv6_ADDRESS)); 1034 1035 InsertTailList (Dns6ServerList, &NewServerIp->AllServerLink); 1036 1037 return EFI_SUCCESS; 1038 } 1039 1040 /** 1041 Find out whether the response is valid or invalid. 1042 1043 @param TokensMap All DNS transmittal Tokens entry. 1044 @param Identification Identification for queried packet. 1045 @param Type Type for queried packet. 1046 @param Class Class for queried packet. 1047 @param Item Return corresponding Token entry. 1048 1049 @retval TRUE The response is valid. 1050 @retval FALSE The response is invalid. 1051 1052 **/ 1053 BOOLEAN 1054 IsValidDnsResponse ( 1055 IN NET_MAP *TokensMap, 1056 IN UINT16 Identification, 1057 IN UINT16 Type, 1058 IN UINT16 Class, 1059 OUT NET_MAP_ITEM **Item 1060 ) 1061 { 1062 LIST_ENTRY *Entry; 1063 1064 NET_BUF *Packet; 1065 UINT8 *TxString; 1066 DNS_HEADER *DnsHeader; 1067 CHAR8 *QueryName; 1068 DNS_QUERY_SECTION *QuerySection; 1069 1070 NET_LIST_FOR_EACH (Entry, &TokensMap->Used) { 1071 *Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link); 1072 Packet = (NET_BUF *) ((*Item)->Value); 1073 if (Packet == NULL){ 1074 1075 continue; 1076 } else { 1077 TxString = NetbufGetByte (Packet, 0, NULL); 1078 ASSERT (TxString != NULL); 1079 DnsHeader = (DNS_HEADER *) TxString; 1080 QueryName = (CHAR8 *) (TxString + sizeof (*DnsHeader)); 1081 QuerySection = (DNS_QUERY_SECTION *) (QueryName + AsciiStrLen (QueryName) + 1); 1082 1083 if (NTOHS (DnsHeader->Identification) == Identification && 1084 NTOHS (QuerySection->Type) == Type && 1085 NTOHS (QuerySection->Class) == Class) { 1086 return TRUE; 1087 } 1088 } 1089 } 1090 1091 *Item = NULL; 1092 1093 return FALSE; 1094 } 1095 1096 /** 1097 Parse Dns Response. 1098 1099 @param Instance The DNS instance 1100 @param RxString Received buffer. 1101 @param Completed Flag to indicate that Dns response is valid. 1102 1103 @retval EFI_SUCCESS Parse Dns Response successfully. 1104 @retval Others Failed to parse Dns Response. 1105 1106 **/ 1107 EFI_STATUS 1108 ParseDnsResponse ( 1109 IN OUT DNS_INSTANCE *Instance, 1110 IN UINT8 *RxString, 1111 OUT BOOLEAN *Completed 1112 ) 1113 { 1114 DNS_HEADER *DnsHeader; 1115 1116 CHAR8 *QueryName; 1117 DNS_QUERY_SECTION *QuerySection; 1118 1119 CHAR8 *AnswerName; 1120 DNS_ANSWER_SECTION *AnswerSection; 1121 UINT8 *AnswerData; 1122 1123 NET_MAP_ITEM *Item; 1124 DNS4_TOKEN_ENTRY *Dns4TokenEntry; 1125 DNS6_TOKEN_ENTRY *Dns6TokenEntry; 1126 1127 UINT32 IpCount; 1128 UINT32 RRCount; 1129 UINT32 AnswerSectionNum; 1130 UINT32 CNameTtl; 1131 1132 EFI_IPv4_ADDRESS *HostAddr4; 1133 EFI_IPv6_ADDRESS *HostAddr6; 1134 1135 EFI_DNS4_CACHE_ENTRY *Dns4CacheEntry; 1136 EFI_DNS6_CACHE_ENTRY *Dns6CacheEntry; 1137 1138 DNS_RESOURCE_RECORD *Dns4RR; 1139 DNS6_RESOURCE_RECORD *Dns6RR; 1140 1141 EFI_STATUS Status; 1142 1143 EFI_TPL OldTpl; 1144 1145 Item = NULL; 1146 Dns4TokenEntry = NULL; 1147 Dns6TokenEntry = NULL; 1148 1149 IpCount = 0; 1150 RRCount = 0; 1151 AnswerSectionNum = 0; 1152 CNameTtl = 0; 1153 1154 HostAddr4 = NULL; 1155 HostAddr6 = NULL; 1156 1157 Dns4CacheEntry = NULL; 1158 Dns6CacheEntry = NULL; 1159 1160 Dns4RR = NULL; 1161 Dns6RR = NULL; 1162 1163 *Completed = TRUE; 1164 Status = EFI_SUCCESS; 1165 1166 // 1167 // Get header 1168 // 1169 DnsHeader = (DNS_HEADER *) RxString; 1170 1171 DnsHeader->Identification = NTOHS (DnsHeader->Identification); 1172 DnsHeader->Flags.Uint16 = NTOHS (DnsHeader->Flags.Uint16); 1173 DnsHeader->QuestionsNum = NTOHS (DnsHeader->QuestionsNum); 1174 DnsHeader->AnswersNum = NTOHS (DnsHeader->AnswersNum); 1175 DnsHeader->AuthorityNum = NTOHS (DnsHeader->AuthorityNum); 1176 DnsHeader->AditionalNum = NTOHS (DnsHeader->AditionalNum); 1177 1178 // 1179 // Get Query name 1180 // 1181 QueryName = (CHAR8 *) (RxString + sizeof (*DnsHeader)); 1182 1183 // 1184 // Get query section 1185 // 1186 QuerySection = (DNS_QUERY_SECTION *) (QueryName + AsciiStrLen (QueryName) + 1); 1187 QuerySection->Type = NTOHS (QuerySection->Type); 1188 QuerySection->Class = NTOHS (QuerySection->Class); 1189 1190 // 1191 // Get Answer name 1192 // 1193 AnswerName = (CHAR8 *) QuerySection + sizeof (*QuerySection); 1194 1195 OldTpl = gBS->RaiseTPL (TPL_CALLBACK); 1196 1197 // 1198 // Check DnsResponse Validity, if so, also get a valid NET_MAP_ITEM. 1199 // 1200 if (Instance->Service->IpVersion == IP_VERSION_4) { 1201 if (!IsValidDnsResponse ( 1202 &Instance->Dns4TxTokens, 1203 DnsHeader->Identification, 1204 QuerySection->Type, 1205 QuerySection->Class, 1206 &Item 1207 )) { 1208 *Completed = FALSE; 1209 Status = EFI_ABORTED; 1210 goto ON_EXIT; 1211 } 1212 ASSERT (Item != NULL); 1213 Dns4TokenEntry = (DNS4_TOKEN_ENTRY *) (Item->Key); 1214 } else { 1215 if (!IsValidDnsResponse ( 1216 &Instance->Dns6TxTokens, 1217 DnsHeader->Identification, 1218 QuerySection->Type, 1219 QuerySection->Class, 1220 &Item 1221 )) { 1222 *Completed = FALSE; 1223 Status = EFI_ABORTED; 1224 goto ON_EXIT; 1225 } 1226 ASSERT (Item != NULL); 1227 Dns6TokenEntry = (DNS6_TOKEN_ENTRY *) (Item->Key); 1228 } 1229 1230 // 1231 // Continue Check Some Errors. 1232 // 1233 if (DnsHeader->Flags.Bits.RCode != DNS_FLAGS_RCODE_NO_ERROR || DnsHeader->AnswersNum < 1 || \ 1234 DnsHeader->Flags.Bits.QR != DNS_FLAGS_QR_RESPONSE) { 1235 // 1236 // The domain name referenced in the query does not exist. 1237 // 1238 if (DnsHeader->Flags.Bits.RCode == DNS_FLAGS_RCODE_NAME_ERROR) { 1239 Status = EFI_NOT_FOUND; 1240 } else { 1241 Status = EFI_DEVICE_ERROR; 1242 } 1243 1244 goto ON_COMPLETE; 1245 } 1246 1247 // 1248 // Do some buffer allocations. 1249 // 1250 if (Instance->Service->IpVersion == IP_VERSION_4) { 1251 ASSERT (Dns4TokenEntry != NULL); 1252 1253 if (Dns4TokenEntry->GeneralLookUp) { 1254 // 1255 // It's the GeneralLookUp querying. 1256 // 1257 Dns4TokenEntry->Token->RspData.GLookupData = AllocatePool (sizeof (DNS_RESOURCE_RECORD)); 1258 if (Dns4TokenEntry->Token->RspData.GLookupData == NULL) { 1259 Status = EFI_OUT_OF_RESOURCES; 1260 goto ON_EXIT; 1261 } 1262 Dns4TokenEntry->Token->RspData.GLookupData->RRList = AllocatePool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD)); 1263 if (Dns4TokenEntry->Token->RspData.GLookupData->RRList == NULL) { 1264 Status = EFI_OUT_OF_RESOURCES; 1265 goto ON_EXIT; 1266 } 1267 } else { 1268 // 1269 // It's not the GeneralLookUp querying. Check the Query type. 1270 // 1271 if (QuerySection->Type == DNS_TYPE_A) { 1272 Dns4TokenEntry->Token->RspData.H2AData = AllocatePool (sizeof (DNS_HOST_TO_ADDR_DATA)); 1273 if (Dns4TokenEntry->Token->RspData.H2AData == NULL) { 1274 Status = EFI_OUT_OF_RESOURCES; 1275 goto ON_EXIT; 1276 } 1277 Dns4TokenEntry->Token->RspData.H2AData->IpList = AllocatePool (DnsHeader->AnswersNum * sizeof (EFI_IPv4_ADDRESS)); 1278 if (Dns4TokenEntry->Token->RspData.H2AData->IpList == NULL) { 1279 Status = EFI_OUT_OF_RESOURCES; 1280 goto ON_EXIT; 1281 } 1282 } else { 1283 Status = EFI_UNSUPPORTED; 1284 goto ON_EXIT; 1285 } 1286 } 1287 } else { 1288 ASSERT (Dns6TokenEntry != NULL); 1289 1290 if (Dns6TokenEntry->GeneralLookUp) { 1291 // 1292 // It's the GeneralLookUp querying. 1293 // 1294 Dns6TokenEntry->Token->RspData.GLookupData = AllocatePool (sizeof (DNS_RESOURCE_RECORD)); 1295 if (Dns6TokenEntry->Token->RspData.GLookupData == NULL) { 1296 Status = EFI_OUT_OF_RESOURCES; 1297 goto ON_EXIT; 1298 } 1299 Dns6TokenEntry->Token->RspData.GLookupData->RRList = AllocatePool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD)); 1300 if (Dns6TokenEntry->Token->RspData.GLookupData->RRList == NULL) { 1301 Status = EFI_OUT_OF_RESOURCES; 1302 goto ON_EXIT; 1303 } 1304 } else { 1305 // 1306 // It's not the GeneralLookUp querying. Check the Query type. 1307 // 1308 if (QuerySection->Type == DNS_TYPE_AAAA) { 1309 Dns6TokenEntry->Token->RspData.H2AData = AllocatePool (sizeof (DNS6_HOST_TO_ADDR_DATA)); 1310 if (Dns6TokenEntry->Token->RspData.H2AData == NULL) { 1311 Status = EFI_OUT_OF_RESOURCES; 1312 goto ON_EXIT; 1313 } 1314 Dns6TokenEntry->Token->RspData.H2AData->IpList = AllocatePool (DnsHeader->AnswersNum * sizeof (EFI_IPv6_ADDRESS)); 1315 if (Dns6TokenEntry->Token->RspData.H2AData->IpList == NULL) { 1316 Status = EFI_OUT_OF_RESOURCES; 1317 goto ON_EXIT; 1318 } 1319 } else { 1320 Status = EFI_UNSUPPORTED; 1321 goto ON_EXIT; 1322 } 1323 } 1324 } 1325 1326 Status = EFI_NOT_FOUND; 1327 1328 // 1329 // Processing AnswerSection. 1330 // 1331 while (AnswerSectionNum < DnsHeader->AnswersNum) { 1332 // 1333 // Answer name should be PTR, else EFI_UNSUPPORTED returned. 1334 // 1335 if ((*(UINT8 *) AnswerName & 0xC0) != 0xC0) { 1336 Status = EFI_UNSUPPORTED; 1337 goto ON_EXIT; 1338 } 1339 1340 // 1341 // Get Answer section. 1342 // 1343 AnswerSection = (DNS_ANSWER_SECTION *) (AnswerName + sizeof (UINT16)); 1344 AnswerSection->Type = NTOHS (AnswerSection->Type); 1345 AnswerSection->Class = NTOHS (AnswerSection->Class); 1346 AnswerSection->Ttl = NTOHL (AnswerSection->Ttl); 1347 AnswerSection->DataLength = NTOHS (AnswerSection->DataLength); 1348 1349 // 1350 // Check whether it's the GeneralLookUp querying. 1351 // 1352 if (Instance->Service->IpVersion == IP_VERSION_4 && Dns4TokenEntry->GeneralLookUp) { 1353 Dns4RR = Dns4TokenEntry->Token->RspData.GLookupData->RRList; 1354 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection); 1355 1356 // 1357 // Fill the ResourceRecord. 1358 // 1359 Dns4RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1); 1360 if (Dns4RR[RRCount].QName == NULL) { 1361 Status = EFI_OUT_OF_RESOURCES; 1362 goto ON_EXIT; 1363 } 1364 CopyMem (Dns4RR[RRCount].QName, QueryName, AsciiStrLen (QueryName)); 1365 Dns4RR[RRCount].QType = AnswerSection->Type; 1366 Dns4RR[RRCount].QClass = AnswerSection->Class; 1367 Dns4RR[RRCount].TTL = AnswerSection->Ttl; 1368 Dns4RR[RRCount].DataLength = AnswerSection->DataLength; 1369 Dns4RR[RRCount].RData = AllocateZeroPool (Dns4RR[RRCount].DataLength); 1370 if (Dns4RR[RRCount].RData == NULL) { 1371 Status = EFI_OUT_OF_RESOURCES; 1372 goto ON_EXIT; 1373 } 1374 CopyMem (Dns4RR[RRCount].RData, AnswerData, Dns4RR[RRCount].DataLength); 1375 1376 RRCount ++; 1377 Status = EFI_SUCCESS; 1378 } else if (Instance->Service->IpVersion == IP_VERSION_6 && Dns6TokenEntry->GeneralLookUp) { 1379 Dns6RR = Dns6TokenEntry->Token->RspData.GLookupData->RRList; 1380 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection); 1381 1382 // 1383 // Fill the ResourceRecord. 1384 // 1385 Dns6RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1); 1386 if (Dns6RR[RRCount].QName == NULL) { 1387 Status = EFI_OUT_OF_RESOURCES; 1388 goto ON_EXIT; 1389 } 1390 CopyMem (Dns6RR[RRCount].QName, QueryName, AsciiStrLen (QueryName)); 1391 Dns6RR[RRCount].QType = AnswerSection->Type; 1392 Dns6RR[RRCount].QClass = AnswerSection->Class; 1393 Dns6RR[RRCount].TTL = AnswerSection->Ttl; 1394 Dns6RR[RRCount].DataLength = AnswerSection->DataLength; 1395 Dns6RR[RRCount].RData = AllocateZeroPool (Dns6RR[RRCount].DataLength); 1396 if (Dns6RR[RRCount].RData == NULL) { 1397 Status = EFI_OUT_OF_RESOURCES; 1398 goto ON_EXIT; 1399 } 1400 CopyMem (Dns6RR[RRCount].RData, AnswerData, Dns6RR[RRCount].DataLength); 1401 1402 RRCount ++; 1403 Status = EFI_SUCCESS; 1404 } else { 1405 // 1406 // It's not the GeneralLookUp querying. 1407 // Check the Query type, parse the response packet. 1408 // 1409 switch (AnswerSection->Type) { 1410 case DNS_TYPE_A: 1411 // 1412 // This is address entry, get Data. 1413 // 1414 ASSERT (Dns4TokenEntry != NULL); 1415 1416 if (AnswerSection->DataLength != 4) { 1417 Status = EFI_ABORTED; 1418 goto ON_EXIT; 1419 } 1420 1421 HostAddr4 = Dns4TokenEntry->Token->RspData.H2AData->IpList; 1422 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection); 1423 CopyMem (&HostAddr4[IpCount], AnswerData, sizeof (EFI_IPv4_ADDRESS)); 1424 1425 // 1426 // Allocate new CacheEntry pool to update DNS cache dynamically. 1427 // 1428 Dns4CacheEntry = AllocateZeroPool (sizeof (EFI_DNS4_CACHE_ENTRY)); 1429 if (Dns4CacheEntry == NULL) { 1430 Status = EFI_OUT_OF_RESOURCES; 1431 goto ON_EXIT; 1432 } 1433 Dns4CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1)); 1434 if (Dns4CacheEntry->HostName == NULL) { 1435 Status = EFI_OUT_OF_RESOURCES; 1436 goto ON_EXIT; 1437 } 1438 CopyMem (Dns4CacheEntry->HostName, Dns4TokenEntry->QueryHostName, 2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1)); 1439 Dns4CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv4_ADDRESS)); 1440 if (Dns4CacheEntry->IpAddress == NULL) { 1441 Status = EFI_OUT_OF_RESOURCES; 1442 goto ON_EXIT; 1443 } 1444 CopyMem (Dns4CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv4_ADDRESS)); 1445 1446 if (CNameTtl != 0 && AnswerSection->Ttl != 0) { 1447 Dns4CacheEntry->Timeout = MIN (CNameTtl, AnswerSection->Ttl); 1448 } else { 1449 Dns4CacheEntry->Timeout = MAX (CNameTtl, AnswerSection->Ttl); 1450 } 1451 1452 UpdateDns4Cache (&mDriverData->Dns4CacheList, FALSE, TRUE, *Dns4CacheEntry); 1453 1454 // 1455 // Free allocated CacheEntry pool. 1456 // 1457 FreePool (Dns4CacheEntry->HostName); 1458 Dns4CacheEntry->HostName = NULL; 1459 1460 FreePool (Dns4CacheEntry->IpAddress); 1461 Dns4CacheEntry->IpAddress = NULL; 1462 1463 FreePool (Dns4CacheEntry); 1464 Dns4CacheEntry = NULL; 1465 1466 IpCount ++; 1467 Status = EFI_SUCCESS; 1468 break; 1469 case DNS_TYPE_AAAA: 1470 // 1471 // This is address entry, get Data. 1472 // 1473 ASSERT (Dns6TokenEntry != NULL); 1474 1475 if (AnswerSection->DataLength != 16) { 1476 Status = EFI_ABORTED; 1477 goto ON_EXIT; 1478 } 1479 1480 HostAddr6 = Dns6TokenEntry->Token->RspData.H2AData->IpList; 1481 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection); 1482 CopyMem (&HostAddr6[IpCount], AnswerData, sizeof (EFI_IPv6_ADDRESS)); 1483 1484 // 1485 // Allocate new CacheEntry pool to update DNS cache dynamically. 1486 // 1487 Dns6CacheEntry = AllocateZeroPool (sizeof (EFI_DNS6_CACHE_ENTRY)); 1488 if (Dns6CacheEntry == NULL) { 1489 Status = EFI_OUT_OF_RESOURCES; 1490 goto ON_EXIT; 1491 } 1492 Dns6CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1)); 1493 if (Dns6CacheEntry->HostName == NULL) { 1494 Status = EFI_OUT_OF_RESOURCES; 1495 goto ON_EXIT; 1496 } 1497 CopyMem (Dns6CacheEntry->HostName, Dns6TokenEntry->QueryHostName, 2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1)); 1498 Dns6CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS)); 1499 if (Dns6CacheEntry->IpAddress == NULL) { 1500 Status = EFI_OUT_OF_RESOURCES; 1501 goto ON_EXIT; 1502 } 1503 CopyMem (Dns6CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv6_ADDRESS)); 1504 1505 if (CNameTtl != 0 && AnswerSection->Ttl != 0) { 1506 Dns6CacheEntry->Timeout = MIN (CNameTtl, AnswerSection->Ttl); 1507 } else { 1508 Dns6CacheEntry->Timeout = MAX (CNameTtl, AnswerSection->Ttl); 1509 } 1510 1511 UpdateDns6Cache (&mDriverData->Dns6CacheList, FALSE, TRUE, *Dns6CacheEntry); 1512 1513 // 1514 // Free allocated CacheEntry pool. 1515 // 1516 FreePool (Dns6CacheEntry->HostName); 1517 Dns6CacheEntry->HostName = NULL; 1518 1519 FreePool (Dns6CacheEntry->IpAddress); 1520 Dns6CacheEntry->IpAddress = NULL; 1521 1522 FreePool (Dns6CacheEntry); 1523 Dns6CacheEntry = NULL; 1524 1525 IpCount ++; 1526 Status = EFI_SUCCESS; 1527 break; 1528 case DNS_TYPE_CNAME: 1529 // 1530 // According RFC 1034 - 3.6.2, if the query name is an alias, the name server will include the CNAME 1531 // record in the response and restart the query at the domain name specified in the data field of the 1532 // CNAME record. So, just record the TTL value of the CNAME, then skip to parse the next record. 1533 // 1534 CNameTtl = AnswerSection->Ttl; 1535 break; 1536 default: 1537 Status = EFI_UNSUPPORTED; 1538 goto ON_EXIT; 1539 } 1540 } 1541 1542 // 1543 // Find next one 1544 // 1545 AnswerName = (CHAR8 *) AnswerSection + sizeof (*AnswerSection) + AnswerSection->DataLength; 1546 AnswerSectionNum ++; 1547 } 1548 1549 if (Instance->Service->IpVersion == IP_VERSION_4) { 1550 ASSERT (Dns4TokenEntry != NULL); 1551 1552 if (Dns4TokenEntry->GeneralLookUp) { 1553 Dns4TokenEntry->Token->RspData.GLookupData->RRCount = RRCount; 1554 } else { 1555 if (QuerySection->Type == DNS_TYPE_A) { 1556 Dns4TokenEntry->Token->RspData.H2AData->IpCount = IpCount; 1557 } else { 1558 Status = EFI_UNSUPPORTED; 1559 goto ON_EXIT; 1560 } 1561 } 1562 } else { 1563 ASSERT (Dns6TokenEntry != NULL); 1564 1565 if (Dns6TokenEntry->GeneralLookUp) { 1566 Dns6TokenEntry->Token->RspData.GLookupData->RRCount = RRCount; 1567 } else { 1568 if (QuerySection->Type == DNS_TYPE_AAAA) { 1569 Dns6TokenEntry->Token->RspData.H2AData->IpCount = IpCount; 1570 } else { 1571 Status = EFI_UNSUPPORTED; 1572 goto ON_EXIT; 1573 } 1574 } 1575 } 1576 1577 ON_COMPLETE: 1578 // 1579 // Parsing is complete, free the sending packet and signal Event here. 1580 // 1581 if (Item != NULL && Item->Value != NULL) { 1582 NetbufFree ((NET_BUF *) (Item->Value)); 1583 } 1584 1585 if (Instance->Service->IpVersion == IP_VERSION_4) { 1586 ASSERT (Dns4TokenEntry != NULL); 1587 Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry); 1588 Dns4TokenEntry->Token->Status = Status; 1589 if (Dns4TokenEntry->Token->Event != NULL) { 1590 gBS->SignalEvent (Dns4TokenEntry->Token->Event); 1591 DispatchDpc (); 1592 } 1593 } else { 1594 ASSERT (Dns6TokenEntry != NULL); 1595 Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry); 1596 Dns6TokenEntry->Token->Status = Status; 1597 if (Dns6TokenEntry->Token->Event != NULL) { 1598 gBS->SignalEvent (Dns6TokenEntry->Token->Event); 1599 DispatchDpc (); 1600 } 1601 } 1602 1603 ON_EXIT: 1604 gBS->RestoreTPL (OldTpl); 1605 return Status; 1606 } 1607 1608 /** 1609 Parse response packet. 1610 1611 @param Packet The packets received. 1612 @param EndPoint The local/remote UDP access point 1613 @param IoStatus The status of the UDP receive 1614 @param Context The opaque parameter to the function. 1615 1616 **/ 1617 VOID 1618 EFIAPI 1619 DnsOnPacketReceived ( 1620 NET_BUF *Packet, 1621 UDP_END_POINT *EndPoint, 1622 EFI_STATUS IoStatus, 1623 VOID *Context 1624 ) 1625 { 1626 DNS_INSTANCE *Instance; 1627 1628 UINT8 *RcvString; 1629 1630 BOOLEAN Completed; 1631 1632 Instance = (DNS_INSTANCE *) Context; 1633 NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE); 1634 1635 RcvString = NULL; 1636 Completed = FALSE; 1637 1638 if (EFI_ERROR (IoStatus)) { 1639 goto ON_EXIT; 1640 } 1641 1642 ASSERT (Packet != NULL); 1643 1644 if (Packet->TotalSize <= sizeof (DNS_HEADER)) { 1645 goto ON_EXIT; 1646 } 1647 1648 RcvString = NetbufGetByte (Packet, 0, NULL); 1649 ASSERT (RcvString != NULL); 1650 1651 // 1652 // Parse Dns Response 1653 // 1654 ParseDnsResponse (Instance, RcvString, &Completed); 1655 1656 ON_EXIT: 1657 1658 if (Packet != NULL) { 1659 NetbufFree (Packet); 1660 } 1661 1662 if (!Completed) { 1663 UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0); 1664 } 1665 } 1666 1667 /** 1668 Release the net buffer when packet is sent. 1669 1670 @param Packet The packets received. 1671 @param EndPoint The local/remote UDP access point 1672 @param IoStatus The status of the UDP receive 1673 @param Context The opaque parameter to the function. 1674 1675 **/ 1676 VOID 1677 EFIAPI 1678 DnsOnPacketSent ( 1679 NET_BUF *Packet, 1680 UDP_END_POINT *EndPoint, 1681 EFI_STATUS IoStatus, 1682 VOID *Context 1683 ) 1684 { 1685 DNS_INSTANCE *Instance; 1686 LIST_ENTRY *Entry; 1687 NET_MAP_ITEM *Item; 1688 DNS4_TOKEN_ENTRY *Dns4TokenEntry; 1689 DNS6_TOKEN_ENTRY *Dns6TokenEntry; 1690 1691 Dns4TokenEntry = NULL; 1692 Dns6TokenEntry = NULL; 1693 1694 Instance = (DNS_INSTANCE *) Context; 1695 NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE); 1696 1697 if (Instance->Service->IpVersion == IP_VERSION_4) { 1698 NET_LIST_FOR_EACH (Entry, &Instance->Dns4TxTokens.Used) { 1699 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link); 1700 if (Packet == (NET_BUF *)(Item->Value)) { 1701 Dns4TokenEntry = ((DNS4_TOKEN_ENTRY *)Item->Key); 1702 Dns4TokenEntry->PacketToLive = Dns4TokenEntry->Token->RetryInterval; 1703 break; 1704 } 1705 } 1706 } else { 1707 NET_LIST_FOR_EACH (Entry, &Instance->Dns6TxTokens.Used) { 1708 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link); 1709 if (Packet == (NET_BUF *)(Item->Value)) { 1710 Dns6TokenEntry = ((DNS6_TOKEN_ENTRY *)Item->Key); 1711 Dns6TokenEntry->PacketToLive = Dns6TokenEntry->Token->RetryInterval; 1712 break; 1713 } 1714 } 1715 } 1716 1717 NetbufFree (Packet); 1718 } 1719 1720 /** 1721 Query request information. 1722 1723 @param Instance The DNS instance 1724 @param Packet The packet for querying request information. 1725 1726 @retval EFI_SUCCESS Query request information successfully. 1727 @retval Others Failed to query request information. 1728 1729 **/ 1730 EFI_STATUS 1731 DoDnsQuery ( 1732 IN DNS_INSTANCE *Instance, 1733 IN NET_BUF *Packet 1734 ) 1735 { 1736 EFI_STATUS Status; 1737 1738 // 1739 // Ready to receive the DNS response. 1740 // 1741 if (Instance->UdpIo->RecvRequest == NULL) { 1742 Status = UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0); 1743 if (EFI_ERROR (Status)) { 1744 return Status; 1745 } 1746 } 1747 1748 // 1749 // Transmit the DNS packet. 1750 // 1751 NET_GET_REF (Packet); 1752 1753 Status = UdpIoSendDatagram (Instance->UdpIo, Packet, NULL, NULL, DnsOnPacketSent, Instance); 1754 1755 return Status; 1756 } 1757 1758 /** 1759 Construct the Packet according query section. 1760 1761 @param Instance The DNS instance 1762 @param QueryName Queried Name 1763 @param Type Queried Type 1764 @param Class Queried Class 1765 @param Packet The packet for query 1766 1767 @retval EFI_SUCCESS The packet is constructed. 1768 @retval Others Failed to construct the Packet. 1769 1770 **/ 1771 EFI_STATUS 1772 ConstructDNSQuery ( 1773 IN DNS_INSTANCE *Instance, 1774 IN CHAR8 *QueryName, 1775 IN UINT16 Type, 1776 IN UINT16 Class, 1777 OUT NET_BUF **Packet 1778 ) 1779 { 1780 NET_FRAGMENT Frag; 1781 DNS_HEADER *DnsHeader; 1782 DNS_QUERY_SECTION *DnsQuery; 1783 1784 // 1785 // Messages carried by UDP are restricted to 512 bytes (not counting the IP 1786 // or UDP headers). 1787 // 1788 Frag.Bulk = AllocatePool (DNS_MAX_MESSAGE_SIZE * sizeof (UINT8)); 1789 if (Frag.Bulk == NULL) { 1790 return EFI_OUT_OF_RESOURCES; 1791 } 1792 1793 // 1794 // Fill header 1795 // 1796 DnsHeader = (DNS_HEADER *) Frag.Bulk; 1797 DnsHeader->Identification = (UINT16)NET_RANDOM (NetRandomInitSeed()); 1798 DnsHeader->Flags.Uint16 = 0x0000; 1799 DnsHeader->Flags.Bits.RD = 1; 1800 DnsHeader->Flags.Bits.OpCode = DNS_FLAGS_OPCODE_STANDARD; 1801 DnsHeader->Flags.Bits.QR = DNS_FLAGS_QR_QUERY; 1802 DnsHeader->QuestionsNum = 1; 1803 DnsHeader->AnswersNum = 0; 1804 DnsHeader->AuthorityNum = 0; 1805 DnsHeader->AditionalNum = 0; 1806 1807 DnsHeader->Identification = HTONS (DnsHeader->Identification); 1808 DnsHeader->Flags.Uint16 = HTONS (DnsHeader->Flags.Uint16); 1809 DnsHeader->QuestionsNum = HTONS (DnsHeader->QuestionsNum); 1810 DnsHeader->AnswersNum = HTONS (DnsHeader->AnswersNum); 1811 DnsHeader->AuthorityNum = HTONS (DnsHeader->AuthorityNum); 1812 DnsHeader->AditionalNum = HTONS (DnsHeader->AditionalNum); 1813 1814 Frag.Len = sizeof (*DnsHeader); 1815 1816 // 1817 // Fill Query name 1818 // 1819 CopyMem (Frag.Bulk + Frag.Len, QueryName, AsciiStrLen (QueryName)); 1820 Frag.Len = (UINT32) (Frag.Len + AsciiStrLen (QueryName)); 1821 *(Frag.Bulk + Frag.Len) = 0; 1822 Frag.Len ++; 1823 1824 // 1825 // Rest query section 1826 // 1827 DnsQuery = (DNS_QUERY_SECTION *) (Frag.Bulk + Frag.Len); 1828 1829 DnsQuery->Type = HTONS (Type); 1830 DnsQuery->Class = HTONS (Class); 1831 1832 Frag.Len += sizeof (*DnsQuery); 1833 1834 // 1835 // Wrap the Frag in a net buffer. 1836 // 1837 *Packet = NetbufFromExt (&Frag, 1, 0, 0, DnsDummyExtFree, NULL); 1838 if (*Packet == NULL) { 1839 FreePool (Frag.Bulk); 1840 return EFI_OUT_OF_RESOURCES; 1841 } 1842 1843 // 1844 // Store the UdpIo in ProtoData. 1845 // 1846 *((UINTN *) &((*Packet)->ProtoData[0])) = (UINTN) (Instance->UdpIo); 1847 1848 return EFI_SUCCESS; 1849 } 1850 1851 /** 1852 Retransmit the packet. 1853 1854 @param Instance The DNS instance 1855 @param Packet Retransmit the packet 1856 1857 @retval EFI_SUCCESS The packet is retransmitted. 1858 @retval Others Failed to retransmit. 1859 1860 **/ 1861 EFI_STATUS 1862 DnsRetransmit ( 1863 IN DNS_INSTANCE *Instance, 1864 IN NET_BUF *Packet 1865 ) 1866 { 1867 EFI_STATUS Status; 1868 1869 UINT8 *Buffer; 1870 1871 ASSERT (Packet != NULL); 1872 1873 // 1874 // Set the requests to the listening port, other packets to the connected port 1875 // 1876 Buffer = NetbufGetByte (Packet, 0, NULL); 1877 ASSERT (Buffer != NULL); 1878 1879 NET_GET_REF (Packet); 1880 1881 Status = UdpIoSendDatagram ( 1882 Instance->UdpIo, 1883 Packet, 1884 NULL, 1885 NULL, 1886 DnsOnPacketSent, 1887 Instance 1888 ); 1889 1890 if (EFI_ERROR (Status)) { 1891 NET_PUT_REF (Packet); 1892 } 1893 1894 return Status; 1895 } 1896 1897 /** 1898 The timer ticking function for the DNS services. 1899 1900 @param Event The ticking event 1901 @param Context The DNS service instance 1902 1903 **/ 1904 VOID 1905 EFIAPI 1906 DnsOnTimerRetransmit ( 1907 IN EFI_EVENT Event, 1908 IN VOID *Context 1909 ) 1910 { 1911 DNS_SERVICE *Service; 1912 1913 LIST_ENTRY *Entry; 1914 LIST_ENTRY *Next; 1915 1916 DNS_INSTANCE *Instance; 1917 LIST_ENTRY *EntryNetMap; 1918 NET_MAP_ITEM *ItemNetMap; 1919 DNS4_TOKEN_ENTRY *Dns4TokenEntry; 1920 DNS6_TOKEN_ENTRY *Dns6TokenEntry; 1921 1922 Dns4TokenEntry = NULL; 1923 Dns6TokenEntry = NULL; 1924 1925 Service = (DNS_SERVICE *) Context; 1926 1927 1928 if (Service->IpVersion == IP_VERSION_4) { 1929 // 1930 // Iterate through all the children of the DNS service instance. Time 1931 // out the packet. If maximum retries reached, clean the Token up. 1932 // 1933 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Service->Dns4ChildrenList) { 1934 Instance = NET_LIST_USER_STRUCT (Entry, DNS_INSTANCE, Link); 1935 1936 EntryNetMap = Instance->Dns4TxTokens.Used.ForwardLink; 1937 while (EntryNetMap != &Instance->Dns4TxTokens.Used) { 1938 ItemNetMap = NET_LIST_USER_STRUCT (EntryNetMap, NET_MAP_ITEM, Link); 1939 Dns4TokenEntry = (DNS4_TOKEN_ENTRY *)(ItemNetMap->Key); 1940 if (Dns4TokenEntry->PacketToLive == 0 || (--Dns4TokenEntry->PacketToLive > 0)) { 1941 EntryNetMap = EntryNetMap->ForwardLink; 1942 continue; 1943 } 1944 1945 // 1946 // Retransmit the packet if haven't reach the maxmium retry count, 1947 // otherwise exit the transfer. 1948 // 1949 if (++Dns4TokenEntry->Token->RetryCount < Instance->MaxRetry) { 1950 DnsRetransmit (Instance, (NET_BUF *)ItemNetMap->Value); 1951 EntryNetMap = EntryNetMap->ForwardLink; 1952 } else { 1953 // 1954 // Maximum retries reached, clean the Token up. 1955 // 1956 Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry); 1957 Dns4TokenEntry->Token->Status = EFI_TIMEOUT; 1958 gBS->SignalEvent (Dns4TokenEntry->Token->Event); 1959 DispatchDpc (); 1960 1961 // 1962 // Free the sending packet. 1963 // 1964 if (ItemNetMap->Value != NULL) { 1965 NetbufFree ((NET_BUF *)(ItemNetMap->Value)); 1966 } 1967 1968 EntryNetMap = Instance->Dns4TxTokens.Used.ForwardLink; 1969 } 1970 } 1971 } 1972 }else { 1973 // 1974 // Iterate through all the children of the DNS service instance. Time 1975 // out the packet. If maximum retries reached, clean the Token up. 1976 // 1977 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Service->Dns6ChildrenList) { 1978 Instance = NET_LIST_USER_STRUCT (Entry, DNS_INSTANCE, Link); 1979 1980 EntryNetMap = Instance->Dns6TxTokens.Used.ForwardLink; 1981 while (EntryNetMap != &Instance->Dns6TxTokens.Used) { 1982 ItemNetMap = NET_LIST_USER_STRUCT (EntryNetMap, NET_MAP_ITEM, Link); 1983 Dns6TokenEntry = (DNS6_TOKEN_ENTRY *) (ItemNetMap->Key); 1984 if (Dns6TokenEntry->PacketToLive == 0 || (--Dns6TokenEntry->PacketToLive > 0)) { 1985 EntryNetMap = EntryNetMap->ForwardLink; 1986 continue; 1987 } 1988 1989 // 1990 // Retransmit the packet if haven't reach the maxmium retry count, 1991 // otherwise exit the transfer. 1992 // 1993 if (++Dns6TokenEntry->Token->RetryCount < Instance->MaxRetry) { 1994 DnsRetransmit (Instance, (NET_BUF *) ItemNetMap->Value); 1995 EntryNetMap = EntryNetMap->ForwardLink; 1996 } else { 1997 // 1998 // Maximum retries reached, clean the Token up. 1999 // 2000 Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry); 2001 Dns6TokenEntry->Token->Status = EFI_TIMEOUT; 2002 gBS->SignalEvent (Dns6TokenEntry->Token->Event); 2003 DispatchDpc (); 2004 2005 // 2006 // Free the sending packet. 2007 // 2008 if (ItemNetMap->Value != NULL) { 2009 NetbufFree ((NET_BUF *) (ItemNetMap->Value)); 2010 } 2011 2012 EntryNetMap = Instance->Dns6TxTokens.Used.ForwardLink; 2013 } 2014 } 2015 } 2016 } 2017 } 2018 2019 /** 2020 The timer ticking function for the DNS driver. 2021 2022 @param Event The ticking event 2023 @param Context NULL 2024 2025 **/ 2026 VOID 2027 EFIAPI 2028 DnsOnTimerUpdate ( 2029 IN EFI_EVENT Event, 2030 IN VOID *Context 2031 ) 2032 { 2033 LIST_ENTRY *Entry; 2034 LIST_ENTRY *Next; 2035 DNS4_CACHE *Item4; 2036 DNS6_CACHE *Item6; 2037 2038 Item4 = NULL; 2039 Item6 = NULL; 2040 2041 // 2042 // Iterate through all the DNS4 cache list. 2043 // 2044 NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) { 2045 Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink); 2046 Item4->DnsCache.Timeout--; 2047 } 2048 2049 Entry = mDriverData->Dns4CacheList.ForwardLink; 2050 while (Entry != &mDriverData->Dns4CacheList) { 2051 Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink); 2052 if (Item4->DnsCache.Timeout == 0) { 2053 RemoveEntryList (&Item4->AllCacheLink); 2054 Entry = mDriverData->Dns4CacheList.ForwardLink; 2055 } else { 2056 Entry = Entry->ForwardLink; 2057 } 2058 } 2059 2060 // 2061 // Iterate through all the DNS6 cache list. 2062 // 2063 NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6CacheList) { 2064 Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink); 2065 Item6->DnsCache.Timeout--; 2066 } 2067 2068 Entry = mDriverData->Dns6CacheList.ForwardLink; 2069 while (Entry != &mDriverData->Dns6CacheList) { 2070 Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink); 2071 if (Item6->DnsCache.Timeout == 0) { 2072 RemoveEntryList (&Item6->AllCacheLink); 2073 Entry = mDriverData->Dns6CacheList.ForwardLink; 2074 } else { 2075 Entry = Entry->ForwardLink; 2076 } 2077 } 2078 } 2079 2080