]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/DnsDxe/DnsImpl.c
BaseTools: StructurePcd array Value support flexible format
[mirror_edk2.git] / NetworkPkg / DnsDxe / DnsImpl.c
index 8725670a8e8a4a51c098dcd7b1e61f067039c021..7057bfbbec9c5a91655c586ab42a09d2ff4d611b 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 DnsDxe support functions implementation.\r
   \r
-Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -565,7 +565,7 @@ Dns4GetMapping (
     return FALSE;\r
   }\r
 \r
-  while (!EFI_ERROR (gBS->CheckEvent (Service->TimerToGetMap))) {\r
+  while (EFI_ERROR (gBS->CheckEvent (Service->TimerToGetMap))) {\r
     Udp->Poll (Udp);\r
 \r
     if (!EFI_ERROR (Udp->GetModeData (Udp, NULL, &Ip4Mode, NULL, NULL)) &&\r
@@ -615,14 +615,40 @@ Dns6GetMapping (
     return FALSE;\r
   }\r
 \r
-  while (!EFI_ERROR (gBS->CheckEvent (Service->TimerToGetMap))) {\r
+  while (EFI_ERROR (gBS->CheckEvent (Service->TimerToGetMap))) {\r
     Udp->Poll (Udp);\r
 \r
-    if (!EFI_ERROR (Udp->GetModeData (Udp, NULL, &Ip6Mode, NULL, NULL)) &&\r
-        Ip6Mode.IsConfigured) {\r
+    if (!EFI_ERROR (Udp->GetModeData (Udp, NULL, &Ip6Mode, NULL, NULL))) {\r
+      if (Ip6Mode.AddressList != NULL) {\r
+        FreePool (Ip6Mode.AddressList);\r
+      }\r
 \r
-      Udp->Configure (Udp, NULL);\r
-      return (BOOLEAN) (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS);\r
+      if (Ip6Mode.GroupTable != NULL) {\r
+        FreePool (Ip6Mode.GroupTable);\r
+      }\r
+\r
+      if (Ip6Mode.RouteTable != NULL) {\r
+        FreePool (Ip6Mode.RouteTable);\r
+      }\r
+\r
+      if (Ip6Mode.NeighborCache != NULL) {\r
+        FreePool (Ip6Mode.NeighborCache);\r
+      }\r
+\r
+      if (Ip6Mode.PrefixTable != NULL) {\r
+        FreePool (Ip6Mode.PrefixTable);\r
+      }\r
+\r
+      if (Ip6Mode.IcmpTypeList != NULL) {\r
+        FreePool (Ip6Mode.IcmpTypeList);\r
+      }\r
+\r
+      if (!Ip6Mode.IsStarted || Ip6Mode.IsConfigured) {\r
+        Udp->Configure (Udp, NULL);\r
+        if (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS) {\r
+          return TRUE;\r
+        }\r
+      }\r
     }\r
   }\r
 \r
@@ -766,6 +792,10 @@ UpdateDns4Cache (
         // Delete matching DNS Cache entry\r
         //\r
         RemoveEntryList (&Item->AllCacheLink);\r
+\r
+        FreePool (Item->DnsCache.HostName);\r
+        FreePool (Item->DnsCache.IpAddress);\r
+        FreePool (Item);\r
         \r
         return EFI_SUCCESS;\r
       } else if (Override) {\r
@@ -793,13 +823,16 @@ UpdateDns4Cache (
    \r
   NewDnsCache->DnsCache.HostName = AllocatePool (StrSize (DnsCacheEntry.HostName));\r
   if (NewDnsCache->DnsCache.HostName == NULL) { \r
+    FreePool (NewDnsCache);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
   \r
   CopyMem (NewDnsCache->DnsCache.HostName, DnsCacheEntry.HostName, StrSize (DnsCacheEntry.HostName));\r
 \r
   NewDnsCache->DnsCache.IpAddress = AllocatePool (sizeof (EFI_IPv4_ADDRESS));\r
-  if (NewDnsCache->DnsCache.IpAddress == NULL) { \r
+  if (NewDnsCache->DnsCache.IpAddress == NULL) {\r
+    FreePool (NewDnsCache->DnsCache.HostName);\r
+    FreePool (NewDnsCache);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
@@ -858,6 +891,10 @@ UpdateDns6Cache (
         //\r
         RemoveEntryList (&Item->AllCacheLink);\r
         \r
+        FreePool (Item->DnsCache.HostName);\r
+        FreePool (Item->DnsCache.IpAddress);\r
+        FreePool (Item);\r
+        \r
         return EFI_SUCCESS;\r
       } else if (Override) {\r
         //\r
@@ -884,13 +921,16 @@ UpdateDns6Cache (
    \r
   NewDnsCache->DnsCache.HostName = AllocatePool (StrSize (DnsCacheEntry.HostName));\r
   if (NewDnsCache->DnsCache.HostName == NULL) { \r
+    FreePool (NewDnsCache);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
   \r
   CopyMem (NewDnsCache->DnsCache.HostName, DnsCacheEntry.HostName, StrSize (DnsCacheEntry.HostName));\r
 \r
   NewDnsCache->DnsCache.IpAddress = AllocatePool (sizeof (EFI_IPv6_ADDRESS));\r
-  if (NewDnsCache->DnsCache.IpAddress == NULL) { \r
+  if (NewDnsCache->DnsCache.IpAddress == NULL) {\r
+    FreePool (NewDnsCache->DnsCache.HostName);\r
+    FreePool (NewDnsCache);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
   \r
@@ -1013,67 +1053,13 @@ AddDns6ServerIp (
   return EFI_SUCCESS;\r
 }\r
 \r
-/**\r
-  Fill QName for IP querying. QName is a domain name represented as \r
-  a sequence of labels, where each label consists of a length octet \r
-  followed by that number of octets. The domain name terminates with \r
-  the zero length octet for the null label of the root. Caller should \r
-  take responsibility to the buffer in QName.\r
-\r
-  @param  HostName          Queried HostName    \r
-\r
-  @retval NULL      Failed to fill QName.\r
-  @return           QName filled successfully.\r
-  \r
-**/ \r
-UINT8 *\r
-EFIAPI\r
-DnsFillinQNameForQueryIp (\r
-  IN  CHAR16              *HostName\r
-  )\r
-{\r
-  CHAR8                 *QueryName;\r
-  CHAR8                 *Header;\r
-  CHAR8                 *Tail;\r
-  UINTN                 Len;\r
-  UINTN                 Index;\r
-\r
-  QueryName  = NULL;\r
-  Header     = NULL;\r
-  Tail       = NULL;\r
-\r
-  QueryName = AllocateZeroPool (DNS_DEFAULT_BLKSIZE);\r
-  if (QueryName == NULL) {\r
-    return NULL;\r
-  }\r
-  \r
-  Header = QueryName;\r
-  Tail = Header + 1;\r
-  Len = 0;\r
-  for (Index = 0; HostName[Index] != 0; Index++) {\r
-    *Tail = (CHAR8) HostName[Index];\r
-    if (*Tail == '.') {\r
-      *Header = (CHAR8) Len;\r
-      Header = Tail;\r
-      Tail ++;\r
-      Len = 0;\r
-    } else {\r
-      Tail++;\r
-      Len++;\r
-    }\r
-  }\r
-  *Header = (CHAR8) Len;\r
-  *Tail = 0;\r
-\r
-  return QueryName;\r
-}\r
-\r
 /**\r
   Find out whether the response is valid or invalid.\r
 \r
   @param  TokensMap       All DNS transmittal Tokens entry.  \r
   @param  Identification  Identification for queried packet.  \r
   @param  Type            Type for queried packet.\r
+  @param  Class           Class for queried packet.\r
   @param  Item            Return corresponding Token entry.\r
 \r
   @retval TRUE            The response is valid.\r
@@ -1085,6 +1071,7 @@ IsValidDnsResponse (
   IN     NET_MAP      *TokensMap,\r
   IN     UINT16       Identification,\r
   IN     UINT16       Type,\r
+  IN     UINT16       Class,\r
      OUT NET_MAP_ITEM **Item\r
   )\r
 {\r
@@ -1108,17 +1095,16 @@ IsValidDnsResponse (
       DnsHeader = (DNS_HEADER *) TxString;\r
       QueryName = (CHAR8 *) (TxString + sizeof (*DnsHeader));\r
       QuerySection = (DNS_QUERY_SECTION *) (QueryName + AsciiStrLen (QueryName) + 1);\r
-\r
-      DnsHeader->Identification = NTOHS (DnsHeader->Identification);\r
-      QuerySection->Type = NTOHS (QuerySection->Type);\r
         \r
-      if (DnsHeader->Identification == Identification && QuerySection->Type == Type) {\r
+      if (NTOHS (DnsHeader->Identification) == Identification &&\r
+          NTOHS (QuerySection->Type) == Type && \r
+          NTOHS (QuerySection->Class) == Class) {\r
         return TRUE;\r
       }\r
     } \r
   }\r
   \r
-  *Item =NULL;\r
+  *Item = NULL;\r
   \r
   return FALSE;\r
 }\r
@@ -1157,6 +1143,7 @@ ParseDnsResponse (
   UINT32                IpCount;\r
   UINT32                RRCount;\r
   UINT32                AnswerSectionNum;\r
+  UINT32                CNameTtl;\r
   \r
   EFI_IPv4_ADDRESS      *HostAddr4;\r
   EFI_IPv6_ADDRESS      *HostAddr6;\r
@@ -1178,6 +1165,7 @@ ParseDnsResponse (
   IpCount          = 0;\r
   RRCount          = 0;\r
   AnswerSectionNum = 0;\r
+  CNameTtl         = 0;\r
   \r
   HostAddr4        = NULL;\r
   HostAddr6        = NULL;\r
@@ -1226,7 +1214,13 @@ ParseDnsResponse (
   // Check DnsResponse Validity, if so, also get a valid NET_MAP_ITEM.\r
   //\r
   if (Instance->Service->IpVersion == IP_VERSION_4) {\r
-    if (!IsValidDnsResponse (&Instance->Dns4TxTokens, DnsHeader->Identification, QuerySection->Type, &Item)) {\r
+    if (!IsValidDnsResponse (\r
+           &Instance->Dns4TxTokens, \r
+           DnsHeader->Identification, \r
+           QuerySection->Type,\r
+           QuerySection->Class,\r
+           &Item\r
+           )) {\r
       *Completed = FALSE;\r
       Status = EFI_ABORTED;\r
       goto ON_EXIT;\r
@@ -1234,7 +1228,13 @@ ParseDnsResponse (
     ASSERT (Item != NULL);\r
     Dns4TokenEntry = (DNS4_TOKEN_ENTRY *) (Item->Key);\r
   } else {\r
-    if (!IsValidDnsResponse (&Instance->Dns6TxTokens, DnsHeader->Identification, QuerySection->Type, &Item)) {\r
+    if (!IsValidDnsResponse (\r
+           &Instance->Dns6TxTokens, \r
+           DnsHeader->Identification, \r
+           QuerySection->Type,\r
+           QuerySection->Class,\r
+           &Item\r
+           )) {\r
       *Completed = FALSE;\r
       Status = EFI_ABORTED;\r
       goto ON_EXIT;\r
@@ -1247,16 +1247,17 @@ ParseDnsResponse (
   // Continue Check Some Errors.\r
   //\r
   if (DnsHeader->Flags.Bits.RCode != DNS_FLAGS_RCODE_NO_ERROR || DnsHeader->AnswersNum < 1 || \\r
-      DnsHeader->Flags.Bits.QR != DNS_FLAGS_QR_RESPONSE || QuerySection->Class != DNS_CLASS_INET) {\r
-      Status = EFI_ABORTED;\r
-      goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Free the sending packet.\r
-  //\r
-  if (Item->Value != NULL) {\r
-    NetbufFree ((NET_BUF *) (Item->Value));\r
+      DnsHeader->Flags.Bits.QR != DNS_FLAGS_QR_RESPONSE) {\r
+    //\r
+    // The domain name referenced in the query does not exist.\r
+    //\r
+    if (DnsHeader->Flags.Bits.RCode == DNS_FLAGS_RCODE_NAME_ERROR) {\r
+      Status = EFI_NOT_FOUND; \r
+    } else {\r
+      Status = EFI_DEVICE_ERROR;\r
+    }\r
+    \r
+    goto ON_COMPLETE;\r
   }\r
   \r
   //\r
@@ -1269,12 +1270,12 @@ ParseDnsResponse (
       //\r
       // It's the GeneralLookUp querying.\r
       //\r
-      Dns4TokenEntry->Token->RspData.GLookupData = AllocatePool (sizeof (DNS_RESOURCE_RECORD));\r
+      Dns4TokenEntry->Token->RspData.GLookupData = AllocateZeroPool (sizeof (DNS_RESOURCE_RECORD));\r
       if (Dns4TokenEntry->Token->RspData.GLookupData == NULL) {\r
         Status = EFI_OUT_OF_RESOURCES;\r
         goto ON_EXIT;\r
       }\r
-      Dns4TokenEntry->Token->RspData.GLookupData->RRList = AllocatePool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD));\r
+      Dns4TokenEntry->Token->RspData.GLookupData->RRList = AllocateZeroPool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD));\r
       if (Dns4TokenEntry->Token->RspData.GLookupData->RRList == NULL) {\r
         Status = EFI_OUT_OF_RESOURCES;\r
         goto ON_EXIT;\r
@@ -1284,12 +1285,12 @@ ParseDnsResponse (
       // It's not the GeneralLookUp querying. Check the Query type.\r
       //\r
       if (QuerySection->Type == DNS_TYPE_A) {\r
-        Dns4TokenEntry->Token->RspData.H2AData = AllocatePool (sizeof (DNS_HOST_TO_ADDR_DATA));\r
+        Dns4TokenEntry->Token->RspData.H2AData = AllocateZeroPool (sizeof (DNS_HOST_TO_ADDR_DATA));\r
         if (Dns4TokenEntry->Token->RspData.H2AData == NULL) {\r
           Status = EFI_OUT_OF_RESOURCES;\r
           goto ON_EXIT;\r
         }\r
-        Dns4TokenEntry->Token->RspData.H2AData->IpList = AllocatePool (DnsHeader->AnswersNum * sizeof (EFI_IPv4_ADDRESS));\r
+        Dns4TokenEntry->Token->RspData.H2AData->IpList = AllocateZeroPool (DnsHeader->AnswersNum * sizeof (EFI_IPv4_ADDRESS));\r
         if (Dns4TokenEntry->Token->RspData.H2AData->IpList == NULL) {\r
           Status = EFI_OUT_OF_RESOURCES;\r
           goto ON_EXIT;\r
@@ -1306,14 +1307,14 @@ ParseDnsResponse (
       //\r
       // It's the GeneralLookUp querying.\r
       //\r
-      Dns6TokenEntry->Token->RspData.GLookupData = AllocatePool (sizeof (DNS_RESOURCE_RECORD));\r
+      Dns6TokenEntry->Token->RspData.GLookupData = AllocateZeroPool (sizeof (DNS_RESOURCE_RECORD));\r
       if (Dns6TokenEntry->Token->RspData.GLookupData == NULL) {\r
-        Status = EFI_UNSUPPORTED;\r
+        Status = EFI_OUT_OF_RESOURCES;\r
         goto ON_EXIT;\r
       }\r
-      Dns6TokenEntry->Token->RspData.GLookupData->RRList = AllocatePool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD));\r
+      Dns6TokenEntry->Token->RspData.GLookupData->RRList = AllocateZeroPool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD));\r
       if (Dns6TokenEntry->Token->RspData.GLookupData->RRList == NULL) {\r
-        Status = EFI_UNSUPPORTED;\r
+        Status = EFI_OUT_OF_RESOURCES;\r
         goto ON_EXIT;\r
       }\r
     } else {\r
@@ -1321,14 +1322,14 @@ ParseDnsResponse (
       // It's not the GeneralLookUp querying. Check the Query type.\r
       //\r
       if (QuerySection->Type == DNS_TYPE_AAAA) {\r
-        Dns6TokenEntry->Token->RspData.H2AData = AllocatePool (sizeof (DNS6_HOST_TO_ADDR_DATA));\r
+        Dns6TokenEntry->Token->RspData.H2AData = AllocateZeroPool (sizeof (DNS6_HOST_TO_ADDR_DATA));\r
         if (Dns6TokenEntry->Token->RspData.H2AData == NULL) {\r
-          Status = EFI_UNSUPPORTED;\r
+          Status = EFI_OUT_OF_RESOURCES;\r
           goto ON_EXIT;\r
         }\r
-        Dns6TokenEntry->Token->RspData.H2AData->IpList = AllocatePool (DnsHeader->AnswersNum * sizeof (EFI_IPv6_ADDRESS));\r
+        Dns6TokenEntry->Token->RspData.H2AData->IpList = AllocateZeroPool (DnsHeader->AnswersNum * sizeof (EFI_IPv6_ADDRESS));\r
         if (Dns6TokenEntry->Token->RspData.H2AData->IpList == NULL) {\r
-          Status = EFI_UNSUPPORTED;\r
+          Status = EFI_OUT_OF_RESOURCES;\r
           goto ON_EXIT;\r
         }\r
       } else {\r
@@ -1338,14 +1339,19 @@ ParseDnsResponse (
     }\r
   }\r
 \r
+  Status = EFI_NOT_FOUND;\r
+\r
   //\r
   // Processing AnswerSection.\r
   //\r
   while (AnswerSectionNum < DnsHeader->AnswersNum) {\r
     //\r
-    // Answer name should be PTR.\r
+    // Answer name should be PTR, else EFI_UNSUPPORTED returned.\r
     //\r
-    ASSERT ((*(UINT8 *) AnswerName & 0xC0) == 0xC0);\r
+    if ((*(UINT8 *) AnswerName & 0xC0) != 0xC0) {\r
+      Status = EFI_UNSUPPORTED;\r
+      goto ON_EXIT;\r
+    }\r
     \r
     //\r
     // Get Answer section.\r
@@ -1360,8 +1366,6 @@ ParseDnsResponse (
     // Check whether it's the GeneralLookUp querying.\r
     //\r
     if (Instance->Service->IpVersion == IP_VERSION_4 && Dns4TokenEntry->GeneralLookUp) {\r
-      ASSERT (Dns4TokenEntry != NULL);\r
-      \r
       Dns4RR = Dns4TokenEntry->Token->RspData.GLookupData->RRList;\r
       AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);\r
 \r
@@ -1370,7 +1374,7 @@ ParseDnsResponse (
       //\r
       Dns4RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1);\r
       if (Dns4RR[RRCount].QName == NULL) {\r
-        Status = EFI_UNSUPPORTED;\r
+        Status = EFI_OUT_OF_RESOURCES;\r
         goto ON_EXIT;\r
       }\r
       CopyMem (Dns4RR[RRCount].QName, QueryName, AsciiStrLen (QueryName));\r
@@ -1380,15 +1384,14 @@ ParseDnsResponse (
       Dns4RR[RRCount].DataLength = AnswerSection->DataLength;\r
       Dns4RR[RRCount].RData = AllocateZeroPool (Dns4RR[RRCount].DataLength);\r
       if (Dns4RR[RRCount].RData == NULL) {\r
-        Status = EFI_UNSUPPORTED;\r
+        Status = EFI_OUT_OF_RESOURCES;\r
         goto ON_EXIT;\r
       }\r
       CopyMem (Dns4RR[RRCount].RData, AnswerData, Dns4RR[RRCount].DataLength);\r
       \r
       RRCount ++;\r
+      Status = EFI_SUCCESS;\r
     } else if (Instance->Service->IpVersion == IP_VERSION_6 && Dns6TokenEntry->GeneralLookUp) {\r
-      ASSERT (Dns6TokenEntry != NULL);\r
-      \r
       Dns6RR = Dns6TokenEntry->Token->RspData.GLookupData->RRList;\r
       AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);\r
 \r
@@ -1397,7 +1400,7 @@ ParseDnsResponse (
       //\r
       Dns6RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1);\r
       if (Dns6RR[RRCount].QName == NULL) {\r
-        Status = EFI_UNSUPPORTED;\r
+        Status = EFI_OUT_OF_RESOURCES;\r
         goto ON_EXIT;\r
       }\r
       CopyMem (Dns6RR[RRCount].QName, QueryName, AsciiStrLen (QueryName));\r
@@ -1407,12 +1410,13 @@ ParseDnsResponse (
       Dns6RR[RRCount].DataLength = AnswerSection->DataLength;\r
       Dns6RR[RRCount].RData = AllocateZeroPool (Dns6RR[RRCount].DataLength);\r
       if (Dns6RR[RRCount].RData == NULL) {\r
-        Status = EFI_UNSUPPORTED;\r
+        Status = EFI_OUT_OF_RESOURCES;\r
         goto ON_EXIT;\r
       }\r
       CopyMem (Dns6RR[RRCount].RData, AnswerData, Dns6RR[RRCount].DataLength);\r
       \r
       RRCount ++;\r
+      Status = EFI_SUCCESS;\r
     } else {\r
       //\r
       // It's not the GeneralLookUp querying. \r
@@ -1423,103 +1427,127 @@ ParseDnsResponse (
         //\r
         // This is address entry, get Data.\r
         //\r
-        ASSERT (Dns4TokenEntry != NULL && AnswerSection->DataLength == 4);\r
+        ASSERT (Dns4TokenEntry != NULL);\r
+\r
+        if (AnswerSection->DataLength != 4) {\r
+          Status = EFI_ABORTED;\r
+          goto ON_EXIT;\r
+        }\r
         \r
         HostAddr4 = Dns4TokenEntry->Token->RspData.H2AData->IpList;\r
         AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);\r
         CopyMem (&HostAddr4[IpCount], AnswerData, sizeof (EFI_IPv4_ADDRESS));\r
 \r
-        //\r
-        // Update DNS cache dynamically.\r
-        //\r
-        if (Dns4CacheEntry != NULL) {\r
-          if (Dns4CacheEntry->HostName != NULL) {\r
-            FreePool (Dns4CacheEntry->HostName);\r
-          }\r
-\r
-          if (Dns4CacheEntry->IpAddress != NULL) {\r
-            FreePool (Dns4CacheEntry->IpAddress);\r
-          }\r
-          \r
-          FreePool (Dns4CacheEntry);\r
-        }\r
-\r
         // \r
-        // Allocate new CacheEntry pool.\r
+        // Allocate new CacheEntry pool to update DNS cache dynamically.\r
         //\r
         Dns4CacheEntry = AllocateZeroPool (sizeof (EFI_DNS4_CACHE_ENTRY));\r
         if (Dns4CacheEntry == NULL) {\r
-          Status = EFI_UNSUPPORTED;\r
+          Status = EFI_OUT_OF_RESOURCES;\r
           goto ON_EXIT;\r
         }\r
         Dns4CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1));\r
         if (Dns4CacheEntry->HostName == NULL) {\r
-          Status = EFI_UNSUPPORTED;\r
+          Status = EFI_OUT_OF_RESOURCES;\r
           goto ON_EXIT;\r
         }\r
         CopyMem (Dns4CacheEntry->HostName, Dns4TokenEntry->QueryHostName, 2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1));\r
         Dns4CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv4_ADDRESS));\r
         if (Dns4CacheEntry->IpAddress == NULL) {\r
-          Status = EFI_UNSUPPORTED;\r
+          Status = EFI_OUT_OF_RESOURCES;\r
           goto ON_EXIT;\r
         }\r
         CopyMem (Dns4CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv4_ADDRESS));\r
-        Dns4CacheEntry->Timeout = AnswerSection->Ttl;\r
+\r
+        if (CNameTtl != 0 && AnswerSection->Ttl != 0) {\r
+          Dns4CacheEntry->Timeout = MIN (CNameTtl, AnswerSection->Ttl);\r
+        } else {\r
+          Dns4CacheEntry->Timeout = MAX (CNameTtl, AnswerSection->Ttl);\r
+        }\r
+        \r
+        UpdateDns4Cache (&mDriverData->Dns4CacheList, FALSE, TRUE, *Dns4CacheEntry);\r
+\r
+        // \r
+        // Free allocated CacheEntry pool.\r
+        //\r
+        FreePool (Dns4CacheEntry->HostName);\r
+        Dns4CacheEntry->HostName = NULL;\r
         \r
-        UpdateDns4Cache (&mDriverData->Dns4CacheList, FALSE, TRUE, *Dns4CacheEntry);  \r
+        FreePool (Dns4CacheEntry->IpAddress);\r
+        Dns4CacheEntry->IpAddress = NULL;\r
+\r
+        FreePool (Dns4CacheEntry);\r
+        Dns4CacheEntry = NULL;\r
 \r
-        IpCount ++; \r
+        IpCount ++;\r
+        Status = EFI_SUCCESS;\r
         break;\r
       case DNS_TYPE_AAAA:\r
         //\r
         // This is address entry, get Data.\r
         //\r
-        ASSERT (Dns6TokenEntry != NULL && AnswerSection->DataLength == 16);\r
+        ASSERT (Dns6TokenEntry != NULL);\r
+\r
+        if (AnswerSection->DataLength != 16) {\r
+          Status = EFI_ABORTED;\r
+          goto ON_EXIT;\r
+        }\r
         \r
         HostAddr6 = Dns6TokenEntry->Token->RspData.H2AData->IpList;\r
         AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);\r
         CopyMem (&HostAddr6[IpCount], AnswerData, sizeof (EFI_IPv6_ADDRESS));\r
 \r
-        //\r
-        // Update DNS cache dynamically.\r
-        //\r
-        if (Dns6CacheEntry != NULL) {\r
-          if (Dns6CacheEntry->HostName != NULL) {\r
-            FreePool (Dns6CacheEntry->HostName);\r
-          }\r
-\r
-          if (Dns6CacheEntry->IpAddress != NULL) {\r
-            FreePool (Dns6CacheEntry->IpAddress);\r
-          }\r
-          \r
-          FreePool (Dns6CacheEntry);\r
-        }\r
-\r
         // \r
-        // Allocate new CacheEntry pool.\r
+        // Allocate new CacheEntry pool to update DNS cache dynamically.\r
         //\r
         Dns6CacheEntry = AllocateZeroPool (sizeof (EFI_DNS6_CACHE_ENTRY));\r
         if (Dns6CacheEntry == NULL) {\r
-          Status = EFI_UNSUPPORTED;\r
+          Status = EFI_OUT_OF_RESOURCES;\r
           goto ON_EXIT;\r
         }\r
         Dns6CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1));\r
         if (Dns6CacheEntry->HostName == NULL) {\r
-          Status = EFI_UNSUPPORTED;\r
+          Status = EFI_OUT_OF_RESOURCES;\r
           goto ON_EXIT;\r
         }\r
         CopyMem (Dns6CacheEntry->HostName, Dns6TokenEntry->QueryHostName, 2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1));\r
         Dns6CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS));\r
         if (Dns6CacheEntry->IpAddress == NULL) {\r
-          Status = EFI_UNSUPPORTED;\r
+          Status = EFI_OUT_OF_RESOURCES;\r
           goto ON_EXIT;\r
         }\r
         CopyMem (Dns6CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv6_ADDRESS));\r
-        Dns6CacheEntry->Timeout = AnswerSection->Ttl;\r
+\r
+        if (CNameTtl != 0 && AnswerSection->Ttl != 0) {\r
+          Dns6CacheEntry->Timeout = MIN (CNameTtl, AnswerSection->Ttl);\r
+        } else {\r
+          Dns6CacheEntry->Timeout = MAX (CNameTtl, AnswerSection->Ttl);\r
+        }\r
         \r
-        UpdateDns6Cache (&mDriverData->Dns6CacheList, FALSE, TRUE, *Dns6CacheEntry);  \r
+        UpdateDns6Cache (&mDriverData->Dns6CacheList, FALSE, TRUE, *Dns6CacheEntry);\r
+\r
+        // \r
+        // Free allocated CacheEntry pool.\r
+        //\r
+        FreePool (Dns6CacheEntry->HostName);\r
+        Dns6CacheEntry->HostName = NULL;\r
+        \r
+        FreePool (Dns6CacheEntry->IpAddress);\r
+        Dns6CacheEntry->IpAddress = NULL;\r
+\r
+        FreePool (Dns6CacheEntry);\r
+        Dns6CacheEntry = NULL;\r
         \r
         IpCount ++;\r
+        Status = EFI_SUCCESS;\r
+        break;\r
+      case DNS_TYPE_CNAME:\r
+        //\r
+        // According RFC 1034 - 3.6.2, if the query name is an alias, the name server will include the CNAME \r
+        // record in the response and restart the query at the domain name specified in the data field of the \r
+        // CNAME record. So, just record the TTL value of the CNAME, then skip to parse the next record.\r
+        //\r
+        CNameTtl = AnswerSection->Ttl;\r
         break;\r
       default:\r
         Status = EFI_UNSUPPORTED;\r
@@ -1561,14 +1589,19 @@ ParseDnsResponse (
       }\r
     }\r
   }\r
-\r
+  \r
+ON_COMPLETE:\r
   //\r
-  // Parsing is complete, SignalEvent here.\r
+  // Parsing is complete, free the sending packet and signal Event here.\r
   //\r
+  if (Item != NULL && Item->Value != NULL) {\r
+    NetbufFree ((NET_BUF *) (Item->Value));\r
+  }\r
+  \r
   if (Instance->Service->IpVersion == IP_VERSION_4) {\r
     ASSERT (Dns4TokenEntry != NULL);\r
     Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry);\r
-    Dns4TokenEntry->Token->Status = EFI_SUCCESS;\r
+    Dns4TokenEntry->Token->Status = Status;\r
     if (Dns4TokenEntry->Token->Event != NULL) {\r
       gBS->SignalEvent (Dns4TokenEntry->Token->Event);\r
       DispatchDpc ();\r
@@ -1576,41 +1609,105 @@ ParseDnsResponse (
   } else {\r
     ASSERT (Dns6TokenEntry != NULL);\r
     Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry);\r
-    Dns6TokenEntry->Token->Status = EFI_SUCCESS;\r
+    Dns6TokenEntry->Token->Status = Status;\r
     if (Dns6TokenEntry->Token->Event != NULL) {\r
       gBS->SignalEvent (Dns6TokenEntry->Token->Event);\r
       DispatchDpc ();\r
     }\r
   }\r
 \r
-  // \r
-  // Free allocated CacheEntry pool.\r
+ON_EXIT:\r
+  //\r
+  // Free the allocated buffer if error happen.\r
   //\r
-  if (Dns4CacheEntry != NULL) {\r
-    if (Dns4CacheEntry->HostName != NULL) {\r
-      FreePool (Dns4CacheEntry->HostName);\r
+  if (EFI_ERROR (Status)) {\r
+    if (Dns4TokenEntry != NULL) {\r
+      if (Dns4TokenEntry->GeneralLookUp) {\r
+        if (Dns4TokenEntry->Token->RspData.GLookupData != NULL) {\r
+          if (Dns4TokenEntry->Token->RspData.GLookupData->RRList != NULL) {\r
+            while (RRCount != 0) {\r
+              RRCount --;\r
+              if (Dns4TokenEntry->Token->RspData.GLookupData->RRList[RRCount].QName != NULL) {\r
+                FreePool (Dns4TokenEntry->Token->RspData.GLookupData->RRList[RRCount].QName);\r
+              }\r
+\r
+              if (Dns4TokenEntry->Token->RspData.GLookupData->RRList[RRCount].RData != NULL) {\r
+                FreePool (Dns4TokenEntry->Token->RspData.GLookupData->RRList[RRCount].RData);\r
+              }\r
+            }\r
+            \r
+            FreePool (Dns4TokenEntry->Token->RspData.GLookupData->RRList);\r
+          }\r
+          \r
+          FreePool (Dns4TokenEntry->Token->RspData.GLookupData);\r
+        }\r
+      } else {\r
+        if (QuerySection->Type == DNS_TYPE_A && Dns4TokenEntry->Token->RspData.H2AData != NULL) {\r
+          if (Dns4TokenEntry->Token->RspData.H2AData->IpList != NULL) {\r
+            FreePool (Dns4TokenEntry->Token->RspData.H2AData->IpList);\r
+          }\r
+          \r
+          FreePool (Dns4TokenEntry->Token->RspData.H2AData);\r
+        }\r
+      }\r
     }\r
 \r
-    if (Dns4CacheEntry->IpAddress != NULL) {\r
-      FreePool (Dns4CacheEntry->IpAddress);\r
+    if (Dns6TokenEntry != NULL) {\r
+      if (Dns6TokenEntry->GeneralLookUp) {\r
+        if (Dns6TokenEntry->Token->RspData.GLookupData != NULL) {\r
+          if (Dns6TokenEntry->Token->RspData.GLookupData->RRList != NULL) {\r
+            while (RRCount != 0) {\r
+              RRCount --;\r
+              if (Dns6TokenEntry->Token->RspData.GLookupData->RRList[RRCount].QName != NULL) {\r
+                FreePool (Dns6TokenEntry->Token->RspData.GLookupData->RRList[RRCount].QName);\r
+              }\r
+\r
+              if (Dns6TokenEntry->Token->RspData.GLookupData->RRList[RRCount].RData != NULL) {\r
+                FreePool (Dns6TokenEntry->Token->RspData.GLookupData->RRList[RRCount].RData);\r
+              }\r
+            }\r
+            \r
+            FreePool (Dns6TokenEntry->Token->RspData.GLookupData->RRList);\r
+          }\r
+          \r
+          FreePool (Dns6TokenEntry->Token->RspData.GLookupData);\r
+        }\r
+      } else {\r
+        if (QuerySection->Type == DNS_TYPE_AAAA && Dns6TokenEntry->Token->RspData.H2AData != NULL) {\r
+          if (Dns6TokenEntry->Token->RspData.H2AData->IpList != NULL) {\r
+            FreePool (Dns6TokenEntry->Token->RspData.H2AData->IpList);\r
+          }\r
+          \r
+          FreePool (Dns6TokenEntry->Token->RspData.H2AData);\r
+        }\r
+      }\r
     }\r
 \r
-    FreePool (Dns4CacheEntry);\r
-  }\r
-  \r
-  if (Dns6CacheEntry != NULL) {\r
-    if (Dns6CacheEntry->HostName != NULL) {\r
-      FreePool (Dns6CacheEntry->HostName);\r
-    }\r
+    if (Dns4CacheEntry != NULL) {\r
+      if (Dns4CacheEntry->HostName != NULL) {\r
+        FreePool (Dns4CacheEntry->HostName);\r
+      }\r
 \r
-    if (Dns6CacheEntry->IpAddress != NULL) {\r
-      FreePool (Dns6CacheEntry->IpAddress);\r
+      if (Dns4CacheEntry->IpAddress != NULL) {\r
+        FreePool (Dns4CacheEntry->IpAddress);\r
+      }\r
+\r
+      FreePool (Dns4CacheEntry);\r
     }\r
-  \r
-    FreePool (Dns6CacheEntry);\r
-  }\r
 \r
-ON_EXIT:\r
+    if (Dns6CacheEntry != NULL) {\r
+      if (Dns6CacheEntry->HostName != NULL) {\r
+        FreePool (Dns6CacheEntry->HostName);\r
+      }\r
+\r
+      if (Dns6CacheEntry->IpAddress != NULL) {\r
+        FreePool (Dns6CacheEntry->IpAddress);\r
+      }\r
+\r
+      FreePool (Dns6CacheEntry);\r
+    }    \r
+  }\r
+  \r
   gBS->RestoreTPL (OldTpl);\r
   return Status;\r
 }\r
@@ -1650,6 +1747,10 @@ DnsOnPacketReceived (
   }\r
 \r
   ASSERT (Packet != NULL);\r
+\r
+  if (Packet->TotalSize <= sizeof (DNS_HEADER)) {\r
+    goto ON_EXIT;\r
+  }\r
   \r
   RcvString = NetbufGetByte (Packet, 0, NULL);\r
   ASSERT (RcvString != NULL);\r
@@ -1659,15 +1760,15 @@ DnsOnPacketReceived (
   //\r
   ParseDnsResponse (Instance, RcvString, &Completed);\r
 \r
-  ON_EXIT:\r
+ON_EXIT:\r
 \r
-    if (Packet != NULL) {\r
-      NetbufFree (Packet);\r
-    }\r
+  if (Packet != NULL) {\r
+    NetbufFree (Packet);\r
+  }\r
 \r
-    if (!Completed) {\r
-      UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);\r
-    }\r
+  if (!Completed) {\r
+    UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);\r
+  }\r
 }\r
 \r
 /**\r
@@ -1786,8 +1887,12 @@ ConstructDNSQuery (
   NET_FRAGMENT        Frag;\r
   DNS_HEADER          *DnsHeader;\r
   DNS_QUERY_SECTION   *DnsQuery;\r
-  \r
-  Frag.Bulk = AllocatePool (DNS_DEFAULT_BLKSIZE * sizeof (UINT8));\r
+\r
+  //\r
+  // Messages carried by UDP are restricted to 512 bytes (not counting the IP\r
+  // or UDP headers).\r
+  //\r
+  Frag.Bulk = AllocatePool (DNS_MAX_MESSAGE_SIZE * sizeof (UINT8));\r
   if (Frag.Bulk == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
@@ -1948,7 +2053,7 @@ DnsOnTimerRetransmit (
         // Retransmit the packet if haven't reach the maxmium retry count,\r
         // otherwise exit the transfer.\r
         //\r
-        if (++Dns4TokenEntry->Token->RetryCount < Instance->MaxRetry) {\r
+        if (++Dns4TokenEntry->RetryCounting <= Dns4TokenEntry->Token->RetryCount) {\r
           DnsRetransmit (Instance, (NET_BUF *)ItemNetMap->Value);\r
           EntryNetMap = EntryNetMap->ForwardLink;\r
         } else {\r
@@ -1992,7 +2097,7 @@ DnsOnTimerRetransmit (
         // Retransmit the packet if haven't reach the maxmium retry count,\r
         // otherwise exit the transfer.\r
         //\r
-        if (++Dns6TokenEntry->Token->RetryCount < Instance->MaxRetry) {\r
+        if (++Dns6TokenEntry->RetryCounting <= Dns6TokenEntry->Token->RetryCount) {\r
           DnsRetransmit (Instance, (NET_BUF *) ItemNetMap->Value);\r
           EntryNetMap = EntryNetMap->ForwardLink;\r
         } else {\r
@@ -2051,8 +2156,11 @@ DnsOnTimerUpdate (
   Entry = mDriverData->Dns4CacheList.ForwardLink;\r
   while (Entry != &mDriverData->Dns4CacheList) {\r
     Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);\r
-    if (Item4->DnsCache.Timeout<=0) {\r
+    if (Item4->DnsCache.Timeout == 0) {\r
       RemoveEntryList (&Item4->AllCacheLink);\r
+      FreePool (Item4->DnsCache.HostName);\r
+      FreePool (Item4->DnsCache.IpAddress);\r
+      FreePool (Item4);\r
       Entry = mDriverData->Dns4CacheList.ForwardLink;\r
     } else {\r
       Entry = Entry->ForwardLink;\r
@@ -2070,8 +2178,11 @@ DnsOnTimerUpdate (
   Entry = mDriverData->Dns6CacheList.ForwardLink;\r
   while (Entry != &mDriverData->Dns6CacheList) {\r
     Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);\r
-    if (Item6->DnsCache.Timeout<=0) {\r
+    if (Item6->DnsCache.Timeout == 0) {\r
       RemoveEntryList (&Item6->AllCacheLink);\r
+      FreePool (Item6->DnsCache.HostName);\r
+      FreePool (Item6->DnsCache.IpAddress);\r
+      FreePool (Item6);\r
       Entry = mDriverData->Dns6CacheList.ForwardLink;\r
     } else {\r
       Entry = Entry->ForwardLink;\r