Home | History | Annotate | Download | only in DnsDxe
      1 /** @file
      2 Implementation of EFI_DNS4_PROTOCOL and EFI_DNS6_PROTOCOL interfaces.
      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 EFI_DNS4_PROTOCOL  mDns4Protocol = {
     18   Dns4GetModeData,
     19   Dns4Configure,
     20   Dns4HostNameToIp,
     21   Dns4IpToHostName,
     22   Dns4GeneralLookUp,
     23   Dns4UpdateDnsCache,
     24   Dns4Poll,
     25   Dns4Cancel
     26 };
     27 
     28 EFI_DNS6_PROTOCOL  mDns6Protocol = {
     29   Dns6GetModeData,
     30   Dns6Configure,
     31   Dns6HostNameToIp,
     32   Dns6IpToHostName,
     33   Dns6GeneralLookUp,
     34   Dns6UpdateDnsCache,
     35   Dns6Poll,
     36   Dns6Cancel
     37 };
     38 
     39 /**
     40   This function is used to retrieve DNS mode data for this DNS instance.
     41 
     42   @param[in]  This               Pointer to EFI_DNS4_PROTOCOL instance.
     43   @param[out] DnsModeData        Pointer to the caller-allocated storage for the EFI_DNS4_MODE_DATA structure.
     44 
     45   @retval  EFI_SUCCESS           The operation completed successfully.
     46   @retval  EFI_NOT_STARTED       When DnsConfigData is queried, no configuration data is
     47                                  available because this instance has not been configured.
     48   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate needed resources.
     49   @retval  EFI_INVALID_PARAMETER This is NULL or DnsModeData is NULL.
     50 
     51 **/
     52 EFI_STATUS
     53 EFIAPI
     54 Dns4GetModeData (
     55   IN  EFI_DNS4_PROTOCOL          *This,
     56   OUT EFI_DNS4_MODE_DATA         *DnsModeData
     57   )
     58 {
     59   DNS_INSTANCE         *Instance;
     60 
     61   EFI_TPL              OldTpl;
     62 
     63   UINTN                Index;
     64 
     65   LIST_ENTRY           *Entry;
     66   LIST_ENTRY           *Next;
     67 
     68   DNS4_SERVER_IP       *ServerItem;
     69   EFI_IPv4_ADDRESS     *ServerList;
     70   DNS4_CACHE           *CacheItem;
     71   EFI_DNS4_CACHE_ENTRY *CacheList;
     72   EFI_STATUS           Status;
     73 
     74   ServerItem = NULL;
     75   ServerList = NULL;
     76   CacheItem  = NULL;
     77   CacheList  = NULL;
     78   Status     = EFI_SUCCESS;
     79 
     80 
     81   if ((This == NULL) || (DnsModeData == NULL)) {
     82     return EFI_INVALID_PARAMETER;
     83   }
     84 
     85   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
     86 
     87   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (This);
     88   if (Instance->State == DNS_STATE_UNCONFIGED) {
     89     gBS->RestoreTPL (OldTpl);
     90     return  EFI_NOT_STARTED;
     91   }
     92 
     93   ZeroMem (DnsModeData, sizeof (EFI_DNS4_MODE_DATA));
     94 
     95   //
     96   // Get the current configuration data of this instance.
     97   //
     98   Status = Dns4CopyConfigure (&DnsModeData->DnsConfigData, &Instance->Dns4CfgData);
     99   if (EFI_ERROR (Status)) {
    100     gBS->RestoreTPL (OldTpl);
    101     return Status;
    102   }
    103 
    104   //
    105   // Get the DnsServerCount and DnsServerList
    106   //
    107   Index = 0;
    108   NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4ServerList) {
    109     Index++;
    110   }
    111   DnsModeData->DnsServerCount = (UINT32) Index;
    112   ServerList = AllocatePool (sizeof (EFI_IPv4_ADDRESS) * DnsModeData->DnsServerCount);
    113   ASSERT (ServerList != NULL);
    114   Index = 0;
    115   NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4ServerList) {
    116     ServerItem = NET_LIST_USER_STRUCT (Entry, DNS4_SERVER_IP, AllServerLink);
    117     CopyMem (ServerList + Index, &ServerItem->Dns4ServerIp, sizeof (EFI_IPv4_ADDRESS));
    118     Index++;
    119   }
    120   DnsModeData->DnsServerList = ServerList;
    121 
    122   //
    123   // Get the DnsCacheCount and DnsCacheList
    124   //
    125   Index =0;
    126   NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) {
    127     Index++;
    128   }
    129   DnsModeData->DnsCacheCount = (UINT32) Index;
    130   CacheList = AllocatePool (sizeof (EFI_DNS4_CACHE_ENTRY) * DnsModeData->DnsCacheCount);
    131   ASSERT (CacheList != NULL);
    132   Index =0;
    133   NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) {
    134     CacheItem = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
    135     CopyMem (CacheList + Index, &CacheItem->DnsCache, sizeof (EFI_DNS4_CACHE_ENTRY));
    136     Index++;
    137   }
    138   DnsModeData->DnsCacheList = CacheList;
    139 
    140   gBS->RestoreTPL (OldTpl);
    141 
    142   return EFI_SUCCESS;
    143 }
    144 
    145 /**
    146   This function is used to configure DNS configuration data for this DNS instance.
    147 
    148   @param[in]  This               Pointer to EFI_DNS4_PROTOCOL instance.
    149   @param[in]  DnsConfigData      Pointer to caller-allocated buffer containing EFI_DNS4_CONFIG_DATA structure.
    150                                  If NULL, the driver will reinitialize the protocol instance to the unconfigured state.
    151 
    152   @retval  EFI_SUCCESS           The operation completed successfully.
    153   @retval  EFI_UNSUPPORTED       The designated protocol is not supported.
    154   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate needed resources.
    155   @retval  EFI_INVALID_PARAMETER This is NULL.
    156                                  The StationIp address provided in DnsConfigData is not a valid unicast.
    157                                  DnsServerList is NULL while DnsServerListCount is not equal to Zero.
    158                                  DnsServerListCount is Zero while DnsServerListCount is not equal to NULL.
    159   @retval  EFI_DEVICE_ERROR      An unexpected system or network error occurred. The EFI DNSv4 Protocol instance is not configured.
    160 
    161 **/
    162 EFI_STATUS
    163 EFIAPI
    164 Dns4Configure (
    165   IN EFI_DNS4_PROTOCOL           *This,
    166   IN EFI_DNS4_CONFIG_DATA        *DnsConfigData
    167   )
    168 {
    169   EFI_STATUS                Status;
    170   DNS_INSTANCE              *Instance;
    171 
    172   EFI_TPL                   OldTpl;
    173   IP4_ADDR                  Ip;
    174   IP4_ADDR                  Netmask;
    175 
    176   UINT32                    ServerListCount;
    177   EFI_IPv4_ADDRESS          *ServerList;
    178 
    179   Status     = EFI_SUCCESS;
    180   ServerList = NULL;
    181 
    182   if (This == NULL ||
    183      (DnsConfigData != NULL && ((DnsConfigData->DnsServerListCount != 0 && DnsConfigData->DnsServerList == NULL) ||
    184                                 (DnsConfigData->DnsServerListCount == 0 && DnsConfigData->DnsServerList != NULL)))) {
    185     return EFI_INVALID_PARAMETER;
    186   }
    187 
    188   if (DnsConfigData != NULL && DnsConfigData->Protocol != DNS_PROTOCOL_UDP) {
    189     return EFI_UNSUPPORTED;
    190   }
    191 
    192   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    193 
    194   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (This);
    195 
    196   if (DnsConfigData == NULL) {
    197     ZeroMem (&Instance->SessionDnsServer, sizeof (EFI_IP_ADDRESS));
    198 
    199     //
    200     // Reset the Instance if ConfigData is NULL
    201     //
    202     if (!NetMapIsEmpty(&Instance->Dns4TxTokens)) {
    203       Dns4InstanceCancelToken(Instance, NULL);
    204     }
    205 
    206     Instance->MaxRetry = 0;
    207 
    208     if (Instance->UdpIo != NULL){
    209       UdpIoCleanIo (Instance->UdpIo);
    210     }
    211 
    212     if (Instance->Dns4CfgData.DnsServerList != NULL) {
    213       FreePool (Instance->Dns4CfgData.DnsServerList);
    214     }
    215     ZeroMem (&Instance->Dns4CfgData, sizeof (EFI_DNS4_CONFIG_DATA));
    216 
    217     Instance->State = DNS_STATE_UNCONFIGED;
    218   } else {
    219     //
    220     // Configure the parameters for new operation.
    221     //
    222     CopyMem (&Ip, &DnsConfigData->StationIp, sizeof (IP4_ADDR));
    223     CopyMem (&Netmask, &DnsConfigData->SubnetMask, sizeof (IP4_ADDR));
    224 
    225     Ip       = NTOHL (Ip);
    226     Netmask  = NTOHL (Netmask);
    227 
    228     if (!DnsConfigData->UseDefaultSetting &&
    229        ((!IP4_IS_VALID_NETMASK (Netmask) || !NetIp4IsUnicast (Ip, Netmask)))) {
    230       Status = EFI_INVALID_PARAMETER;
    231       goto ON_EXIT;
    232     }
    233 
    234     Status = Dns4CopyConfigure (&Instance->Dns4CfgData, DnsConfigData);
    235     if (EFI_ERROR (Status)) {
    236       goto ON_EXIT;
    237     }
    238 
    239     if (DnsConfigData->DnsServerListCount == 0 || DnsConfigData->DnsServerList == NULL) {
    240       gBS->RestoreTPL (OldTpl);
    241 
    242       //
    243       // The DNS instance will retrieve DNS server from DHCP Server
    244       //
    245       Status = GetDns4ServerFromDhcp4 (
    246                  Instance,
    247                  &ServerListCount,
    248                  &ServerList
    249                  );
    250       if (EFI_ERROR (Status)) {
    251         return Status;
    252       }
    253 
    254       ASSERT(ServerList != NULL);
    255 
    256       OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    257 
    258       CopyMem (&Instance->SessionDnsServer.v4, &ServerList[0], sizeof (EFI_IPv4_ADDRESS));
    259     } else {
    260       CopyMem (&Instance->SessionDnsServer.v4, &DnsConfigData->DnsServerList[0], sizeof (EFI_IPv4_ADDRESS));
    261     }
    262 
    263     //
    264     // Config UDP
    265     //
    266     Status = Dns4ConfigUdp (Instance, Instance->UdpIo);
    267     if (EFI_ERROR (Status)) {
    268       if (Instance->Dns4CfgData.DnsServerList != NULL) {
    269         FreePool (Instance->Dns4CfgData.DnsServerList);
    270       }
    271       goto ON_EXIT;
    272     }
    273 
    274     //
    275     // Add configured DNS server used by this instance to ServerList.
    276     //
    277     Status = AddDns4ServerIp (&mDriverData->Dns4ServerList, Instance->SessionDnsServer.v4);
    278     if (EFI_ERROR (Status)) {
    279       if (Instance->Dns4CfgData.DnsServerList != NULL) {
    280         FreePool (Instance->Dns4CfgData.DnsServerList);
    281       }
    282       goto ON_EXIT;
    283     }
    284 
    285     Instance->State = DNS_STATE_CONFIGED;
    286   }
    287 
    288 ON_EXIT:
    289   gBS->RestoreTPL (OldTpl);
    290   return Status;
    291 }
    292 
    293 /**
    294   The function is used to translate the host name to host IP address.
    295   A type A query is used to get the one or more IP addresses for this host.
    296 
    297   @param[in]  This               Pointer to EFI_DNS4_PROTOCOL instance.
    298   @param[in]  HostName           Pointer to caller-supplied buffer containing Host name to be translated.
    299                                  This buffer contains 16 bit characters but these are translated to ASCII for use with
    300                                  DNSv4 server and there is no requirement for driver to support non-ASCII Unicode characters.
    301   @param[in]  Token              Pointer to the caller-allocated completion token to return at the completion of the process to translate host name to host address.
    302 
    303   @retval  EFI_SUCCESS           The operation completed successfully.
    304   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate needed resources.
    305   @retval  EFI_INVALID_PARAMETER This is NULL.
    306                                  Token is NULL.
    307                                  Token.Event is.NULL
    308                                  HostName is NULL
    309   @retval  EFI_NO_MAPPING        There's no source address is available for use.
    310   @retval  EFI_NOT_STARTED       This instance has not been started.
    311 
    312 **/
    313 EFI_STATUS
    314 EFIAPI
    315 Dns4HostNameToIp (
    316   IN  EFI_DNS4_PROTOCOL          *This,
    317   IN  CHAR16                     *HostName,
    318   IN  EFI_DNS4_COMPLETION_TOKEN  *Token
    319   )
    320 {
    321   EFI_STATUS            Status;
    322 
    323   DNS_INSTANCE          *Instance;
    324 
    325   EFI_DNS4_CONFIG_DATA  *ConfigData;
    326 
    327   UINTN                 Index;
    328   DNS4_CACHE            *Item;
    329   LIST_ENTRY            *Entry;
    330   LIST_ENTRY            *Next;
    331 
    332   CHAR8                 *QueryName;
    333 
    334   DNS4_TOKEN_ENTRY      *TokenEntry;
    335   NET_BUF               *Packet;
    336 
    337   EFI_TPL               OldTpl;
    338 
    339   Status     = EFI_SUCCESS;
    340   Item       = NULL;
    341   QueryName  = NULL;
    342   TokenEntry = NULL;
    343   Packet     = NULL;
    344 
    345   //
    346   // Validate the parameters
    347   //
    348   if ((This == NULL) || (HostName == NULL) || Token == NULL) {
    349     return EFI_INVALID_PARAMETER;
    350   }
    351 
    352   OldTpl   = gBS->RaiseTPL (TPL_CALLBACK);
    353 
    354   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (This);
    355 
    356   ConfigData = &(Instance->Dns4CfgData);
    357 
    358   Instance->MaxRetry = ConfigData->RetryCount;
    359 
    360   Token->Status = EFI_NOT_READY;
    361   Token->RetryCount = 0;
    362   Token->RetryInterval = ConfigData->RetryInterval;
    363 
    364   if (Instance->State != DNS_STATE_CONFIGED) {
    365     Status = EFI_NOT_STARTED;
    366     goto ON_EXIT;
    367   }
    368 
    369   //
    370   // Check the MaxRetry and RetryInterval values.
    371   //
    372   if (Instance->MaxRetry == 0) {
    373     Instance->MaxRetry = DNS_DEFAULT_RETRY;
    374   }
    375 
    376   if (Token->RetryInterval < DNS_DEFAULT_TIMEOUT) {
    377     Token->RetryInterval = DNS_DEFAULT_TIMEOUT;
    378   }
    379 
    380   //
    381   // Check cache
    382   //
    383   if (ConfigData->EnableDnsCache) {
    384     Index = 0;
    385     NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) {
    386       Item = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
    387       if (StrCmp (HostName, Item->DnsCache.HostName) == 0) {
    388         Index++;
    389       }
    390     }
    391 
    392     if (Index != 0) {
    393       Token->RspData.H2AData = AllocatePool (sizeof (DNS_HOST_TO_ADDR_DATA));
    394       if (Token->RspData.H2AData == NULL) {
    395         Status = EFI_OUT_OF_RESOURCES;
    396         goto ON_EXIT;
    397       }
    398 
    399       Token->RspData.H2AData->IpCount = (UINT32)Index;
    400       Token->RspData.H2AData->IpList = AllocatePool (sizeof (EFI_IPv4_ADDRESS) * Index);
    401       if (Token->RspData.H2AData->IpList == NULL) {
    402         if (Token->RspData.H2AData != NULL) {
    403           FreePool (Token->RspData.H2AData);
    404         }
    405 
    406         Status = EFI_OUT_OF_RESOURCES;
    407         goto ON_EXIT;
    408       }
    409 
    410       Index = 0;
    411       NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) {
    412         Item = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
    413         if ((UINT32)Index < Token->RspData.H2AData->IpCount && StrCmp (HostName, Item->DnsCache.HostName) == 0) {
    414           CopyMem ((Token->RspData.H2AData->IpList) + Index, Item->DnsCache.IpAddress, sizeof (EFI_IPv4_ADDRESS));
    415           Index++;
    416         }
    417       }
    418 
    419       Token->Status = EFI_SUCCESS;
    420 
    421       if (Token->Event != NULL) {
    422         gBS->SignalEvent (Token->Event);
    423         DispatchDpc ();
    424       }
    425 
    426       Status = Token->Status;
    427       goto ON_EXIT;
    428     }
    429   }
    430 
    431   //
    432   // Construct DNS TokenEntry.
    433   //
    434   TokenEntry = AllocateZeroPool (sizeof(DNS4_TOKEN_ENTRY));
    435   if (TokenEntry == NULL) {
    436     Status = EFI_OUT_OF_RESOURCES;
    437     goto ON_EXIT;
    438   }
    439 
    440   TokenEntry->PacketToLive = Token->RetryInterval;
    441   TokenEntry->QueryHostName = HostName;
    442   TokenEntry->Token = Token;
    443 
    444   //
    445   // Construct QName.
    446   //
    447   QueryName = DnsFillinQNameForQueryIp (TokenEntry->QueryHostName);
    448   if (QueryName == NULL) {
    449     Status = EFI_OUT_OF_RESOURCES;
    450     goto ON_EXIT;
    451   }
    452 
    453   //
    454   // Construct DNS Query Packet.
    455   //
    456   Status = ConstructDNSQuery (Instance, QueryName, DNS_TYPE_A, DNS_CLASS_INET, &Packet);
    457   if (EFI_ERROR (Status)) {
    458     if (TokenEntry != NULL) {
    459       FreePool (TokenEntry);
    460     }
    461 
    462     goto ON_EXIT;
    463   }
    464 
    465   ASSERT (Packet != NULL);
    466 
    467   //
    468   // Save the token into the Dns4TxTokens map.
    469   //
    470   Status = NetMapInsertTail (&Instance->Dns4TxTokens, TokenEntry, Packet);
    471   if (EFI_ERROR (Status)) {
    472     if (TokenEntry != NULL) {
    473       FreePool (TokenEntry);
    474     }
    475 
    476     NetbufFree (Packet);
    477 
    478     goto ON_EXIT;
    479   }
    480 
    481   //
    482   // Dns Query Ip
    483   //
    484   Status = DoDnsQuery (Instance, Packet);
    485   if (EFI_ERROR (Status)) {
    486     if (TokenEntry != NULL) {
    487       FreePool (TokenEntry);
    488     }
    489 
    490     NetbufFree (Packet);
    491   }
    492 
    493 ON_EXIT:
    494   if (QueryName != NULL) {
    495     FreePool (QueryName);
    496   }
    497 
    498   gBS->RestoreTPL (OldTpl);
    499   return Status;
    500 }
    501 
    502 /**
    503   The function is used to translate the host address to host name.
    504   A type PTR query is used to get the primary name of the host.
    505 
    506   @param[in]  This               Pointer to EFI_DNS4_PROTOCOL instance.
    507   @param[in]  IpAddress          IP address.
    508   @param[in]  Token              Pointer to the caller-allocated completion used token to translate host address to host name.
    509 
    510   @retval  EFI_SUCCESS           The operation completed successfully.
    511   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate needed resources.
    512   @retval  EFI_INVALID_PARAMETER This is NULL.
    513                                  Token is NULL.
    514                                  Token.Event is NULL.
    515                                  IpAddress is not valid IP address.
    516   @retval  EFI_NO_MAPPING        There's no source address is available for use.
    517   @retval  EFI_NOT_STARTED       This instance has not been started.
    518   @retval  EFI_UNSUPPORTED       This function is not supported.
    519 
    520 **/
    521 EFI_STATUS
    522 EFIAPI
    523 Dns4IpToHostName (
    524   IN  EFI_DNS4_PROTOCOL              *This,
    525   IN  EFI_IPv4_ADDRESS               IpAddress,
    526   IN  EFI_DNS4_COMPLETION_TOKEN      *Token
    527   )
    528 {
    529   return EFI_UNSUPPORTED;
    530 }
    531 
    532 /**
    533   This function retrieves arbitrary information from the DNS.
    534   The caller supplies a QNAME, QTYPE, and QCLASS, and all of the matching RRs are returned.
    535   All RR content (e.g., Ttl) was returned.
    536   The caller need parse the returned RR to get required information. This function is optional.
    537 
    538   @param[in]  This               Pointer to EFI_DNS4_PROTOCOL instance.
    539   @param[in]  QName              Pointer to Query Name.
    540   @param[in]  QType              Query Type.
    541   @param[in]  QClass             Query Name.
    542   @param[in]  Token              Point to the caller-allocated completion token to retrieve arbitrary information.
    543 
    544   @retval  EFI_SUCCESS           The operation completed successfully.
    545   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate needed resources.
    546   @retval  EFI_INVALID_PARAMETER This is NULL.
    547                                  Token is NULL.
    548                                  Token.Event is NULL.
    549                                  QName is NULL.
    550   @retval  EFI_NO_MAPPING        There's no source address is available for use.
    551   @retval  EFI_ALREADY_STARTED   This Token is being used in another DNS session.
    552   @retval  EFI_UNSUPPORTED       This function is not supported. Or the requested QType is not supported
    553 
    554 **/
    555 EFI_STATUS
    556 EFIAPI
    557 Dns4GeneralLookUp (
    558   IN  EFI_DNS4_PROTOCOL                *This,
    559   IN  CHAR8                            *QName,
    560   IN  UINT16                           QType,
    561   IN  UINT16                           QClass,
    562   IN  EFI_DNS4_COMPLETION_TOKEN        *Token
    563   )
    564 {
    565   EFI_STATUS            Status;
    566 
    567   DNS_INSTANCE          *Instance;
    568 
    569   EFI_DNS4_CONFIG_DATA  *ConfigData;
    570 
    571   DNS4_TOKEN_ENTRY      *TokenEntry;
    572   NET_BUF               *Packet;
    573 
    574   EFI_TPL               OldTpl;
    575 
    576   Status     = EFI_SUCCESS;
    577   TokenEntry = NULL;
    578   Packet     = NULL;
    579 
    580   //
    581   // Validate the parameters
    582   //
    583   if ((This == NULL) || (QName == NULL) || Token == NULL) {
    584     return EFI_INVALID_PARAMETER;
    585   }
    586 
    587   OldTpl   = gBS->RaiseTPL (TPL_CALLBACK);
    588 
    589   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (This);
    590 
    591   ConfigData = &(Instance->Dns4CfgData);
    592 
    593   Instance->MaxRetry = ConfigData->RetryCount;
    594 
    595   Token->Status = EFI_NOT_READY;
    596   Token->RetryCount = 0;
    597   Token->RetryInterval = ConfigData->RetryInterval;
    598 
    599   if (Instance->State != DNS_STATE_CONFIGED) {
    600     Status = EFI_NOT_STARTED;
    601     goto ON_EXIT;
    602   }
    603 
    604   //
    605   // Check the MaxRetry and RetryInterval values.
    606   //
    607   if (Instance->MaxRetry == 0) {
    608     Instance->MaxRetry = DNS_DEFAULT_RETRY;
    609   }
    610 
    611   if (Token->RetryInterval < DNS_DEFAULT_TIMEOUT) {
    612     Token->RetryInterval = DNS_DEFAULT_TIMEOUT;
    613   }
    614 
    615   //
    616   // Construct DNS TokenEntry.
    617   //
    618   TokenEntry = AllocateZeroPool (sizeof(DNS4_TOKEN_ENTRY));
    619   if (TokenEntry == NULL) {
    620     Status = EFI_OUT_OF_RESOURCES;
    621     goto ON_EXIT;
    622   }
    623 
    624   TokenEntry->PacketToLive = Token->RetryInterval;
    625   TokenEntry->GeneralLookUp = TRUE;
    626   TokenEntry->Token = Token;
    627 
    628   //
    629   // Construct DNS Query Packet.
    630   //
    631   Status = ConstructDNSQuery (Instance, QName, QType, QClass, &Packet);
    632   if (EFI_ERROR (Status)) {
    633     if (TokenEntry != NULL) {
    634       FreePool (TokenEntry);
    635     }
    636 
    637     goto ON_EXIT;
    638   }
    639 
    640   ASSERT (Packet != NULL);
    641 
    642   //
    643   // Save the token into the Dns4TxTokens map.
    644   //
    645   Status = NetMapInsertTail (&Instance->Dns4TxTokens, TokenEntry, Packet);
    646   if (EFI_ERROR (Status)) {
    647     if (TokenEntry != NULL) {
    648       FreePool (TokenEntry);
    649     }
    650 
    651     NetbufFree (Packet);
    652 
    653     goto ON_EXIT;
    654   }
    655 
    656   //
    657   // Dns Query Ip
    658   //
    659   Status = DoDnsQuery (Instance, Packet);
    660   if (EFI_ERROR (Status)) {
    661     if (TokenEntry != NULL) {
    662       FreePool (TokenEntry);
    663     }
    664 
    665     NetbufFree (Packet);
    666   }
    667 
    668 ON_EXIT:
    669   gBS->RestoreTPL (OldTpl);
    670   return Status;
    671 }
    672 
    673 /**
    674   This function is used to add/delete/modify DNS cache entry.
    675   DNS cache can be normally dynamically updated after the DNS resolve succeeds.
    676   This function provided capability to manually add/delete/modify the DNS cache.
    677 
    678   @param[in]  This               Pointer to EFI_DNS4_PROTOCOL instance.
    679   @param[in]  DeleteFlag         If FALSE, this function is to add one entry to the DNS Cache.
    680                                  If TRUE, this function will delete matching DNS Cache entry.
    681   @param[in]  Override           If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
    682                                  If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
    683   @param[in]  DnsCacheEntry      Pointer to DNS Cache entry.
    684 
    685   @retval  EFI_SUCCESS           The operation completed successfully.
    686   @retval  EFI_INVALID_PARAMETER This is NULL.
    687                                  DnsCacheEntry.HostName is NULL.
    688                                  DnsCacheEntry.IpAddress is NULL.
    689                                  DnsCacheEntry.Timeout is zero.
    690   @retval  EFI_ACCESS_DENIED     The DNS cache entry already exists and Override is not TRUE.
    691 
    692 **/
    693 EFI_STATUS
    694 EFIAPI
    695 Dns4UpdateDnsCache (
    696   IN EFI_DNS4_PROTOCOL      *This,
    697   IN BOOLEAN                DeleteFlag,
    698   IN BOOLEAN                Override,
    699   IN EFI_DNS4_CACHE_ENTRY   DnsCacheEntry
    700   )
    701 {
    702   EFI_STATUS    Status;
    703   EFI_TPL       OldTpl;
    704 
    705   Status = EFI_SUCCESS;
    706 
    707   if (DnsCacheEntry.HostName == NULL || DnsCacheEntry.IpAddress == NULL || DnsCacheEntry.Timeout == 0) {
    708     return EFI_INVALID_PARAMETER;
    709   }
    710 
    711   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    712 
    713   //
    714   // Update Dns4Cache here.
    715   //
    716   Status = UpdateDns4Cache (&mDriverData->Dns4CacheList, DeleteFlag, Override, DnsCacheEntry);
    717 
    718   gBS->RestoreTPL (OldTpl);
    719 
    720   return Status;
    721 }
    722 
    723 /**
    724   This function can be used by network drivers and applications to increase the rate that data packets are moved between
    725   the communications device and the transmit and receive queues. In some systems, the periodic timer event in the managed
    726   network driver may not poll the underlying communications device fast enough to transmit and/or receive all data packets
    727   without missing incoming packets or dropping outgoing packets.
    728 
    729   @param[in]  This               Pointer to EFI_DNS4_PROTOCOL instance.
    730 
    731   @retval  EFI_SUCCESS           Incoming or outgoing data was processed.
    732   @retval  EFI_INVALID_PARAMETER This is NULL.
    733   @retval  EFI_NOT_STARTED       This EFI DNS Protocol instance has not been started.
    734   @retval  EFI_DEVICE_ERROR      An unexpected system or network error occurred.
    735   @retval  EFI_TIMEOUT           Data was dropped out of the transmit and/or receive queue.
    736                                  Consider increasing the polling rate.
    737 
    738 **/
    739 EFI_STATUS
    740 EFIAPI
    741 Dns4Poll (
    742   IN EFI_DNS4_PROTOCOL    *This
    743   )
    744 {
    745   DNS_INSTANCE           *Instance;
    746   EFI_UDP4_PROTOCOL      *Udp;
    747 
    748   if (This == NULL) {
    749     return EFI_INVALID_PARAMETER;
    750   }
    751 
    752   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (This);
    753 
    754   if (Instance->State == DNS_STATE_UNCONFIGED) {
    755     return EFI_NOT_STARTED;
    756   } else if (Instance->State == DNS_STATE_DESTROY) {
    757     return EFI_DEVICE_ERROR;
    758   }
    759 
    760   Udp = Instance->UdpIo->Protocol.Udp4;
    761 
    762   return Udp->Poll (Udp);
    763 }
    764 
    765 /**
    766   This function is used to abort a pending resolution request.
    767   After calling this function, Token.Status will be set to EFI_ABORTED and then Token.
    768 
    769   @param[in]  This               Pointer to EFI_DNS4_PROTOCOL instance.
    770   @param[in]  Token              Pointer to a token that has been issued by EFI_DNS4_PROTOCOL.HostNameToIp(),
    771                                  EFI_DNS4_PROTOCOL.IpToHostName() or EFI_DNS4_PROTOCOL.GeneralLookup().
    772                                  If NULL, all pending tokens are aborted.
    773 
    774   @retval  EFI_SUCCESS           Incoming or outgoing data was processed.
    775   @retval  EFI_INVALID_PARAMETER This is NULL.
    776   @retval  EFI_NOT_STARTED       This EFI DNS Protocol instance has not been started.
    777   @retval  EFI_NOT_FOUND         When Token is not NULL, and the asynchronous DNS operation was not found in the transmit queue.
    778                                  It was either completed or was not issued by HostNameToIp(), IpToHostName() or GeneralLookup().
    779 
    780 **/
    781 EFI_STATUS
    782 EFIAPI
    783 Dns4Cancel (
    784   IN  EFI_DNS4_PROTOCOL          *This,
    785   IN  EFI_DNS4_COMPLETION_TOKEN  *Token
    786   )
    787 {
    788   EFI_STATUS          Status;
    789   DNS_INSTANCE        *Instance;
    790   EFI_TPL             OldTpl;
    791 
    792   if (This == NULL) {
    793     return EFI_INVALID_PARAMETER;
    794   }
    795 
    796   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (This);
    797 
    798   if (Instance->State == DNS_STATE_UNCONFIGED) {
    799     return EFI_NOT_STARTED;
    800   }
    801 
    802   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    803 
    804   //
    805   // Cancle the tokens specified by Token for this instance.
    806   //
    807   Status = Dns4InstanceCancelToken (Instance, Token);
    808 
    809   //
    810   // Dispatch the DPC queued by the NotifyFunction of the canceled token's events.
    811   //
    812   DispatchDpc ();
    813 
    814   gBS->RestoreTPL (OldTpl);
    815 
    816   return Status;
    817 }
    818 
    819 /**
    820   This function is used to retrieve DNS mode data for this DNS instance.
    821 
    822   @param[in]  This               Pointer to EFI_DNS6_PROTOCOL instance.
    823   @param[out] DnsModeData        Pointer to the caller-allocated storage for the EFI_DNS6_MODE_DATA structure.
    824 
    825   @retval  EFI_SUCCESS           The operation completed successfully.
    826   @retval  EFI_NOT_STARTED       When DnsConfigData is queried, no configuration data is
    827                                  available because this instance has not been configured.
    828   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate needed resources.
    829   @retval  EFI_INVALID_PARAMETER This is NULL or DnsModeData is NULL.
    830 
    831 **/
    832 EFI_STATUS
    833 EFIAPI
    834 Dns6GetModeData (
    835   IN  EFI_DNS6_PROTOCOL          *This,
    836   OUT EFI_DNS6_MODE_DATA         *DnsModeData
    837   )
    838 {
    839   DNS_INSTANCE         *Instance;
    840 
    841   EFI_TPL              OldTpl;
    842 
    843   UINTN                Index;
    844 
    845   LIST_ENTRY           *Entry;
    846   LIST_ENTRY           *Next;
    847 
    848   DNS6_SERVER_IP       *ServerItem;
    849   EFI_IPv6_ADDRESS     *ServerList;
    850   DNS6_CACHE           *CacheItem;
    851   EFI_DNS6_CACHE_ENTRY *CacheList;
    852   EFI_STATUS           Status;
    853 
    854   ServerItem = NULL;
    855   ServerList = NULL;
    856   CacheItem  = NULL;
    857   CacheList  = NULL;
    858   Status     = EFI_SUCCESS;
    859 
    860   if ((This == NULL) || (DnsModeData == NULL)) {
    861     return EFI_INVALID_PARAMETER;
    862   }
    863 
    864   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    865 
    866   Instance  = DNS_INSTANCE_FROM_THIS_PROTOCOL6 (This);
    867   if (Instance->State == DNS_STATE_UNCONFIGED) {
    868     gBS->RestoreTPL (OldTpl);
    869     return  EFI_NOT_STARTED;
    870   }
    871 
    872   ZeroMem (DnsModeData, sizeof (EFI_DNS6_MODE_DATA));
    873 
    874   //
    875   // Get the current configuration data of this instance.
    876   //
    877   Status = Dns6CopyConfigure(&DnsModeData->DnsConfigData, &Instance->Dns6CfgData);
    878   if (EFI_ERROR (Status)) {
    879     gBS->RestoreTPL (OldTpl);
    880     return Status;
    881   }
    882 
    883   //
    884   // Get the DnsServerCount and DnsServerList
    885   //
    886   Index = 0;
    887   NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6ServerList) {
    888     Index++;
    889   }
    890   DnsModeData->DnsServerCount = (UINT32) Index;
    891   ServerList = AllocatePool (sizeof(EFI_IPv6_ADDRESS) * DnsModeData->DnsServerCount);
    892   ASSERT (ServerList != NULL);
    893   Index = 0;
    894   NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6ServerList) {
    895     ServerItem = NET_LIST_USER_STRUCT (Entry, DNS6_SERVER_IP, AllServerLink);
    896     CopyMem (ServerList + Index, &ServerItem->Dns6ServerIp, sizeof (EFI_IPv6_ADDRESS));
    897     Index++;
    898   }
    899   DnsModeData->DnsServerList = ServerList;
    900 
    901   //
    902   // Get the DnsCacheCount and DnsCacheList
    903   //
    904   Index =0;
    905   NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6CacheList) {
    906     Index++;
    907   }
    908   DnsModeData->DnsCacheCount = (UINT32) Index;
    909   CacheList = AllocatePool (sizeof(EFI_DNS6_CACHE_ENTRY) * DnsModeData->DnsCacheCount);
    910   ASSERT (CacheList != NULL);
    911   Index =0;
    912   NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6CacheList) {
    913     CacheItem = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
    914     CopyMem (CacheList + Index, &CacheItem->DnsCache, sizeof (EFI_DNS6_CACHE_ENTRY));
    915     Index++;
    916   }
    917   DnsModeData->DnsCacheList = CacheList;
    918 
    919   gBS->RestoreTPL (OldTpl);
    920 
    921   return EFI_SUCCESS;
    922 }
    923 
    924 /**
    925   The function is used to set and change the configuration data for this EFI DNSv6 Protocol driver instance.
    926   Reset the DNS instance if DnsConfigData is NULL.
    927 
    928   @param[in]  This               Pointer to EFI_DNS6_PROTOCOL instance.
    929   @param[in]  DnsConfigData      Pointer to the configuration data structure.
    930                                  All associated storage to be allocated and released by caller.
    931 
    932   @retval  EFI_SUCCESS           The operation completed successfully.
    933   @retval  EFI_UNSUPPORTED       The designated protocol is not supported.
    934   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate needed resources.
    935   @retval  EFI_INVALID_PARAMETER This is NULL.
    936                                  The StationIp address provided in DnsConfigData is not a valid unicast.
    937                                  DnsServerList is NULL while DnsServerListCount is not equal to Zero.
    938                                  DnsServerListCount is Zero while DnsServerList is not equal to NULL.
    939   @retval  EFI_DEVICE_ERROR      An unexpected system or network error occurred. The EFI DNSv6 Protocol instance is not configured.
    940 
    941 **/
    942 EFI_STATUS
    943 EFIAPI
    944 Dns6Configure (
    945   IN EFI_DNS6_PROTOCOL           *This,
    946   IN EFI_DNS6_CONFIG_DATA        *DnsConfigData
    947   )
    948 {
    949   EFI_STATUS                Status;
    950   DNS_INSTANCE              *Instance;
    951 
    952   EFI_TPL                   OldTpl;
    953 
    954   UINT32                    ServerListCount;
    955   EFI_IPv6_ADDRESS          *ServerList;
    956 
    957   Status     = EFI_SUCCESS;
    958   ServerList = NULL;
    959 
    960   if (This == NULL ||
    961      (DnsConfigData != NULL && ((DnsConfigData->DnsServerCount != 0 && DnsConfigData->DnsServerList == NULL) ||
    962                                 (DnsConfigData->DnsServerCount == 0 && DnsConfigData->DnsServerList != NULL)))) {
    963     return EFI_INVALID_PARAMETER;
    964   }
    965 
    966   if (DnsConfigData != NULL && DnsConfigData->Protocol != DNS_PROTOCOL_UDP) {
    967     return EFI_UNSUPPORTED;
    968   }
    969 
    970   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    971 
    972   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL6 (This);
    973 
    974   if (DnsConfigData == NULL) {
    975     ZeroMem (&Instance->SessionDnsServer, sizeof (EFI_IP_ADDRESS));
    976 
    977     //
    978     // Reset the Instance if ConfigData is NULL
    979     //
    980     if (!NetMapIsEmpty(&Instance->Dns6TxTokens)) {
    981       Dns6InstanceCancelToken(Instance, NULL);
    982     }
    983 
    984     Instance->MaxRetry = 0;
    985 
    986     if (Instance->UdpIo != NULL){
    987       UdpIoCleanIo (Instance->UdpIo);
    988     }
    989 
    990     if (Instance->Dns6CfgData.DnsServerList != NULL) {
    991       FreePool (Instance->Dns6CfgData.DnsServerList);
    992     }
    993     ZeroMem (&Instance->Dns6CfgData, sizeof (EFI_DNS6_CONFIG_DATA));
    994 
    995     Instance->State = DNS_STATE_UNCONFIGED;
    996   } else {
    997     //
    998     // Configure the parameters for new operation.
    999     //
   1000     if (!NetIp6IsUnspecifiedAddr (&DnsConfigData->StationIp) && !NetIp6IsValidUnicast (&DnsConfigData->StationIp)) {
   1001       Status = EFI_INVALID_PARAMETER;
   1002       goto ON_EXIT;
   1003     }
   1004 
   1005     Status = Dns6CopyConfigure (&Instance->Dns6CfgData, DnsConfigData);
   1006     if (EFI_ERROR (Status)) {
   1007       goto ON_EXIT;
   1008     }
   1009 
   1010     if (DnsConfigData->DnsServerCount == 0 || DnsConfigData->DnsServerList == NULL) {
   1011       gBS->RestoreTPL (OldTpl);
   1012 
   1013       //
   1014       //The DNS instance will retrieve DNS server from DHCP Server.
   1015       //
   1016       Status = GetDns6ServerFromDhcp6 (
   1017                  Instance->Service->ImageHandle,
   1018                  Instance->Service->ControllerHandle,
   1019                  &ServerListCount,
   1020                  &ServerList
   1021                  );
   1022       if (EFI_ERROR (Status)) {
   1023         goto ON_EXIT;
   1024       }
   1025 
   1026       ASSERT(ServerList != NULL);
   1027 
   1028       OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
   1029 
   1030       CopyMem (&Instance->SessionDnsServer.v6, &ServerList[0], sizeof (EFI_IPv6_ADDRESS));
   1031     } else {
   1032       CopyMem (&Instance->SessionDnsServer.v6, &DnsConfigData->DnsServerList[0], sizeof (EFI_IPv6_ADDRESS));
   1033     }
   1034 
   1035     //
   1036     // Config UDP
   1037     //
   1038     Status = Dns6ConfigUdp (Instance, Instance->UdpIo);
   1039     if (EFI_ERROR (Status)) {
   1040       if (Instance->Dns6CfgData.DnsServerList != NULL) {
   1041         FreePool (Instance->Dns6CfgData.DnsServerList);
   1042       }
   1043       goto ON_EXIT;
   1044     }
   1045 
   1046     //
   1047     // Add configured DNS server used by this instance to ServerList.
   1048     //
   1049     Status = AddDns6ServerIp (&mDriverData->Dns6ServerList, Instance->SessionDnsServer.v6);
   1050     if (EFI_ERROR (Status)) {
   1051       if (Instance->Dns6CfgData.DnsServerList != NULL) {
   1052         FreePool (Instance->Dns6CfgData.DnsServerList);
   1053       }
   1054       goto ON_EXIT;
   1055     }
   1056 
   1057     Instance->State = DNS_STATE_CONFIGED;
   1058   }
   1059 
   1060 ON_EXIT:
   1061   gBS->RestoreTPL (OldTpl);
   1062   return Status;
   1063 }
   1064 
   1065 /**
   1066   The function is used to translate the host name to host IP address.
   1067   A type AAAA query is used to get the one or more IPv6 addresses for this host.
   1068 
   1069   @param[in]  This               Pointer to EFI_DNS6_PROTOCOL instance.
   1070   @param[in]  HostName           Pointer to caller-supplied buffer containing Host name to be translated.
   1071                                  This buffer contains 16 bit characters but these are translated to ASCII for use with
   1072                                  DNSv4 server and there is no requirement for driver to support non-ASCII Unicode characters.
   1073   @param[in]  Token              Pointer to the caller-allocated completion token to return at the completion of the process to translate host name to host address.
   1074 
   1075   @retval  EFI_SUCCESS           The operation completed successfully.
   1076   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate needed resources.
   1077   @retval  EFI_INVALID_PARAMETER This is NULL.
   1078                                  Token is NULL.
   1079                                  Token.Event is.NULL
   1080                                  HostName is NULL
   1081   @retval  EFI_NO_MAPPING        There's no source address is available for use.
   1082   @retval  EFI_NOT_STARTED       This instance has not been started.
   1083 
   1084 **/
   1085 EFI_STATUS
   1086 EFIAPI
   1087 Dns6HostNameToIp (
   1088   IN  EFI_DNS6_PROTOCOL          *This,
   1089   IN  CHAR16                     *HostName,
   1090   IN  EFI_DNS6_COMPLETION_TOKEN  *Token
   1091   )
   1092 {
   1093   EFI_STATUS            Status;
   1094 
   1095   DNS_INSTANCE          *Instance;
   1096 
   1097   EFI_DNS6_CONFIG_DATA  *ConfigData;
   1098 
   1099   UINTN                 Index;
   1100   DNS6_CACHE            *Item;
   1101   LIST_ENTRY            *Entry;
   1102   LIST_ENTRY            *Next;
   1103 
   1104   CHAR8                 *QueryName;
   1105 
   1106   DNS6_TOKEN_ENTRY      *TokenEntry;
   1107   NET_BUF               *Packet;
   1108 
   1109   EFI_TPL               OldTpl;
   1110 
   1111   Status     = EFI_SUCCESS;
   1112   Item       = NULL;
   1113   QueryName  = NULL;
   1114   TokenEntry = NULL;
   1115   Packet     = NULL;
   1116 
   1117   //
   1118   // Validate the parameters
   1119   //
   1120   if ((This == NULL) || (HostName == NULL) || Token == NULL) {
   1121     return EFI_INVALID_PARAMETER;
   1122   }
   1123 
   1124   OldTpl   = gBS->RaiseTPL (TPL_CALLBACK);
   1125 
   1126   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL6 (This);
   1127 
   1128   ConfigData = &(Instance->Dns6CfgData);
   1129 
   1130   Instance->MaxRetry = ConfigData->RetryCount;
   1131 
   1132   Token->Status = EFI_NOT_READY;
   1133   Token->RetryCount = 0;
   1134   Token->RetryInterval = ConfigData->RetryInterval;
   1135 
   1136   if (Instance->State != DNS_STATE_CONFIGED) {
   1137     Status = EFI_NOT_STARTED;
   1138     goto ON_EXIT;
   1139   }
   1140 
   1141   //
   1142   // Check the MaxRetry and RetryInterval values.
   1143   //
   1144   if (Instance->MaxRetry == 0) {
   1145     Instance->MaxRetry = DNS_DEFAULT_RETRY;
   1146   }
   1147 
   1148   if (Token->RetryInterval < DNS_DEFAULT_TIMEOUT) {
   1149     Token->RetryInterval = DNS_DEFAULT_TIMEOUT;
   1150   }
   1151 
   1152   //
   1153   // Check cache
   1154   //
   1155   if (ConfigData->EnableDnsCache) {
   1156     Index = 0;
   1157     NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6CacheList) {
   1158       Item = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
   1159       if (StrCmp (HostName, Item->DnsCache.HostName) == 0) {
   1160         Index++;
   1161       }
   1162     }
   1163 
   1164     if (Index != 0) {
   1165       Token->RspData.H2AData = AllocatePool (sizeof (DNS6_HOST_TO_ADDR_DATA));
   1166       if (Token->RspData.H2AData == NULL) {
   1167         Status = EFI_OUT_OF_RESOURCES;
   1168         goto ON_EXIT;
   1169       }
   1170 
   1171       Token->RspData.H2AData->IpCount = (UINT32)Index;
   1172       Token->RspData.H2AData->IpList = AllocatePool (sizeof (EFI_IPv6_ADDRESS) * Index);
   1173       if (Token->RspData.H2AData->IpList == NULL) {
   1174         if (Token->RspData.H2AData != NULL) {
   1175           FreePool (Token->RspData.H2AData);
   1176         }
   1177 
   1178         Status = EFI_OUT_OF_RESOURCES;
   1179         goto ON_EXIT;
   1180       }
   1181 
   1182       Index = 0;
   1183       NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6CacheList) {
   1184         Item = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
   1185         if ((UINT32)Index < Token->RspData.H2AData->IpCount && StrCmp (HostName, Item->DnsCache.HostName) == 0) {
   1186           CopyMem ((Token->RspData.H2AData->IpList) + Index, Item->DnsCache.IpAddress, sizeof (EFI_IPv6_ADDRESS));
   1187           Index++;
   1188         }
   1189       }
   1190 
   1191       Token->Status = EFI_SUCCESS;
   1192 
   1193       if (Token->Event != NULL) {
   1194         gBS->SignalEvent (Token->Event);
   1195         DispatchDpc ();
   1196       }
   1197 
   1198       Status = Token->Status;
   1199       goto ON_EXIT;
   1200     }
   1201   }
   1202 
   1203   //
   1204   // Construct DNS TokenEntry.
   1205   //
   1206   TokenEntry = AllocateZeroPool (sizeof (DNS6_TOKEN_ENTRY));
   1207   if (TokenEntry == NULL) {
   1208     Status = EFI_OUT_OF_RESOURCES;
   1209     goto ON_EXIT;
   1210   }
   1211 
   1212   TokenEntry->PacketToLive = Token->RetryInterval;
   1213   TokenEntry->QueryHostName = HostName;
   1214   TokenEntry->Token = Token;
   1215 
   1216 
   1217   //
   1218   // Construct QName.
   1219   //
   1220   QueryName = DnsFillinQNameForQueryIp (TokenEntry->QueryHostName);
   1221   if (QueryName == NULL) {
   1222     Status = EFI_OUT_OF_RESOURCES;
   1223     goto ON_EXIT;
   1224   }
   1225 
   1226   //
   1227   // Construct DNS Query Packet.
   1228   //
   1229   Status = ConstructDNSQuery (Instance, QueryName, DNS_TYPE_AAAA, DNS_CLASS_INET, &Packet);
   1230   if (EFI_ERROR (Status)) {
   1231     if (TokenEntry != NULL) {
   1232       FreePool (TokenEntry);
   1233     }
   1234 
   1235     goto ON_EXIT;
   1236   }
   1237 
   1238   ASSERT (Packet != NULL);
   1239 
   1240   //
   1241   // Save the token into the Dns6TxTokens map.
   1242   //
   1243   Status = NetMapInsertTail (&Instance->Dns6TxTokens, TokenEntry, Packet);
   1244   if (EFI_ERROR (Status)) {
   1245     if (TokenEntry != NULL) {
   1246       FreePool (TokenEntry);
   1247     }
   1248 
   1249     NetbufFree (Packet);
   1250 
   1251     goto ON_EXIT;
   1252   }
   1253 
   1254   //
   1255   // Dns Query Ip
   1256   //
   1257   Status = DoDnsQuery (Instance, Packet);
   1258   if (EFI_ERROR (Status)) {
   1259     if (TokenEntry != NULL) {
   1260       FreePool (TokenEntry);
   1261     }
   1262 
   1263     NetbufFree (Packet);
   1264   }
   1265 
   1266 ON_EXIT:
   1267   if (QueryName != NULL) {
   1268     FreePool (QueryName);
   1269   }
   1270 
   1271   gBS->RestoreTPL (OldTpl);
   1272   return Status;
   1273 }
   1274 
   1275 /**
   1276   The function is used to translate the host address to host name.
   1277   A type PTR query is used to get the primary name of the host.
   1278 
   1279   @param[in]  This               Pointer to EFI_DNS6_PROTOCOL instance.
   1280   @param[in]  IpAddress          IP address.
   1281   @param[in]  Token              Pointer to the caller-allocated completion used token to translate host address to host name.
   1282 
   1283   @retval  EFI_SUCCESS           The operation completed successfully.
   1284   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate needed resources.
   1285   @retval  EFI_INVALID_PARAMETER This is NULL.
   1286                                  Token is NULL.
   1287                                  Token.Event is NULL.
   1288                                  IpAddress is not valid IP address.
   1289   @retval  EFI_NO_MAPPING        There's no source address is available for use.
   1290   @retval  EFI_NOT_STARTED       This instance has not been started.
   1291   @retval  EFI_UNSUPPORTED       This function is not supported.
   1292 
   1293 **/
   1294 EFI_STATUS
   1295 EFIAPI
   1296 Dns6IpToHostName (
   1297   IN  EFI_DNS6_PROTOCOL              *This,
   1298   IN  EFI_IPv6_ADDRESS               IpAddress,
   1299   IN  EFI_DNS6_COMPLETION_TOKEN      *Token
   1300   )
   1301 {
   1302   return EFI_UNSUPPORTED;
   1303 }
   1304 
   1305 /**
   1306   This function retrieves arbitrary information from the DNS.
   1307   The caller supplies a QNAME, QTYPE, and QCLASS, and all of the matching RRs are returned.
   1308   All RR content (e.g., Ttl) was returned.
   1309   The caller need parse the returned RR to get required information. This function is optional.
   1310 
   1311   @param[in]  This               Pointer to EFI_DNS6_PROTOCOL instance.
   1312   @param[in]  QName              Pointer to Query Name.
   1313   @param[in]  QType              Query Type.
   1314   @param[in]  QClass             Query Name.
   1315   @param[in]  Token              Point to the caller-allocated completion token to retrieve arbitrary information.
   1316 
   1317   @retval  EFI_SUCCESS           The operation completed successfully.
   1318   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate needed resources.
   1319   @retval  EFI_INVALID_PARAMETER This is NULL.
   1320                                  Token is NULL.
   1321                                  Token.Event is NULL.
   1322                                  QName is NULL.
   1323   @retval  EFI_NO_MAPPING        There's no source address is available for use.
   1324   @retval  EFI_NOT_STARTED       This instance has not been started.
   1325   @retval  EFI_UNSUPPORTED       This function is not supported. Or the requested QType is not supported
   1326 
   1327 **/
   1328 EFI_STATUS
   1329 EFIAPI
   1330 Dns6GeneralLookUp (
   1331   IN  EFI_DNS6_PROTOCOL                 *This,
   1332   IN  CHAR8                             *QName,
   1333   IN  UINT16                            QType,
   1334   IN  UINT16                            QClass,
   1335   IN  EFI_DNS6_COMPLETION_TOKEN         *Token
   1336   )
   1337 {
   1338   EFI_STATUS            Status;
   1339 
   1340   DNS_INSTANCE          *Instance;
   1341 
   1342   EFI_DNS6_CONFIG_DATA  *ConfigData;
   1343 
   1344   DNS6_TOKEN_ENTRY      *TokenEntry;
   1345   NET_BUF               *Packet;
   1346 
   1347   EFI_TPL               OldTpl;
   1348 
   1349   Status     = EFI_SUCCESS;
   1350   TokenEntry = NULL;
   1351   Packet     = NULL;
   1352 
   1353   //
   1354   // Validate the parameters
   1355   //
   1356   if ((This == NULL) || (QName == NULL) || Token == NULL) {
   1357     return EFI_INVALID_PARAMETER;
   1358   }
   1359 
   1360   OldTpl   = gBS->RaiseTPL (TPL_CALLBACK);
   1361 
   1362   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL6 (This);
   1363 
   1364   ConfigData = &(Instance->Dns6CfgData);
   1365 
   1366   Instance->MaxRetry = ConfigData->RetryCount;
   1367 
   1368   Token->Status = EFI_NOT_READY;
   1369   Token->RetryCount = 0;
   1370   Token->RetryInterval = ConfigData->RetryInterval;
   1371 
   1372   if (Instance->State != DNS_STATE_CONFIGED) {
   1373     Status = EFI_NOT_STARTED;
   1374     goto ON_EXIT;
   1375   }
   1376 
   1377   //
   1378   // Check the MaxRetry and RetryInterval values.
   1379   //
   1380   if (Instance->MaxRetry == 0) {
   1381     Instance->MaxRetry = DNS_DEFAULT_RETRY;
   1382   }
   1383 
   1384   if (Token->RetryInterval < DNS_DEFAULT_TIMEOUT) {
   1385     Token->RetryInterval = DNS_DEFAULT_TIMEOUT;
   1386   }
   1387 
   1388   //
   1389   // Construct DNS TokenEntry.
   1390   //
   1391   TokenEntry = AllocateZeroPool (sizeof(DNS6_TOKEN_ENTRY));
   1392   if (TokenEntry == NULL) {
   1393     Status = EFI_OUT_OF_RESOURCES;
   1394     goto ON_EXIT;
   1395   }
   1396 
   1397   TokenEntry->PacketToLive = Token->RetryInterval;
   1398   TokenEntry->GeneralLookUp = TRUE;
   1399   TokenEntry->Token = Token;
   1400 
   1401   //
   1402   // Construct DNS Query Packet.
   1403   //
   1404   Status = ConstructDNSQuery (Instance, QName, QType, QClass, &Packet);
   1405   if (EFI_ERROR (Status)) {
   1406     if (TokenEntry != NULL) {
   1407       FreePool (TokenEntry);
   1408     }
   1409 
   1410     goto ON_EXIT;
   1411   }
   1412 
   1413   ASSERT (Packet != NULL);
   1414 
   1415   //
   1416   // Save the token into the Dns6TxTokens map.
   1417   //
   1418   Status = NetMapInsertTail (&Instance->Dns6TxTokens, TokenEntry, Packet);
   1419   if (EFI_ERROR (Status)) {
   1420     if (TokenEntry != NULL) {
   1421       FreePool (TokenEntry);
   1422     }
   1423 
   1424     NetbufFree (Packet);
   1425 
   1426     goto ON_EXIT;
   1427   }
   1428 
   1429   //
   1430   // Dns Query Ip
   1431   //
   1432   Status = DoDnsQuery (Instance, Packet);
   1433   if (EFI_ERROR (Status)) {
   1434     if (TokenEntry != NULL) {
   1435       FreePool (TokenEntry);
   1436     }
   1437 
   1438     NetbufFree (Packet);
   1439   }
   1440 
   1441 ON_EXIT:
   1442   gBS->RestoreTPL (OldTpl);
   1443   return Status;
   1444 }
   1445 
   1446 /**
   1447   This function is used to add/delete/modify DNS cache entry.
   1448   DNS cache can be normally dynamically updated after the DNS resolve succeeds.
   1449   This function provided capability to manually add/delete/modify the DNS cache.
   1450 
   1451   @param[in]  This               Pointer to EFI_DNS6_PROTOCOL instance.
   1452   @param[in]  DeleteFlag         If FALSE, this function is to add one entry to the DNS Cache.
   1453                                  If TRUE, this function will delete matching DNS Cache entry.
   1454   @param[in]  Override           If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
   1455                                  If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
   1456   @param[in]  DnsCacheEntry      Pointer to DNS Cache entry.
   1457 
   1458   @retval  EFI_SUCCESS           The operation completed successfully.
   1459   @retval  EFI_INVALID_PARAMETER This is NULL.
   1460                                  DnsCacheEntry.HostName is NULL.
   1461                                  DnsCacheEntry.IpAddress is NULL.
   1462                                  DnsCacheEntry.Timeout is zero.
   1463   @retval  EFI_ACCESS_DENIED     The DNS cache entry already exists and Override is not TRUE.
   1464 
   1465 **/
   1466 EFI_STATUS
   1467 EFIAPI
   1468 Dns6UpdateDnsCache (
   1469   IN EFI_DNS6_PROTOCOL      *This,
   1470   IN BOOLEAN                DeleteFlag,
   1471   IN BOOLEAN                Override,
   1472   IN EFI_DNS6_CACHE_ENTRY   DnsCacheEntry
   1473   )
   1474 {
   1475   EFI_STATUS    Status;
   1476   EFI_TPL       OldTpl;
   1477 
   1478   Status = EFI_SUCCESS;
   1479 
   1480   if (DnsCacheEntry.HostName == NULL || DnsCacheEntry.IpAddress == NULL || DnsCacheEntry.Timeout == 0) {
   1481     return EFI_INVALID_PARAMETER;
   1482   }
   1483 
   1484   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
   1485 
   1486   //
   1487   // Update Dns6Cache here.
   1488   //
   1489   Status = UpdateDns6Cache (&mDriverData->Dns6CacheList, DeleteFlag, Override, DnsCacheEntry);
   1490 
   1491   gBS->RestoreTPL (OldTpl);
   1492 
   1493   return Status;
   1494 }
   1495 
   1496 /**
   1497   This function can be used by network drivers and applications to increase the rate that data packets are moved between
   1498   the communications device and the transmit and receive queues. In some systems, the periodic timer event in the managed
   1499   network driver may not poll the underlying communications device fast enough to transmit and/or receive all data packets
   1500   without missing incoming packets or dropping outgoing packets.
   1501 
   1502   @param[in]  This               Pointer to EFI_DNS6_PROTOCOL instance.
   1503 
   1504   @retval  EFI_SUCCESS           Incoming or outgoing data was processed.
   1505   @retval  EFI_INVALID_PARAMETER This is NULL.
   1506   @retval  EFI_NOT_STARTED       This EFI DNS Protocol instance has not been started.
   1507   @retval  EFI_DEVICE_ERROR      An unexpected system or network error occurred.
   1508   @retval  EFI_TIMEOUT           Data was dropped out of the transmit and/or receive queue.
   1509                                  Consider increasing the polling rate.
   1510 
   1511 **/
   1512 EFI_STATUS
   1513 EFIAPI
   1514 Dns6Poll (
   1515   IN EFI_DNS6_PROTOCOL    *This
   1516   )
   1517 {
   1518   DNS_INSTANCE           *Instance;
   1519   EFI_UDP6_PROTOCOL      *Udp;
   1520 
   1521   if (This == NULL) {
   1522     return EFI_INVALID_PARAMETER;
   1523   }
   1524 
   1525   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL6 (This);
   1526 
   1527   if (Instance->State == DNS_STATE_UNCONFIGED) {
   1528     return EFI_NOT_STARTED;
   1529   } else if (Instance->State == DNS_STATE_DESTROY) {
   1530     return EFI_DEVICE_ERROR;
   1531   }
   1532 
   1533   Udp = Instance->UdpIo->Protocol.Udp6;
   1534 
   1535   return Udp->Poll (Udp);
   1536 }
   1537 
   1538 /**
   1539   This function is used to abort a pending resolution request.
   1540   After calling this function, Token.Status will be set to EFI_ABORTED and then Token.
   1541 
   1542   @param[in]  This               Pointer to EFI_DNS6_PROTOCOL instance.
   1543   @param[in]  Token              Pointer to a token that has been issued by EFI_DNS6_PROTOCOL.HostNameToIp(),
   1544                                  EFI_DNS6_PROTOCOL.IpToHostName() or EFI_DNS6_PROTOCOL.GeneralLookup().
   1545                                  If NULL, all pending tokens are aborted.
   1546 
   1547   @retval  EFI_SUCCESS           Incoming or outgoing data was processed.
   1548   @retval  EFI_INVALID_PARAMETER This is NULL.
   1549   @retval  EFI_NOT_STARTED       This EFI DNS Protocol instance has not been started.
   1550   @retval  EFI_NOT_FOUND         When Token is not NULL, and the asynchronous DNS operation was not found in the transmit queue.
   1551                                  It was either completed or was not issued by HostNameToIp(), IpToHostName() or GeneralLookup().
   1552 
   1553 **/
   1554 EFI_STATUS
   1555 EFIAPI
   1556 Dns6Cancel (
   1557   IN  EFI_DNS6_PROTOCOL          *This,
   1558   IN  EFI_DNS6_COMPLETION_TOKEN  *Token
   1559   )
   1560 {
   1561   EFI_STATUS          Status;
   1562   DNS_INSTANCE        *Instance;
   1563   EFI_TPL             OldTpl;
   1564 
   1565   if (This == NULL) {
   1566     return EFI_INVALID_PARAMETER;
   1567   }
   1568 
   1569   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL6 (This);
   1570 
   1571   if (Instance->State == DNS_STATE_UNCONFIGED) {
   1572     return EFI_NOT_STARTED;
   1573   }
   1574 
   1575   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
   1576 
   1577   //
   1578   // Cancle the tokens specified by Token for this instance.
   1579   //
   1580   Status = Dns6InstanceCancelToken (Instance, Token);
   1581 
   1582   //
   1583   // Dispatch the DPC queued by the NotifyFunction of the canceled token's events.
   1584   //
   1585   DispatchDpc ();
   1586 
   1587   gBS->RestoreTPL (OldTpl);
   1588 
   1589   return Status;
   1590 }
   1591 
   1592