add whitespace according to coding style. Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com> Cc: Jiaxin Wu <jiaxin.wu@intel.com> Cc: Siyuan Fu <siyuan.fu@intel.com> Signed-off-by: Wenyi Xie <xiewenyi2@huawei.com> Reviewed-by: Maciej Rabeda <maciej.rabeda@linux.intel.com>
		
			
				
	
	
		
			2244 lines
		
	
	
		
			65 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2244 lines
		
	
	
		
			65 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
DnsDxe support functions implementation.
 | 
						|
 | 
						|
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "DnsImpl.h"
 | 
						|
 | 
						|
/**
 | 
						|
  Remove TokenEntry from TokenMap.
 | 
						|
 | 
						|
  @param[in] TokenMap          All DNSv4 Token entrys.
 | 
						|
  @param[in] TokenEntry        TokenEntry need to be removed.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS          Remove TokenEntry from TokenMap successfully.
 | 
						|
  @retval EFI_NOT_FOUND        TokenEntry is not found in TokenMap.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Dns4RemoveTokenEntry (
 | 
						|
  IN NET_MAP                    *TokenMap,
 | 
						|
  IN DNS4_TOKEN_ENTRY           *TokenEntry
 | 
						|
  )
 | 
						|
{
 | 
						|
  NET_MAP_ITEM  *Item;
 | 
						|
 | 
						|
  //
 | 
						|
  // Find the TokenEntry first.
 | 
						|
  //
 | 
						|
  Item = NetMapFindKey (TokenMap, (VOID *) TokenEntry);
 | 
						|
 | 
						|
  if (Item != NULL) {
 | 
						|
    //
 | 
						|
    // Remove the TokenEntry if it's found in the map.
 | 
						|
    //
 | 
						|
    NetMapRemoveItem (TokenMap, Item, NULL);
 | 
						|
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Remove TokenEntry from TokenMap.
 | 
						|
 | 
						|
  @param[in] TokenMap           All DNSv6 Token entrys.
 | 
						|
  @param[in] TokenEntry         TokenEntry need to be removed.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           Remove TokenEntry from TokenMap successfully.
 | 
						|
  @retval EFI_NOT_FOUND         TokenEntry is not found in TokenMap.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Dns6RemoveTokenEntry (
 | 
						|
  IN NET_MAP                    *TokenMap,
 | 
						|
  IN DNS6_TOKEN_ENTRY           *TokenEntry
 | 
						|
  )
 | 
						|
{
 | 
						|
  NET_MAP_ITEM  *Item;
 | 
						|
 | 
						|
  //
 | 
						|
  // Find the TokenEntry first.
 | 
						|
  //
 | 
						|
  Item = NetMapFindKey (TokenMap, (VOID *) TokenEntry);
 | 
						|
 | 
						|
  if (Item != NULL) {
 | 
						|
    //
 | 
						|
    // Remove the TokenEntry if it's found in the map.
 | 
						|
    //
 | 
						|
    NetMapRemoveItem (TokenMap, Item, NULL);
 | 
						|
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function cancel the token specified by Arg in the Map.
 | 
						|
 | 
						|
  @param[in]  Map             Pointer to the NET_MAP.
 | 
						|
  @param[in]  Item            Pointer to the NET_MAP_ITEM.
 | 
						|
  @param[in]  Arg             Pointer to the token to be cancelled. If NULL, all
 | 
						|
                              the tokens in this Map will be cancelled.
 | 
						|
                              This parameter is optional and may be NULL.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS         The token is cancelled if Arg is NULL, or the token
 | 
						|
                              is not the same as that in the Item, if Arg is not
 | 
						|
                              NULL.
 | 
						|
  @retval EFI_ABORTED         Arg is not NULL, and the token specified by Arg is
 | 
						|
                              cancelled.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Dns4CancelTokens (
 | 
						|
  IN NET_MAP       *Map,
 | 
						|
  IN NET_MAP_ITEM  *Item,
 | 
						|
  IN VOID          *Arg OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  DNS4_TOKEN_ENTRY           *TokenEntry;
 | 
						|
  NET_BUF                    *Packet;
 | 
						|
  UDP_IO                     *UdpIo;
 | 
						|
 | 
						|
  if ((Arg != NULL) && (Item->Key != Arg)) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Item->Value != NULL) {
 | 
						|
    //
 | 
						|
    // If the TokenEntry is a transmit TokenEntry, the corresponding Packet is recorded in
 | 
						|
    // Item->Value.
 | 
						|
    //
 | 
						|
    Packet  = (NET_BUF *) (Item->Value);
 | 
						|
    UdpIo = (UDP_IO *) (*((UINTN *) &Packet->ProtoData[0]));
 | 
						|
 | 
						|
    UdpIoCancelSentDatagram (UdpIo, Packet);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Remove TokenEntry from Dns4TxTokens.
 | 
						|
  //
 | 
						|
  TokenEntry = (DNS4_TOKEN_ENTRY *) Item->Key;
 | 
						|
  if (Dns4RemoveTokenEntry (Map, TokenEntry) == EFI_SUCCESS) {
 | 
						|
    TokenEntry->Token->Status = EFI_ABORTED;
 | 
						|
    gBS->SignalEvent (TokenEntry->Token->Event);
 | 
						|
    DispatchDpc ();
 | 
						|
  }
 | 
						|
 | 
						|
  if (Arg != NULL) {
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function cancel the token specified by Arg in the Map.
 | 
						|
 | 
						|
  @param[in]  Map             Pointer to the NET_MAP.
 | 
						|
  @param[in]  Item            Pointer to the NET_MAP_ITEM.
 | 
						|
  @param[in]  Arg             Pointer to the token to be cancelled. If NULL, all
 | 
						|
                              the tokens in this Map will be cancelled.
 | 
						|
                              This parameter is optional and may be NULL.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS         The token is cancelled if Arg is NULL, or the token
 | 
						|
                              is not the same as that in the Item, if Arg is not
 | 
						|
                              NULL.
 | 
						|
  @retval EFI_ABORTED         Arg is not NULL, and the token specified by Arg is
 | 
						|
                              cancelled.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Dns6CancelTokens (
 | 
						|
  IN NET_MAP       *Map,
 | 
						|
  IN NET_MAP_ITEM  *Item,
 | 
						|
  IN VOID          *Arg OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  DNS6_TOKEN_ENTRY           *TokenEntry;
 | 
						|
  NET_BUF                    *Packet;
 | 
						|
  UDP_IO                     *UdpIo;
 | 
						|
 | 
						|
  if ((Arg != NULL) && (Item->Key != Arg)) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Item->Value != NULL) {
 | 
						|
    //
 | 
						|
    // If the TokenEntry is a transmit TokenEntry, the corresponding Packet is recorded in
 | 
						|
    // Item->Value.
 | 
						|
    //
 | 
						|
    Packet  = (NET_BUF *) (Item->Value);
 | 
						|
    UdpIo = (UDP_IO *) (*((UINTN *) &Packet->ProtoData[0]));
 | 
						|
 | 
						|
    UdpIoCancelSentDatagram (UdpIo, Packet);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Remove TokenEntry from Dns6TxTokens.
 | 
						|
  //
 | 
						|
  TokenEntry = (DNS6_TOKEN_ENTRY *) Item->Key;
 | 
						|
  if (Dns6RemoveTokenEntry (Map, TokenEntry) == EFI_SUCCESS) {
 | 
						|
    TokenEntry->Token->Status = EFI_ABORTED;
 | 
						|
    gBS->SignalEvent (TokenEntry->Token->Event);
 | 
						|
    DispatchDpc ();
 | 
						|
  }
 | 
						|
 | 
						|
  if (Arg != NULL) {
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the TokenEntry from the TokensMap.
 | 
						|
 | 
						|
  @param[in]  TokensMap           All DNSv4 Token entrys
 | 
						|
  @param[in]  Token               Pointer to the token to be get.
 | 
						|
  @param[out] TokenEntry          Pointer to TokenEntry corresponding Token.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             Get the TokenEntry from the TokensMap successfully.
 | 
						|
  @retval EFI_NOT_FOUND           TokenEntry is not found in TokenMap.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
GetDns4TokenEntry (
 | 
						|
  IN     NET_MAP                   *TokensMap,
 | 
						|
  IN     EFI_DNS4_COMPLETION_TOKEN *Token,
 | 
						|
     OUT DNS4_TOKEN_ENTRY          **TokenEntry
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY              *Entry;
 | 
						|
 | 
						|
  NET_MAP_ITEM            *Item;
 | 
						|
 | 
						|
  NET_LIST_FOR_EACH (Entry, &TokensMap->Used) {
 | 
						|
    Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
 | 
						|
    *TokenEntry = (DNS4_TOKEN_ENTRY *) (Item->Key);
 | 
						|
    if ((*TokenEntry)->Token == Token) {
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  *TokenEntry = NULL;
 | 
						|
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the TokenEntry from the TokensMap.
 | 
						|
 | 
						|
  @param[in]  TokensMap           All DNSv6 Token entrys
 | 
						|
  @param[in]  Token               Pointer to the token to be get.
 | 
						|
  @param[out] TokenEntry          Pointer to TokenEntry corresponding Token.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             Get the TokenEntry from the TokensMap successfully.
 | 
						|
  @retval EFI_NOT_FOUND           TokenEntry is not found in TokenMap.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
GetDns6TokenEntry (
 | 
						|
  IN     NET_MAP                   *TokensMap,
 | 
						|
  IN     EFI_DNS6_COMPLETION_TOKEN *Token,
 | 
						|
     OUT DNS6_TOKEN_ENTRY          **TokenEntry
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY              *Entry;
 | 
						|
 | 
						|
  NET_MAP_ITEM            *Item;
 | 
						|
 | 
						|
  NET_LIST_FOR_EACH (Entry, &TokensMap->Used) {
 | 
						|
    Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
 | 
						|
    *TokenEntry = (DNS6_TOKEN_ENTRY *) (Item->Key);
 | 
						|
    if ((*TokenEntry)->Token == Token) {
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  *TokenEntry =NULL;
 | 
						|
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Cancel DNS4 tokens from the DNS4 instance.
 | 
						|
 | 
						|
  @param[in]  Instance           Pointer to the DNS instance context data.
 | 
						|
  @param[in]  Token              Pointer to the token to be canceled. If NULL, all
 | 
						|
                                 tokens in this instance will be cancelled.
 | 
						|
                                 This parameter is optional and may be NULL.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            The Token is cancelled.
 | 
						|
  @retval EFI_NOT_FOUND          The Token is not found.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Dns4InstanceCancelToken (
 | 
						|
  IN DNS_INSTANCE               *Instance,
 | 
						|
  IN EFI_DNS4_COMPLETION_TOKEN  *Token
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS        Status;
 | 
						|
  DNS4_TOKEN_ENTRY  *TokenEntry;
 | 
						|
 | 
						|
  TokenEntry = NULL;
 | 
						|
 | 
						|
  if(Token != NULL  ) {
 | 
						|
    Status = GetDns4TokenEntry (&Instance->Dns4TxTokens, Token, &TokenEntry);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    TokenEntry = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Cancel this TokenEntry from the Dns4TxTokens map.
 | 
						|
  //
 | 
						|
  Status = NetMapIterate (&Instance->Dns4TxTokens, Dns4CancelTokens, TokenEntry);
 | 
						|
 | 
						|
  if ((TokenEntry != NULL) && (Status == EFI_ABORTED)) {
 | 
						|
    //
 | 
						|
    // If Token isn't NULL and Status is EFI_ABORTED, the token is cancelled from
 | 
						|
    // the Dns4TxTokens and returns success.
 | 
						|
    //
 | 
						|
    if (NetMapIsEmpty (&Instance->Dns4TxTokens)) {
 | 
						|
       Instance->UdpIo->Protocol.Udp4->Cancel (Instance->UdpIo->Protocol.Udp4, &Instance->UdpIo->RecvRequest->Token.Udp4);
 | 
						|
    }
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  ASSERT ((TokenEntry != NULL) || (0 == NetMapGetCount (&Instance->Dns4TxTokens)));
 | 
						|
 | 
						|
  if (NetMapIsEmpty (&Instance->Dns4TxTokens)) {
 | 
						|
    Instance->UdpIo->Protocol.Udp4->Cancel (Instance->UdpIo->Protocol.Udp4, &Instance->UdpIo->RecvRequest->Token.Udp4);
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Cancel DNS6 tokens from the DNS6 instance.
 | 
						|
 | 
						|
  @param[in]  Instance           Pointer to the DNS instance context data.
 | 
						|
  @param[in]  Token              Pointer to the token to be canceled. If NULL, all
 | 
						|
                                 tokens in this instance will be cancelled.
 | 
						|
                                 This parameter is optional and may be NULL.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            The Token is cancelled.
 | 
						|
  @retval EFI_NOT_FOUND          The Token is not found.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Dns6InstanceCancelToken (
 | 
						|
  IN DNS_INSTANCE               *Instance,
 | 
						|
  IN EFI_DNS6_COMPLETION_TOKEN  *Token
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS        Status;
 | 
						|
  DNS6_TOKEN_ENTRY  *TokenEntry;
 | 
						|
 | 
						|
  TokenEntry = NULL;
 | 
						|
 | 
						|
  if(Token != NULL  ) {
 | 
						|
    Status = GetDns6TokenEntry (&Instance->Dns6TxTokens, Token, &TokenEntry);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    TokenEntry = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Cancel this TokenEntry from the Dns6TxTokens map.
 | 
						|
  //
 | 
						|
  Status = NetMapIterate (&Instance->Dns6TxTokens, Dns6CancelTokens, TokenEntry);
 | 
						|
 | 
						|
  if ((TokenEntry != NULL) && (Status == EFI_ABORTED)) {
 | 
						|
    //
 | 
						|
    // If Token isn't NULL and Status is EFI_ABORTED, the token is cancelled from
 | 
						|
    // the Dns6TxTokens and returns success.
 | 
						|
    //
 | 
						|
    if (NetMapIsEmpty (&Instance->Dns6TxTokens)) {
 | 
						|
       Instance->UdpIo->Protocol.Udp6->Cancel (Instance->UdpIo->Protocol.Udp6, &Instance->UdpIo->RecvRequest->Token.Udp6);
 | 
						|
    }
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  ASSERT ((TokenEntry != NULL) || (0 == NetMapGetCount (&Instance->Dns6TxTokens)));
 | 
						|
 | 
						|
  if (NetMapIsEmpty (&Instance->Dns6TxTokens)) {
 | 
						|
    Instance->UdpIo->Protocol.Udp6->Cancel (Instance->UdpIo->Protocol.Udp6, &Instance->UdpIo->RecvRequest->Token.Udp6);
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Free the resource related to the configure parameters.
 | 
						|
 | 
						|
  @param  Config                 The DNS configure data
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
Dns4CleanConfigure (
 | 
						|
  IN OUT EFI_DNS4_CONFIG_DATA  *Config
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (Config->DnsServerList != NULL) {
 | 
						|
    FreePool (Config->DnsServerList);
 | 
						|
  }
 | 
						|
 | 
						|
  ZeroMem (Config, sizeof (EFI_DNS4_CONFIG_DATA));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Free the resource related to the configure parameters.
 | 
						|
 | 
						|
  @param  Config                 The DNS configure data
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
Dns6CleanConfigure (
 | 
						|
  IN OUT EFI_DNS6_CONFIG_DATA  *Config
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (Config->DnsServerList != NULL) {
 | 
						|
    FreePool (Config->DnsServerList);
 | 
						|
  }
 | 
						|
 | 
						|
  ZeroMem (Config, sizeof (EFI_DNS6_CONFIG_DATA));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Allocate memory for configure parameter such as timeout value for Dst,
 | 
						|
  then copy the configure parameter from Src to Dst.
 | 
						|
 | 
						|
  @param[out]  Dst               The destination DHCP configure data.
 | 
						|
  @param[in]   Src               The source DHCP configure data.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
 | 
						|
  @retval EFI_SUCCESS            The configure is copied.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Dns4CopyConfigure (
 | 
						|
  OUT EFI_DNS4_CONFIG_DATA  *Dst,
 | 
						|
  IN  EFI_DNS4_CONFIG_DATA  *Src
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                     Len;
 | 
						|
  UINT32                    Index;
 | 
						|
 | 
						|
  CopyMem (Dst, Src, sizeof (*Dst));
 | 
						|
  Dst->DnsServerList = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate a memory then copy DnsServerList to it
 | 
						|
  //
 | 
						|
  if (Src->DnsServerList != NULL) {
 | 
						|
    Len                = Src->DnsServerListCount * sizeof (EFI_IPv4_ADDRESS);
 | 
						|
    Dst->DnsServerList = AllocatePool (Len);
 | 
						|
    if (Dst->DnsServerList == NULL) {
 | 
						|
      Dns4CleanConfigure (Dst);
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    for (Index = 0; Index < Src->DnsServerListCount; Index++) {
 | 
						|
      CopyMem (&Dst->DnsServerList[Index], &Src->DnsServerList[Index], sizeof (EFI_IPv4_ADDRESS));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Allocate memory for configure parameter such as timeout value for Dst,
 | 
						|
  then copy the configure parameter from Src to Dst.
 | 
						|
 | 
						|
  @param[out]  Dst               The destination DHCP configure data.
 | 
						|
  @param[in]   Src               The source DHCP configure data.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
 | 
						|
  @retval EFI_SUCCESS            The configure is copied.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Dns6CopyConfigure (
 | 
						|
  OUT EFI_DNS6_CONFIG_DATA  *Dst,
 | 
						|
  IN  EFI_DNS6_CONFIG_DATA  *Src
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                     Len;
 | 
						|
  UINT32                    Index;
 | 
						|
 | 
						|
  CopyMem (Dst, Src, sizeof (*Dst));
 | 
						|
  Dst->DnsServerList = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate a memory then copy DnsServerList to it
 | 
						|
  //
 | 
						|
  if (Src->DnsServerList != NULL) {
 | 
						|
    Len                = Src->DnsServerCount * sizeof (EFI_IPv6_ADDRESS);
 | 
						|
    Dst->DnsServerList = AllocatePool (Len);
 | 
						|
    if (Dst->DnsServerList == NULL) {
 | 
						|
      Dns6CleanConfigure (Dst);
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    for (Index = 0; Index < Src->DnsServerCount; Index++) {
 | 
						|
      CopyMem (&Dst->DnsServerList[Index], &Src->DnsServerList[Index], sizeof (EFI_IPv6_ADDRESS));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Callback of Dns packet. Does nothing.
 | 
						|
 | 
						|
  @param Arg           The context.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
DnsDummyExtFree (
 | 
						|
  IN VOID                   *Arg
 | 
						|
  )
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Poll the UDP to get the IP4 default address, which may be retrieved
 | 
						|
  by DHCP.
 | 
						|
 | 
						|
  The default time out value is 5 seconds. If IP has retrieved the default address,
 | 
						|
  the UDP is reconfigured.
 | 
						|
 | 
						|
  @param  Instance               The DNS instance
 | 
						|
  @param  UdpIo                  The UDP_IO to poll
 | 
						|
  @param  UdpCfgData             The UDP configure data to reconfigure the UDP_IO
 | 
						|
 | 
						|
  @retval TRUE                   The default address is retrieved and UDP is reconfigured.
 | 
						|
  @retval FALSE                  Some error occurred.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
Dns4GetMapping (
 | 
						|
  IN DNS_INSTANCE           *Instance,
 | 
						|
  IN UDP_IO                 *UdpIo,
 | 
						|
  IN EFI_UDP4_CONFIG_DATA   *UdpCfgData
 | 
						|
  )
 | 
						|
{
 | 
						|
  DNS_SERVICE               *Service;
 | 
						|
  EFI_IP4_MODE_DATA         Ip4Mode;
 | 
						|
  EFI_UDP4_PROTOCOL         *Udp;
 | 
						|
  EFI_STATUS                Status;
 | 
						|
 | 
						|
  ASSERT (Instance->Dns4CfgData.UseDefaultSetting);
 | 
						|
 | 
						|
  Service = Instance->Service;
 | 
						|
  Udp     = UdpIo->Protocol.Udp4;
 | 
						|
 | 
						|
  Status = gBS->SetTimer (
 | 
						|
                  Service->TimerToGetMap,
 | 
						|
                  TimerRelative,
 | 
						|
                  DNS_TIME_TO_GETMAP * TICKS_PER_SECOND
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  while (EFI_ERROR (gBS->CheckEvent (Service->TimerToGetMap))) {
 | 
						|
    Udp->Poll (Udp);
 | 
						|
 | 
						|
    if (!EFI_ERROR (Udp->GetModeData (Udp, NULL, &Ip4Mode, NULL, NULL)) &&
 | 
						|
        Ip4Mode.IsConfigured) {
 | 
						|
 | 
						|
      Udp->Configure (Udp, NULL);
 | 
						|
      return (BOOLEAN) (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Configure the opened Udp6 instance until the corresponding Ip6 instance
 | 
						|
  has been configured.
 | 
						|
 | 
						|
  @param  Instance               The DNS instance
 | 
						|
  @param  UdpIo                  The UDP_IO to poll
 | 
						|
  @param  UdpCfgData             The UDP configure data to reconfigure the UDP_IO
 | 
						|
 | 
						|
  @retval TRUE                   Configure the Udp6 instance successfully.
 | 
						|
  @retval FALSE                  Some error occurred.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
Dns6GetMapping (
 | 
						|
  IN DNS_INSTANCE           *Instance,
 | 
						|
  IN UDP_IO                 *UdpIo,
 | 
						|
  IN EFI_UDP6_CONFIG_DATA   *UdpCfgData
 | 
						|
  )
 | 
						|
{
 | 
						|
  DNS_SERVICE               *Service;
 | 
						|
  EFI_IP6_MODE_DATA         Ip6Mode;
 | 
						|
  EFI_UDP6_PROTOCOL         *Udp;
 | 
						|
  EFI_STATUS                Status;
 | 
						|
 | 
						|
  Service = Instance->Service;
 | 
						|
  Udp     = UdpIo->Protocol.Udp6;
 | 
						|
 | 
						|
  Status = gBS->SetTimer (
 | 
						|
                  Service->TimerToGetMap,
 | 
						|
                  TimerRelative,
 | 
						|
                  DNS_TIME_TO_GETMAP * TICKS_PER_SECOND
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  while (EFI_ERROR (gBS->CheckEvent (Service->TimerToGetMap))) {
 | 
						|
    Udp->Poll (Udp);
 | 
						|
 | 
						|
    if (!EFI_ERROR (Udp->GetModeData (Udp, NULL, &Ip6Mode, NULL, NULL))) {
 | 
						|
      if (Ip6Mode.AddressList != NULL) {
 | 
						|
        FreePool (Ip6Mode.AddressList);
 | 
						|
      }
 | 
						|
 | 
						|
      if (Ip6Mode.GroupTable != NULL) {
 | 
						|
        FreePool (Ip6Mode.GroupTable);
 | 
						|
      }
 | 
						|
 | 
						|
      if (Ip6Mode.RouteTable != NULL) {
 | 
						|
        FreePool (Ip6Mode.RouteTable);
 | 
						|
      }
 | 
						|
 | 
						|
      if (Ip6Mode.NeighborCache != NULL) {
 | 
						|
        FreePool (Ip6Mode.NeighborCache);
 | 
						|
      }
 | 
						|
 | 
						|
      if (Ip6Mode.PrefixTable != NULL) {
 | 
						|
        FreePool (Ip6Mode.PrefixTable);
 | 
						|
      }
 | 
						|
 | 
						|
      if (Ip6Mode.IcmpTypeList != NULL) {
 | 
						|
        FreePool (Ip6Mode.IcmpTypeList);
 | 
						|
      }
 | 
						|
 | 
						|
      if (!Ip6Mode.IsStarted || Ip6Mode.IsConfigured) {
 | 
						|
        Udp->Configure (Udp, NULL);
 | 
						|
        if (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS) {
 | 
						|
          return TRUE;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Configure the UDP.
 | 
						|
 | 
						|
  @param  Instance               The DNS session
 | 
						|
  @param  UdpIo                  The UDP_IO instance
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            The UDP is successfully configured for the
 | 
						|
                                 session.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Dns4ConfigUdp (
 | 
						|
  IN DNS_INSTANCE           *Instance,
 | 
						|
  IN UDP_IO                 *UdpIo
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_DNS4_CONFIG_DATA      *Config;
 | 
						|
  EFI_UDP4_CONFIG_DATA      UdpConfig;
 | 
						|
  EFI_STATUS                Status;
 | 
						|
 | 
						|
  Config = &Instance->Dns4CfgData;
 | 
						|
 | 
						|
  UdpConfig.AcceptBroadcast    = FALSE;
 | 
						|
  UdpConfig.AcceptPromiscuous  = FALSE;
 | 
						|
  UdpConfig.AcceptAnyPort      = FALSE;
 | 
						|
  UdpConfig.AllowDuplicatePort = FALSE;
 | 
						|
  UdpConfig.TypeOfService      = 0;
 | 
						|
  UdpConfig.TimeToLive         = 128;
 | 
						|
  UdpConfig.DoNotFragment      = FALSE;
 | 
						|
  UdpConfig.ReceiveTimeout     = 0;
 | 
						|
  UdpConfig.TransmitTimeout    = 0;
 | 
						|
  UdpConfig.UseDefaultAddress  = Config->UseDefaultSetting;
 | 
						|
  UdpConfig.SubnetMask         = Config->SubnetMask;
 | 
						|
  UdpConfig.StationPort        = Config->LocalPort;
 | 
						|
  UdpConfig.RemotePort         = DNS_SERVER_PORT;
 | 
						|
 | 
						|
  CopyMem (&UdpConfig.StationAddress, &Config->StationIp, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
  CopyMem (&UdpConfig.RemoteAddress, &Instance->SessionDnsServer.v4, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
 | 
						|
  Status = UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfig);
 | 
						|
 | 
						|
  if ((Status == EFI_NO_MAPPING) && Dns4GetMapping (Instance, UdpIo, &UdpConfig)) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Configure the UDP.
 | 
						|
 | 
						|
  @param  Instance               The DNS session
 | 
						|
  @param  UdpIo                  The UDP_IO instance
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            The UDP is successfully configured for the
 | 
						|
                                 session.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Dns6ConfigUdp (
 | 
						|
  IN DNS_INSTANCE           *Instance,
 | 
						|
  IN UDP_IO                 *UdpIo
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_DNS6_CONFIG_DATA      *Config;
 | 
						|
  EFI_UDP6_CONFIG_DATA      UdpConfig;
 | 
						|
  EFI_STATUS                Status;
 | 
						|
 | 
						|
  Config = &Instance->Dns6CfgData;
 | 
						|
 | 
						|
  UdpConfig.AcceptPromiscuous  = FALSE;
 | 
						|
  UdpConfig.AcceptAnyPort      = FALSE;
 | 
						|
  UdpConfig.AllowDuplicatePort = FALSE;
 | 
						|
  UdpConfig.TrafficClass       = 0;
 | 
						|
  UdpConfig.HopLimit           = 128;
 | 
						|
  UdpConfig.ReceiveTimeout     = 0;
 | 
						|
  UdpConfig.TransmitTimeout    = 0;
 | 
						|
  UdpConfig.StationPort        = Config->LocalPort;
 | 
						|
  UdpConfig.RemotePort         = DNS_SERVER_PORT;
 | 
						|
  CopyMem (&UdpConfig.StationAddress, &Config->StationIp, sizeof (EFI_IPv6_ADDRESS));
 | 
						|
  CopyMem (&UdpConfig.RemoteAddress, &Instance->SessionDnsServer.v6, sizeof (EFI_IPv6_ADDRESS));
 | 
						|
 | 
						|
  Status = UdpIo->Protocol.Udp6->Configure (UdpIo->Protocol.Udp6, &UdpConfig);
 | 
						|
 | 
						|
  if ((Status == EFI_NO_MAPPING) && Dns6GetMapping (Instance, UdpIo, &UdpConfig)) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Update Dns4 cache to shared list of caches of all DNSv4 instances.
 | 
						|
 | 
						|
  @param  Dns4CacheList      All Dns4 cache list.
 | 
						|
  @param  DeleteFlag         If FALSE, this function is to add one entry to the DNS Cache.
 | 
						|
                             If TRUE, this function will delete matching DNS Cache entry.
 | 
						|
  @param  Override           If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
 | 
						|
                             If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
 | 
						|
  @param  DnsCacheEntry      Entry Pointer to DNS Cache entry.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS        Update Dns4 cache successfully.
 | 
						|
  @retval Others             Failed to update Dns4 cache.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UpdateDns4Cache (
 | 
						|
  IN LIST_ENTRY             *Dns4CacheList,
 | 
						|
  IN BOOLEAN                DeleteFlag,
 | 
						|
  IN BOOLEAN                Override,
 | 
						|
  IN EFI_DNS4_CACHE_ENTRY   DnsCacheEntry
 | 
						|
  )
 | 
						|
{
 | 
						|
  DNS4_CACHE    *NewDnsCache;
 | 
						|
  DNS4_CACHE    *Item;
 | 
						|
  LIST_ENTRY    *Entry;
 | 
						|
  LIST_ENTRY    *Next;
 | 
						|
 | 
						|
  NewDnsCache = NULL;
 | 
						|
  Item        = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Search the database for the matching EFI_DNS_CACHE_ENTRY
 | 
						|
  //
 | 
						|
  NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns4CacheList) {
 | 
						|
    Item = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
 | 
						|
    if (StrCmp (DnsCacheEntry.HostName, Item->DnsCache.HostName) == 0 && \
 | 
						|
        CompareMem (DnsCacheEntry.IpAddress, Item->DnsCache.IpAddress, sizeof (EFI_IPv4_ADDRESS)) == 0) {
 | 
						|
      //
 | 
						|
      // This is the Dns cache entry
 | 
						|
      //
 | 
						|
      if (DeleteFlag) {
 | 
						|
        //
 | 
						|
        // Delete matching DNS Cache entry
 | 
						|
        //
 | 
						|
        RemoveEntryList (&Item->AllCacheLink);
 | 
						|
 | 
						|
        FreePool (Item->DnsCache.HostName);
 | 
						|
        FreePool (Item->DnsCache.IpAddress);
 | 
						|
        FreePool (Item);
 | 
						|
 | 
						|
        return EFI_SUCCESS;
 | 
						|
      } else if (Override) {
 | 
						|
        //
 | 
						|
        // Update this one
 | 
						|
        //
 | 
						|
        Item->DnsCache.Timeout = DnsCacheEntry.Timeout;
 | 
						|
 | 
						|
        return EFI_SUCCESS;
 | 
						|
      } else {
 | 
						|
        return EFI_ACCESS_DENIED;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Add new one
 | 
						|
  //
 | 
						|
  NewDnsCache = AllocatePool (sizeof (DNS4_CACHE));
 | 
						|
  if (NewDnsCache == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  InitializeListHead (&NewDnsCache->AllCacheLink);
 | 
						|
 | 
						|
  NewDnsCache->DnsCache.HostName = AllocatePool (StrSize (DnsCacheEntry.HostName));
 | 
						|
  if (NewDnsCache->DnsCache.HostName == NULL) {
 | 
						|
    FreePool (NewDnsCache);
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (NewDnsCache->DnsCache.HostName, DnsCacheEntry.HostName, StrSize (DnsCacheEntry.HostName));
 | 
						|
 | 
						|
  NewDnsCache->DnsCache.IpAddress = AllocatePool (sizeof (EFI_IPv4_ADDRESS));
 | 
						|
  if (NewDnsCache->DnsCache.IpAddress == NULL) {
 | 
						|
    FreePool (NewDnsCache->DnsCache.HostName);
 | 
						|
    FreePool (NewDnsCache);
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (NewDnsCache->DnsCache.IpAddress, DnsCacheEntry.IpAddress, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
 | 
						|
  NewDnsCache->DnsCache.Timeout = DnsCacheEntry.Timeout;
 | 
						|
 | 
						|
  InsertTailList (Dns4CacheList, &NewDnsCache->AllCacheLink);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Update Dns6 cache to shared list of caches of all DNSv6 instances.
 | 
						|
 | 
						|
  @param  Dns6CacheList      All Dns6 cache list.
 | 
						|
  @param  DeleteFlag         If FALSE, this function is to add one entry to the DNS Cache.
 | 
						|
                             If TRUE, this function will delete matching DNS Cache entry.
 | 
						|
  @param  Override           If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
 | 
						|
                             If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
 | 
						|
  @param  DnsCacheEntry      Entry Pointer to DNS Cache entry.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS        Update Dns6 cache successfully.
 | 
						|
  @retval Others             Failed to update Dns6 cache.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UpdateDns6Cache (
 | 
						|
  IN LIST_ENTRY             *Dns6CacheList,
 | 
						|
  IN BOOLEAN                DeleteFlag,
 | 
						|
  IN BOOLEAN                Override,
 | 
						|
  IN EFI_DNS6_CACHE_ENTRY   DnsCacheEntry
 | 
						|
  )
 | 
						|
{
 | 
						|
  DNS6_CACHE    *NewDnsCache;
 | 
						|
  DNS6_CACHE    *Item;
 | 
						|
  LIST_ENTRY    *Entry;
 | 
						|
  LIST_ENTRY    *Next;
 | 
						|
 | 
						|
  NewDnsCache = NULL;
 | 
						|
  Item        = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Search the database for the matching EFI_DNS_CACHE_ENTRY
 | 
						|
  //
 | 
						|
  NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns6CacheList) {
 | 
						|
    Item = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
 | 
						|
    if (StrCmp (DnsCacheEntry.HostName, Item->DnsCache.HostName) == 0 && \
 | 
						|
        CompareMem (DnsCacheEntry.IpAddress, Item->DnsCache.IpAddress, sizeof (EFI_IPv6_ADDRESS)) == 0) {
 | 
						|
      //
 | 
						|
      // This is the Dns cache entry
 | 
						|
      //
 | 
						|
      if (DeleteFlag) {
 | 
						|
        //
 | 
						|
        // Delete matching DNS Cache entry
 | 
						|
        //
 | 
						|
        RemoveEntryList (&Item->AllCacheLink);
 | 
						|
 | 
						|
        FreePool (Item->DnsCache.HostName);
 | 
						|
        FreePool (Item->DnsCache.IpAddress);
 | 
						|
        FreePool (Item);
 | 
						|
 | 
						|
        return EFI_SUCCESS;
 | 
						|
      } else if (Override) {
 | 
						|
        //
 | 
						|
        // Update this one
 | 
						|
        //
 | 
						|
        Item->DnsCache.Timeout = DnsCacheEntry.Timeout;
 | 
						|
 | 
						|
        return EFI_SUCCESS;
 | 
						|
      } else {
 | 
						|
        return EFI_ACCESS_DENIED;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Add new one
 | 
						|
  //
 | 
						|
  NewDnsCache = AllocatePool (sizeof (DNS6_CACHE));
 | 
						|
  if (NewDnsCache == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  InitializeListHead (&NewDnsCache->AllCacheLink);
 | 
						|
 | 
						|
  NewDnsCache->DnsCache.HostName = AllocatePool (StrSize (DnsCacheEntry.HostName));
 | 
						|
  if (NewDnsCache->DnsCache.HostName == NULL) {
 | 
						|
    FreePool (NewDnsCache);
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (NewDnsCache->DnsCache.HostName, DnsCacheEntry.HostName, StrSize (DnsCacheEntry.HostName));
 | 
						|
 | 
						|
  NewDnsCache->DnsCache.IpAddress = AllocatePool (sizeof (EFI_IPv6_ADDRESS));
 | 
						|
  if (NewDnsCache->DnsCache.IpAddress == NULL) {
 | 
						|
    FreePool (NewDnsCache->DnsCache.HostName);
 | 
						|
    FreePool (NewDnsCache);
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (NewDnsCache->DnsCache.IpAddress, DnsCacheEntry.IpAddress, sizeof (EFI_IPv6_ADDRESS));
 | 
						|
 | 
						|
  NewDnsCache->DnsCache.Timeout = DnsCacheEntry.Timeout;
 | 
						|
 | 
						|
  InsertTailList (Dns6CacheList, &NewDnsCache->AllCacheLink);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Add Dns4 ServerIp to common list of addresses of all configured DNSv4 server.
 | 
						|
 | 
						|
  @param  Dns4ServerList    Common list of addresses of all configured DNSv4 server.
 | 
						|
  @param  ServerIp          DNS server Ip.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS       Add Dns4 ServerIp to common list successfully.
 | 
						|
  @retval Others            Failed to add Dns4 ServerIp to common list.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AddDns4ServerIp (
 | 
						|
  IN LIST_ENTRY                *Dns4ServerList,
 | 
						|
  IN EFI_IPv4_ADDRESS           ServerIp
 | 
						|
  )
 | 
						|
{
 | 
						|
  DNS4_SERVER_IP    *NewServerIp;
 | 
						|
  DNS4_SERVER_IP    *Item;
 | 
						|
  LIST_ENTRY        *Entry;
 | 
						|
  LIST_ENTRY        *Next;
 | 
						|
 | 
						|
  NewServerIp = NULL;
 | 
						|
  Item        = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Search the database for the matching ServerIp
 | 
						|
  //
 | 
						|
  NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns4ServerList) {
 | 
						|
    Item = NET_LIST_USER_STRUCT (Entry, DNS4_SERVER_IP, AllServerLink);
 | 
						|
    if (CompareMem (&Item->Dns4ServerIp, &ServerIp, sizeof (EFI_IPv4_ADDRESS)) == 0) {
 | 
						|
      //
 | 
						|
      // Already done.
 | 
						|
      //
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Add new one
 | 
						|
  //
 | 
						|
  NewServerIp = AllocatePool (sizeof (DNS4_SERVER_IP));
 | 
						|
  if (NewServerIp == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  InitializeListHead (&NewServerIp->AllServerLink);
 | 
						|
 | 
						|
  CopyMem (&NewServerIp->Dns4ServerIp, &ServerIp, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
 | 
						|
  InsertTailList (Dns4ServerList, &NewServerIp->AllServerLink);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Add Dns6 ServerIp to common list of addresses of all configured DNSv6 server.
 | 
						|
 | 
						|
  @param  Dns6ServerList    Common list of addresses of all configured DNSv6 server.
 | 
						|
  @param  ServerIp          DNS server Ip.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS       Add Dns6 ServerIp to common list successfully.
 | 
						|
  @retval Others            Failed to add Dns6 ServerIp to common list.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AddDns6ServerIp (
 | 
						|
  IN LIST_ENTRY                *Dns6ServerList,
 | 
						|
  IN EFI_IPv6_ADDRESS           ServerIp
 | 
						|
  )
 | 
						|
{
 | 
						|
  DNS6_SERVER_IP    *NewServerIp;
 | 
						|
  DNS6_SERVER_IP    *Item;
 | 
						|
  LIST_ENTRY        *Entry;
 | 
						|
  LIST_ENTRY        *Next;
 | 
						|
 | 
						|
  NewServerIp = NULL;
 | 
						|
  Item        = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Search the database for the matching ServerIp
 | 
						|
  //
 | 
						|
  NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns6ServerList) {
 | 
						|
    Item = NET_LIST_USER_STRUCT (Entry, DNS6_SERVER_IP, AllServerLink);
 | 
						|
    if (CompareMem (&Item->Dns6ServerIp, &ServerIp, sizeof (EFI_IPv6_ADDRESS)) == 0) {
 | 
						|
      //
 | 
						|
      // Already done.
 | 
						|
      //
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Add new one
 | 
						|
  //
 | 
						|
  NewServerIp = AllocatePool (sizeof (DNS6_SERVER_IP));
 | 
						|
  if (NewServerIp == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  InitializeListHead (&NewServerIp->AllServerLink);
 | 
						|
 | 
						|
  CopyMem (&NewServerIp->Dns6ServerIp, &ServerIp, sizeof (EFI_IPv6_ADDRESS));
 | 
						|
 | 
						|
  InsertTailList (Dns6ServerList, &NewServerIp->AllServerLink);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Find out whether the response is valid or invalid.
 | 
						|
 | 
						|
  @param  TokensMap       All DNS transmittal Tokens entry.
 | 
						|
  @param  Identification  Identification for queried packet.
 | 
						|
  @param  Type            Type for queried packet.
 | 
						|
  @param  Class           Class for queried packet.
 | 
						|
  @param  Item            Return corresponding Token entry.
 | 
						|
 | 
						|
  @retval TRUE            The response is valid.
 | 
						|
  @retval FALSE           The response is invalid.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsValidDnsResponse (
 | 
						|
  IN     NET_MAP      *TokensMap,
 | 
						|
  IN     UINT16       Identification,
 | 
						|
  IN     UINT16       Type,
 | 
						|
  IN     UINT16       Class,
 | 
						|
     OUT NET_MAP_ITEM **Item
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY              *Entry;
 | 
						|
 | 
						|
  NET_BUF                 *Packet;
 | 
						|
  UINT8                   *TxString;
 | 
						|
  DNS_HEADER              *DnsHeader;
 | 
						|
  CHAR8                   *QueryName;
 | 
						|
  DNS_QUERY_SECTION       *QuerySection;
 | 
						|
 | 
						|
  NET_LIST_FOR_EACH (Entry, &TokensMap->Used) {
 | 
						|
    *Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
 | 
						|
    Packet = (NET_BUF *) ((*Item)->Value);
 | 
						|
    if (Packet == NULL) {
 | 
						|
 | 
						|
      continue;
 | 
						|
    } else {
 | 
						|
      TxString = NetbufGetByte (Packet, 0, NULL);
 | 
						|
      ASSERT (TxString != NULL);
 | 
						|
      DnsHeader = (DNS_HEADER *) TxString;
 | 
						|
      QueryName = (CHAR8 *) (TxString + sizeof (*DnsHeader));
 | 
						|
      QuerySection = (DNS_QUERY_SECTION *) (QueryName + AsciiStrLen (QueryName) + 1);
 | 
						|
 | 
						|
      if (NTOHS (DnsHeader->Identification) == Identification &&
 | 
						|
          NTOHS (QuerySection->Type) == Type &&
 | 
						|
          NTOHS (QuerySection->Class) == Class) {
 | 
						|
        return TRUE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  *Item = NULL;
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Parse Dns Response.
 | 
						|
 | 
						|
  @param  Instance              The DNS instance
 | 
						|
  @param  RxString              Received buffer.
 | 
						|
  @param  Length                Received buffer length.
 | 
						|
  @param  Completed             Flag to indicate that Dns response is valid.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           Parse Dns Response successfully.
 | 
						|
  @retval Others                Failed to parse Dns Response.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ParseDnsResponse (
 | 
						|
  IN OUT DNS_INSTANCE              *Instance,
 | 
						|
  IN     UINT8                     *RxString,
 | 
						|
  IN     UINT32                    Length,
 | 
						|
     OUT BOOLEAN                   *Completed
 | 
						|
  )
 | 
						|
{
 | 
						|
  DNS_HEADER            *DnsHeader;
 | 
						|
 | 
						|
  CHAR8                 *QueryName;
 | 
						|
  UINT32                QueryNameLen;
 | 
						|
  DNS_QUERY_SECTION     *QuerySection;
 | 
						|
 | 
						|
  CHAR8                 *AnswerName;
 | 
						|
  DNS_ANSWER_SECTION    *AnswerSection;
 | 
						|
  UINT8                 *AnswerData;
 | 
						|
 | 
						|
  NET_MAP_ITEM          *Item;
 | 
						|
  DNS4_TOKEN_ENTRY      *Dns4TokenEntry;
 | 
						|
  DNS6_TOKEN_ENTRY      *Dns6TokenEntry;
 | 
						|
 | 
						|
  UINT32                IpCount;
 | 
						|
  UINT32                RRCount;
 | 
						|
  UINT32                AnswerSectionNum;
 | 
						|
  UINT32                CNameTtl;
 | 
						|
 | 
						|
  EFI_IPv4_ADDRESS      *HostAddr4;
 | 
						|
  EFI_IPv6_ADDRESS      *HostAddr6;
 | 
						|
 | 
						|
  EFI_DNS4_CACHE_ENTRY  *Dns4CacheEntry;
 | 
						|
  EFI_DNS6_CACHE_ENTRY  *Dns6CacheEntry;
 | 
						|
 | 
						|
  DNS_RESOURCE_RECORD   *Dns4RR;
 | 
						|
  DNS6_RESOURCE_RECORD  *Dns6RR;
 | 
						|
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  UINT32                RemainingLength;
 | 
						|
 | 
						|
  EFI_TPL               OldTpl;
 | 
						|
 | 
						|
  Item             = NULL;
 | 
						|
  Dns4TokenEntry   = NULL;
 | 
						|
  Dns6TokenEntry   = NULL;
 | 
						|
 | 
						|
  IpCount          = 0;
 | 
						|
  RRCount          = 0;
 | 
						|
  AnswerSectionNum = 0;
 | 
						|
  CNameTtl         = 0;
 | 
						|
 | 
						|
  HostAddr4        = NULL;
 | 
						|
  HostAddr6        = NULL;
 | 
						|
 | 
						|
  Dns4CacheEntry   = NULL;
 | 
						|
  Dns6CacheEntry   = NULL;
 | 
						|
 | 
						|
  Dns4RR           = NULL;
 | 
						|
  Dns6RR           = NULL;
 | 
						|
 | 
						|
  *Completed       = TRUE;
 | 
						|
  Status           = EFI_SUCCESS;
 | 
						|
  RemainingLength  = Length;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check whether the remaining packet length is available or not.
 | 
						|
  //
 | 
						|
  if (RemainingLength <= sizeof (DNS_HEADER)) {
 | 
						|
    *Completed = FALSE;
 | 
						|
    return EFI_ABORTED;
 | 
						|
  } else {
 | 
						|
    RemainingLength -= sizeof (DNS_HEADER);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get header
 | 
						|
  //
 | 
						|
  DnsHeader = (DNS_HEADER *) RxString;
 | 
						|
 | 
						|
  DnsHeader->Identification = NTOHS (DnsHeader->Identification);
 | 
						|
  DnsHeader->Flags.Uint16 = NTOHS (DnsHeader->Flags.Uint16);
 | 
						|
  DnsHeader->QuestionsNum = NTOHS (DnsHeader->QuestionsNum);
 | 
						|
  DnsHeader->AnswersNum = NTOHS (DnsHeader->AnswersNum);
 | 
						|
  DnsHeader->AuthorityNum = NTOHS (DnsHeader->AuthorityNum);
 | 
						|
  DnsHeader->AditionalNum = NTOHS (DnsHeader->AditionalNum);
 | 
						|
 | 
						|
  //
 | 
						|
  // There is always one QuestionsNum in DNS message. The capability to handle more
 | 
						|
  // than one requires to redesign the message format. Currently, it's not supported.
 | 
						|
  //
 | 
						|
  if (DnsHeader->QuestionsNum > 1) {
 | 
						|
    *Completed = FALSE;
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get Query name
 | 
						|
  //
 | 
						|
  QueryName = (CHAR8 *) (RxString + sizeof (*DnsHeader));
 | 
						|
 | 
						|
  QueryNameLen = (UINT32) AsciiStrLen (QueryName) + 1;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check whether the remaining packet length is available or not.
 | 
						|
  //
 | 
						|
  if (RemainingLength <= QueryNameLen + sizeof (DNS_QUERY_SECTION)) {
 | 
						|
    *Completed = FALSE;
 | 
						|
    return EFI_ABORTED;
 | 
						|
  } else {
 | 
						|
    RemainingLength -= (QueryNameLen + sizeof (DNS_QUERY_SECTION));
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get query section
 | 
						|
  //
 | 
						|
  QuerySection = (DNS_QUERY_SECTION *) (QueryName + QueryNameLen);
 | 
						|
  QuerySection->Type = NTOHS (QuerySection->Type);
 | 
						|
  QuerySection->Class = NTOHS (QuerySection->Class);
 | 
						|
 | 
						|
  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | 
						|
 | 
						|
  //
 | 
						|
  // Check DnsResponse Validity, if so, also get a valid NET_MAP_ITEM.
 | 
						|
  //
 | 
						|
  if (Instance->Service->IpVersion == IP_VERSION_4) {
 | 
						|
    if (!IsValidDnsResponse (
 | 
						|
           &Instance->Dns4TxTokens,
 | 
						|
           DnsHeader->Identification,
 | 
						|
           QuerySection->Type,
 | 
						|
           QuerySection->Class,
 | 
						|
           &Item
 | 
						|
           )) {
 | 
						|
      *Completed = FALSE;
 | 
						|
      Status = EFI_ABORTED;
 | 
						|
      goto ON_EXIT;
 | 
						|
    }
 | 
						|
    ASSERT (Item != NULL);
 | 
						|
    Dns4TokenEntry = (DNS4_TOKEN_ENTRY *) (Item->Key);
 | 
						|
  } else {
 | 
						|
    if (!IsValidDnsResponse (
 | 
						|
           &Instance->Dns6TxTokens,
 | 
						|
           DnsHeader->Identification,
 | 
						|
           QuerySection->Type,
 | 
						|
           QuerySection->Class,
 | 
						|
           &Item
 | 
						|
           )) {
 | 
						|
      *Completed = FALSE;
 | 
						|
      Status = EFI_ABORTED;
 | 
						|
      goto ON_EXIT;
 | 
						|
    }
 | 
						|
    ASSERT (Item != NULL);
 | 
						|
    Dns6TokenEntry = (DNS6_TOKEN_ENTRY *) (Item->Key);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Continue Check Some Errors.
 | 
						|
  //
 | 
						|
  if (DnsHeader->Flags.Bits.RCode != DNS_FLAGS_RCODE_NO_ERROR || DnsHeader->AnswersNum < 1 || \
 | 
						|
      DnsHeader->Flags.Bits.QR != DNS_FLAGS_QR_RESPONSE) {
 | 
						|
    //
 | 
						|
    // The domain name referenced in the query does not exist.
 | 
						|
    //
 | 
						|
    if (DnsHeader->Flags.Bits.RCode == DNS_FLAGS_RCODE_NAME_ERROR) {
 | 
						|
      Status = EFI_NOT_FOUND;
 | 
						|
    } else {
 | 
						|
      Status = EFI_DEVICE_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
    goto ON_COMPLETE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Do some buffer allocations.
 | 
						|
  //
 | 
						|
  if (Instance->Service->IpVersion == IP_VERSION_4) {
 | 
						|
    ASSERT (Dns4TokenEntry != NULL);
 | 
						|
 | 
						|
    if (Dns4TokenEntry->GeneralLookUp) {
 | 
						|
      //
 | 
						|
      // It's the GeneralLookUp querying.
 | 
						|
      //
 | 
						|
      Dns4TokenEntry->Token->RspData.GLookupData = AllocateZeroPool (sizeof (DNS_RESOURCE_RECORD));
 | 
						|
      if (Dns4TokenEntry->Token->RspData.GLookupData == NULL) {
 | 
						|
        Status = EFI_OUT_OF_RESOURCES;
 | 
						|
        goto ON_EXIT;
 | 
						|
      }
 | 
						|
      Dns4TokenEntry->Token->RspData.GLookupData->RRList = AllocateZeroPool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD));
 | 
						|
      if (Dns4TokenEntry->Token->RspData.GLookupData->RRList == NULL) {
 | 
						|
        Status = EFI_OUT_OF_RESOURCES;
 | 
						|
        goto ON_EXIT;
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // It's not the GeneralLookUp querying. Check the Query type.
 | 
						|
      //
 | 
						|
      if (QuerySection->Type == DNS_TYPE_A) {
 | 
						|
        Dns4TokenEntry->Token->RspData.H2AData = AllocateZeroPool (sizeof (DNS_HOST_TO_ADDR_DATA));
 | 
						|
        if (Dns4TokenEntry->Token->RspData.H2AData == NULL) {
 | 
						|
          Status = EFI_OUT_OF_RESOURCES;
 | 
						|
          goto ON_EXIT;
 | 
						|
        }
 | 
						|
        Dns4TokenEntry->Token->RspData.H2AData->IpList = AllocateZeroPool (DnsHeader->AnswersNum * sizeof (EFI_IPv4_ADDRESS));
 | 
						|
        if (Dns4TokenEntry->Token->RspData.H2AData->IpList == NULL) {
 | 
						|
          Status = EFI_OUT_OF_RESOURCES;
 | 
						|
          goto ON_EXIT;
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        Status = EFI_UNSUPPORTED;
 | 
						|
        goto ON_EXIT;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    ASSERT (Dns6TokenEntry != NULL);
 | 
						|
 | 
						|
    if (Dns6TokenEntry->GeneralLookUp) {
 | 
						|
      //
 | 
						|
      // It's the GeneralLookUp querying.
 | 
						|
      //
 | 
						|
      Dns6TokenEntry->Token->RspData.GLookupData = AllocateZeroPool (sizeof (DNS_RESOURCE_RECORD));
 | 
						|
      if (Dns6TokenEntry->Token->RspData.GLookupData == NULL) {
 | 
						|
        Status = EFI_OUT_OF_RESOURCES;
 | 
						|
        goto ON_EXIT;
 | 
						|
      }
 | 
						|
      Dns6TokenEntry->Token->RspData.GLookupData->RRList = AllocateZeroPool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD));
 | 
						|
      if (Dns6TokenEntry->Token->RspData.GLookupData->RRList == NULL) {
 | 
						|
        Status = EFI_OUT_OF_RESOURCES;
 | 
						|
        goto ON_EXIT;
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // It's not the GeneralLookUp querying. Check the Query type.
 | 
						|
      //
 | 
						|
      if (QuerySection->Type == DNS_TYPE_AAAA) {
 | 
						|
        Dns6TokenEntry->Token->RspData.H2AData = AllocateZeroPool (sizeof (DNS6_HOST_TO_ADDR_DATA));
 | 
						|
        if (Dns6TokenEntry->Token->RspData.H2AData == NULL) {
 | 
						|
          Status = EFI_OUT_OF_RESOURCES;
 | 
						|
          goto ON_EXIT;
 | 
						|
        }
 | 
						|
        Dns6TokenEntry->Token->RspData.H2AData->IpList = AllocateZeroPool (DnsHeader->AnswersNum * sizeof (EFI_IPv6_ADDRESS));
 | 
						|
        if (Dns6TokenEntry->Token->RspData.H2AData->IpList == NULL) {
 | 
						|
          Status = EFI_OUT_OF_RESOURCES;
 | 
						|
          goto ON_EXIT;
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        Status = EFI_UNSUPPORTED;
 | 
						|
        goto ON_EXIT;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Status = EFI_NOT_FOUND;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get Answer name
 | 
						|
  //
 | 
						|
  AnswerName = (CHAR8 *) QuerySection + sizeof (*QuerySection);
 | 
						|
 | 
						|
  //
 | 
						|
  // Processing AnswerSection.
 | 
						|
  //
 | 
						|
  while (AnswerSectionNum < DnsHeader->AnswersNum) {
 | 
						|
    //
 | 
						|
    // Check whether the remaining packet length is available or not.
 | 
						|
    //
 | 
						|
    if (RemainingLength <= sizeof (UINT16) + sizeof (DNS_ANSWER_SECTION)) {
 | 
						|
      *Completed = FALSE;
 | 
						|
      Status = EFI_ABORTED;
 | 
						|
      goto ON_EXIT;
 | 
						|
    } else {
 | 
						|
      RemainingLength -= (sizeof (UINT16) + sizeof (DNS_ANSWER_SECTION));
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Answer name should be PTR, else EFI_UNSUPPORTED returned.
 | 
						|
    //
 | 
						|
    if ((*(UINT8 *) AnswerName & 0xC0) != 0xC0) {
 | 
						|
      Status = EFI_UNSUPPORTED;
 | 
						|
      goto ON_EXIT;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Get Answer section.
 | 
						|
    //
 | 
						|
    AnswerSection = (DNS_ANSWER_SECTION *) (AnswerName + sizeof (UINT16));
 | 
						|
    AnswerSection->Type = NTOHS (AnswerSection->Type);
 | 
						|
    AnswerSection->Class = NTOHS (AnswerSection->Class);
 | 
						|
    AnswerSection->Ttl = NTOHL (AnswerSection->Ttl);
 | 
						|
    AnswerSection->DataLength = NTOHS (AnswerSection->DataLength);
 | 
						|
 | 
						|
    //
 | 
						|
    // Check whether the remaining packet length is available or not.
 | 
						|
    //
 | 
						|
    if (RemainingLength < AnswerSection->DataLength) {
 | 
						|
      *Completed = FALSE;
 | 
						|
      Status = EFI_ABORTED;
 | 
						|
      goto ON_EXIT;
 | 
						|
    } else {
 | 
						|
      RemainingLength -= AnswerSection->DataLength;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Check whether it's the GeneralLookUp querying.
 | 
						|
    //
 | 
						|
    if (Instance->Service->IpVersion == IP_VERSION_4 && Dns4TokenEntry->GeneralLookUp) {
 | 
						|
      Dns4RR = Dns4TokenEntry->Token->RspData.GLookupData->RRList;
 | 
						|
      AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
 | 
						|
 | 
						|
      //
 | 
						|
      // Fill the ResourceRecord.
 | 
						|
      //
 | 
						|
      Dns4RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1);
 | 
						|
      if (Dns4RR[RRCount].QName == NULL) {
 | 
						|
        Status = EFI_OUT_OF_RESOURCES;
 | 
						|
        goto ON_EXIT;
 | 
						|
      }
 | 
						|
      CopyMem (Dns4RR[RRCount].QName, QueryName, AsciiStrLen (QueryName));
 | 
						|
      Dns4RR[RRCount].QType = AnswerSection->Type;
 | 
						|
      Dns4RR[RRCount].QClass = AnswerSection->Class;
 | 
						|
      Dns4RR[RRCount].TTL = AnswerSection->Ttl;
 | 
						|
      Dns4RR[RRCount].DataLength = AnswerSection->DataLength;
 | 
						|
      Dns4RR[RRCount].RData = AllocateZeroPool (Dns4RR[RRCount].DataLength);
 | 
						|
      if (Dns4RR[RRCount].RData == NULL) {
 | 
						|
        Status = EFI_OUT_OF_RESOURCES;
 | 
						|
        goto ON_EXIT;
 | 
						|
      }
 | 
						|
      CopyMem (Dns4RR[RRCount].RData, AnswerData, Dns4RR[RRCount].DataLength);
 | 
						|
 | 
						|
      RRCount ++;
 | 
						|
      Status = EFI_SUCCESS;
 | 
						|
    } else if (Instance->Service->IpVersion == IP_VERSION_6 && Dns6TokenEntry->GeneralLookUp) {
 | 
						|
      Dns6RR = Dns6TokenEntry->Token->RspData.GLookupData->RRList;
 | 
						|
      AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
 | 
						|
 | 
						|
      //
 | 
						|
      // Fill the ResourceRecord.
 | 
						|
      //
 | 
						|
      Dns6RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1);
 | 
						|
      if (Dns6RR[RRCount].QName == NULL) {
 | 
						|
        Status = EFI_OUT_OF_RESOURCES;
 | 
						|
        goto ON_EXIT;
 | 
						|
      }
 | 
						|
      CopyMem (Dns6RR[RRCount].QName, QueryName, AsciiStrLen (QueryName));
 | 
						|
      Dns6RR[RRCount].QType = AnswerSection->Type;
 | 
						|
      Dns6RR[RRCount].QClass = AnswerSection->Class;
 | 
						|
      Dns6RR[RRCount].TTL = AnswerSection->Ttl;
 | 
						|
      Dns6RR[RRCount].DataLength = AnswerSection->DataLength;
 | 
						|
      Dns6RR[RRCount].RData = AllocateZeroPool (Dns6RR[RRCount].DataLength);
 | 
						|
      if (Dns6RR[RRCount].RData == NULL) {
 | 
						|
        Status = EFI_OUT_OF_RESOURCES;
 | 
						|
        goto ON_EXIT;
 | 
						|
      }
 | 
						|
      CopyMem (Dns6RR[RRCount].RData, AnswerData, Dns6RR[RRCount].DataLength);
 | 
						|
 | 
						|
      RRCount ++;
 | 
						|
      Status = EFI_SUCCESS;
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // It's not the GeneralLookUp querying.
 | 
						|
      // Check the Query type, parse the response packet.
 | 
						|
      //
 | 
						|
      switch (AnswerSection->Type) {
 | 
						|
      case DNS_TYPE_A:
 | 
						|
        //
 | 
						|
        // This is address entry, get Data.
 | 
						|
        //
 | 
						|
        ASSERT (Dns4TokenEntry != NULL);
 | 
						|
 | 
						|
        if (AnswerSection->DataLength != 4) {
 | 
						|
          Status = EFI_ABORTED;
 | 
						|
          goto ON_EXIT;
 | 
						|
        }
 | 
						|
 | 
						|
        HostAddr4 = Dns4TokenEntry->Token->RspData.H2AData->IpList;
 | 
						|
        AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
 | 
						|
        CopyMem (&HostAddr4[IpCount], AnswerData, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
 | 
						|
        //
 | 
						|
        // Allocate new CacheEntry pool to update DNS cache dynamically.
 | 
						|
        //
 | 
						|
        Dns4CacheEntry = AllocateZeroPool (sizeof (EFI_DNS4_CACHE_ENTRY));
 | 
						|
        if (Dns4CacheEntry == NULL) {
 | 
						|
          Status = EFI_OUT_OF_RESOURCES;
 | 
						|
          goto ON_EXIT;
 | 
						|
        }
 | 
						|
        Dns4CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1));
 | 
						|
        if (Dns4CacheEntry->HostName == NULL) {
 | 
						|
          Status = EFI_OUT_OF_RESOURCES;
 | 
						|
          goto ON_EXIT;
 | 
						|
        }
 | 
						|
        CopyMem (Dns4CacheEntry->HostName, Dns4TokenEntry->QueryHostName, 2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1));
 | 
						|
        Dns4CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv4_ADDRESS));
 | 
						|
        if (Dns4CacheEntry->IpAddress == NULL) {
 | 
						|
          Status = EFI_OUT_OF_RESOURCES;
 | 
						|
          goto ON_EXIT;
 | 
						|
        }
 | 
						|
        CopyMem (Dns4CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
 | 
						|
        if (CNameTtl != 0 && AnswerSection->Ttl != 0) {
 | 
						|
          Dns4CacheEntry->Timeout = MIN (CNameTtl, AnswerSection->Ttl);
 | 
						|
        } else {
 | 
						|
          Dns4CacheEntry->Timeout = MAX (CNameTtl, AnswerSection->Ttl);
 | 
						|
        }
 | 
						|
 | 
						|
        UpdateDns4Cache (&mDriverData->Dns4CacheList, FALSE, TRUE, *Dns4CacheEntry);
 | 
						|
 | 
						|
        //
 | 
						|
        // Free allocated CacheEntry pool.
 | 
						|
        //
 | 
						|
        FreePool (Dns4CacheEntry->HostName);
 | 
						|
        Dns4CacheEntry->HostName = NULL;
 | 
						|
 | 
						|
        FreePool (Dns4CacheEntry->IpAddress);
 | 
						|
        Dns4CacheEntry->IpAddress = NULL;
 | 
						|
 | 
						|
        FreePool (Dns4CacheEntry);
 | 
						|
        Dns4CacheEntry = NULL;
 | 
						|
 | 
						|
        IpCount ++;
 | 
						|
        Status = EFI_SUCCESS;
 | 
						|
        break;
 | 
						|
      case DNS_TYPE_AAAA:
 | 
						|
        //
 | 
						|
        // This is address entry, get Data.
 | 
						|
        //
 | 
						|
        ASSERT (Dns6TokenEntry != NULL);
 | 
						|
 | 
						|
        if (AnswerSection->DataLength != 16) {
 | 
						|
          Status = EFI_ABORTED;
 | 
						|
          goto ON_EXIT;
 | 
						|
        }
 | 
						|
 | 
						|
        HostAddr6 = Dns6TokenEntry->Token->RspData.H2AData->IpList;
 | 
						|
        AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
 | 
						|
        CopyMem (&HostAddr6[IpCount], AnswerData, sizeof (EFI_IPv6_ADDRESS));
 | 
						|
 | 
						|
        //
 | 
						|
        // Allocate new CacheEntry pool to update DNS cache dynamically.
 | 
						|
        //
 | 
						|
        Dns6CacheEntry = AllocateZeroPool (sizeof (EFI_DNS6_CACHE_ENTRY));
 | 
						|
        if (Dns6CacheEntry == NULL) {
 | 
						|
          Status = EFI_OUT_OF_RESOURCES;
 | 
						|
          goto ON_EXIT;
 | 
						|
        }
 | 
						|
        Dns6CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1));
 | 
						|
        if (Dns6CacheEntry->HostName == NULL) {
 | 
						|
          Status = EFI_OUT_OF_RESOURCES;
 | 
						|
          goto ON_EXIT;
 | 
						|
        }
 | 
						|
        CopyMem (Dns6CacheEntry->HostName, Dns6TokenEntry->QueryHostName, 2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1));
 | 
						|
        Dns6CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS));
 | 
						|
        if (Dns6CacheEntry->IpAddress == NULL) {
 | 
						|
          Status = EFI_OUT_OF_RESOURCES;
 | 
						|
          goto ON_EXIT;
 | 
						|
        }
 | 
						|
        CopyMem (Dns6CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv6_ADDRESS));
 | 
						|
 | 
						|
        if (CNameTtl != 0 && AnswerSection->Ttl != 0) {
 | 
						|
          Dns6CacheEntry->Timeout = MIN (CNameTtl, AnswerSection->Ttl);
 | 
						|
        } else {
 | 
						|
          Dns6CacheEntry->Timeout = MAX (CNameTtl, AnswerSection->Ttl);
 | 
						|
        }
 | 
						|
 | 
						|
        UpdateDns6Cache (&mDriverData->Dns6CacheList, FALSE, TRUE, *Dns6CacheEntry);
 | 
						|
 | 
						|
        //
 | 
						|
        // Free allocated CacheEntry pool.
 | 
						|
        //
 | 
						|
        FreePool (Dns6CacheEntry->HostName);
 | 
						|
        Dns6CacheEntry->HostName = NULL;
 | 
						|
 | 
						|
        FreePool (Dns6CacheEntry->IpAddress);
 | 
						|
        Dns6CacheEntry->IpAddress = NULL;
 | 
						|
 | 
						|
        FreePool (Dns6CacheEntry);
 | 
						|
        Dns6CacheEntry = NULL;
 | 
						|
 | 
						|
        IpCount ++;
 | 
						|
        Status = EFI_SUCCESS;
 | 
						|
        break;
 | 
						|
      case DNS_TYPE_CNAME:
 | 
						|
        //
 | 
						|
        // According RFC 1034 - 3.6.2, if the query name is an alias, the name server will include the CNAME
 | 
						|
        // record in the response and restart the query at the domain name specified in the data field of the
 | 
						|
        // CNAME record. So, just record the TTL value of the CNAME, then skip to parse the next record.
 | 
						|
        //
 | 
						|
        CNameTtl = AnswerSection->Ttl;
 | 
						|
        break;
 | 
						|
      default:
 | 
						|
        Status = EFI_UNSUPPORTED;
 | 
						|
        goto ON_EXIT;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Find next one
 | 
						|
    //
 | 
						|
    AnswerName = (CHAR8 *) AnswerSection + sizeof (*AnswerSection) + AnswerSection->DataLength;
 | 
						|
    AnswerSectionNum ++;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Instance->Service->IpVersion == IP_VERSION_4) {
 | 
						|
    ASSERT (Dns4TokenEntry != NULL);
 | 
						|
 | 
						|
    if (Dns4TokenEntry->GeneralLookUp) {
 | 
						|
      Dns4TokenEntry->Token->RspData.GLookupData->RRCount = RRCount;
 | 
						|
    } else {
 | 
						|
      if (QuerySection->Type == DNS_TYPE_A) {
 | 
						|
        Dns4TokenEntry->Token->RspData.H2AData->IpCount = IpCount;
 | 
						|
      } else {
 | 
						|
        Status = EFI_UNSUPPORTED;
 | 
						|
        goto ON_EXIT;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    ASSERT (Dns6TokenEntry != NULL);
 | 
						|
 | 
						|
    if (Dns6TokenEntry->GeneralLookUp) {
 | 
						|
      Dns6TokenEntry->Token->RspData.GLookupData->RRCount = RRCount;
 | 
						|
    } else {
 | 
						|
      if (QuerySection->Type == DNS_TYPE_AAAA) {
 | 
						|
        Dns6TokenEntry->Token->RspData.H2AData->IpCount = IpCount;
 | 
						|
      } else {
 | 
						|
        Status = EFI_UNSUPPORTED;
 | 
						|
        goto ON_EXIT;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
ON_COMPLETE:
 | 
						|
  //
 | 
						|
  // Parsing is complete, free the sending packet and signal Event here.
 | 
						|
  //
 | 
						|
  if (Item != NULL && Item->Value != NULL) {
 | 
						|
    NetbufFree ((NET_BUF *) (Item->Value));
 | 
						|
  }
 | 
						|
 | 
						|
  if (Instance->Service->IpVersion == IP_VERSION_4) {
 | 
						|
    ASSERT (Dns4TokenEntry != NULL);
 | 
						|
    Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry);
 | 
						|
    Dns4TokenEntry->Token->Status = Status;
 | 
						|
    if (Dns4TokenEntry->Token->Event != NULL) {
 | 
						|
      gBS->SignalEvent (Dns4TokenEntry->Token->Event);
 | 
						|
      DispatchDpc ();
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    ASSERT (Dns6TokenEntry != NULL);
 | 
						|
    Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry);
 | 
						|
    Dns6TokenEntry->Token->Status = Status;
 | 
						|
    if (Dns6TokenEntry->Token->Event != NULL) {
 | 
						|
      gBS->SignalEvent (Dns6TokenEntry->Token->Event);
 | 
						|
      DispatchDpc ();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
ON_EXIT:
 | 
						|
  //
 | 
						|
  // Free the allocated buffer if error happen.
 | 
						|
  //
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    if (Dns4TokenEntry != NULL) {
 | 
						|
      if (Dns4TokenEntry->GeneralLookUp) {
 | 
						|
        if (Dns4TokenEntry->Token->RspData.GLookupData != NULL) {
 | 
						|
          if (Dns4TokenEntry->Token->RspData.GLookupData->RRList != NULL) {
 | 
						|
            while (RRCount != 0) {
 | 
						|
              RRCount --;
 | 
						|
              if (Dns4TokenEntry->Token->RspData.GLookupData->RRList[RRCount].QName != NULL) {
 | 
						|
                FreePool (Dns4TokenEntry->Token->RspData.GLookupData->RRList[RRCount].QName);
 | 
						|
              }
 | 
						|
 | 
						|
              if (Dns4TokenEntry->Token->RspData.GLookupData->RRList[RRCount].RData != NULL) {
 | 
						|
                FreePool (Dns4TokenEntry->Token->RspData.GLookupData->RRList[RRCount].RData);
 | 
						|
              }
 | 
						|
            }
 | 
						|
 | 
						|
            FreePool (Dns4TokenEntry->Token->RspData.GLookupData->RRList);
 | 
						|
          }
 | 
						|
 | 
						|
          FreePool (Dns4TokenEntry->Token->RspData.GLookupData);
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        if (QuerySection->Type == DNS_TYPE_A && Dns4TokenEntry->Token->RspData.H2AData != NULL) {
 | 
						|
          if (Dns4TokenEntry->Token->RspData.H2AData->IpList != NULL) {
 | 
						|
            FreePool (Dns4TokenEntry->Token->RspData.H2AData->IpList);
 | 
						|
          }
 | 
						|
 | 
						|
          FreePool (Dns4TokenEntry->Token->RspData.H2AData);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (Dns6TokenEntry != NULL) {
 | 
						|
      if (Dns6TokenEntry->GeneralLookUp) {
 | 
						|
        if (Dns6TokenEntry->Token->RspData.GLookupData != NULL) {
 | 
						|
          if (Dns6TokenEntry->Token->RspData.GLookupData->RRList != NULL) {
 | 
						|
            while (RRCount != 0) {
 | 
						|
              RRCount --;
 | 
						|
              if (Dns6TokenEntry->Token->RspData.GLookupData->RRList[RRCount].QName != NULL) {
 | 
						|
                FreePool (Dns6TokenEntry->Token->RspData.GLookupData->RRList[RRCount].QName);
 | 
						|
              }
 | 
						|
 | 
						|
              if (Dns6TokenEntry->Token->RspData.GLookupData->RRList[RRCount].RData != NULL) {
 | 
						|
                FreePool (Dns6TokenEntry->Token->RspData.GLookupData->RRList[RRCount].RData);
 | 
						|
              }
 | 
						|
            }
 | 
						|
 | 
						|
            FreePool (Dns6TokenEntry->Token->RspData.GLookupData->RRList);
 | 
						|
          }
 | 
						|
 | 
						|
          FreePool (Dns6TokenEntry->Token->RspData.GLookupData);
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        if (QuerySection->Type == DNS_TYPE_AAAA && Dns6TokenEntry->Token->RspData.H2AData != NULL) {
 | 
						|
          if (Dns6TokenEntry->Token->RspData.H2AData->IpList != NULL) {
 | 
						|
            FreePool (Dns6TokenEntry->Token->RspData.H2AData->IpList);
 | 
						|
          }
 | 
						|
 | 
						|
          FreePool (Dns6TokenEntry->Token->RspData.H2AData);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (Dns4CacheEntry != NULL) {
 | 
						|
      if (Dns4CacheEntry->HostName != NULL) {
 | 
						|
        FreePool (Dns4CacheEntry->HostName);
 | 
						|
      }
 | 
						|
 | 
						|
      if (Dns4CacheEntry->IpAddress != NULL) {
 | 
						|
        FreePool (Dns4CacheEntry->IpAddress);
 | 
						|
      }
 | 
						|
 | 
						|
      FreePool (Dns4CacheEntry);
 | 
						|
    }
 | 
						|
 | 
						|
    if (Dns6CacheEntry != NULL) {
 | 
						|
      if (Dns6CacheEntry->HostName != NULL) {
 | 
						|
        FreePool (Dns6CacheEntry->HostName);
 | 
						|
      }
 | 
						|
 | 
						|
      if (Dns6CacheEntry->IpAddress != NULL) {
 | 
						|
        FreePool (Dns6CacheEntry->IpAddress);
 | 
						|
      }
 | 
						|
 | 
						|
      FreePool (Dns6CacheEntry);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  gBS->RestoreTPL (OldTpl);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Parse response packet.
 | 
						|
 | 
						|
  @param  Packet                The packets received.
 | 
						|
  @param  EndPoint              The local/remote UDP access point
 | 
						|
  @param  IoStatus              The status of the UDP receive
 | 
						|
  @param  Context               The opaque parameter to the function.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
DnsOnPacketReceived (
 | 
						|
  NET_BUF                   *Packet,
 | 
						|
  UDP_END_POINT             *EndPoint,
 | 
						|
  EFI_STATUS                IoStatus,
 | 
						|
  VOID                      *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  DNS_INSTANCE              *Instance;
 | 
						|
 | 
						|
  UINT8                     *RcvString;
 | 
						|
  UINT32                    Len;
 | 
						|
 | 
						|
  BOOLEAN                   Completed;
 | 
						|
 | 
						|
  Instance  = (DNS_INSTANCE *) Context;
 | 
						|
  NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE);
 | 
						|
 | 
						|
  RcvString = NULL;
 | 
						|
  Completed = FALSE;
 | 
						|
 | 
						|
  if (EFI_ERROR (IoStatus)) {
 | 
						|
    goto ON_EXIT;
 | 
						|
  }
 | 
						|
 | 
						|
  ASSERT (Packet != NULL);
 | 
						|
 | 
						|
  Len = Packet->TotalSize;
 | 
						|
 | 
						|
  RcvString = NetbufGetByte (Packet, 0, NULL);
 | 
						|
  ASSERT (RcvString != NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Parse Dns Response
 | 
						|
  //
 | 
						|
  ParseDnsResponse (Instance, RcvString, Len, &Completed);
 | 
						|
 | 
						|
ON_EXIT:
 | 
						|
 | 
						|
  if (Packet != NULL) {
 | 
						|
    NetbufFree (Packet);
 | 
						|
  }
 | 
						|
 | 
						|
  if (!Completed) {
 | 
						|
    UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Release the net buffer when packet is sent.
 | 
						|
 | 
						|
  @param  Packet                The packets received.
 | 
						|
  @param  EndPoint              The local/remote UDP access point
 | 
						|
  @param  IoStatus              The status of the UDP receive
 | 
						|
  @param  Context               The opaque parameter to the function.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
DnsOnPacketSent (
 | 
						|
  NET_BUF                   *Packet,
 | 
						|
  UDP_END_POINT             *EndPoint,
 | 
						|
  EFI_STATUS                IoStatus,
 | 
						|
  VOID                      *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  DNS_INSTANCE              *Instance;
 | 
						|
  LIST_ENTRY                *Entry;
 | 
						|
  NET_MAP_ITEM              *Item;
 | 
						|
  DNS4_TOKEN_ENTRY          *Dns4TokenEntry;
 | 
						|
  DNS6_TOKEN_ENTRY          *Dns6TokenEntry;
 | 
						|
 | 
						|
  Dns4TokenEntry = NULL;
 | 
						|
  Dns6TokenEntry = NULL;
 | 
						|
 | 
						|
  Instance  = (DNS_INSTANCE *) Context;
 | 
						|
  NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE);
 | 
						|
 | 
						|
  if (Instance->Service->IpVersion == IP_VERSION_4) {
 | 
						|
    NET_LIST_FOR_EACH (Entry, &Instance->Dns4TxTokens.Used) {
 | 
						|
      Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
 | 
						|
      if (Packet == (NET_BUF *)(Item->Value)) {
 | 
						|
        Dns4TokenEntry = ((DNS4_TOKEN_ENTRY *)Item->Key);
 | 
						|
        Dns4TokenEntry->PacketToLive = Dns4TokenEntry->Token->RetryInterval;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    NET_LIST_FOR_EACH (Entry, &Instance->Dns6TxTokens.Used) {
 | 
						|
      Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
 | 
						|
      if (Packet == (NET_BUF *)(Item->Value)) {
 | 
						|
        Dns6TokenEntry = ((DNS6_TOKEN_ENTRY *)Item->Key);
 | 
						|
        Dns6TokenEntry->PacketToLive = Dns6TokenEntry->Token->RetryInterval;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  NetbufFree (Packet);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Query request information.
 | 
						|
 | 
						|
  @param  Instance              The DNS instance
 | 
						|
  @param  Packet                The packet for querying request information.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           Query request information successfully.
 | 
						|
  @retval Others                Failed to query request information.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
DoDnsQuery (
 | 
						|
  IN  DNS_INSTANCE              *Instance,
 | 
						|
  IN  NET_BUF                   *Packet
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS      Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // Ready to receive the DNS response.
 | 
						|
  //
 | 
						|
  if (Instance->UdpIo->RecvRequest == NULL) {
 | 
						|
    Status = UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Transmit the DNS packet.
 | 
						|
  //
 | 
						|
  NET_GET_REF (Packet);
 | 
						|
 | 
						|
  Status = UdpIoSendDatagram (Instance->UdpIo, Packet, NULL, NULL, DnsOnPacketSent, Instance);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Construct the Packet according query section.
 | 
						|
 | 
						|
  @param  Instance              The DNS instance
 | 
						|
  @param  QueryName             Queried Name
 | 
						|
  @param  Type                  Queried Type
 | 
						|
  @param  Class                 Queried Class
 | 
						|
  @param  Packet                The packet for query
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The packet is constructed.
 | 
						|
  @retval Others                Failed to construct the Packet.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ConstructDNSQuery (
 | 
						|
  IN  DNS_INSTANCE              *Instance,
 | 
						|
  IN  CHAR8                     *QueryName,
 | 
						|
  IN  UINT16                    Type,
 | 
						|
  IN  UINT16                    Class,
 | 
						|
  OUT NET_BUF                   **Packet
 | 
						|
  )
 | 
						|
{
 | 
						|
  NET_FRAGMENT        Frag;
 | 
						|
  DNS_HEADER          *DnsHeader;
 | 
						|
  DNS_QUERY_SECTION   *DnsQuery;
 | 
						|
 | 
						|
  //
 | 
						|
  // Messages carried by UDP are restricted to 512 bytes (not counting the IP
 | 
						|
  // or UDP headers).
 | 
						|
  //
 | 
						|
  Frag.Bulk = AllocatePool (DNS_MAX_MESSAGE_SIZE * sizeof (UINT8));
 | 
						|
  if (Frag.Bulk == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Fill header
 | 
						|
  //
 | 
						|
  DnsHeader = (DNS_HEADER *) Frag.Bulk;
 | 
						|
  DnsHeader->Identification = (UINT16)NET_RANDOM (NetRandomInitSeed());
 | 
						|
  DnsHeader->Flags.Uint16 = 0x0000;
 | 
						|
  DnsHeader->Flags.Bits.RD = 1;
 | 
						|
  DnsHeader->Flags.Bits.OpCode = DNS_FLAGS_OPCODE_STANDARD;
 | 
						|
  DnsHeader->Flags.Bits.QR = DNS_FLAGS_QR_QUERY;
 | 
						|
  DnsHeader->QuestionsNum = 1;
 | 
						|
  DnsHeader->AnswersNum = 0;
 | 
						|
  DnsHeader->AuthorityNum = 0;
 | 
						|
  DnsHeader->AditionalNum = 0;
 | 
						|
 | 
						|
  DnsHeader->Identification = HTONS (DnsHeader->Identification);
 | 
						|
  DnsHeader->Flags.Uint16 = HTONS (DnsHeader->Flags.Uint16);
 | 
						|
  DnsHeader->QuestionsNum = HTONS (DnsHeader->QuestionsNum);
 | 
						|
  DnsHeader->AnswersNum = HTONS (DnsHeader->AnswersNum);
 | 
						|
  DnsHeader->AuthorityNum = HTONS (DnsHeader->AuthorityNum);
 | 
						|
  DnsHeader->AditionalNum = HTONS (DnsHeader->AditionalNum);
 | 
						|
 | 
						|
  Frag.Len = sizeof (*DnsHeader);
 | 
						|
 | 
						|
  //
 | 
						|
  // Fill Query name
 | 
						|
  //
 | 
						|
  CopyMem (Frag.Bulk + Frag.Len, QueryName, AsciiStrLen (QueryName));
 | 
						|
  Frag.Len = (UINT32) (Frag.Len + AsciiStrLen (QueryName));
 | 
						|
  *(Frag.Bulk + Frag.Len) = 0;
 | 
						|
  Frag.Len ++;
 | 
						|
 | 
						|
  //
 | 
						|
  // Rest query section
 | 
						|
  //
 | 
						|
  DnsQuery = (DNS_QUERY_SECTION *) (Frag.Bulk + Frag.Len);
 | 
						|
 | 
						|
  DnsQuery->Type = HTONS (Type);
 | 
						|
  DnsQuery->Class = HTONS (Class);
 | 
						|
 | 
						|
  Frag.Len += sizeof (*DnsQuery);
 | 
						|
 | 
						|
  //
 | 
						|
  // Wrap the Frag in a net buffer.
 | 
						|
  //
 | 
						|
  *Packet = NetbufFromExt (&Frag, 1, 0, 0, DnsDummyExtFree, NULL);
 | 
						|
  if (*Packet == NULL) {
 | 
						|
    FreePool (Frag.Bulk);
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Store the UdpIo in ProtoData.
 | 
						|
  //
 | 
						|
  *((UINTN *) &((*Packet)->ProtoData[0])) = (UINTN) (Instance->UdpIo);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Retransmit the packet.
 | 
						|
 | 
						|
  @param  Instance              The DNS instance
 | 
						|
  @param  Packet                Retransmit the packet
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The packet is retransmitted.
 | 
						|
  @retval Others                Failed to retransmit.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
DnsRetransmit (
 | 
						|
  IN DNS_INSTANCE        *Instance,
 | 
						|
  IN NET_BUF             *Packet
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS      Status;
 | 
						|
 | 
						|
  UINT8           *Buffer;
 | 
						|
 | 
						|
  ASSERT (Packet != NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Set the requests to the listening port, other packets to the connected port
 | 
						|
  //
 | 
						|
  Buffer = NetbufGetByte (Packet, 0, NULL);
 | 
						|
  ASSERT (Buffer != NULL);
 | 
						|
 | 
						|
  NET_GET_REF (Packet);
 | 
						|
 | 
						|
  Status = UdpIoSendDatagram (
 | 
						|
             Instance->UdpIo,
 | 
						|
             Packet,
 | 
						|
             NULL,
 | 
						|
             NULL,
 | 
						|
             DnsOnPacketSent,
 | 
						|
             Instance
 | 
						|
             );
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    NET_PUT_REF (Packet);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  The timer ticking function for the DNS services.
 | 
						|
 | 
						|
  @param  Event                 The ticking event
 | 
						|
  @param  Context               The DNS service instance
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
DnsOnTimerRetransmit (
 | 
						|
  IN EFI_EVENT              Event,
 | 
						|
  IN VOID                   *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  DNS_SERVICE                *Service;
 | 
						|
 | 
						|
  LIST_ENTRY                 *Entry;
 | 
						|
  LIST_ENTRY                 *Next;
 | 
						|
 | 
						|
  DNS_INSTANCE               *Instance;
 | 
						|
  LIST_ENTRY                 *EntryNetMap;
 | 
						|
  NET_MAP_ITEM               *ItemNetMap;
 | 
						|
  DNS4_TOKEN_ENTRY           *Dns4TokenEntry;
 | 
						|
  DNS6_TOKEN_ENTRY           *Dns6TokenEntry;
 | 
						|
 | 
						|
  Dns4TokenEntry = NULL;
 | 
						|
  Dns6TokenEntry = NULL;
 | 
						|
 | 
						|
  Service = (DNS_SERVICE *) Context;
 | 
						|
 | 
						|
 | 
						|
  if (Service->IpVersion == IP_VERSION_4) {
 | 
						|
    //
 | 
						|
    // Iterate through all the children of the DNS service instance. Time
 | 
						|
    // out the packet. If maximum retries reached, clean the Token up.
 | 
						|
    //
 | 
						|
    NET_LIST_FOR_EACH_SAFE (Entry, Next, &Service->Dns4ChildrenList) {
 | 
						|
      Instance = NET_LIST_USER_STRUCT (Entry, DNS_INSTANCE, Link);
 | 
						|
 | 
						|
      EntryNetMap = Instance->Dns4TxTokens.Used.ForwardLink;
 | 
						|
      while (EntryNetMap != &Instance->Dns4TxTokens.Used) {
 | 
						|
        ItemNetMap = NET_LIST_USER_STRUCT (EntryNetMap, NET_MAP_ITEM, Link);
 | 
						|
        Dns4TokenEntry = (DNS4_TOKEN_ENTRY *)(ItemNetMap->Key);
 | 
						|
        if (Dns4TokenEntry->PacketToLive == 0 || (--Dns4TokenEntry->PacketToLive > 0)) {
 | 
						|
          EntryNetMap = EntryNetMap->ForwardLink;
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
 | 
						|
        //
 | 
						|
        // Retransmit the packet if haven't reach the maximum retry count,
 | 
						|
        // otherwise exit the transfer.
 | 
						|
        //
 | 
						|
        if (++Dns4TokenEntry->RetryCounting <= Dns4TokenEntry->Token->RetryCount) {
 | 
						|
          DnsRetransmit (Instance, (NET_BUF *)ItemNetMap->Value);
 | 
						|
          EntryNetMap = EntryNetMap->ForwardLink;
 | 
						|
        } else {
 | 
						|
          //
 | 
						|
          // Maximum retries reached, clean the Token up.
 | 
						|
          //
 | 
						|
          Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry);
 | 
						|
          Dns4TokenEntry->Token->Status = EFI_TIMEOUT;
 | 
						|
          gBS->SignalEvent (Dns4TokenEntry->Token->Event);
 | 
						|
          DispatchDpc ();
 | 
						|
 | 
						|
          //
 | 
						|
          // Free the sending packet.
 | 
						|
          //
 | 
						|
          if (ItemNetMap->Value != NULL) {
 | 
						|
            NetbufFree ((NET_BUF *)(ItemNetMap->Value));
 | 
						|
          }
 | 
						|
 | 
						|
          EntryNetMap = Instance->Dns4TxTokens.Used.ForwardLink;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Iterate through all the children of the DNS service instance. Time
 | 
						|
    // out the packet. If maximum retries reached, clean the Token up.
 | 
						|
    //
 | 
						|
    NET_LIST_FOR_EACH_SAFE (Entry, Next, &Service->Dns6ChildrenList) {
 | 
						|
      Instance = NET_LIST_USER_STRUCT (Entry, DNS_INSTANCE, Link);
 | 
						|
 | 
						|
      EntryNetMap = Instance->Dns6TxTokens.Used.ForwardLink;
 | 
						|
      while (EntryNetMap != &Instance->Dns6TxTokens.Used) {
 | 
						|
        ItemNetMap = NET_LIST_USER_STRUCT (EntryNetMap, NET_MAP_ITEM, Link);
 | 
						|
        Dns6TokenEntry = (DNS6_TOKEN_ENTRY *) (ItemNetMap->Key);
 | 
						|
        if (Dns6TokenEntry->PacketToLive == 0 || (--Dns6TokenEntry->PacketToLive > 0)) {
 | 
						|
          EntryNetMap = EntryNetMap->ForwardLink;
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
 | 
						|
        //
 | 
						|
        // Retransmit the packet if haven't reach the maximum retry count,
 | 
						|
        // otherwise exit the transfer.
 | 
						|
        //
 | 
						|
        if (++Dns6TokenEntry->RetryCounting <= Dns6TokenEntry->Token->RetryCount) {
 | 
						|
          DnsRetransmit (Instance, (NET_BUF *) ItemNetMap->Value);
 | 
						|
          EntryNetMap = EntryNetMap->ForwardLink;
 | 
						|
        } else {
 | 
						|
          //
 | 
						|
          // Maximum retries reached, clean the Token up.
 | 
						|
          //
 | 
						|
          Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry);
 | 
						|
          Dns6TokenEntry->Token->Status = EFI_TIMEOUT;
 | 
						|
          gBS->SignalEvent (Dns6TokenEntry->Token->Event);
 | 
						|
          DispatchDpc ();
 | 
						|
 | 
						|
          //
 | 
						|
          // Free the sending packet.
 | 
						|
          //
 | 
						|
          if (ItemNetMap->Value != NULL) {
 | 
						|
            NetbufFree ((NET_BUF *) (ItemNetMap->Value));
 | 
						|
          }
 | 
						|
 | 
						|
          EntryNetMap = Instance->Dns6TxTokens.Used.ForwardLink;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  The timer ticking function for the DNS driver.
 | 
						|
 | 
						|
  @param  Event                 The ticking event
 | 
						|
  @param  Context               NULL
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
DnsOnTimerUpdate (
 | 
						|
  IN EFI_EVENT              Event,
 | 
						|
  IN VOID                   *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY                 *Entry;
 | 
						|
  LIST_ENTRY                 *Next;
 | 
						|
  DNS4_CACHE                 *Item4;
 | 
						|
  DNS6_CACHE                 *Item6;
 | 
						|
 | 
						|
  Item4 = NULL;
 | 
						|
  Item6 = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Iterate through all the DNS4 cache list.
 | 
						|
  //
 | 
						|
  NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) {
 | 
						|
    Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
 | 
						|
    Item4->DnsCache.Timeout--;
 | 
						|
  }
 | 
						|
 | 
						|
  Entry = mDriverData->Dns4CacheList.ForwardLink;
 | 
						|
  while (Entry != &mDriverData->Dns4CacheList) {
 | 
						|
    Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
 | 
						|
    if (Item4->DnsCache.Timeout == 0) {
 | 
						|
      RemoveEntryList (&Item4->AllCacheLink);
 | 
						|
      FreePool (Item4->DnsCache.HostName);
 | 
						|
      FreePool (Item4->DnsCache.IpAddress);
 | 
						|
      FreePool (Item4);
 | 
						|
      Entry = mDriverData->Dns4CacheList.ForwardLink;
 | 
						|
    } else {
 | 
						|
      Entry = Entry->ForwardLink;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Iterate through all the DNS6 cache list.
 | 
						|
  //
 | 
						|
  NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6CacheList) {
 | 
						|
    Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
 | 
						|
    Item6->DnsCache.Timeout--;
 | 
						|
  }
 | 
						|
 | 
						|
  Entry = mDriverData->Dns6CacheList.ForwardLink;
 | 
						|
  while (Entry != &mDriverData->Dns6CacheList) {
 | 
						|
    Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
 | 
						|
    if (Item6->DnsCache.Timeout == 0) {
 | 
						|
      RemoveEntryList (&Item6->AllCacheLink);
 | 
						|
      FreePool (Item6->DnsCache.HostName);
 | 
						|
      FreePool (Item6->DnsCache.IpAddress);
 | 
						|
      FreePool (Item6);
 | 
						|
      Entry = mDriverData->Dns6CacheList.ForwardLink;
 | 
						|
    } else {
 | 
						|
      Entry = Entry->ForwardLink;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 |