Reviewed-by: Fu Siyuan <siyuan...@intel.com>
> -----Original Message----- > From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of > Jiaxin Wu > Sent: Tuesday, September 6, 2016 4:51 PM > To: edk2-devel@lists.01.org > Cc: Ye, Ting <ting...@intel.com>; Fu, Siyuan <siyuan...@intel.com> > Subject: [edk2] [PATCH v2] 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.he...@hpe.com> > Cc: Fu Siyuan <siyuan...@intel.com> > Cc: Ye Ting <ting...@intel.com> > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Jiaxin Wu <jiaxin...@intel.com> > --- > NetworkPkg/DnsDxe/DnsImpl.c | 81 +++++++++++++++++++++++++++++----------- > ----- > 1 file changed, 52 insertions(+), 29 deletions(-) > > diff --git a/NetworkPkg/DnsDxe/DnsImpl.c b/NetworkPkg/DnsDxe/DnsImpl.c > index 360f68e..cfaa4c7 100644 > --- a/NetworkPkg/DnsDxe/DnsImpl.c > +++ b/NetworkPkg/DnsDxe/DnsImpl.c > @@ -1125,10 +1125,11 @@ ParseDnsResponse ( > 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; > @@ -1146,10 +1147,11 @@ ParseDnsResponse ( > Dns6TokenEntry = NULL; > > IpCount = 0; > RRCount = 0; > AnswerSectionNum = 0; > + CNameTtl = 0; > > HostAddr4 = NULL; > HostAddr6 = NULL; > > Dns4CacheEntry = NULL; > @@ -1231,17 +1233,10 @@ ParseDnsResponse ( > if (DnsHeader->Flags.Bits.RCode != DNS_FLAGS_RCODE_NO_ERROR || > DnsHeader->AnswersNum < 1 || \ > DnsHeader->Flags.Bits.QR != DNS_FLAGS_QR_RESPONSE) { > Status = EFI_ABORTED; > goto ON_EXIT; > } > - > - // > - // Free the sending packet. > - // > - if (Item->Value != NULL) { > - NetbufFree ((NET_BUF *) (Item->Value)); > - } > > // > // Do some buffer allocations. > // > if (Instance->Service->IpVersion == IP_VERSION_4) { > @@ -1288,40 +1283,42 @@ ParseDnsResponse ( > // > // It's the GeneralLookUp querying. > // > 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 { > // > // It's not the GeneralLookUp querying. Check the Query type. > // > 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 { > Status = EFI_UNSUPPORTED; > goto ON_EXIT; > } > } > } > > + Status = EFI_NOT_FOUND; > + > // > // Processing AnswerSection. > // > while (AnswerSectionNum < DnsHeader->AnswersNum) { > // > @@ -1348,51 +1345,53 @@ ParseDnsResponse ( > // > // Fill the ResourceRecord. > // > 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)); > 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_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); > > // > // Fill the ResourceRecord. > // > 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)); > 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_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. > // Check the Query type, parse the response packet. > // > @@ -1425,30 +1424,36 @@ ParseDnsResponse ( > // > // Allocate new CacheEntry pool. > // > 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: > // > // This is address entry, get Data. > // > @@ -1476,30 +1481,44 @@ ParseDnsResponse ( > // > // Allocate new CacheEntry pool. > // > 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; > goto ON_EXIT; > } > @@ -1539,24 +1558,28 @@ 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 (); > } > } 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 (); > } > } > @@ -2035,11 +2058,11 @@ 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 { > Entry = Entry->ForwardLink; > } > @@ -2054,11 +2077,11 @@ 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 { > Entry = Entry->ForwardLink; > } > -- > 1.9.5.msysgit.1 > > _______________________________________________ > edk2-devel mailing list > edk2-devel@lists.01.org > https://lists.01.org/mailman/listinfo/edk2-devel _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel