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
-CHAR8 *\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
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
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
UINT32 IpCount;\r
UINT32 RRCount;\r
UINT32 AnswerSectionNum;\r
+ UINT32 CNameTtl;\r
\r
EFI_IPv4_ADDRESS *HostAddr4;\r
EFI_IPv6_ADDRESS *HostAddr6;\r
IpCount = 0;\r
RRCount = 0;\r
AnswerSectionNum = 0;\r
+ CNameTtl = 0;\r
\r
HostAddr4 = NULL;\r
HostAddr6 = NULL;\r
// 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
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
// 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
//\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
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
}\r
}\r
\r
+ Status = EFI_NOT_FOUND;\r
+\r
//\r
// Processing AnswerSection.\r
//\r
//\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
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
//\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
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
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
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
}\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
} 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
}\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
//\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
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
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
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