/** @file\r
+ The implementation of the ARP protocol.\r
\r
-Copyright (c) 2006 - 2007, Intel Corporation\r
-All rights reserved. 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
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-Module Name:\r
-\r
- ArpImpl.c\r
-\r
-Abstract:\r
-\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
-\r
#include "ArpImpl.h"\r
\r
+//\r
+// Global variable of EFI ARP Protocol Interface.\r
+//\r
EFI_ARP_PROTOCOL mEfiArpProtocolTemplate = {\r
ArpConfigure,\r
ArpAdd,\r
/**\r
Initialize the instance context data.\r
\r
- @param ArpService Pointer to the arp service context data this\r
+ @param[in] ArpService Pointer to the arp service context data this\r
instance belongs to.\r
- @param Instance Pointer to the instance context data.\r
+ @param[out] Instance Pointer to the instance context data.\r
\r
@return None.\r
\r
**/\r
VOID\r
ArpInitInstance (\r
- IN ARP_SERVICE_DATA *ArpService,\r
- IN ARP_INSTANCE_DATA *Instance\r
+ IN ARP_SERVICE_DATA *ArpService,\r
+ OUT ARP_INSTANCE_DATA *Instance\r
)\r
{\r
NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);\r
CopyMem (&Instance->ArpProto, &mEfiArpProtocolTemplate, sizeof (Instance->ArpProto));\r
\r
Instance->Configured = FALSE;\r
- Instance->Destroyed = FALSE;\r
+ Instance->InDestroy = FALSE;\r
\r
InitializeListHead (&Instance->List);\r
}\r
/**\r
Process the Arp packets received from Mnp, the procedure conforms to RFC826.\r
\r
- @param Context Pointer to the context data registerd to the\r
+ @param[in] Context Pointer to the context data registerd to the\r
Event.\r
\r
@return None.\r
// Status is EFI_SUCCESS, process the received frame.\r
//\r
RxData = RxToken->Packet.RxData;\r
- Head = (ARP_HEAD *) RxData->PacketData;\r
+ //\r
+ // Sanity check.\r
+ //\r
+ if (RxData->DataLength < sizeof (ARP_HEAD)) {\r
+ //\r
+ // Restart the receiving if packet size is not correct.\r
+ //\r
+ goto RESTART_RECEIVE;\r
+ }\r
\r
//\r
// Convert the byte order of the multi-byte fields.\r
//\r
+ Head = (ARP_HEAD *) RxData->PacketData;\r
Head->HwType = NTOHS (Head->HwType);\r
Head->ProtoType = NTOHS (Head->ProtoType);\r
Head->OpCode = NTOHS (Head->OpCode);\r
\r
+ if (RxData->DataLength < (sizeof (ARP_HEAD) + 2 * Head->HwAddrLen + 2 * Head->ProtoAddrLen)) {\r
+ goto RESTART_RECEIVE;\r
+ }\r
+\r
if ((Head->HwType != ArpService->SnpMode.IfType) ||\r
(Head->HwAddrLen != ArpService->SnpMode.HwAddressSize) ||\r
(RxData->ProtocolType != ARP_ETHER_PROTO_TYPE)) {\r
/**\r
Queue ArpOnFrameRcvdDpc as a DPC at TPL_CALLBACK.\r
\r
- @param Event The Event this notify function registered to.\r
- @param Context Pointer to the context data registerd to the\r
- Event.\r
+ @param[in] Event The Event this notify function registered to.\r
+ @param[in] Context Pointer to the context data registerd to the\r
+ Event.\r
\r
@return None.\r
\r
//\r
// Request ArpOnFrameRcvdDpc as a DPC at TPL_CALLBACK\r
//\r
- NetLibQueueDpc (TPL_CALLBACK, ArpOnFrameRcvdDpc, Context);\r
+ QueueDpc (TPL_CALLBACK, ArpOnFrameRcvdDpc, Context);\r
}\r
\r
/**\r
Process the already sent arp packets.\r
\r
- @param Context Pointer to the context data registerd to the\r
- Event.\r
+ @param[in] Context Pointer to the context data registerd to the\r
+ Event.\r
\r
@return None.\r
\r
//\r
// Free the allocated memory and close the event.\r
//\r
- gBS->FreePool (TxData->FragmentTable[0].FragmentBuffer);\r
- gBS->FreePool (TxData);\r
+ FreePool (TxData->FragmentTable[0].FragmentBuffer);\r
+ FreePool (TxData);\r
gBS->CloseEvent (TxToken->Event);\r
- gBS->FreePool (TxToken);\r
+ FreePool (TxToken);\r
}\r
\r
/**\r
Request ArpOnFrameSentDpc as a DPC at TPL_CALLBACK.\r
\r
- @param Event The Event this notify function registered to.\r
- @param Context Pointer to the context data registerd to the\r
- Event.\r
+ @param[in] Event The Event this notify function registered to.\r
+ @param[in] Context Pointer to the context data registerd to the\r
+ Event.\r
\r
@return None.\r
\r
//\r
// Request ArpOnFrameSentDpc as a DPC at TPL_CALLBACK\r
//\r
- NetLibQueueDpc (TPL_CALLBACK, ArpOnFrameSentDpc, Context);\r
+ QueueDpc (TPL_CALLBACK, ArpOnFrameSentDpc, Context);\r
}\r
\r
\r
/**\r
Process the arp cache olding and drive the retrying arp requests.\r
\r
- @param Event The Event this notify function registered to.\r
- @param Context Pointer to the context data registerd to the\r
- Event.\r
+ @param[in] Event The Event this notify function registered to.\r
+ @param[in] Context Pointer to the context data registerd to the\r
+ Event.\r
\r
@return None.\r
\r
ASSERT (IsListEmpty (&CacheEntry->UserRequestList));\r
\r
RemoveEntryList (&CacheEntry->List);\r
- gBS->FreePool (CacheEntry);\r
+ FreePool (CacheEntry);\r
} else {\r
//\r
// resend the ARP request.\r
// Time out, remove it.\r
//\r
RemoveEntryList (&CacheEntry->List);\r
- gBS->FreePool (CacheEntry);\r
+ FreePool (CacheEntry);\r
} else {\r
//\r
// Update the DecayTime.\r
// Time out, remove it.\r
//\r
RemoveEntryList (&CacheEntry->List);\r
- gBS->FreePool (CacheEntry);\r
+ FreePool (CacheEntry);\r
} else {\r
//\r
// Update the DecayTime.\r
/**\r
Match the two NET_ARP_ADDRESSes.\r
\r
- @param AddressOne Pointer to the first address to match.\r
- @param AddressTwo Pointer to the second address to match.\r
+ @param[in] AddressOne Pointer to the first address to match.\r
+ @param[in] AddressTwo Pointer to the second address to match.\r
\r
@return The two addresses match or not.\r
\r
**/\r
-STATIC\r
BOOLEAN\r
ArpMatchAddress (\r
IN NET_ARP_ADDRESS *AddressOne,\r
IN NET_ARP_ADDRESS *AddressTwo\r
)\r
{\r
+ ASSERT (AddressOne != NULL && AddressTwo != NULL);\r
+\r
if ((AddressOne->Type != AddressTwo->Type) ||\r
(AddressOne->Length != AddressTwo->Length)) {\r
//\r
/**\r
Find the CacheEntry which matches the requirements in the specified CacheTable.\r
\r
- @param CacheTable Pointer to the arp cache table.\r
- @param StartEntry Pointer to the start entry this search begins with\r
- in the cache table.\r
- @param FindOpType The search type.\r
- @param ProtocolAddress Pointer to the protocol address to match.\r
- @param HardwareAddress Pointer to the hardware address to match.\r
+ @param[in] CacheTable Pointer to the arp cache table.\r
+ @param[in] StartEntry Pointer to the start entry this search begins with\r
+ in the cache table.\r
+ @param[in] FindOpType The search type.\r
+ @param[in] ProtocolAddress Pointer to the protocol address to match.\r
+ @param[in] HardwareAddress Pointer to the hardware address to match.\r
\r
@return Pointer to the matched arp cache entry, if NULL, no match is found.\r
\r
for (Entry = StartEntry->ForwardLink; Entry != CacheTable; Entry = Entry->ForwardLink) {\r
CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);\r
\r
- if (FindOpType & MATCH_SW_ADDRESS) {\r
+ if ((FindOpType & MATCH_SW_ADDRESS) != 0) {\r
//\r
// Find by the software address.\r
//\r
}\r
}\r
\r
- if (FindOpType & MATCH_HW_ADDRESS) {\r
+ if ((FindOpType & MATCH_HW_ADDRESS) != 0) {\r
//\r
// Find by the hardware address.\r
//\r
Find the CacheEntry, using ProtocolAddress or HardwareAddress or both, as the keyword,\r
in the DeniedCacheTable.\r
\r
- @param ArpService Pointer to the arp service context data.\r
- @param ProtocolAddress Pointer to the protocol address.\r
- @param HardwareAddress Pointer to the hardware address.\r
+ @param[in] ArpService Pointer to the arp service context data.\r
+ @param[in] ProtocolAddress Pointer to the protocol address.\r
+ @param[in] HardwareAddress Pointer to the hardware address.\r
\r
@return Pointer to the matched cache entry, if NULL no match is found.\r
\r
/**\r
Allocate a cache entry and initialize it.\r
\r
- @param Instance Pointer to the instance context data.\r
+ @param[in] Instance Pointer to the instance context data.\r
\r
@return Pointer to the new created cache entry.\r
\r
/**\r
Turn the CacheEntry into the resolved status.\r
\r
- @param CacheEntry Pointer to the resolved cache entry.\r
- @param Instance Pointer to the instance context data.\r
- @param UserEvent Pointer to the UserEvent to notify.\r
+ @param[in] CacheEntry Pointer to the resolved cache entry.\r
+ @param[in] Instance Pointer to the instance context data.\r
+ @param[in] UserEvent Pointer to the UserEvent to notify.\r
\r
@return The count of notifications sent to the instance.\r
\r
// Remove this user request and free the context data.\r
//\r
RemoveEntryList (&Context->List);\r
- gBS->FreePool (Context);\r
+ FreePool (Context);\r
\r
Count++;\r
}\r
//\r
// Dispatch the DPCs queued by the NotifyFunction of the Context->UserRequestEvent.\r
//\r
- NetLibDispatchDpc ();\r
+ DispatchDpc ();\r
\r
return Count;\r
}\r
Fill the addresses in the CacheEntry using the information passed in by\r
HwAddr and SwAddr.\r
\r
- @param CacheEntry Pointer to the cache entry.\r
- @param HwAddr Pointer to the software address.\r
- @param SwAddr Pointer to the hardware address.\r
+ @param[in] CacheEntry Pointer to the cache entry.\r
+ @param[in] HwAddr Pointer to the software address.\r
+ @param[in] SwAddr Pointer to the hardware address.\r
\r
@return None.\r
\r
/**\r
Configure the instance using the ConfigData. ConfigData is already validated.\r
\r
- @param Instance Pointer to the instance context data to be\r
+ @param[in] Instance Pointer to the instance context data to be\r
configured.\r
- @param ConfigData Pointer to the configuration data used to\r
+ @param[in] ConfigData Pointer to the configuration data used to\r
configure the instance.\r
\r
@retval EFI_SUCCESS The instance is configured with the ConfigData.\r
// The instance is not configured.\r
//\r
\r
- if (ConfigData->SwAddressType == IPv4_ETHER_PROTO_TYPE) {\r
+ if (ConfigData->SwAddressType == IPV4_ETHER_PROTO_TYPE) {\r
CopyMem (&Ip, ConfigData->StationAddress, sizeof (IP4_ADDR));\r
\r
- if (!Ip4IsUnicast (NTOHL (Ip), 0)) {\r
+ if (IP4_IS_UNSPECIFIED (Ip) || IP4_IS_LOCAL_BROADCAST (Ip)) {\r
//\r
- // The station address is not a valid IPv4 unicast address.\r
+ // The station address should not be zero or broadcast address.\r
//\r
return EFI_INVALID_PARAMETER;\r
}\r
//\r
// Free the buffer previously allocated to hold the station address.\r
//\r
- gBS->FreePool (OldConfigData->StationAddress);\r
+ FreePool (OldConfigData->StationAddress);\r
}\r
\r
Instance->Configured = FALSE;\r
/**\r
Send out an arp frame using the CachEntry and the ArpOpCode.\r
\r
- @param Instance Pointer to the instance context data.\r
- @param CacheEntry Pointer to the configuration data used to\r
- configure the instance.\r
- @param ArpOpCode The opcode used to send out this Arp frame, either\r
- request or reply.\r
+ @param[in] Instance Pointer to the instance context data.\r
+ @param[in] CacheEntry Pointer to the configuration data used to\r
+ configure the instance.\r
+ @param[in] ArpOpCode The opcode used to send out this Arp frame, either\r
+ request or reply.\r
\r
@return None.\r
\r
Packet = AllocatePool (TotalLength);\r
if (Packet == NULL) {\r
DEBUG ((EFI_D_ERROR, "ArpSendFrame: Allocate memory for Packet failed.\n"));\r
+ ASSERT (Packet != NULL);\r
}\r
\r
TmpPtr = Packet;\r
CLEAN_EXIT:\r
\r
if (Packet != NULL) {\r
- gBS->FreePool (Packet);\r
+ FreePool (Packet);\r
}\r
\r
if (TxData != NULL) {\r
- gBS->FreePool (TxData);\r
+ FreePool (TxData);\r
}\r
\r
if (TxToken->Event != NULL) {\r
gBS->CloseEvent (TxToken->Event);\r
}\r
\r
- gBS->FreePool (TxToken);\r
+ FreePool (TxToken);\r
}\r
\r
\r
SwAddressType, AddressBuffer combination as the matching key, if Force is TRUE,\r
the cache is deleted event it's a static entry.\r
\r
- @param CacheTable Pointer to the cache table to do the deletion.\r
- @param BySwAddress Delete the cache entry by software address or by\r
- hardware address.\r
- @param SwAddressType The software address used to do the deletion.\r
- @param AddressBuffer Pointer to the buffer containing the address to\r
- match for the deletion.\r
- @param Force This deletion is forced or not.\r
+ @param[in] CacheTable Pointer to the cache table to do the deletion.\r
+ @param[in] BySwAddress Delete the cache entry by software address or by\r
+ hardware address.\r
+ @param[in] SwAddressType The software address used to do the deletion.\r
+ @param[in] AddressBuffer Pointer to the buffer containing the address to\r
+ match for the deletion.\r
+ @param[in] Force This deletion is forced or not.\r
\r
@return The count of the deleted cache entries.\r
\r
**/\r
-STATIC\r
UINTN\r
ArpDeleteCacheEntryInTable (\r
IN LIST_ENTRY *CacheTable,\r
//\r
RemoveEntryList (&CacheEntry->List);\r
ASSERT (IsListEmpty (&CacheEntry->UserRequestList));\r
- gBS->FreePool (CacheEntry);\r
+ FreePool (CacheEntry);\r
\r
Count++;\r
}\r
/**\r
Delete cache entries in all the cache tables.\r
\r
- @param Instance Pointer to the instance context data.\r
- @param BySwAddress Delete the cache entry by software address or by\r
- hardware address.\r
- @param AddressBuffer Pointer to the buffer containing the address to\r
- match for the deletion.\r
- @param Force This deletion is forced or not.\r
+ @param[in] Instance Pointer to the instance context data.\r
+ @param[in] BySwAddress Delete the cache entry by software address or by\r
+ hardware address.\r
+ @param[in] AddressBuffer Pointer to the buffer containing the address to\r
+ match for the deletion.\r
+ @param[in] Force This deletion is forced or not.\r
\r
@return The count of the deleted cache entries.\r
\r
/**\r
Cancel the arp request.\r
\r
- @param Instance Pointer to the instance context data.\r
- @param TargetSwAddress Pointer to the buffer containing the target\r
- software address to match the arp request.\r
- @param UserEvent The user event used to notify this request\r
- cancellation.\r
+ @param[in] Instance Pointer to the instance context data.\r
+ @param[in] TargetSwAddress Pointer to the buffer containing the target\r
+ software address to match the arp request.\r
+ @param[in] UserEvent The user event used to notify this request\r
+ cancellation.\r
\r
@return The count of the cancelled requests.\r
\r
// No user requests any more, remove this request cache entry.\r
//\r
RemoveEntryList (&CacheEntry->List);\r
- gBS->FreePool (CacheEntry);\r
+ FreePool (CacheEntry);\r
}\r
}\r
}\r
/**\r
Find the cache entry in the cache table.\r
\r
- @param Instance Pointer to the instance context data.\r
- @param BySwAddress Set to TRUE to look for matching software protocol\r
+ @param[in] Instance Pointer to the instance context data.\r
+ @param[in] BySwAddress Set to TRUE to look for matching software protocol\r
addresses. Set to FALSE to look for matching\r
hardware protocol addresses.\r
- @param AddressBuffer Pointer to address buffer. Set to NULL to match\r
+ @param[in] AddressBuffer Pointer to address buffer. Set to NULL to match\r
all addresses.\r
- @param EntryLength The size of an entry in the entries buffer.\r
- @param EntryCount The number of ARP cache entries that are found by\r
+ @param[out] EntryLength The size of an entry in the entries buffer.\r
+ @param[out] EntryCount The number of ARP cache entries that are found by\r
the specified criteria.\r
- @param Entries Pointer to the buffer that will receive the ARP\r
+ @param[out] Entries Pointer to the buffer that will receive the ARP\r
cache entries.\r
- @param Refresh Set to TRUE to refresh the timeout value of the\r
+ @param[in] Refresh Set to TRUE to refresh the timeout value of the\r
matching ARP cache entry.\r
\r
@retval EFI_SUCCESS The requested ARP cache entries are copied into\r
UINT32 FoundCount;\r
EFI_ARP_FIND_DATA *FindData;\r
LIST_ENTRY *CacheTable;\r
+ UINT32 FoundEntryLength;\r
\r
ArpService = Instance->ArpService;\r
\r
goto CLEAN_EXIT;\r
}\r
\r
+ //\r
+ // Found the entry length, make sure its 8 bytes alignment.\r
+ //\r
+ FoundEntryLength = (((sizeof (EFI_ARP_FIND_DATA) + Instance->ConfigData.SwAddressLength +\r
+ ArpService->SnpMode.HwAddressSize) + 3) & ~(0x3));\r
+\r
if (EntryLength != NULL) {\r
- //\r
- // Return the entry length, make sure its 8 bytes alignment.\r
- //\r
- *EntryLength = (((sizeof (EFI_ARP_FIND_DATA) + Instance->ConfigData.SwAddressLength +\r
- ArpService->SnpMode.HwAddressSize) + 3) & ~(0x3));\r
+ *EntryLength = FoundEntryLength;\r
}\r
\r
if (EntryCount != NULL) {\r
//\r
// Allocate buffer to copy the found entries.\r
//\r
- FindData = AllocatePool (FoundCount * (*EntryLength));\r
+ FindData = AllocatePool (FoundCount * FoundEntryLength);\r
if (FindData == NULL) {\r
DEBUG ((EFI_D_ERROR, "ArpFindCacheEntry: Failed to allocate memory.\n"));\r
Status = EFI_OUT_OF_RESOURCES;\r
//\r
// Set the fields in FindData.\r
//\r
- FindData->Size = *EntryLength;\r
+ FindData->Size = FoundEntryLength;\r
FindData->DenyFlag = (BOOLEAN)(CacheTable == &ArpService->DeniedCacheTable);\r
FindData->StaticFlag = (BOOLEAN)(CacheEntry->DefaultDecayTime == 0);\r
FindData->HwAddressType = ArpService->SnpMode.IfType;\r
//\r
// Slip to the next FindData.\r
//\r
- FindData = (EFI_ARP_FIND_DATA *)((UINT8 *)FindData + *EntryLength);\r
+ FindData = (EFI_ARP_FIND_DATA *)((UINT8 *)FindData + FoundEntryLength);\r
}\r
\r
CLEAN_EXIT:\r