1 /** @file 2 DnsDxe support functions implementation. 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 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 Ip6Mode.IsConfigured) { 623 624 Udp->Configure (Udp, NULL); 625 return (BOOLEAN) (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS); 626 } 627 } 628 629 return FALSE; 630 } 631 632 /** 633 Configure the UDP. 634 635 @param Instance The DNS session 636 @param UdpIo The UDP_IO instance 637 638 @retval EFI_SUCCESS The UDP is successfully configured for the 639 session. 640 641 **/ 642 EFI_STATUS 643 Dns4ConfigUdp ( 644 IN DNS_INSTANCE *Instance, 645 IN UDP_IO *UdpIo 646 ) 647 { 648 EFI_DNS4_CONFIG_DATA *Config; 649 EFI_UDP4_CONFIG_DATA UdpConfig; 650 EFI_STATUS Status; 651 652 Config = &Instance->Dns4CfgData; 653 654 UdpConfig.AcceptBroadcast = FALSE; 655 UdpConfig.AcceptPromiscuous = FALSE; 656 UdpConfig.AcceptAnyPort = FALSE; 657 UdpConfig.AllowDuplicatePort = FALSE; 658 UdpConfig.TypeOfService = 0; 659 UdpConfig.TimeToLive = 128; 660 UdpConfig.DoNotFragment = FALSE; 661 UdpConfig.ReceiveTimeout = 0; 662 UdpConfig.TransmitTimeout = 0; 663 UdpConfig.UseDefaultAddress = Config->UseDefaultSetting; 664 UdpConfig.SubnetMask = Config->SubnetMask; 665 UdpConfig.StationPort = Config->LocalPort; 666 UdpConfig.RemotePort = DNS_SERVER_PORT; 667 668 CopyMem (&UdpConfig.StationAddress, &Config->StationIp, sizeof (EFI_IPv4_ADDRESS)); 669 CopyMem (&UdpConfig.RemoteAddress, &Instance->SessionDnsServer.v4, sizeof (EFI_IPv4_ADDRESS)); 670 671 Status = UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfig); 672 673 if ((Status == EFI_NO_MAPPING) && Dns4GetMapping (Instance, UdpIo, &UdpConfig)) { 674 return EFI_SUCCESS; 675 } 676 677 return Status; 678 } 679 680 /** 681 Configure the UDP. 682 683 @param Instance The DNS session 684 @param UdpIo The UDP_IO instance 685 686 @retval EFI_SUCCESS The UDP is successfully configured for the 687 session. 688 689 **/ 690 EFI_STATUS 691 Dns6ConfigUdp ( 692 IN DNS_INSTANCE *Instance, 693 IN UDP_IO *UdpIo 694 ) 695 { 696 EFI_DNS6_CONFIG_DATA *Config; 697 EFI_UDP6_CONFIG_DATA UdpConfig; 698 EFI_STATUS Status; 699 700 Config = &Instance->Dns6CfgData; 701 702 UdpConfig.AcceptPromiscuous = FALSE; 703 UdpConfig.AcceptAnyPort = FALSE; 704 UdpConfig.AllowDuplicatePort = FALSE; 705 UdpConfig.TrafficClass = 0; 706 UdpConfig.HopLimit = 128; 707 UdpConfig.ReceiveTimeout = 0; 708 UdpConfig.TransmitTimeout = 0; 709 UdpConfig.StationPort = Config->LocalPort; 710 UdpConfig.RemotePort = DNS_SERVER_PORT; 711 CopyMem (&UdpConfig.StationAddress, &Config->StationIp, sizeof (EFI_IPv6_ADDRESS)); 712 CopyMem (&UdpConfig.RemoteAddress, &Instance->SessionDnsServer.v6, sizeof (EFI_IPv6_ADDRESS)); 713 714 Status = UdpIo->Protocol.Udp6->Configure (UdpIo->Protocol.Udp6, &UdpConfig); 715 716 if ((Status == EFI_NO_MAPPING) && Dns6GetMapping (Instance, UdpIo, &UdpConfig)) { 717 return EFI_SUCCESS; 718 } 719 720 return Status; 721 } 722 723 /** 724 Update Dns4 cache to shared list of caches of all DNSv4 instances. 725 726 @param Dns4CacheList All Dns4 cache list. 727 @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache. 728 If TRUE, this function will delete matching DNS Cache entry. 729 @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter. 730 If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists. 731 @param DnsCacheEntry Entry Pointer to DNS Cache entry. 732 733 @retval EFI_SUCCESS Update Dns4 cache successfully. 734 @retval Others Failed to update Dns4 cache. 735 736 **/ 737 EFI_STATUS 738 EFIAPI 739 UpdateDns4Cache ( 740 IN LIST_ENTRY *Dns4CacheList, 741 IN BOOLEAN DeleteFlag, 742 IN BOOLEAN Override, 743 IN EFI_DNS4_CACHE_ENTRY DnsCacheEntry 744 ) 745 { 746 DNS4_CACHE *NewDnsCache; 747 DNS4_CACHE *Item; 748 LIST_ENTRY *Entry; 749 LIST_ENTRY *Next; 750 751 NewDnsCache = NULL; 752 Item = NULL; 753 754 // 755 // Search the database for the matching EFI_DNS_CACHE_ENTRY 756 // 757 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns4CacheList) { 758 Item = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink); 759 if (StrCmp (DnsCacheEntry.HostName, Item->DnsCache.HostName) == 0 && \ 760 CompareMem (DnsCacheEntry.IpAddress, Item->DnsCache.IpAddress, sizeof (EFI_IPv4_ADDRESS)) == 0) { 761 // 762 // This is the Dns cache entry 763 // 764 if (DeleteFlag) { 765 // 766 // Delete matching DNS Cache entry 767 // 768 RemoveEntryList (&Item->AllCacheLink); 769 770 return EFI_SUCCESS; 771 } else if (Override) { 772 // 773 // Update this one 774 // 775 Item->DnsCache.Timeout = DnsCacheEntry.Timeout; 776 777 return EFI_SUCCESS; 778 }else { 779 return EFI_ACCESS_DENIED; 780 } 781 } 782 } 783 784 // 785 // Add new one 786 // 787 NewDnsCache = AllocatePool (sizeof (DNS4_CACHE)); 788 if (NewDnsCache == NULL) { 789 return EFI_OUT_OF_RESOURCES; 790 } 791 792 InitializeListHead (&NewDnsCache->AllCacheLink); 793 794 NewDnsCache->DnsCache.HostName = AllocatePool (StrSize (DnsCacheEntry.HostName)); 795 if (NewDnsCache->DnsCache.HostName == NULL) { 796 return EFI_OUT_OF_RESOURCES; 797 } 798 799 CopyMem (NewDnsCache->DnsCache.HostName, DnsCacheEntry.HostName, StrSize (DnsCacheEntry.HostName)); 800 801 NewDnsCache->DnsCache.IpAddress = AllocatePool (sizeof (EFI_IPv4_ADDRESS)); 802 if (NewDnsCache->DnsCache.IpAddress == NULL) { 803 return EFI_OUT_OF_RESOURCES; 804 } 805 806 CopyMem (NewDnsCache->DnsCache.IpAddress, DnsCacheEntry.IpAddress, sizeof (EFI_IPv4_ADDRESS)); 807 808 NewDnsCache->DnsCache.Timeout = DnsCacheEntry.Timeout; 809 810 InsertTailList (Dns4CacheList, &NewDnsCache->AllCacheLink); 811 812 return EFI_SUCCESS; 813 } 814 815 /** 816 Update Dns6 cache to shared list of caches of all DNSv6 instances. 817 818 @param Dns6CacheList All Dns6 cache list. 819 @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache. 820 If TRUE, this function will delete matching DNS Cache entry. 821 @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter. 822 If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists. 823 @param DnsCacheEntry Entry Pointer to DNS Cache entry. 824 825 @retval EFI_SUCCESS Update Dns6 cache successfully. 826 @retval Others Failed to update Dns6 cache. 827 **/ 828 EFI_STATUS 829 EFIAPI 830 UpdateDns6Cache ( 831 IN LIST_ENTRY *Dns6CacheList, 832 IN BOOLEAN DeleteFlag, 833 IN BOOLEAN Override, 834 IN EFI_DNS6_CACHE_ENTRY DnsCacheEntry 835 ) 836 { 837 DNS6_CACHE *NewDnsCache; 838 DNS6_CACHE *Item; 839 LIST_ENTRY *Entry; 840 LIST_ENTRY *Next; 841 842 NewDnsCache = NULL; 843 Item = NULL; 844 845 // 846 // Search the database for the matching EFI_DNS_CACHE_ENTRY 847 // 848 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns6CacheList) { 849 Item = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink); 850 if (StrCmp (DnsCacheEntry.HostName, Item->DnsCache.HostName) == 0 && \ 851 CompareMem (DnsCacheEntry.IpAddress, Item->DnsCache.IpAddress, sizeof (EFI_IPv6_ADDRESS)) == 0) { 852 // 853 // This is the Dns cache entry 854 // 855 if (DeleteFlag) { 856 // 857 // Delete matching DNS Cache entry 858 // 859 RemoveEntryList (&Item->AllCacheLink); 860 861 return EFI_SUCCESS; 862 } else if (Override) { 863 // 864 // Update this one 865 // 866 Item->DnsCache.Timeout = DnsCacheEntry.Timeout; 867 868 return EFI_SUCCESS; 869 }else { 870 return EFI_ACCESS_DENIED; 871 } 872 } 873 } 874 875 // 876 // Add new one 877 // 878 NewDnsCache = AllocatePool (sizeof (DNS6_CACHE)); 879 if (NewDnsCache == NULL) { 880 return EFI_OUT_OF_RESOURCES; 881 } 882 883 InitializeListHead (&NewDnsCache->AllCacheLink); 884 885 NewDnsCache->DnsCache.HostName = AllocatePool (StrSize (DnsCacheEntry.HostName)); 886 if (NewDnsCache->DnsCache.HostName == NULL) { 887 return EFI_OUT_OF_RESOURCES; 888 } 889 890 CopyMem (NewDnsCache->DnsCache.HostName, DnsCacheEntry.HostName, StrSize (DnsCacheEntry.HostName)); 891 892 NewDnsCache->DnsCache.IpAddress = AllocatePool (sizeof (EFI_IPv6_ADDRESS)); 893 if (NewDnsCache->DnsCache.IpAddress == NULL) { 894 return EFI_OUT_OF_RESOURCES; 895 } 896 897 CopyMem (NewDnsCache->DnsCache.IpAddress, DnsCacheEntry.IpAddress, sizeof (EFI_IPv6_ADDRESS)); 898 899 NewDnsCache->DnsCache.Timeout = DnsCacheEntry.Timeout; 900 901 InsertTailList (Dns6CacheList, &NewDnsCache->AllCacheLink); 902 903 return EFI_SUCCESS; 904 } 905 906 /** 907 Add Dns4 ServerIp to common list of addresses of all configured DNSv4 server. 908 909 @param Dns4ServerList Common list of addresses of all configured DNSv4 server. 910 @param ServerIp DNS server Ip. 911 912 @retval EFI_SUCCESS Add Dns4 ServerIp to common list successfully. 913 @retval Others Failed to add Dns4 ServerIp to common list. 914 915 **/ 916 EFI_STATUS 917 EFIAPI 918 AddDns4ServerIp ( 919 IN LIST_ENTRY *Dns4ServerList, 920 IN EFI_IPv4_ADDRESS ServerIp 921 ) 922 { 923 DNS4_SERVER_IP *NewServerIp; 924 DNS4_SERVER_IP *Item; 925 LIST_ENTRY *Entry; 926 LIST_ENTRY *Next; 927 928 NewServerIp = NULL; 929 Item = NULL; 930 931 // 932 // Search the database for the matching ServerIp 933 // 934 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns4ServerList) { 935 Item = NET_LIST_USER_STRUCT (Entry, DNS4_SERVER_IP, AllServerLink); 936 if (CompareMem (&Item->Dns4ServerIp, &ServerIp, sizeof (EFI_IPv4_ADDRESS)) == 0) { 937 // 938 // Already done. 939 // 940 return EFI_SUCCESS; 941 } 942 } 943 944 // 945 // Add new one 946 // 947 NewServerIp = AllocatePool (sizeof (DNS4_SERVER_IP)); 948 if (NewServerIp == NULL) { 949 return EFI_OUT_OF_RESOURCES; 950 } 951 952 InitializeListHead (&NewServerIp->AllServerLink); 953 954 CopyMem (&NewServerIp->Dns4ServerIp, &ServerIp, sizeof (EFI_IPv4_ADDRESS)); 955 956 InsertTailList (Dns4ServerList, &NewServerIp->AllServerLink); 957 958 return EFI_SUCCESS; 959 } 960 961 /** 962 Add Dns6 ServerIp to common list of addresses of all configured DNSv6 server. 963 964 @param Dns6ServerList Common list of addresses of all configured DNSv6 server. 965 @param ServerIp DNS server Ip. 966 967 @retval EFI_SUCCESS Add Dns6 ServerIp to common list successfully. 968 @retval Others Failed to add Dns6 ServerIp to common list. 969 970 **/ 971 EFI_STATUS 972 EFIAPI 973 AddDns6ServerIp ( 974 IN LIST_ENTRY *Dns6ServerList, 975 IN EFI_IPv6_ADDRESS ServerIp 976 ) 977 { 978 DNS6_SERVER_IP *NewServerIp; 979 DNS6_SERVER_IP *Item; 980 LIST_ENTRY *Entry; 981 LIST_ENTRY *Next; 982 983 NewServerIp = NULL; 984 Item = NULL; 985 986 // 987 // Search the database for the matching ServerIp 988 // 989 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns6ServerList) { 990 Item = NET_LIST_USER_STRUCT (Entry, DNS6_SERVER_IP, AllServerLink); 991 if (CompareMem (&Item->Dns6ServerIp, &ServerIp, sizeof (EFI_IPv6_ADDRESS)) == 0) { 992 // 993 // Already done. 994 // 995 return EFI_SUCCESS; 996 } 997 } 998 999 // 1000 // Add new one 1001 // 1002 NewServerIp = AllocatePool (sizeof (DNS6_SERVER_IP)); 1003 if (NewServerIp == NULL) { 1004 return EFI_OUT_OF_RESOURCES; 1005 } 1006 1007 InitializeListHead (&NewServerIp->AllServerLink); 1008 1009 CopyMem (&NewServerIp->Dns6ServerIp, &ServerIp, sizeof (EFI_IPv6_ADDRESS)); 1010 1011 InsertTailList (Dns6ServerList, &NewServerIp->AllServerLink); 1012 1013 return EFI_SUCCESS; 1014 } 1015 1016 /** 1017 Fill QName for IP querying. QName is a domain name represented as 1018 a sequence of labels, where each label consists of a length octet 1019 followed by that number of octets. The domain name terminates with 1020 the zero length octet for the null label of the root. Caller should 1021 take responsibility to the buffer in QName. 1022 1023 @param HostName Queried HostName 1024 1025 @retval NULL Failed to fill QName. 1026 @return QName filled successfully. 1027 1028 **/ 1029 CHAR8 * 1030 EFIAPI 1031 DnsFillinQNameForQueryIp ( 1032 IN CHAR16 *HostName 1033 ) 1034 { 1035 CHAR8 *QueryName; 1036 CHAR8 *Header; 1037 CHAR8 *Tail; 1038 UINTN Len; 1039 UINTN Index; 1040 1041 QueryName = NULL; 1042 Header = NULL; 1043 Tail = NULL; 1044 1045 QueryName = AllocateZeroPool (DNS_DEFAULT_BLKSIZE); 1046 if (QueryName == NULL) { 1047 return NULL; 1048 } 1049 1050 Header = QueryName; 1051 Tail = Header + 1; 1052 Len = 0; 1053 for (Index = 0; HostName[Index] != 0; Index++) { 1054 *Tail = (CHAR8) HostName[Index]; 1055 if (*Tail == '.') { 1056 *Header = (CHAR8) Len; 1057 Header = Tail; 1058 Tail ++; 1059 Len = 0; 1060 } else { 1061 Tail++; 1062 Len++; 1063 } 1064 } 1065 *Header = (CHAR8) Len; 1066 *Tail = 0; 1067 1068 return QueryName; 1069 } 1070 1071 /** 1072 Find out whether the response is valid or invalid. 1073 1074 @param TokensMap All DNS transmittal Tokens entry. 1075 @param Identification Identification for queried packet. 1076 @param Type Type for queried packet. 1077 @param Item Return corresponding Token entry. 1078 1079 @retval TRUE The response is valid. 1080 @retval FALSE The response is invalid. 1081 1082 **/ 1083 BOOLEAN 1084 IsValidDnsResponse ( 1085 IN NET_MAP *TokensMap, 1086 IN UINT16 Identification, 1087 IN UINT16 Type, 1088 OUT NET_MAP_ITEM **Item 1089 ) 1090 { 1091 LIST_ENTRY *Entry; 1092 1093 NET_BUF *Packet; 1094 UINT8 *TxString; 1095 DNS_HEADER *DnsHeader; 1096 CHAR8 *QueryName; 1097 DNS_QUERY_SECTION *QuerySection; 1098 1099 NET_LIST_FOR_EACH (Entry, &TokensMap->Used) { 1100 *Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link); 1101 Packet = (NET_BUF *) ((*Item)->Value); 1102 if (Packet == NULL){ 1103 1104 continue; 1105 } else { 1106 TxString = NetbufGetByte (Packet, 0, NULL); 1107 ASSERT (TxString != NULL); 1108 DnsHeader = (DNS_HEADER *) TxString; 1109 QueryName = (CHAR8 *) (TxString + sizeof (*DnsHeader)); 1110 QuerySection = (DNS_QUERY_SECTION *) (QueryName + AsciiStrLen (QueryName) + 1); 1111 1112 DnsHeader->Identification = NTOHS (DnsHeader->Identification); 1113 QuerySection->Type = NTOHS (QuerySection->Type); 1114 1115 if (DnsHeader->Identification == Identification && QuerySection->Type == Type) { 1116 return TRUE; 1117 } 1118 } 1119 } 1120 1121 *Item =NULL; 1122 1123 return FALSE; 1124 } 1125 1126 /** 1127 Parse Dns Response. 1128 1129 @param Instance The DNS instance 1130 @param RxString Received buffer. 1131 @param Completed Flag to indicate that Dns response is valid. 1132 1133 @retval EFI_SUCCESS Parse Dns Response successfully. 1134 @retval Others Failed to parse Dns Response. 1135 1136 **/ 1137 EFI_STATUS 1138 ParseDnsResponse ( 1139 IN OUT DNS_INSTANCE *Instance, 1140 IN UINT8 *RxString, 1141 OUT BOOLEAN *Completed 1142 ) 1143 { 1144 DNS_HEADER *DnsHeader; 1145 1146 CHAR8 *QueryName; 1147 DNS_QUERY_SECTION *QuerySection; 1148 1149 CHAR8 *AnswerName; 1150 DNS_ANSWER_SECTION *AnswerSection; 1151 UINT8 *AnswerData; 1152 1153 NET_MAP_ITEM *Item; 1154 DNS4_TOKEN_ENTRY *Dns4TokenEntry; 1155 DNS6_TOKEN_ENTRY *Dns6TokenEntry; 1156 1157 UINT32 IpCount; 1158 UINT32 RRCount; 1159 UINT32 AnswerSectionNum; 1160 1161 EFI_IPv4_ADDRESS *HostAddr4; 1162 EFI_IPv6_ADDRESS *HostAddr6; 1163 1164 EFI_DNS4_CACHE_ENTRY *Dns4CacheEntry; 1165 EFI_DNS6_CACHE_ENTRY *Dns6CacheEntry; 1166 1167 DNS_RESOURCE_RECORD *Dns4RR; 1168 DNS6_RESOURCE_RECORD *Dns6RR; 1169 1170 EFI_STATUS Status; 1171 1172 EFI_TPL OldTpl; 1173 1174 Item = NULL; 1175 Dns4TokenEntry = NULL; 1176 Dns6TokenEntry = NULL; 1177 1178 IpCount = 0; 1179 RRCount = 0; 1180 AnswerSectionNum = 0; 1181 1182 HostAddr4 = NULL; 1183 HostAddr6 = NULL; 1184 1185 Dns4CacheEntry = NULL; 1186 Dns6CacheEntry = NULL; 1187 1188 Dns4RR = NULL; 1189 Dns6RR = NULL; 1190 1191 *Completed = TRUE; 1192 Status = EFI_SUCCESS; 1193 1194 // 1195 // Get header 1196 // 1197 DnsHeader = (DNS_HEADER *) RxString; 1198 1199 DnsHeader->Identification = NTOHS (DnsHeader->Identification); 1200 DnsHeader->Flags.Uint16 = NTOHS (DnsHeader->Flags.Uint16); 1201 DnsHeader->QuestionsNum = NTOHS (DnsHeader->QuestionsNum); 1202 DnsHeader->AnswersNum = NTOHS (DnsHeader->AnswersNum); 1203 DnsHeader->AuthorityNum = NTOHS (DnsHeader->AuthorityNum); 1204 DnsHeader->AditionalNum = NTOHS (DnsHeader->AditionalNum); 1205 1206 // 1207 // Get Query name 1208 // 1209 QueryName = (CHAR8 *) (RxString + sizeof (*DnsHeader)); 1210 1211 // 1212 // Get query section 1213 // 1214 QuerySection = (DNS_QUERY_SECTION *) (QueryName + AsciiStrLen (QueryName) + 1); 1215 QuerySection->Type = NTOHS (QuerySection->Type); 1216 QuerySection->Class = NTOHS (QuerySection->Class); 1217 1218 // 1219 // Get Answer name 1220 // 1221 AnswerName = (CHAR8 *) QuerySection + sizeof (*QuerySection); 1222 1223 OldTpl = gBS->RaiseTPL (TPL_CALLBACK); 1224 1225 // 1226 // Check DnsResponse Validity, if so, also get a valid NET_MAP_ITEM. 1227 // 1228 if (Instance->Service->IpVersion == IP_VERSION_4) { 1229 if (!IsValidDnsResponse (&Instance->Dns4TxTokens, DnsHeader->Identification, QuerySection->Type, &Item)) { 1230 *Completed = FALSE; 1231 Status = EFI_ABORTED; 1232 goto ON_EXIT; 1233 } 1234 ASSERT (Item != NULL); 1235 Dns4TokenEntry = (DNS4_TOKEN_ENTRY *) (Item->Key); 1236 } else { 1237 if (!IsValidDnsResponse (&Instance->Dns6TxTokens, DnsHeader->Identification, QuerySection->Type, &Item)) { 1238 *Completed = FALSE; 1239 Status = EFI_ABORTED; 1240 goto ON_EXIT; 1241 } 1242 ASSERT (Item != NULL); 1243 Dns6TokenEntry = (DNS6_TOKEN_ENTRY *) (Item->Key); 1244 } 1245 1246 // 1247 // Continue Check Some Errors. 1248 // 1249 if (DnsHeader->Flags.Bits.RCode != DNS_FLAGS_RCODE_NO_ERROR || DnsHeader->AnswersNum < 1 || \ 1250 DnsHeader->Flags.Bits.QR != DNS_FLAGS_QR_RESPONSE || QuerySection->Class != DNS_CLASS_INET) { 1251 Status = EFI_ABORTED; 1252 goto ON_EXIT; 1253 } 1254 1255 // 1256 // Free the sending packet. 1257 // 1258 if (Item->Value != NULL) { 1259 NetbufFree ((NET_BUF *) (Item->Value)); 1260 } 1261 1262 // 1263 // Do some buffer allocations. 1264 // 1265 if (Instance->Service->IpVersion == IP_VERSION_4) { 1266 ASSERT (Dns4TokenEntry != NULL); 1267 1268 if (Dns4TokenEntry->GeneralLookUp) { 1269 // 1270 // It's the GeneralLookUp querying. 1271 // 1272 Dns4TokenEntry->Token->RspData.GLookupData = AllocatePool (sizeof (DNS_RESOURCE_RECORD)); 1273 if (Dns4TokenEntry->Token->RspData.GLookupData == NULL) { 1274 Status = EFI_OUT_OF_RESOURCES; 1275 goto ON_EXIT; 1276 } 1277 Dns4TokenEntry->Token->RspData.GLookupData->RRList = AllocatePool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD)); 1278 if (Dns4TokenEntry->Token->RspData.GLookupData->RRList == NULL) { 1279 Status = EFI_OUT_OF_RESOURCES; 1280 goto ON_EXIT; 1281 } 1282 } else { 1283 // 1284 // It's not the GeneralLookUp querying. Check the Query type. 1285 // 1286 if (QuerySection->Type == DNS_TYPE_A) { 1287 Dns4TokenEntry->Token->RspData.H2AData = AllocatePool (sizeof (DNS_HOST_TO_ADDR_DATA)); 1288 if (Dns4TokenEntry->Token->RspData.H2AData == NULL) { 1289 Status = EFI_OUT_OF_RESOURCES; 1290 goto ON_EXIT; 1291 } 1292 Dns4TokenEntry->Token->RspData.H2AData->IpList = AllocatePool (DnsHeader->AnswersNum * sizeof (EFI_IPv4_ADDRESS)); 1293 if (Dns4TokenEntry->Token->RspData.H2AData->IpList == NULL) { 1294 Status = EFI_OUT_OF_RESOURCES; 1295 goto ON_EXIT; 1296 } 1297 } else { 1298 Status = EFI_UNSUPPORTED; 1299 goto ON_EXIT; 1300 } 1301 } 1302 } else { 1303 ASSERT (Dns6TokenEntry != NULL); 1304 1305 if (Dns6TokenEntry->GeneralLookUp) { 1306 // 1307 // It's the GeneralLookUp querying. 1308 // 1309 Dns6TokenEntry->Token->RspData.GLookupData = AllocatePool (sizeof (DNS_RESOURCE_RECORD)); 1310 if (Dns6TokenEntry->Token->RspData.GLookupData == NULL) { 1311 Status = EFI_UNSUPPORTED; 1312 goto ON_EXIT; 1313 } 1314 Dns6TokenEntry->Token->RspData.GLookupData->RRList = AllocatePool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD)); 1315 if (Dns6TokenEntry->Token->RspData.GLookupData->RRList == NULL) { 1316 Status = EFI_UNSUPPORTED; 1317 goto ON_EXIT; 1318 } 1319 } else { 1320 // 1321 // It's not the GeneralLookUp querying. Check the Query type. 1322 // 1323 if (QuerySection->Type == DNS_TYPE_AAAA) { 1324 Dns6TokenEntry->Token->RspData.H2AData = AllocatePool (sizeof (DNS6_HOST_TO_ADDR_DATA)); 1325 if (Dns6TokenEntry->Token->RspData.H2AData == NULL) { 1326 Status = EFI_UNSUPPORTED; 1327 goto ON_EXIT; 1328 } 1329 Dns6TokenEntry->Token->RspData.H2AData->IpList = AllocatePool (DnsHeader->AnswersNum * sizeof (EFI_IPv6_ADDRESS)); 1330 if (Dns6TokenEntry->Token->RspData.H2AData->IpList == NULL) { 1331 Status = EFI_UNSUPPORTED; 1332 goto ON_EXIT; 1333 } 1334 } else { 1335 Status = EFI_UNSUPPORTED; 1336 goto ON_EXIT; 1337 } 1338 } 1339 } 1340 1341 // 1342 // Processing AnswerSection. 1343 // 1344 while (AnswerSectionNum < DnsHeader->AnswersNum) { 1345 // 1346 // Answer name should be PTR. 1347 // 1348 ASSERT ((*(UINT8 *) AnswerName & 0xC0) == 0xC0); 1349 1350 // 1351 // Get Answer section. 1352 // 1353 AnswerSection = (DNS_ANSWER_SECTION *) (AnswerName + sizeof (UINT16)); 1354 AnswerSection->Type = NTOHS (AnswerSection->Type); 1355 AnswerSection->Class = NTOHS (AnswerSection->Class); 1356 AnswerSection->Ttl = NTOHL (AnswerSection->Ttl); 1357 AnswerSection->DataLength = NTOHS (AnswerSection->DataLength); 1358 1359 // 1360 // Check whether it's the GeneralLookUp querying. 1361 // 1362 if (Instance->Service->IpVersion == IP_VERSION_4 && Dns4TokenEntry->GeneralLookUp) { 1363 Dns4RR = Dns4TokenEntry->Token->RspData.GLookupData->RRList; 1364 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection); 1365 1366 // 1367 // Fill the ResourceRecord. 1368 // 1369 Dns4RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1); 1370 if (Dns4RR[RRCount].QName == NULL) { 1371 Status = EFI_UNSUPPORTED; 1372 goto ON_EXIT; 1373 } 1374 CopyMem (Dns4RR[RRCount].QName, QueryName, AsciiStrLen (QueryName)); 1375 Dns4RR[RRCount].QType = AnswerSection->Type; 1376 Dns4RR[RRCount].QClass = AnswerSection->Class; 1377 Dns4RR[RRCount].TTL = AnswerSection->Ttl; 1378 Dns4RR[RRCount].DataLength = AnswerSection->DataLength; 1379 Dns4RR[RRCount].RData = AllocateZeroPool (Dns4RR[RRCount].DataLength); 1380 if (Dns4RR[RRCount].RData == NULL) { 1381 Status = EFI_UNSUPPORTED; 1382 goto ON_EXIT; 1383 } 1384 CopyMem (Dns4RR[RRCount].RData, AnswerData, Dns4RR[RRCount].DataLength); 1385 1386 RRCount ++; 1387 } else if (Instance->Service->IpVersion == IP_VERSION_6 && Dns6TokenEntry->GeneralLookUp) { 1388 Dns6RR = Dns6TokenEntry->Token->RspData.GLookupData->RRList; 1389 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection); 1390 1391 // 1392 // Fill the ResourceRecord. 1393 // 1394 Dns6RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1); 1395 if (Dns6RR[RRCount].QName == NULL) { 1396 Status = EFI_UNSUPPORTED; 1397 goto ON_EXIT; 1398 } 1399 CopyMem (Dns6RR[RRCount].QName, QueryName, AsciiStrLen (QueryName)); 1400 Dns6RR[RRCount].QType = AnswerSection->Type; 1401 Dns6RR[RRCount].QClass = AnswerSection->Class; 1402 Dns6RR[RRCount].TTL = AnswerSection->Ttl; 1403 Dns6RR[RRCount].DataLength = AnswerSection->DataLength; 1404 Dns6RR[RRCount].RData = AllocateZeroPool (Dns6RR[RRCount].DataLength); 1405 if (Dns6RR[RRCount].RData == NULL) { 1406 Status = EFI_UNSUPPORTED; 1407 goto ON_EXIT; 1408 } 1409 CopyMem (Dns6RR[RRCount].RData, AnswerData, Dns6RR[RRCount].DataLength); 1410 1411 RRCount ++; 1412 } else { 1413 // 1414 // It's not the GeneralLookUp querying. 1415 // Check the Query type, parse the response packet. 1416 // 1417 switch (AnswerSection->Type) { 1418 case DNS_TYPE_A: 1419 // 1420 // This is address entry, get Data. 1421 // 1422 ASSERT (Dns4TokenEntry != NULL && AnswerSection->DataLength == 4); 1423 1424 HostAddr4 = Dns4TokenEntry->Token->RspData.H2AData->IpList; 1425 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection); 1426 CopyMem (&HostAddr4[IpCount], AnswerData, sizeof (EFI_IPv4_ADDRESS)); 1427 1428 // 1429 // Update DNS cache dynamically. 1430 // 1431 if (Dns4CacheEntry != NULL) { 1432 if (Dns4CacheEntry->HostName != NULL) { 1433 FreePool (Dns4CacheEntry->HostName); 1434 } 1435 1436 if (Dns4CacheEntry->IpAddress != NULL) { 1437 FreePool (Dns4CacheEntry->IpAddress); 1438 } 1439 1440 FreePool (Dns4CacheEntry); 1441 } 1442 1443 // 1444 // Allocate new CacheEntry pool. 1445 // 1446 Dns4CacheEntry = AllocateZeroPool (sizeof (EFI_DNS4_CACHE_ENTRY)); 1447 if (Dns4CacheEntry == NULL) { 1448 Status = EFI_UNSUPPORTED; 1449 goto ON_EXIT; 1450 } 1451 Dns4CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1)); 1452 if (Dns4CacheEntry->HostName == NULL) { 1453 Status = EFI_UNSUPPORTED; 1454 goto ON_EXIT; 1455 } 1456 CopyMem (Dns4CacheEntry->HostName, Dns4TokenEntry->QueryHostName, 2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1)); 1457 Dns4CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv4_ADDRESS)); 1458 if (Dns4CacheEntry->IpAddress == NULL) { 1459 Status = EFI_UNSUPPORTED; 1460 goto ON_EXIT; 1461 } 1462 CopyMem (Dns4CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv4_ADDRESS)); 1463 Dns4CacheEntry->Timeout = AnswerSection->Ttl; 1464 1465 UpdateDns4Cache (&mDriverData->Dns4CacheList, FALSE, TRUE, *Dns4CacheEntry); 1466 1467 IpCount ++; 1468 break; 1469 case DNS_TYPE_AAAA: 1470 // 1471 // This is address entry, get Data. 1472 // 1473 ASSERT (Dns6TokenEntry != NULL && AnswerSection->DataLength == 16); 1474 1475 HostAddr6 = Dns6TokenEntry->Token->RspData.H2AData->IpList; 1476 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection); 1477 CopyMem (&HostAddr6[IpCount], AnswerData, sizeof (EFI_IPv6_ADDRESS)); 1478 1479 // 1480 // Update DNS cache dynamically. 1481 // 1482 if (Dns6CacheEntry != NULL) { 1483 if (Dns6CacheEntry->HostName != NULL) { 1484 FreePool (Dns6CacheEntry->HostName); 1485 } 1486 1487 if (Dns6CacheEntry->IpAddress != NULL) { 1488 FreePool (Dns6CacheEntry->IpAddress); 1489 } 1490 1491 FreePool (Dns6CacheEntry); 1492 } 1493 1494 // 1495 // Allocate new CacheEntry pool. 1496 // 1497 Dns6CacheEntry = AllocateZeroPool (sizeof (EFI_DNS6_CACHE_ENTRY)); 1498 if (Dns6CacheEntry == NULL) { 1499 Status = EFI_UNSUPPORTED; 1500 goto ON_EXIT; 1501 } 1502 Dns6CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1)); 1503 if (Dns6CacheEntry->HostName == NULL) { 1504 Status = EFI_UNSUPPORTED; 1505 goto ON_EXIT; 1506 } 1507 CopyMem (Dns6CacheEntry->HostName, Dns6TokenEntry->QueryHostName, 2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1)); 1508 Dns6CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS)); 1509 if (Dns6CacheEntry->IpAddress == NULL) { 1510 Status = EFI_UNSUPPORTED; 1511 goto ON_EXIT; 1512 } 1513 CopyMem (Dns6CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv6_ADDRESS)); 1514 Dns6CacheEntry->Timeout = AnswerSection->Ttl; 1515 1516 UpdateDns6Cache (&mDriverData->Dns6CacheList, FALSE, TRUE, *Dns6CacheEntry); 1517 1518 IpCount ++; 1519 break; 1520 default: 1521 Status = EFI_UNSUPPORTED; 1522 goto ON_EXIT; 1523 } 1524 } 1525 1526 // 1527 // Find next one 1528 // 1529 AnswerName = (CHAR8 *) AnswerSection + sizeof (*AnswerSection) + AnswerSection->DataLength; 1530 AnswerSectionNum ++; 1531 } 1532 1533 if (Instance->Service->IpVersion == IP_VERSION_4) { 1534 ASSERT (Dns4TokenEntry != NULL); 1535 1536 if (Dns4TokenEntry->GeneralLookUp) { 1537 Dns4TokenEntry->Token->RspData.GLookupData->RRCount = RRCount; 1538 } else { 1539 if (QuerySection->Type == DNS_TYPE_A) { 1540 Dns4TokenEntry->Token->RspData.H2AData->IpCount = IpCount; 1541 } else { 1542 Status = EFI_UNSUPPORTED; 1543 goto ON_EXIT; 1544 } 1545 } 1546 } else { 1547 ASSERT (Dns6TokenEntry != NULL); 1548 1549 if (Dns6TokenEntry->GeneralLookUp) { 1550 Dns6TokenEntry->Token->RspData.GLookupData->RRCount = RRCount; 1551 } else { 1552 if (QuerySection->Type == DNS_TYPE_AAAA) { 1553 Dns6TokenEntry->Token->RspData.H2AData->IpCount = IpCount; 1554 } else { 1555 Status = EFI_UNSUPPORTED; 1556 goto ON_EXIT; 1557 } 1558 } 1559 } 1560 1561 // 1562 // Parsing is complete, SignalEvent here. 1563 // 1564 if (Instance->Service->IpVersion == IP_VERSION_4) { 1565 ASSERT (Dns4TokenEntry != NULL); 1566 Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry); 1567 Dns4TokenEntry->Token->Status = EFI_SUCCESS; 1568 if (Dns4TokenEntry->Token->Event != NULL) { 1569 gBS->SignalEvent (Dns4TokenEntry->Token->Event); 1570 DispatchDpc (); 1571 } 1572 } else { 1573 ASSERT (Dns6TokenEntry != NULL); 1574 Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry); 1575 Dns6TokenEntry->Token->Status = EFI_SUCCESS; 1576 if (Dns6TokenEntry->Token->Event != NULL) { 1577 gBS->SignalEvent (Dns6TokenEntry->Token->Event); 1578 DispatchDpc (); 1579 } 1580 } 1581 1582 // 1583 // Free allocated CacheEntry pool. 1584 // 1585 if (Dns4CacheEntry != NULL) { 1586 if (Dns4CacheEntry->HostName != NULL) { 1587 FreePool (Dns4CacheEntry->HostName); 1588 } 1589 1590 if (Dns4CacheEntry->IpAddress != NULL) { 1591 FreePool (Dns4CacheEntry->IpAddress); 1592 } 1593 1594 FreePool (Dns4CacheEntry); 1595 } 1596 1597 if (Dns6CacheEntry != NULL) { 1598 if (Dns6CacheEntry->HostName != NULL) { 1599 FreePool (Dns6CacheEntry->HostName); 1600 } 1601 1602 if (Dns6CacheEntry->IpAddress != NULL) { 1603 FreePool (Dns6CacheEntry->IpAddress); 1604 } 1605 1606 FreePool (Dns6CacheEntry); 1607 } 1608 1609 ON_EXIT: 1610 gBS->RestoreTPL (OldTpl); 1611 return Status; 1612 } 1613 1614 /** 1615 Parse response packet. 1616 1617 @param Packet The packets received. 1618 @param EndPoint The local/remote UDP access point 1619 @param IoStatus The status of the UDP receive 1620 @param Context The opaque parameter to the function. 1621 1622 **/ 1623 VOID 1624 EFIAPI 1625 DnsOnPacketReceived ( 1626 NET_BUF *Packet, 1627 UDP_END_POINT *EndPoint, 1628 EFI_STATUS IoStatus, 1629 VOID *Context 1630 ) 1631 { 1632 DNS_INSTANCE *Instance; 1633 1634 UINT8 *RcvString; 1635 1636 BOOLEAN Completed; 1637 1638 Instance = (DNS_INSTANCE *) Context; 1639 NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE); 1640 1641 RcvString = NULL; 1642 Completed = FALSE; 1643 1644 if (EFI_ERROR (IoStatus)) { 1645 goto ON_EXIT; 1646 } 1647 1648 ASSERT (Packet != NULL); 1649 1650 RcvString = NetbufGetByte (Packet, 0, NULL); 1651 ASSERT (RcvString != NULL); 1652 1653 // 1654 // Parse Dns Response 1655 // 1656 ParseDnsResponse (Instance, RcvString, &Completed); 1657 1658 ON_EXIT: 1659 1660 if (Packet != NULL) { 1661 NetbufFree (Packet); 1662 } 1663 1664 if (!Completed) { 1665 UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0); 1666 } 1667 } 1668 1669 /** 1670 Release the net buffer when packet is sent. 1671 1672 @param Packet The packets received. 1673 @param EndPoint The local/remote UDP access point 1674 @param IoStatus The status of the UDP receive 1675 @param Context The opaque parameter to the function. 1676 1677 **/ 1678 VOID 1679 EFIAPI 1680 DnsOnPacketSent ( 1681 NET_BUF *Packet, 1682 UDP_END_POINT *EndPoint, 1683 EFI_STATUS IoStatus, 1684 VOID *Context 1685 ) 1686 { 1687 DNS_INSTANCE *Instance; 1688 LIST_ENTRY *Entry; 1689 NET_MAP_ITEM *Item; 1690 DNS4_TOKEN_ENTRY *Dns4TokenEntry; 1691 DNS6_TOKEN_ENTRY *Dns6TokenEntry; 1692 1693 Dns4TokenEntry = NULL; 1694 Dns6TokenEntry = NULL; 1695 1696 Instance = (DNS_INSTANCE *) Context; 1697 NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE); 1698 1699 if (Instance->Service->IpVersion == IP_VERSION_4) { 1700 NET_LIST_FOR_EACH (Entry, &Instance->Dns4TxTokens.Used) { 1701 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link); 1702 if (Packet == (NET_BUF *)(Item->Value)) { 1703 Dns4TokenEntry = ((DNS4_TOKEN_ENTRY *)Item->Key); 1704 Dns4TokenEntry->PacketToLive = Dns4TokenEntry->Token->RetryInterval; 1705 break; 1706 } 1707 } 1708 } else { 1709 NET_LIST_FOR_EACH (Entry, &Instance->Dns6TxTokens.Used) { 1710 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link); 1711 if (Packet == (NET_BUF *)(Item->Value)) { 1712 Dns6TokenEntry = ((DNS6_TOKEN_ENTRY *)Item->Key); 1713 Dns6TokenEntry->PacketToLive = Dns6TokenEntry->Token->RetryInterval; 1714 break; 1715 } 1716 } 1717 } 1718 1719 NetbufFree (Packet); 1720 } 1721 1722 /** 1723 Query request information. 1724 1725 @param Instance The DNS instance 1726 @param Packet The packet for querying request information. 1727 1728 @retval EFI_SUCCESS Query request information successfully. 1729 @retval Others Failed to query request information. 1730 1731 **/ 1732 EFI_STATUS 1733 DoDnsQuery ( 1734 IN DNS_INSTANCE *Instance, 1735 IN NET_BUF *Packet 1736 ) 1737 { 1738 EFI_STATUS Status; 1739 1740 // 1741 // Ready to receive the DNS response. 1742 // 1743 if (Instance->UdpIo->RecvRequest == NULL) { 1744 Status = UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0); 1745 if (EFI_ERROR (Status)) { 1746 return Status; 1747 } 1748 } 1749 1750 // 1751 // Transmit the DNS packet. 1752 // 1753 NET_GET_REF (Packet); 1754 1755 Status = UdpIoSendDatagram (Instance->UdpIo, Packet, NULL, NULL, DnsOnPacketSent, Instance); 1756 1757 return Status; 1758 } 1759 1760 /** 1761 Construct the Packet according query section. 1762 1763 @param Instance The DNS instance 1764 @param QueryName Queried Name 1765 @param Type Queried Type 1766 @param Class Queried Class 1767 @param Packet The packet for query 1768 1769 @retval EFI_SUCCESS The packet is constructed. 1770 @retval Others Failed to construct the Packet. 1771 1772 **/ 1773 EFI_STATUS 1774 ConstructDNSQuery ( 1775 IN DNS_INSTANCE *Instance, 1776 IN CHAR8 *QueryName, 1777 IN UINT16 Type, 1778 IN UINT16 Class, 1779 OUT NET_BUF **Packet 1780 ) 1781 { 1782 NET_FRAGMENT Frag; 1783 DNS_HEADER *DnsHeader; 1784 DNS_QUERY_SECTION *DnsQuery; 1785 1786 Frag.Bulk = AllocatePool (DNS_DEFAULT_BLKSIZE * sizeof (UINT8)); 1787 if (Frag.Bulk == NULL) { 1788 return EFI_OUT_OF_RESOURCES; 1789 } 1790 1791 // 1792 // Fill header 1793 // 1794 DnsHeader = (DNS_HEADER *) Frag.Bulk; 1795 DnsHeader->Identification = (UINT16)NET_RANDOM (NetRandomInitSeed()); 1796 DnsHeader->Flags.Uint16 = 0x0000; 1797 DnsHeader->Flags.Bits.RD = 1; 1798 DnsHeader->Flags.Bits.OpCode = DNS_FLAGS_OPCODE_STANDARD; 1799 DnsHeader->Flags.Bits.QR = DNS_FLAGS_QR_QUERY; 1800 DnsHeader->QuestionsNum = 1; 1801 DnsHeader->AnswersNum = 0; 1802 DnsHeader->AuthorityNum = 0; 1803 DnsHeader->AditionalNum = 0; 1804 1805 DnsHeader->Identification = HTONS (DnsHeader->Identification); 1806 DnsHeader->Flags.Uint16 = HTONS (DnsHeader->Flags.Uint16); 1807 DnsHeader->QuestionsNum = HTONS (DnsHeader->QuestionsNum); 1808 DnsHeader->AnswersNum = HTONS (DnsHeader->AnswersNum); 1809 DnsHeader->AuthorityNum = HTONS (DnsHeader->AuthorityNum); 1810 DnsHeader->AditionalNum = HTONS (DnsHeader->AditionalNum); 1811 1812 Frag.Len = sizeof (*DnsHeader); 1813 1814 // 1815 // Fill Query name 1816 // 1817 CopyMem (Frag.Bulk + Frag.Len, QueryName, AsciiStrLen (QueryName)); 1818 Frag.Len = (UINT32) (Frag.Len + AsciiStrLen (QueryName)); 1819 *(Frag.Bulk + Frag.Len) = 0; 1820 Frag.Len ++; 1821 1822 // 1823 // Rest query section 1824 // 1825 DnsQuery = (DNS_QUERY_SECTION *) (Frag.Bulk + Frag.Len); 1826 1827 DnsQuery->Type = HTONS (Type); 1828 DnsQuery->Class = HTONS (Class); 1829 1830 Frag.Len += sizeof (*DnsQuery); 1831 1832 // 1833 // Wrap the Frag in a net buffer. 1834 // 1835 *Packet = NetbufFromExt (&Frag, 1, 0, 0, DnsDummyExtFree, NULL); 1836 if (*Packet == NULL) { 1837 FreePool (Frag.Bulk); 1838 return EFI_OUT_OF_RESOURCES; 1839 } 1840 1841 // 1842 // Store the UdpIo in ProtoData. 1843 // 1844 *((UINTN *) &((*Packet)->ProtoData[0])) = (UINTN) (Instance->UdpIo); 1845 1846 return EFI_SUCCESS; 1847 } 1848 1849 /** 1850 Retransmit the packet. 1851 1852 @param Instance The DNS instance 1853 @param Packet Retransmit the packet 1854 1855 @retval EFI_SUCCESS The packet is retransmitted. 1856 @retval Others Failed to retransmit. 1857 1858 **/ 1859 EFI_STATUS 1860 DnsRetransmit ( 1861 IN DNS_INSTANCE *Instance, 1862 IN NET_BUF *Packet 1863 ) 1864 { 1865 EFI_STATUS Status; 1866 1867 UINT8 *Buffer; 1868 1869 ASSERT (Packet != NULL); 1870 1871 // 1872 // Set the requests to the listening port, other packets to the connected port 1873 // 1874 Buffer = NetbufGetByte (Packet, 0, NULL); 1875 ASSERT (Buffer != NULL); 1876 1877 NET_GET_REF (Packet); 1878 1879 Status = UdpIoSendDatagram ( 1880 Instance->UdpIo, 1881 Packet, 1882 NULL, 1883 NULL, 1884 DnsOnPacketSent, 1885 Instance 1886 ); 1887 1888 if (EFI_ERROR (Status)) { 1889 NET_PUT_REF (Packet); 1890 } 1891 1892 return Status; 1893 } 1894 1895 /** 1896 The timer ticking function for the DNS services. 1897 1898 @param Event The ticking event 1899 @param Context The DNS service instance 1900 1901 **/ 1902 VOID 1903 EFIAPI 1904 DnsOnTimerRetransmit ( 1905 IN EFI_EVENT Event, 1906 IN VOID *Context 1907 ) 1908 { 1909 DNS_SERVICE *Service; 1910 1911 LIST_ENTRY *Entry; 1912 LIST_ENTRY *Next; 1913 1914 DNS_INSTANCE *Instance; 1915 LIST_ENTRY *EntryNetMap; 1916 NET_MAP_ITEM *ItemNetMap; 1917 DNS4_TOKEN_ENTRY *Dns4TokenEntry; 1918 DNS6_TOKEN_ENTRY *Dns6TokenEntry; 1919 1920 Dns4TokenEntry = NULL; 1921 Dns6TokenEntry = NULL; 1922 1923 Service = (DNS_SERVICE *) Context; 1924 1925 1926 if (Service->IpVersion == IP_VERSION_4) { 1927 // 1928 // Iterate through all the children of the DNS service instance. Time 1929 // out the packet. If maximum retries reached, clean the Token up. 1930 // 1931 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Service->Dns4ChildrenList) { 1932 Instance = NET_LIST_USER_STRUCT (Entry, DNS_INSTANCE, Link); 1933 1934 EntryNetMap = Instance->Dns4TxTokens.Used.ForwardLink; 1935 while (EntryNetMap != &Instance->Dns4TxTokens.Used) { 1936 ItemNetMap = NET_LIST_USER_STRUCT (EntryNetMap, NET_MAP_ITEM, Link); 1937 Dns4TokenEntry = (DNS4_TOKEN_ENTRY *)(ItemNetMap->Key); 1938 if (Dns4TokenEntry->PacketToLive == 0 || (--Dns4TokenEntry->PacketToLive > 0)) { 1939 EntryNetMap = EntryNetMap->ForwardLink; 1940 continue; 1941 } 1942 1943 // 1944 // Retransmit the packet if haven't reach the maxmium retry count, 1945 // otherwise exit the transfer. 1946 // 1947 if (++Dns4TokenEntry->Token->RetryCount < Instance->MaxRetry) { 1948 DnsRetransmit (Instance, (NET_BUF *)ItemNetMap->Value); 1949 EntryNetMap = EntryNetMap->ForwardLink; 1950 } else { 1951 // 1952 // Maximum retries reached, clean the Token up. 1953 // 1954 Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry); 1955 Dns4TokenEntry->Token->Status = EFI_TIMEOUT; 1956 gBS->SignalEvent (Dns4TokenEntry->Token->Event); 1957 DispatchDpc (); 1958 1959 // 1960 // Free the sending packet. 1961 // 1962 if (ItemNetMap->Value != NULL) { 1963 NetbufFree ((NET_BUF *)(ItemNetMap->Value)); 1964 } 1965 1966 EntryNetMap = Instance->Dns4TxTokens.Used.ForwardLink; 1967 } 1968 } 1969 } 1970 }else { 1971 // 1972 // Iterate through all the children of the DNS service instance. Time 1973 // out the packet. If maximum retries reached, clean the Token up. 1974 // 1975 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Service->Dns6ChildrenList) { 1976 Instance = NET_LIST_USER_STRUCT (Entry, DNS_INSTANCE, Link); 1977 1978 EntryNetMap = Instance->Dns6TxTokens.Used.ForwardLink; 1979 while (EntryNetMap != &Instance->Dns6TxTokens.Used) { 1980 ItemNetMap = NET_LIST_USER_STRUCT (EntryNetMap, NET_MAP_ITEM, Link); 1981 Dns6TokenEntry = (DNS6_TOKEN_ENTRY *) (ItemNetMap->Key); 1982 if (Dns6TokenEntry->PacketToLive == 0 || (--Dns6TokenEntry->PacketToLive > 0)) { 1983 EntryNetMap = EntryNetMap->ForwardLink; 1984 continue; 1985 } 1986 1987 // 1988 // Retransmit the packet if haven't reach the maxmium retry count, 1989 // otherwise exit the transfer. 1990 // 1991 if (++Dns6TokenEntry->Token->RetryCount < Instance->MaxRetry) { 1992 DnsRetransmit (Instance, (NET_BUF *) ItemNetMap->Value); 1993 EntryNetMap = EntryNetMap->ForwardLink; 1994 } else { 1995 // 1996 // Maximum retries reached, clean the Token up. 1997 // 1998 Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry); 1999 Dns6TokenEntry->Token->Status = EFI_TIMEOUT; 2000 gBS->SignalEvent (Dns6TokenEntry->Token->Event); 2001 DispatchDpc (); 2002 2003 // 2004 // Free the sending packet. 2005 // 2006 if (ItemNetMap->Value != NULL) { 2007 NetbufFree ((NET_BUF *) (ItemNetMap->Value)); 2008 } 2009 2010 EntryNetMap = Instance->Dns6TxTokens.Used.ForwardLink; 2011 } 2012 } 2013 } 2014 } 2015 } 2016 2017 /** 2018 The timer ticking function for the DNS driver. 2019 2020 @param Event The ticking event 2021 @param Context NULL 2022 2023 **/ 2024 VOID 2025 EFIAPI 2026 DnsOnTimerUpdate ( 2027 IN EFI_EVENT Event, 2028 IN VOID *Context 2029 ) 2030 { 2031 LIST_ENTRY *Entry; 2032 LIST_ENTRY *Next; 2033 DNS4_CACHE *Item4; 2034 DNS6_CACHE *Item6; 2035 2036 Item4 = NULL; 2037 Item6 = NULL; 2038 2039 // 2040 // Iterate through all the DNS4 cache list. 2041 // 2042 NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) { 2043 Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink); 2044 Item4->DnsCache.Timeout--; 2045 } 2046 2047 Entry = mDriverData->Dns4CacheList.ForwardLink; 2048 while (Entry != &mDriverData->Dns4CacheList) { 2049 Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink); 2050 if (Item4->DnsCache.Timeout<=0) { 2051 RemoveEntryList (&Item4->AllCacheLink); 2052 Entry = mDriverData->Dns4CacheList.ForwardLink; 2053 } else { 2054 Entry = Entry->ForwardLink; 2055 } 2056 } 2057 2058 // 2059 // Iterate through all the DNS6 cache list. 2060 // 2061 NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6CacheList) { 2062 Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink); 2063 Item6->DnsCache.Timeout--; 2064 } 2065 2066 Entry = mDriverData->Dns6CacheList.ForwardLink; 2067 while (Entry != &mDriverData->Dns6CacheList) { 2068 Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink); 2069 if (Item6->DnsCache.Timeout<=0) { 2070 RemoveEntryList (&Item6->AllCacheLink); 2071 Entry = mDriverData->Dns6CacheList.ForwardLink; 2072 } else { 2073 Entry = Entry->ForwardLink; 2074 } 2075 } 2076 } 2077 2078