REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the NetworkPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Maciej Rabeda <maciej.rabeda@linux.intel.com>
		
			
				
	
	
		
			2267 lines
		
	
	
		
			64 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2267 lines
		
	
	
		
			64 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);
 | 
						|
          Dns4TokenEntry->Token->RspData.H2AData = NULL;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    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);
 | 
						|
          Dns6TokenEntry->Token->RspData.H2AData = NULL;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    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;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 |