X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FNetwork%2FArpDxe%2FArpImpl.c;fp=MdeModulePkg%2FUniversal%2FNetwork%2FArpDxe%2FArpImpl.c;h=0000000000000000000000000000000000000000;hp=0e9ef103eff9c31d1f34fb5a1feae5bd97021bed;hb=4542f8b8135f1f1ee5654e25139be9769e139ddd;hpb=c0fd7f734e2d33e22215899b40a47b843129541d diff --git a/MdeModulePkg/Universal/Network/ArpDxe/ArpImpl.c b/MdeModulePkg/Universal/Network/ArpDxe/ArpImpl.c deleted file mode 100644 index 0e9ef103ef..0000000000 --- a/MdeModulePkg/Universal/Network/ArpDxe/ArpImpl.c +++ /dev/null @@ -1,1667 +0,0 @@ -/** @file - The implementation of the ARP protocol. - -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
-SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include "ArpImpl.h" - -// -// Global variable of EFI ARP Protocol Interface. -// -EFI_ARP_PROTOCOL mEfiArpProtocolTemplate = { - ArpConfigure, - ArpAdd, - ArpFind, - ArpDelete, - ArpFlush, - ArpRequest, - ArpCancel -}; - - -/** - Initialize the instance context data. - - @param[in] ArpService Pointer to the arp service context data this - instance belongs to. - @param[out] Instance Pointer to the instance context data. - - @return None. - -**/ -VOID -ArpInitInstance ( - IN ARP_SERVICE_DATA *ArpService, - OUT ARP_INSTANCE_DATA *Instance - ) -{ - NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE); - - Instance->Signature = ARP_INSTANCE_DATA_SIGNATURE; - Instance->ArpService = ArpService; - - CopyMem (&Instance->ArpProto, &mEfiArpProtocolTemplate, sizeof (Instance->ArpProto)); - - Instance->Configured = FALSE; - Instance->InDestroy = FALSE; - - InitializeListHead (&Instance->List); -} - - -/** - Process the Arp packets received from Mnp, the procedure conforms to RFC826. - - @param[in] Context Pointer to the context data registerd to the - Event. - - @return None. - -**/ -VOID -EFIAPI -ArpOnFrameRcvdDpc ( - IN VOID *Context - ) -{ - EFI_STATUS Status; - ARP_SERVICE_DATA *ArpService; - EFI_MANAGED_NETWORK_COMPLETION_TOKEN *RxToken; - EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData; - ARP_HEAD *Head; - ARP_ADDRESS ArpAddress; - ARP_CACHE_ENTRY *CacheEntry; - LIST_ENTRY *Entry; - ARP_INSTANCE_DATA *Instance; - EFI_ARP_CONFIG_DATA *ConfigData; - NET_ARP_ADDRESS SenderAddress[2]; - BOOLEAN ProtoMatched; - BOOLEAN IsTarget; - BOOLEAN MergeFlag; - - ArpService = (ARP_SERVICE_DATA *)Context; - NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE); - - RxToken = &ArpService->RxToken; - - if (RxToken->Status == EFI_ABORTED) { - // - // The Token is aborted, possibly by arp itself, just return and the receiving - // process is stopped. - // - return; - } - - if (EFI_ERROR (RxToken->Status)) { - // - // Restart the receiving if any other error Status occurs. - // - goto RESTART_RECEIVE; - } - - // - // Status is EFI_SUCCESS, process the received frame. - // - RxData = RxToken->Packet.RxData; - // - // Sanity check. - // - if (RxData->DataLength < sizeof (ARP_HEAD)) { - // - // Restart the receiving if packet size is not correct. - // - goto RESTART_RECEIVE; - } - - // - // Convert the byte order of the multi-byte fields. - // - Head = (ARP_HEAD *) RxData->PacketData; - Head->HwType = NTOHS (Head->HwType); - Head->ProtoType = NTOHS (Head->ProtoType); - Head->OpCode = NTOHS (Head->OpCode); - - if (RxData->DataLength < (sizeof (ARP_HEAD) + 2 * Head->HwAddrLen + 2 * Head->ProtoAddrLen)) { - goto RESTART_RECEIVE; - } - - if ((Head->HwType != ArpService->SnpMode.IfType) || - (Head->HwAddrLen != ArpService->SnpMode.HwAddressSize) || - (RxData->ProtocolType != ARP_ETHER_PROTO_TYPE)) { - // - // The hardware type or the hardware address length doesn't match. - // There is a sanity check for the protocol type too. - // - goto RECYCLE_RXDATA; - } - - // - // Set the pointers to the addresses contained in the arp packet. - // - ArpAddress.SenderHwAddr = (UINT8 *)(Head + 1); - ArpAddress.SenderProtoAddr = ArpAddress.SenderHwAddr + Head->HwAddrLen; - ArpAddress.TargetHwAddr = ArpAddress.SenderProtoAddr + Head->ProtoAddrLen; - ArpAddress.TargetProtoAddr = ArpAddress.TargetHwAddr + Head->HwAddrLen; - - SenderAddress[Hardware].Type = Head->HwType; - SenderAddress[Hardware].Length = Head->HwAddrLen; - SenderAddress[Hardware].AddressPtr = ArpAddress.SenderHwAddr; - - SenderAddress[Protocol].Type = Head->ProtoType; - SenderAddress[Protocol].Length = Head->ProtoAddrLen; - SenderAddress[Protocol].AddressPtr = ArpAddress.SenderProtoAddr; - - // - // First, check the denied cache table. - // - CacheEntry = ArpFindDeniedCacheEntry ( - ArpService, - &SenderAddress[Protocol], - &SenderAddress[Hardware] - ); - if (CacheEntry != NULL) { - // - // This address (either hardware or protocol address, or both) is configured to - // be a deny entry, silently skip the normal process. - // - goto RECYCLE_RXDATA; - } - - ProtoMatched = FALSE; - IsTarget = FALSE; - Instance = NULL; - NET_LIST_FOR_EACH (Entry, &ArpService->ChildrenList) { - // - // Iterate all the children. - // - Instance = NET_LIST_USER_STRUCT (Entry, ARP_INSTANCE_DATA, List); - NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE); - ConfigData = &Instance->ConfigData; - - if ((Instance->Configured) && - (Head->ProtoType == ConfigData->SwAddressType) && - (Head->ProtoAddrLen == ConfigData->SwAddressLength)) { - // - // The protocol type is matched for the received arp packet. - // - ProtoMatched = TRUE; - if (0 == CompareMem ( - (VOID *)ArpAddress.TargetProtoAddr, - ConfigData->StationAddress, - ConfigData->SwAddressLength - )) { - // - // The arp driver has the target address required by the received arp packet. - // - IsTarget = TRUE; - break; - } - } - } - - if (!ProtoMatched) { - // - // Protocol type unmatchable, skip. - // - goto RECYCLE_RXDATA; - } - - // - // Check whether the sender's address information is already in the cache. - // - MergeFlag = FALSE; - CacheEntry = ArpFindNextCacheEntryInTable ( - &ArpService->ResolvedCacheTable, - NULL, - ByProtoAddress, - &SenderAddress[Protocol], - NULL - ); - if (CacheEntry != NULL) { - // - // Update the entry with the new information. - // - ArpFillAddressInCacheEntry (CacheEntry, &SenderAddress[Hardware], NULL); - CacheEntry->DecayTime = CacheEntry->DefaultDecayTime; - MergeFlag = TRUE; - } - - if (!IsTarget) { - // - // This arp packet isn't targeted to us, skip now. - // - goto RECYCLE_RXDATA; - } - - if (!MergeFlag) { - // - // Add the triplet - // to the translation table. - // - CacheEntry = ArpFindNextCacheEntryInTable ( - &ArpService->PendingRequestTable, - NULL, - ByProtoAddress, - &SenderAddress[Protocol], - NULL - ); - if (CacheEntry == NULL) { - // - // Allocate a new CacheEntry. - // - CacheEntry = ArpAllocCacheEntry (NULL); - if (CacheEntry == NULL) { - goto RECYCLE_RXDATA; - } - } - - if (!IsListEmpty (&CacheEntry->List)) { - RemoveEntryList (&CacheEntry->List); - } - - // - // Fill the addresses into the CacheEntry. - // - ArpFillAddressInCacheEntry ( - CacheEntry, - &SenderAddress[Hardware], - &SenderAddress[Protocol] - ); - - // - // Inform the user. - // - ArpAddressResolved (CacheEntry, NULL, NULL); - - // - // Add this entry into the ResolvedCacheTable - // - InsertHeadList (&ArpService->ResolvedCacheTable, &CacheEntry->List); - } - - if (Head->OpCode == ARP_OPCODE_REQUEST) { - // - // Send back the ARP Reply. If we reach here, Instance is not NULL and CacheEntry - // is not NULL. - // - ArpSendFrame (Instance, CacheEntry, ARP_OPCODE_REPLY); - } - -RECYCLE_RXDATA: - - // - // Signal Mnp to recycle the RxData. - // - gBS->SignalEvent (RxData->RecycleEvent); - -RESTART_RECEIVE: - - // - // Continue to receive packets from Mnp. - // - Status = ArpService->Mnp->Receive (ArpService->Mnp, RxToken); - - DEBUG_CODE ( - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "ArpOnFrameRcvd: ArpService->Mnp->Receive " - "failed, %r\n.", Status)); - } - ); -} - -/** - Queue ArpOnFrameRcvdDpc as a DPC at TPL_CALLBACK. - - @param[in] Event The Event this notify function registered to. - @param[in] Context Pointer to the context data registerd to the - Event. - - @return None. - -**/ -VOID -EFIAPI -ArpOnFrameRcvd ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - // - // Request ArpOnFrameRcvdDpc as a DPC at TPL_CALLBACK - // - QueueDpc (TPL_CALLBACK, ArpOnFrameRcvdDpc, Context); -} - -/** - Process the already sent arp packets. - - @param[in] Context Pointer to the context data registerd to the - Event. - - @return None. - -**/ -VOID -EFIAPI -ArpOnFrameSentDpc ( - IN VOID *Context - ) -{ - EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TxToken; - EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData; - - ASSERT (Context != NULL); - - TxToken = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *)Context; - TxData = TxToken->Packet.TxData; - - DEBUG_CODE ( - if (EFI_ERROR (TxToken->Status)) { - DEBUG ((EFI_D_ERROR, "ArpOnFrameSent: TxToken->Status, %r.\n", TxToken->Status)); - } - ); - - // - // Free the allocated memory and close the event. - // - FreePool (TxData->FragmentTable[0].FragmentBuffer); - FreePool (TxData); - gBS->CloseEvent (TxToken->Event); - FreePool (TxToken); -} - -/** - Request ArpOnFrameSentDpc as a DPC at TPL_CALLBACK. - - @param[in] Event The Event this notify function registered to. - @param[in] Context Pointer to the context data registerd to the - Event. - - @return None. - -**/ -VOID -EFIAPI -ArpOnFrameSent ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - // - // Request ArpOnFrameSentDpc as a DPC at TPL_CALLBACK - // - QueueDpc (TPL_CALLBACK, ArpOnFrameSentDpc, Context); -} - - -/** - Process the arp cache olding and drive the retrying arp requests. - - @param[in] Event The Event this notify function registered to. - @param[in] Context Pointer to the context data registerd to the - Event. - - @return None. - -**/ -VOID -EFIAPI -ArpTimerHandler ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - ARP_SERVICE_DATA *ArpService; - LIST_ENTRY *Entry; - LIST_ENTRY *NextEntry; - LIST_ENTRY *ContextEntry; - ARP_CACHE_ENTRY *CacheEntry; - USER_REQUEST_CONTEXT *RequestContext; - - ASSERT (Context != NULL); - ArpService = (ARP_SERVICE_DATA *)Context; - - // - // Iterate all the pending requests to see whether a retry is needed to send out - // or the request finally fails because the retry time reaches the limitation. - // - NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->PendingRequestTable) { - CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List); - - if (CacheEntry->NextRetryTime <= ARP_PERIODIC_TIMER_INTERVAL) { - // - // Timeout, if we can retry more, send out the request again, otherwise abort - // this request. - // - if (CacheEntry->RetryCount == 0) { - // - // Abort this request. - // - ArpAddressResolved (CacheEntry, NULL, NULL); - ASSERT (IsListEmpty (&CacheEntry->UserRequestList)); - - RemoveEntryList (&CacheEntry->List); - FreePool (CacheEntry); - } else { - // - // resend the ARP request. - // - ASSERT (!IsListEmpty(&CacheEntry->UserRequestList)); - - ContextEntry = CacheEntry->UserRequestList.ForwardLink; - RequestContext = NET_LIST_USER_STRUCT (ContextEntry, USER_REQUEST_CONTEXT, List); - - ArpSendFrame (RequestContext->Instance, CacheEntry, ARP_OPCODE_REQUEST); - - CacheEntry->RetryCount--; - CacheEntry->NextRetryTime = RequestContext->Instance->ConfigData.RetryTimeOut; - } - } else { - // - // Update the NextRetryTime. - // - CacheEntry->NextRetryTime -= ARP_PERIODIC_TIMER_INTERVAL; - } - } - - // - // Check the timeouts for the DeniedCacheTable. - // - NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->DeniedCacheTable) { - CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List); - ASSERT (IsListEmpty (&CacheEntry->UserRequestList)); - - if (CacheEntry->DefaultDecayTime == 0) { - // - // It's a static entry, skip it. - // - continue; - } - - if (CacheEntry->DecayTime <= ARP_PERIODIC_TIMER_INTERVAL) { - // - // Time out, remove it. - // - RemoveEntryList (&CacheEntry->List); - FreePool (CacheEntry); - } else { - // - // Update the DecayTime. - // - CacheEntry->DecayTime -= ARP_PERIODIC_TIMER_INTERVAL; - } - } - - // - // Check the timeouts for the ResolvedCacheTable. - // - NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->ResolvedCacheTable) { - CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List); - ASSERT (IsListEmpty (&CacheEntry->UserRequestList)); - - if (CacheEntry->DefaultDecayTime == 0) { - // - // It's a static entry, skip it. - // - continue; - } - - if (CacheEntry->DecayTime <= ARP_PERIODIC_TIMER_INTERVAL) { - // - // Time out, remove it. - // - RemoveEntryList (&CacheEntry->List); - FreePool (CacheEntry); - } else { - // - // Update the DecayTime. - // - CacheEntry->DecayTime -= ARP_PERIODIC_TIMER_INTERVAL; - } - } -} - - -/** - Match the two NET_ARP_ADDRESSes. - - @param[in] AddressOne Pointer to the first address to match. - @param[in] AddressTwo Pointer to the second address to match. - - @return The two addresses match or not. - -**/ -BOOLEAN -ArpMatchAddress ( - IN NET_ARP_ADDRESS *AddressOne, - IN NET_ARP_ADDRESS *AddressTwo - ) -{ - ASSERT (AddressOne != NULL && AddressTwo != NULL); - - if ((AddressOne->Type != AddressTwo->Type) || - (AddressOne->Length != AddressTwo->Length)) { - // - // Either Type or Length doesn't match. - // - return FALSE; - } - - if ((AddressOne->AddressPtr != NULL) && - (CompareMem ( - AddressOne->AddressPtr, - AddressTwo->AddressPtr, - AddressOne->Length - ) != 0)) { - // - // The address is not the same. - // - return FALSE; - } - - return TRUE; -} - - -/** - Find the CacheEntry which matches the requirements in the specified CacheTable. - - @param[in] CacheTable Pointer to the arp cache table. - @param[in] StartEntry Pointer to the start entry this search begins with - in the cache table. - @param[in] FindOpType The search type. - @param[in] ProtocolAddress Pointer to the protocol address to match. - @param[in] HardwareAddress Pointer to the hardware address to match. - - @return Pointer to the matched arp cache entry, if NULL, no match is found. - -**/ -ARP_CACHE_ENTRY * -ArpFindNextCacheEntryInTable ( - IN LIST_ENTRY *CacheTable, - IN LIST_ENTRY *StartEntry, - IN FIND_OPTYPE FindOpType, - IN NET_ARP_ADDRESS *ProtocolAddress OPTIONAL, - IN NET_ARP_ADDRESS *HardwareAddress OPTIONAL - ) -{ - LIST_ENTRY *Entry; - ARP_CACHE_ENTRY *CacheEntry; - - if (StartEntry == NULL) { - // - // Start from the beginning of the table if no StartEntry is specified. - // - StartEntry = CacheTable; - } - - for (Entry = StartEntry->ForwardLink; Entry != CacheTable; Entry = Entry->ForwardLink) { - CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List); - - if ((FindOpType & MATCH_SW_ADDRESS) != 0) { - // - // Find by the software address. - // - if (!ArpMatchAddress (ProtocolAddress, &CacheEntry->Addresses[Protocol])) { - // - // The ProtocolAddress doesn't match, continue to the next cache entry. - // - continue; - } - } - - if ((FindOpType & MATCH_HW_ADDRESS) != 0) { - // - // Find by the hardware address. - // - if (!ArpMatchAddress (HardwareAddress, &CacheEntry->Addresses[Hardware])) { - // - // The HardwareAddress doesn't match, continue to the next cache entry. - // - continue; - } - } - - // - // The CacheEntry meets the requirements now, return this entry. - // - return CacheEntry; - } - - // - // No matching. - // - return NULL; -} - - -/** - Find the CacheEntry, using ProtocolAddress or HardwareAddress or both, as the keyword, - in the DeniedCacheTable. - - @param[in] ArpService Pointer to the arp service context data. - @param[in] ProtocolAddress Pointer to the protocol address. - @param[in] HardwareAddress Pointer to the hardware address. - - @return Pointer to the matched cache entry, if NULL no match is found. - -**/ -ARP_CACHE_ENTRY * -ArpFindDeniedCacheEntry ( - IN ARP_SERVICE_DATA *ArpService, - IN NET_ARP_ADDRESS *ProtocolAddress OPTIONAL, - IN NET_ARP_ADDRESS *HardwareAddress OPTIONAL - ) -{ - ARP_CACHE_ENTRY *CacheEntry; - - ASSERT ((ProtocolAddress != NULL) || (HardwareAddress != NULL)); - NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE); - - CacheEntry = NULL; - - if ((ProtocolAddress != NULL) && (ProtocolAddress->AddressPtr != NULL)) { - // - // Find the cache entry in the DeniedCacheTable by the protocol address. - // - CacheEntry = ArpFindNextCacheEntryInTable ( - &ArpService->DeniedCacheTable, - NULL, - ByProtoAddress, - ProtocolAddress, - NULL - ); - if (CacheEntry != NULL) { - // - // There is a match. - // - return CacheEntry; - } - } - - if ((HardwareAddress != NULL) && (HardwareAddress->AddressPtr != NULL)) { - // - // Find the cache entry in the DeniedCacheTable by the hardware address. - // - CacheEntry = ArpFindNextCacheEntryInTable ( - &ArpService->DeniedCacheTable, - NULL, - ByHwAddress, - NULL, - HardwareAddress - ); - } - - return CacheEntry; -} - - -/** - Allocate a cache entry and initialize it. - - @param[in] Instance Pointer to the instance context data. - - @return Pointer to the new created cache entry. - -**/ -ARP_CACHE_ENTRY * -ArpAllocCacheEntry ( - IN ARP_INSTANCE_DATA *Instance - ) -{ - ARP_CACHE_ENTRY *CacheEntry; - NET_ARP_ADDRESS *Address; - UINT16 Index; - - // - // Allocate memory for the cache entry. - // - CacheEntry = AllocatePool (sizeof (ARP_CACHE_ENTRY)); - if (CacheEntry == NULL) { - return NULL; - } - - // - // Init the lists. - // - InitializeListHead (&CacheEntry->List); - InitializeListHead (&CacheEntry->UserRequestList); - - for (Index = 0; Index < 2; Index++) { - // - // Init the address pointers to point to the concrete buffer. - // - Address = &CacheEntry->Addresses[Index]; - Address->AddressPtr = Address->Buffer.ProtoAddress; - } - - // - // Zero the hardware address first. - // - ZeroMem (CacheEntry->Addresses[Hardware].AddressPtr, ARP_MAX_HARDWARE_ADDRESS_LEN); - - if (Instance != NULL) { - // - // Inherit the parameters from the instance configuration. - // - CacheEntry->RetryCount = Instance->ConfigData.RetryCount; - CacheEntry->NextRetryTime = Instance->ConfigData.RetryTimeOut; - CacheEntry->DefaultDecayTime = Instance->ConfigData.EntryTimeOut; - CacheEntry->DecayTime = Instance->ConfigData.EntryTimeOut; - } else { - // - // Use the default parameters if this cache entry isn't allocate in a - // instance's scope. - // - CacheEntry->RetryCount = ARP_DEFAULT_RETRY_COUNT; - CacheEntry->NextRetryTime = ARP_DEFAULT_RETRY_INTERVAL; - CacheEntry->DefaultDecayTime = ARP_DEFAULT_TIMEOUT_VALUE; - CacheEntry->DecayTime = ARP_DEFAULT_TIMEOUT_VALUE; - } - - return CacheEntry; -} - - -/** - Turn the CacheEntry into the resolved status. - - @param[in] CacheEntry Pointer to the resolved cache entry. - @param[in] Instance Pointer to the instance context data. - @param[in] UserEvent Pointer to the UserEvent to notify. - - @return The count of notifications sent to the instance. - -**/ -UINTN -ArpAddressResolved ( - IN ARP_CACHE_ENTRY *CacheEntry, - IN ARP_INSTANCE_DATA *Instance OPTIONAL, - IN EFI_EVENT UserEvent OPTIONAL - ) -{ - LIST_ENTRY *Entry; - LIST_ENTRY *NextEntry; - USER_REQUEST_CONTEXT *Context; - UINTN Count; - - Count = 0; - - // - // Iterate all the linked user requests to notify them. - // - NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &CacheEntry->UserRequestList) { - Context = NET_LIST_USER_STRUCT (Entry, USER_REQUEST_CONTEXT, List); - - if (((Instance == NULL) || (Context->Instance == Instance)) && - ((UserEvent == NULL) || (Context->UserRequestEvent == UserEvent))) { - // - // Copy the address to the user-provided buffer and notify the user. - // - CopyMem ( - Context->UserHwAddrBuffer, - CacheEntry->Addresses[Hardware].AddressPtr, - CacheEntry->Addresses[Hardware].Length - ); - gBS->SignalEvent (Context->UserRequestEvent); - - // - // Remove this user request and free the context data. - // - RemoveEntryList (&Context->List); - FreePool (Context); - - Count++; - } - } - - // - // Dispatch the DPCs queued by the NotifyFunction of the Context->UserRequestEvent. - // - DispatchDpc (); - - return Count; -} - - -/** - Fill the addresses in the CacheEntry using the information passed in by - HwAddr and SwAddr. - - @param[in] CacheEntry Pointer to the cache entry. - @param[in] HwAddr Pointer to the software address. - @param[in] SwAddr Pointer to the hardware address. - - @return None. - -**/ -VOID -ArpFillAddressInCacheEntry ( - IN ARP_CACHE_ENTRY *CacheEntry, - IN NET_ARP_ADDRESS *HwAddr OPTIONAL, - IN NET_ARP_ADDRESS *SwAddr OPTIONAL - ) -{ - NET_ARP_ADDRESS *Address[2]; - NET_ARP_ADDRESS *CacheAddress; - UINT32 Index; - - Address[Hardware] = HwAddr; - Address[Protocol] = SwAddr; - - for (Index = 0; Index < 2; Index++) { - if (Address[Index] != NULL) { - // - // Fill the address if the passed in pointer is not NULL. - // - CacheAddress = &CacheEntry->Addresses[Index]; - - CacheAddress->Type = Address[Index]->Type; - CacheAddress->Length = Address[Index]->Length; - - if (Address[Index]->AddressPtr != NULL) { - // - // Copy it if the AddressPtr points to some buffer. - // - CopyMem ( - CacheAddress->AddressPtr, - Address[Index]->AddressPtr, - CacheAddress->Length - ); - } else { - // - // Zero the corresponding address buffer in the CacheEntry. - // - ZeroMem (CacheAddress->AddressPtr, CacheAddress->Length); - } - } - } -} - - -/** - Configure the instance using the ConfigData. ConfigData is already validated. - - @param[in] Instance Pointer to the instance context data to be - configured. - @param[in] ConfigData Pointer to the configuration data used to - configure the instance. - - @retval EFI_SUCCESS The instance is configured with the ConfigData. - @retval EFI_ACCESS_DENIED The instance is already configured and the - ConfigData tries to reset some unchangeable - fields. - @retval EFI_INVALID_PARAMETER The ConfigData provides a non-unicast IPv4 address - when the SwAddressType is IPv4. - @retval EFI_OUT_OF_RESOURCES The instance fails to configure due to memory - limitation. - -**/ -EFI_STATUS -ArpConfigureInstance ( - IN ARP_INSTANCE_DATA *Instance, - IN EFI_ARP_CONFIG_DATA *ConfigData OPTIONAL - ) -{ - EFI_ARP_CONFIG_DATA *OldConfigData; - IP4_ADDR Ip; - - OldConfigData = &Instance->ConfigData; - - if (ConfigData != NULL) { - - if (Instance->Configured) { - // - // The instance is configured, check the unchangeable fields. - // - if ((OldConfigData->SwAddressType != ConfigData->SwAddressType) || - (OldConfigData->SwAddressLength != ConfigData->SwAddressLength) || - (CompareMem ( - OldConfigData->StationAddress, - ConfigData->StationAddress, - OldConfigData->SwAddressLength - ) != 0)) { - // - // Deny the unallowed changes. - // - return EFI_ACCESS_DENIED; - } - } else { - // - // The instance is not configured. - // - - if (ConfigData->SwAddressType == IPV4_ETHER_PROTO_TYPE) { - CopyMem (&Ip, ConfigData->StationAddress, sizeof (IP4_ADDR)); - - if (IP4_IS_UNSPECIFIED (Ip) || IP4_IS_LOCAL_BROADCAST (Ip)) { - // - // The station address should not be zero or broadcast address. - // - return EFI_INVALID_PARAMETER; - } - } - - // - // Save the configuration. - // - CopyMem (OldConfigData, ConfigData, sizeof (*OldConfigData)); - - OldConfigData->StationAddress = AllocatePool (OldConfigData->SwAddressLength); - if (OldConfigData->StationAddress == NULL) { - DEBUG ((EFI_D_ERROR, "ArpConfigInstance: AllocatePool for the StationAddress " - "failed.\n")); - return EFI_OUT_OF_RESOURCES; - } - - // - // Save the StationAddress. - // - CopyMem ( - OldConfigData->StationAddress, - ConfigData->StationAddress, - OldConfigData->SwAddressLength - ); - - // - // Set the state to configured. - // - Instance->Configured = TRUE; - } - - // - // Use the implementation specific values if the following field is zero. - // - OldConfigData->EntryTimeOut = (ConfigData->EntryTimeOut == 0) ? - ARP_DEFAULT_TIMEOUT_VALUE : ConfigData->EntryTimeOut; - - OldConfigData->RetryCount = (ConfigData->RetryCount == 0) ? - ARP_DEFAULT_RETRY_COUNT : ConfigData->RetryCount; - - OldConfigData->RetryTimeOut = (ConfigData->RetryTimeOut == 0) ? - ARP_DEFAULT_RETRY_INTERVAL : ConfigData->RetryTimeOut; - } else { - // - // Reset the configuration. - // - - if (Instance->Configured) { - // - // Cancel the arp requests issued by this instance. - // - Instance->ArpProto.Cancel (&Instance->ArpProto, NULL, NULL); - - // - // Free the buffer previously allocated to hold the station address. - // - FreePool (OldConfigData->StationAddress); - } - - Instance->Configured = FALSE; - } - - return EFI_SUCCESS; -} - - -/** - Send out an arp frame using the CachEntry and the ArpOpCode. - - @param[in] Instance Pointer to the instance context data. - @param[in] CacheEntry Pointer to the configuration data used to - configure the instance. - @param[in] ArpOpCode The opcode used to send out this Arp frame, either - request or reply. - - @return None. - -**/ -VOID -ArpSendFrame ( - IN ARP_INSTANCE_DATA *Instance, - IN ARP_CACHE_ENTRY *CacheEntry, - IN UINT16 ArpOpCode - ) -{ - EFI_STATUS Status; - EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TxToken; - EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData; - UINT32 TotalLength; - UINT8 *Packet; - ARP_SERVICE_DATA *ArpService; - EFI_SIMPLE_NETWORK_MODE *SnpMode; - EFI_ARP_CONFIG_DATA *ConfigData; - UINT8 *TmpPtr; - ARP_HEAD *ArpHead; - - ASSERT ((Instance != NULL) && (CacheEntry != NULL)); - - // - // Allocate memory for the TxToken. - // - TxToken = AllocatePool (sizeof(EFI_MANAGED_NETWORK_COMPLETION_TOKEN)); - if (TxToken == NULL) { - DEBUG ((EFI_D_ERROR, "ArpSendFrame: Allocate memory for TxToken failed.\n")); - return; - } - - TxToken->Event = NULL; - TxData = NULL; - Packet = NULL; - - // - // Create the event for this TxToken. - // - Status = gBS->CreateEvent ( - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - ArpOnFrameSent, - (VOID *)TxToken, - &TxToken->Event - ); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "ArpSendFrame: CreateEvent failed for TxToken->Event.\n")); - goto CLEAN_EXIT; - } - - // - // Allocate memory for the TxData used in the TxToken. - // - TxData = AllocatePool (sizeof(EFI_MANAGED_NETWORK_TRANSMIT_DATA)); - if (TxData == NULL) { - DEBUG ((EFI_D_ERROR, "ArpSendFrame: Allocate memory for TxData failed.\n")); - goto CLEAN_EXIT; - } - - ArpService = Instance->ArpService; - SnpMode = &ArpService->SnpMode; - ConfigData = &Instance->ConfigData; - - // - // Calculate the buffer length for this arp frame. - // - TotalLength = SnpMode->MediaHeaderSize + sizeof (ARP_HEAD) + - 2 * (ConfigData->SwAddressLength + SnpMode->HwAddressSize); - - // - // Allocate buffer for the arp frame. - // - Packet = AllocatePool (TotalLength); - if (Packet == NULL) { - DEBUG ((EFI_D_ERROR, "ArpSendFrame: Allocate memory for Packet failed.\n")); - ASSERT (Packet != NULL); - } - - TmpPtr = Packet; - - // - // The destination MAC address. - // - if (ArpOpCode == ARP_OPCODE_REQUEST) { - CopyMem (TmpPtr, &SnpMode->BroadcastAddress, SnpMode->HwAddressSize); - } else { - CopyMem ( - TmpPtr, - CacheEntry->Addresses[Hardware].AddressPtr, - SnpMode->HwAddressSize - ); - } - TmpPtr += SnpMode->HwAddressSize; - - // - // The source MAC address. - // - CopyMem (TmpPtr, &SnpMode->CurrentAddress, SnpMode->HwAddressSize); - TmpPtr += SnpMode->HwAddressSize; - - // - // The ethernet protocol type. - // - *(UINT16 *)TmpPtr = HTONS (ARP_ETHER_PROTO_TYPE); - TmpPtr += 2; - - // - // The ARP Head. - // - ArpHead = (ARP_HEAD *) TmpPtr; - ArpHead->HwType = HTONS ((UINT16)SnpMode->IfType); - ArpHead->ProtoType = HTONS (ConfigData->SwAddressType); - ArpHead->HwAddrLen = (UINT8)SnpMode->HwAddressSize; - ArpHead->ProtoAddrLen = ConfigData->SwAddressLength; - ArpHead->OpCode = HTONS (ArpOpCode); - TmpPtr += sizeof (ARP_HEAD); - - // - // The sender hardware address. - // - CopyMem (TmpPtr, &SnpMode->CurrentAddress, SnpMode->HwAddressSize); - TmpPtr += SnpMode->HwAddressSize; - - // - // The sender protocol address. - // - CopyMem (TmpPtr, ConfigData->StationAddress, ConfigData->SwAddressLength); - TmpPtr += ConfigData->SwAddressLength; - - // - // The target hardware address. - // - CopyMem ( - TmpPtr, - CacheEntry->Addresses[Hardware].AddressPtr, - SnpMode->HwAddressSize - ); - TmpPtr += SnpMode->HwAddressSize; - - // - // The target protocol address. - // - CopyMem ( - TmpPtr, - CacheEntry->Addresses[Protocol].AddressPtr, - ConfigData->SwAddressLength - ); - - // - // Set all the fields of the TxData. - // - TxData->DestinationAddress = NULL; - TxData->SourceAddress = NULL; - TxData->ProtocolType = 0; - TxData->DataLength = TotalLength - SnpMode->MediaHeaderSize; - TxData->HeaderLength = (UINT16) SnpMode->MediaHeaderSize; - TxData->FragmentCount = 1; - - TxData->FragmentTable[0].FragmentBuffer = Packet; - TxData->FragmentTable[0].FragmentLength = TotalLength; - - // - // Associate the TxData with the TxToken. - // - TxToken->Packet.TxData = TxData; - TxToken->Status = EFI_NOT_READY; - - // - // Send out this arp packet by Mnp. - // - Status = ArpService->Mnp->Transmit (ArpService->Mnp, TxToken); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Mnp->Transmit failed, %r.\n", Status)); - goto CLEAN_EXIT; - } - - return; - -CLEAN_EXIT: - - if (Packet != NULL) { - FreePool (Packet); - } - - if (TxData != NULL) { - FreePool (TxData); - } - - if (TxToken->Event != NULL) { - gBS->CloseEvent (TxToken->Event); - } - - FreePool (TxToken); -} - - -/** - Delete the cache entries in the specified CacheTable, using the BySwAddress, - SwAddressType, AddressBuffer combination as the matching key, if Force is TRUE, - the cache is deleted event it's a static entry. - - @param[in] CacheTable Pointer to the cache table to do the deletion. - @param[in] BySwAddress Delete the cache entry by software address or by - hardware address. - @param[in] SwAddressType The software address used to do the deletion. - @param[in] AddressBuffer Pointer to the buffer containing the address to - match for the deletion. - @param[in] Force This deletion is forced or not. - - @return The count of the deleted cache entries. - -**/ -UINTN -ArpDeleteCacheEntryInTable ( - IN LIST_ENTRY *CacheTable, - IN BOOLEAN BySwAddress, - IN UINT16 SwAddressType, - IN UINT8 *AddressBuffer OPTIONAL, - IN BOOLEAN Force - ) -{ - LIST_ENTRY *Entry; - LIST_ENTRY *NextEntry; - ARP_CACHE_ENTRY *CacheEntry; - UINTN Count; - - Count = 0; - - NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, CacheTable) { - CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List); - - if ((CacheEntry->DefaultDecayTime == 0) && !Force) { - // - // It's a static entry and we are not forced to delete it, skip. - // - continue; - } - - if (BySwAddress) { - if (SwAddressType == CacheEntry->Addresses[Protocol].Type) { - // - // Protocol address type matched. Check the address. - // - if ((AddressBuffer == NULL) || - (CompareMem ( - AddressBuffer, - CacheEntry->Addresses[Protocol].AddressPtr, - CacheEntry->Addresses[Protocol].Length - ) == 0)) { - // - // Address matched. - // - goto MATCHED; - } - } - } else { - if ((AddressBuffer == NULL) || - (CompareMem ( - AddressBuffer, - CacheEntry->Addresses[Hardware].AddressPtr, - CacheEntry->Addresses[Hardware].Length - ) == 0)) { - // - // Address matched. - // - goto MATCHED; - } - } - - continue; - -MATCHED: - - // - // Delete this entry. - // - RemoveEntryList (&CacheEntry->List); - ASSERT (IsListEmpty (&CacheEntry->UserRequestList)); - FreePool (CacheEntry); - - Count++; - } - - return Count; -} - - -/** - Delete cache entries in all the cache tables. - - @param[in] Instance Pointer to the instance context data. - @param[in] BySwAddress Delete the cache entry by software address or by - hardware address. - @param[in] AddressBuffer Pointer to the buffer containing the address to - match for the deletion. - @param[in] Force This deletion is forced or not. - - @return The count of the deleted cache entries. - -**/ -UINTN -ArpDeleteCacheEntry ( - IN ARP_INSTANCE_DATA *Instance, - IN BOOLEAN BySwAddress, - IN UINT8 *AddressBuffer OPTIONAL, - IN BOOLEAN Force - ) -{ - ARP_SERVICE_DATA *ArpService; - UINTN Count; - - NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE); - - ArpService = Instance->ArpService; - - // - // Delete the cache entries in the DeniedCacheTable. - // - Count = ArpDeleteCacheEntryInTable ( - &ArpService->DeniedCacheTable, - BySwAddress, - Instance->ConfigData.SwAddressType, - AddressBuffer, - Force - ); - - // - // Delete the cache entries inthe ResolvedCacheTable. - // - Count += ArpDeleteCacheEntryInTable ( - &ArpService->ResolvedCacheTable, - BySwAddress, - Instance->ConfigData.SwAddressType, - AddressBuffer, - Force - ); - - return Count; -} - - -/** - Cancel the arp request. - - @param[in] Instance Pointer to the instance context data. - @param[in] TargetSwAddress Pointer to the buffer containing the target - software address to match the arp request. - @param[in] UserEvent The user event used to notify this request - cancellation. - - @return The count of the cancelled requests. - -**/ -UINTN -ArpCancelRequest ( - IN ARP_INSTANCE_DATA *Instance, - IN VOID *TargetSwAddress OPTIONAL, - IN EFI_EVENT UserEvent OPTIONAL - ) -{ - ARP_SERVICE_DATA *ArpService; - LIST_ENTRY *Entry; - LIST_ENTRY *NextEntry; - ARP_CACHE_ENTRY *CacheEntry; - UINTN Count; - - NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE); - - ArpService = Instance->ArpService; - - Count = 0; - NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->PendingRequestTable) { - CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List); - - if ((TargetSwAddress == NULL) || - (CompareMem ( - TargetSwAddress, - CacheEntry->Addresses[Protocol].AddressPtr, - CacheEntry->Addresses[Protocol].Length - ) == 0)) { - // - // This request entry matches the TargetSwAddress or all requests are to be - // cancelled as TargetSwAddress is NULL. - // - Count += ArpAddressResolved (CacheEntry, Instance, UserEvent); - - if (IsListEmpty (&CacheEntry->UserRequestList)) { - // - // No user requests any more, remove this request cache entry. - // - RemoveEntryList (&CacheEntry->List); - FreePool (CacheEntry); - } - } - } - - return Count; -} - - -/** - Find the cache entry in the cache table. - - @param[in] Instance Pointer to the instance context data. - @param[in] BySwAddress Set to TRUE to look for matching software protocol - addresses. Set to FALSE to look for matching - hardware protocol addresses. - @param[in] AddressBuffer Pointer to address buffer. Set to NULL to match - all addresses. - @param[out] EntryLength The size of an entry in the entries buffer. - @param[out] EntryCount The number of ARP cache entries that are found by - the specified criteria. - @param[out] Entries Pointer to the buffer that will receive the ARP - cache entries. - @param[in] Refresh Set to TRUE to refresh the timeout value of the - matching ARP cache entry. - - @retval EFI_SUCCESS The requested ARP cache entries are copied into - the buffer. - @retval EFI_NOT_FOUND No matching entries found. - @retval EFI_OUT_OF_RESOURCE There is a memory allocation failure. - -**/ -EFI_STATUS -ArpFindCacheEntry ( - IN ARP_INSTANCE_DATA *Instance, - IN BOOLEAN BySwAddress, - IN VOID *AddressBuffer OPTIONAL, - OUT UINT32 *EntryLength OPTIONAL, - OUT UINT32 *EntryCount OPTIONAL, - OUT EFI_ARP_FIND_DATA **Entries OPTIONAL, - IN BOOLEAN Refresh - ) -{ - EFI_STATUS Status; - ARP_SERVICE_DATA *ArpService; - NET_ARP_ADDRESS MatchAddress; - FIND_OPTYPE FindOpType; - LIST_ENTRY *StartEntry; - ARP_CACHE_ENTRY *CacheEntry; - NET_MAP FoundEntries; - UINT32 FoundCount; - EFI_ARP_FIND_DATA *FindData; - LIST_ENTRY *CacheTable; - UINT32 FoundEntryLength; - - ArpService = Instance->ArpService; - - // - // Init the FounEntries used to hold the found cache entries. - // - NetMapInit (&FoundEntries); - - // - // Set the MatchAddress. - // - if (BySwAddress) { - MatchAddress.Type = Instance->ConfigData.SwAddressType; - MatchAddress.Length = Instance->ConfigData.SwAddressLength; - FindOpType = ByProtoAddress; - } else { - MatchAddress.Type = ArpService->SnpMode.IfType; - MatchAddress.Length = (UINT8)ArpService->SnpMode.HwAddressSize; - FindOpType = ByHwAddress; - } - - MatchAddress.AddressPtr = AddressBuffer; - - // - // Search the DeniedCacheTable - // - StartEntry = NULL; - while (TRUE) { - // - // Try to find the matched entries in the DeniedCacheTable. - // - CacheEntry = ArpFindNextCacheEntryInTable ( - &ArpService->DeniedCacheTable, - StartEntry, - FindOpType, - &MatchAddress, - &MatchAddress - ); - if (CacheEntry == NULL) { - // - // Once the CacheEntry is NULL, there are no more matches. - // - break; - } - - // - // Insert the found entry into the map. - // - NetMapInsertTail ( - &FoundEntries, - (VOID *)CacheEntry, - (VOID *)&ArpService->DeniedCacheTable - ); - - // - // Let the next search start from this cache entry. - // - StartEntry = &CacheEntry->List; - - if (Refresh) { - // - // Refresh the DecayTime if needed. - // - CacheEntry->DecayTime = CacheEntry->DefaultDecayTime; - } - } - - // - // Search the ResolvedCacheTable - // - StartEntry = NULL; - while (TRUE) { - CacheEntry = ArpFindNextCacheEntryInTable ( - &ArpService->ResolvedCacheTable, - StartEntry, - FindOpType, - &MatchAddress, - &MatchAddress - ); - if (CacheEntry == NULL) { - // - // Once the CacheEntry is NULL, there are no more matches. - // - break; - } - - // - // Insert the found entry into the map. - // - NetMapInsertTail ( - &FoundEntries, - (VOID *)CacheEntry, - (VOID *)&ArpService->ResolvedCacheTable - ); - - // - // Let the next search start from this cache entry. - // - StartEntry = &CacheEntry->List; - - if (Refresh) { - // - // Refresh the DecayTime if needed. - // - CacheEntry->DecayTime = CacheEntry->DefaultDecayTime; - } - } - - Status = EFI_SUCCESS; - - FoundCount = (UINT32) NetMapGetCount (&FoundEntries); - if (FoundCount == 0) { - Status = EFI_NOT_FOUND; - goto CLEAN_EXIT; - } - - // - // Found the entry length, make sure its 8 bytes alignment. - // - FoundEntryLength = (((sizeof (EFI_ARP_FIND_DATA) + Instance->ConfigData.SwAddressLength + - ArpService->SnpMode.HwAddressSize) + 3) & ~(0x3)); - - if (EntryLength != NULL) { - *EntryLength = FoundEntryLength; - } - - if (EntryCount != NULL) { - // - // Return the found entry count. - // - *EntryCount = FoundCount; - } - - if (Entries == NULL) { - goto CLEAN_EXIT; - } - - // - // Allocate buffer to copy the found entries. - // - FindData = AllocatePool (FoundCount * FoundEntryLength); - if (FindData == NULL) { - DEBUG ((EFI_D_ERROR, "ArpFindCacheEntry: Failed to allocate memory.\n")); - Status = EFI_OUT_OF_RESOURCES; - goto CLEAN_EXIT; - } - - // - // Return the address to the user. - // - *Entries = FindData; - - // - // Dump the entries. - // - while (!NetMapIsEmpty (&FoundEntries)) { - // - // Get a cache entry from the map. - // - CacheEntry = NetMapRemoveHead (&FoundEntries, (VOID **)&CacheTable); - - // - // Set the fields in FindData. - // - FindData->Size = FoundEntryLength; - FindData->DenyFlag = (BOOLEAN)(CacheTable == &ArpService->DeniedCacheTable); - FindData->StaticFlag = (BOOLEAN)(CacheEntry->DefaultDecayTime == 0); - FindData->HwAddressType = ArpService->SnpMode.IfType; - FindData->SwAddressType = Instance->ConfigData.SwAddressType; - FindData->HwAddressLength = (UINT8)ArpService->SnpMode.HwAddressSize; - FindData->SwAddressLength = Instance->ConfigData.SwAddressLength; - - // - // Copy the software address. - // - CopyMem ( - FindData + 1, - CacheEntry->Addresses[Protocol].AddressPtr, - FindData->SwAddressLength - ); - - // - // Copy the hardware address. - // - CopyMem ( - (UINT8 *)(FindData + 1) + FindData->SwAddressLength, - CacheEntry->Addresses[Hardware].AddressPtr, - FindData->HwAddressLength - ); - - // - // Slip to the next FindData. - // - FindData = (EFI_ARP_FIND_DATA *)((UINT8 *)FindData + FoundEntryLength); - } - -CLEAN_EXIT: - - NetMapClean (&FoundEntries); - - return Status; -} -