12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670 |
- /** @file
- The implementation of the ARP protocol.
- Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
- 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 registered 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 RECYCLE_RXDATA;
- }
- //
- // 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 RECYCLE_RXDATA;
- }
- 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 <protocol type, sender protocol address, sender hardware address>
- // 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_BEGIN ();
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "ArpOnFrameRcvd: ArpService->Mnp->Receive "
- "failed, %r\n.",
- Status
- ));
- }
- DEBUG_CODE_END ();
- }
- /**
- 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 registered 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 registered 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_BEGIN ();
- if (EFI_ERROR (TxToken->Status)) {
- DEBUG ((DEBUG_ERROR, "ArpOnFrameSent: TxToken->Status, %r.\n", TxToken->Status));
- }
- DEBUG_CODE_END ();
- //
- // 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 registered 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 registered 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 ((
- DEBUG_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 CacheEntry 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 ((DEBUG_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 ((DEBUG_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 ((DEBUG_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 ((DEBUG_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 ((DEBUG_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 in the 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 FoundEntries 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 ((DEBUG_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;
- }
|