summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiaxin Wu <jiaxin.wu@intel.com>2016-09-06 11:23:38 +0800
committerJiaxin Wu <jiaxin.wu@intel.com>2016-09-07 14:28:17 +0800
commit3093f45c44eaea11e2f2552af7ff5c5b370a93d7 (patch)
treeb718e8b1b572f715bc7828c4b3716e74e3b8eca3
parentec68dc28557925e0708d5676288ad140651a3851 (diff)
downloadedk2-platforms-3093f45c44eaea11e2f2552af7ff5c5b370a93d7.tar.xz
NetworkPkg/DnsDxe: Handle CNAME type responded from the name server
v2: * Code refine. * For DnsCache, the minimum value of TTL is selected between CNAME and A/AAAA record. 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. RFC also provides one example server action when A query received: Suppose a name server was processing a query with for USCISIC.ARPA, asking for type A information, and had the following resource records: USC-ISIC.ARPA IN CNAME C.ISI.EDU C.ISI.EDU IN A 10.0.0.52 Both of these RRs would be returned in the response to the type A query. Currently, DnsDxe driver doesn't handle the CNAME type response, which will cause any exception result. The driver need continue the packet parsing while CNAME type record parsed. So, this patch is used to handle it correctly. Cc: Hegde Nagaraj P <nagaraj-p.hegde@hpe.com> Cc: Fu Siyuan <siyuan.fu@intel.com> Cc: Ye Ting <ting.ye@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiaxin Wu <jiaxin.wu@intel.com> Reviewed-by: Fu Siyuan <siyuan.fu@intel.com> Tested-by: Hegde Nagaraj P <nagaraj-p.hegde@hpe.com>
-rw-r--r--NetworkPkg/DnsDxe/DnsImpl.c81
1 files changed, 52 insertions, 29 deletions
diff --git a/NetworkPkg/DnsDxe/DnsImpl.c b/NetworkPkg/DnsDxe/DnsImpl.c
index 360f68e1a4..cfaa4c78a9 100644
--- a/NetworkPkg/DnsDxe/DnsImpl.c
+++ b/NetworkPkg/DnsDxe/DnsImpl.c
@@ -1127,6 +1127,7 @@ ParseDnsResponse (
UINT32 IpCount;
UINT32 RRCount;
UINT32 AnswerSectionNum;
+ UINT32 CNameTtl;
EFI_IPv4_ADDRESS *HostAddr4;
EFI_IPv6_ADDRESS *HostAddr6;
@@ -1148,6 +1149,7 @@ ParseDnsResponse (
IpCount = 0;
RRCount = 0;
AnswerSectionNum = 0;
+ CNameTtl = 0;
HostAddr4 = NULL;
HostAddr6 = NULL;
@@ -1233,13 +1235,6 @@ ParseDnsResponse (
Status = EFI_ABORTED;
goto ON_EXIT;
}
-
- //
- // Free the sending packet.
- //
- if (Item->Value != NULL) {
- NetbufFree ((NET_BUF *) (Item->Value));
- }
//
// Do some buffer allocations.
@@ -1290,12 +1285,12 @@ ParseDnsResponse (
//
Dns6TokenEntry->Token->RspData.GLookupData = AllocatePool (sizeof (DNS_RESOURCE_RECORD));
if (Dns6TokenEntry->Token->RspData.GLookupData == NULL) {
- Status = EFI_UNSUPPORTED;
+ Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
Dns6TokenEntry->Token->RspData.GLookupData->RRList = AllocatePool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD));
if (Dns6TokenEntry->Token->RspData.GLookupData->RRList == NULL) {
- Status = EFI_UNSUPPORTED;
+ Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
} else {
@@ -1305,12 +1300,12 @@ ParseDnsResponse (
if (QuerySection->Type == DNS_TYPE_AAAA) {
Dns6TokenEntry->Token->RspData.H2AData = AllocatePool (sizeof (DNS6_HOST_TO_ADDR_DATA));
if (Dns6TokenEntry->Token->RspData.H2AData == NULL) {
- Status = EFI_UNSUPPORTED;
+ Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
Dns6TokenEntry->Token->RspData.H2AData->IpList = AllocatePool (DnsHeader->AnswersNum * sizeof (EFI_IPv6_ADDRESS));
if (Dns6TokenEntry->Token->RspData.H2AData->IpList == NULL) {
- Status = EFI_UNSUPPORTED;
+ Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
} else {
@@ -1320,6 +1315,8 @@ ParseDnsResponse (
}
}
+ Status = EFI_NOT_FOUND;
+
//
// Processing AnswerSection.
//
@@ -1350,7 +1347,7 @@ ParseDnsResponse (
//
Dns4RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1);
if (Dns4RR[RRCount].QName == NULL) {
- Status = EFI_UNSUPPORTED;
+ Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
CopyMem (Dns4RR[RRCount].QName, QueryName, AsciiStrLen (QueryName));
@@ -1360,12 +1357,13 @@ ParseDnsResponse (
Dns4RR[RRCount].DataLength = AnswerSection->DataLength;
Dns4RR[RRCount].RData = AllocateZeroPool (Dns4RR[RRCount].DataLength);
if (Dns4RR[RRCount].RData == NULL) {
- Status = EFI_UNSUPPORTED;
+ 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);
@@ -1375,7 +1373,7 @@ ParseDnsResponse (
//
Dns6RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1);
if (Dns6RR[RRCount].QName == NULL) {
- Status = EFI_UNSUPPORTED;
+ Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
CopyMem (Dns6RR[RRCount].QName, QueryName, AsciiStrLen (QueryName));
@@ -1385,12 +1383,13 @@ ParseDnsResponse (
Dns6RR[RRCount].DataLength = AnswerSection->DataLength;
Dns6RR[RRCount].RData = AllocateZeroPool (Dns6RR[RRCount].DataLength);
if (Dns6RR[RRCount].RData == NULL) {
- Status = EFI_UNSUPPORTED;
+ 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.
@@ -1427,26 +1426,32 @@ ParseDnsResponse (
//
Dns4CacheEntry = AllocateZeroPool (sizeof (EFI_DNS4_CACHE_ENTRY));
if (Dns4CacheEntry == NULL) {
- Status = EFI_UNSUPPORTED;
+ Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
Dns4CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1));
if (Dns4CacheEntry->HostName == NULL) {
- Status = EFI_UNSUPPORTED;
+ 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_UNSUPPORTED;
+ Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
CopyMem (Dns4CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv4_ADDRESS));
- Dns4CacheEntry->Timeout = AnswerSection->Ttl;
+
+ 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);
- IpCount ++;
+ IpCount ++;
+ Status = EFI_SUCCESS;
break;
case DNS_TYPE_AAAA:
//
@@ -1478,26 +1483,40 @@ ParseDnsResponse (
//
Dns6CacheEntry = AllocateZeroPool (sizeof (EFI_DNS6_CACHE_ENTRY));
if (Dns6CacheEntry == NULL) {
- Status = EFI_UNSUPPORTED;
+ Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
Dns6CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1));
if (Dns6CacheEntry->HostName == NULL) {
- Status = EFI_UNSUPPORTED;
+ 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_UNSUPPORTED;
+ Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
CopyMem (Dns6CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv6_ADDRESS));
- Dns6CacheEntry->Timeout = AnswerSection->Ttl;
+
+ 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);
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;
@@ -1541,12 +1560,16 @@ ParseDnsResponse (
}
//
- // Parsing is complete, SignalEvent here.
+ // 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 = EFI_SUCCESS;
+ Dns4TokenEntry->Token->Status = Status;
if (Dns4TokenEntry->Token->Event != NULL) {
gBS->SignalEvent (Dns4TokenEntry->Token->Event);
DispatchDpc ();
@@ -1554,7 +1577,7 @@ ParseDnsResponse (
} else {
ASSERT (Dns6TokenEntry != NULL);
Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry);
- Dns6TokenEntry->Token->Status = EFI_SUCCESS;
+ Dns6TokenEntry->Token->Status = Status;
if (Dns6TokenEntry->Token->Event != NULL) {
gBS->SignalEvent (Dns6TokenEntry->Token->Event);
DispatchDpc ();
@@ -2037,7 +2060,7 @@ DnsOnTimerUpdate (
Entry = mDriverData->Dns4CacheList.ForwardLink;
while (Entry != &mDriverData->Dns4CacheList) {
Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
- if (Item4->DnsCache.Timeout<=0) {
+ if (Item4->DnsCache.Timeout == 0) {
RemoveEntryList (&Item4->AllCacheLink);
Entry = mDriverData->Dns4CacheList.ForwardLink;
} else {
@@ -2056,7 +2079,7 @@ DnsOnTimerUpdate (
Entry = mDriverData->Dns6CacheList.ForwardLink;
while (Entry != &mDriverData->Dns6CacheList) {
Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
- if (Item6->DnsCache.Timeout<=0) {
+ if (Item6->DnsCache.Timeout == 0) {
RemoveEntryList (&Item6->AllCacheLink);
Entry = mDriverData->Dns6CacheList.ForwardLink;
} else {