]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/DnsDxe/DnsImpl.c
MdePkg/SmmIoLib: Add header file.
[mirror_edk2.git] / NetworkPkg / DnsDxe / DnsImpl.c
index 360f68e1a4941a73b6db36cb59b255d416b0bcc9..ea3d27da52858180da391d8a60585b262463c66d 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 DnsDxe support functions implementation.\r
   \r
-Copyright (c) 2016, 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,7 +615,7 @@ 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
@@ -643,9 +643,11 @@ Dns6GetMapping (
         FreePool (Ip6Mode.IcmpTypeList);\r
       }\r
 \r
-      if (Ip6Mode.IsConfigured) {\r
+      if (!Ip6Mode.IsStarted || Ip6Mode.IsConfigured) {\r
         Udp->Configure (Udp, NULL);\r
-        return (BOOLEAN) (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS);\r
+        if (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS) {\r
+          return TRUE;\r
+        }\r
       }\r
     }\r
   }\r
@@ -1127,6 +1129,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
@@ -1148,6 +1151,7 @@ ParseDnsResponse (
   IpCount          = 0;\r
   RRCount          = 0;\r
   AnswerSectionNum = 0;\r
+  CNameTtl         = 0;\r
   \r
   HostAddr4        = NULL;\r
   HostAddr6        = NULL;\r
@@ -1230,15 +1234,16 @@ ParseDnsResponse (
   //\r
   if (DnsHeader->Flags.Bits.RCode != DNS_FLAGS_RCODE_NO_ERROR || DnsHeader->AnswersNum < 1 || \\r
       DnsHeader->Flags.Bits.QR != DNS_FLAGS_QR_RESPONSE) {\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
+    //\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
@@ -1290,12 +1295,12 @@ ParseDnsResponse (
       //\r
       Dns6TokenEntry->Token->RspData.GLookupData = AllocatePool (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
       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
@@ -1305,12 +1310,12 @@ ParseDnsResponse (
       if (QuerySection->Type == DNS_TYPE_AAAA) {\r
         Dns6TokenEntry->Token->RspData.H2AData = AllocatePool (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
         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
@@ -1320,14 +1325,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
@@ -1350,7 +1360,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
@@ -1360,12 +1370,13 @@ 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
       Dns6RR = Dns6TokenEntry->Token->RspData.GLookupData->RRList;\r
       AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);\r
@@ -1375,7 +1386,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
@@ -1385,12 +1396,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
@@ -1401,103 +1413,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
+        UpdateDns4Cache (&mDriverData->Dns4CacheList, FALSE, TRUE, *Dns4CacheEntry);\r
 \r
-        IpCount ++; \r
+        // \r
+        // Free allocated CacheEntry pool.\r
+        //\r
+        FreePool (Dns4CacheEntry->HostName);\r
+        Dns4CacheEntry->HostName = NULL;\r
+        \r
+        FreePool (Dns4CacheEntry->IpAddress);\r
+        Dns4CacheEntry->IpAddress = NULL;\r
+\r
+        FreePool (Dns4CacheEntry);\r
+        Dns4CacheEntry = NULL;\r
+\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
+\r
+        // \r
+        // Free allocated CacheEntry pool.\r
+        //\r
+        FreePool (Dns6CacheEntry->HostName);\r
+        Dns6CacheEntry->HostName = NULL;\r
         \r
-        UpdateDns6Cache (&mDriverData->Dns6CacheList, FALSE, TRUE, *Dns6CacheEntry);  \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
@@ -1539,14 +1575,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
@@ -1554,40 +1595,13 @@ 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
-  //\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
-  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
 ON_EXIT:\r
   gBS->RestoreTPL (OldTpl);\r
   return Status;\r
@@ -2037,7 +2051,7 @@ 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
       Entry = mDriverData->Dns4CacheList.ForwardLink;\r
     } else {\r
@@ -2056,7 +2070,7 @@ 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
       Entry = mDriverData->Dns6CacheList.ForwardLink;\r
     } else {\r