2 The implementation of the ARP protocol.
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 // Global variable of EFI ARP Protocol Interface.
14 EFI_ARP_PROTOCOL mEfiArpProtocolTemplate
= {
26 Initialize the instance context data.
28 @param[in] ArpService Pointer to the arp service context data this
30 @param[out] Instance Pointer to the instance context data.
37 IN ARP_SERVICE_DATA
*ArpService
,
38 OUT ARP_INSTANCE_DATA
*Instance
41 NET_CHECK_SIGNATURE (ArpService
, ARP_SERVICE_DATA_SIGNATURE
);
43 Instance
->Signature
= ARP_INSTANCE_DATA_SIGNATURE
;
44 Instance
->ArpService
= ArpService
;
46 CopyMem (&Instance
->ArpProto
, &mEfiArpProtocolTemplate
, sizeof (Instance
->ArpProto
));
48 Instance
->Configured
= FALSE
;
49 Instance
->InDestroy
= FALSE
;
51 InitializeListHead (&Instance
->List
);
56 Process the Arp packets received from Mnp, the procedure conforms to RFC826.
58 @param[in] Context Pointer to the context data registerd to the
71 ARP_SERVICE_DATA
*ArpService
;
72 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*RxToken
;
73 EFI_MANAGED_NETWORK_RECEIVE_DATA
*RxData
;
75 ARP_ADDRESS ArpAddress
;
76 ARP_CACHE_ENTRY
*CacheEntry
;
78 ARP_INSTANCE_DATA
*Instance
;
79 EFI_ARP_CONFIG_DATA
*ConfigData
;
80 NET_ARP_ADDRESS SenderAddress
[2];
85 ArpService
= (ARP_SERVICE_DATA
*)Context
;
86 NET_CHECK_SIGNATURE (ArpService
, ARP_SERVICE_DATA_SIGNATURE
);
88 RxToken
= &ArpService
->RxToken
;
90 if (RxToken
->Status
== EFI_ABORTED
) {
92 // The Token is aborted, possibly by arp itself, just return and the receiving
93 // process is stopped.
98 if (EFI_ERROR (RxToken
->Status
)) {
100 // Restart the receiving if any other error Status occurs.
102 goto RESTART_RECEIVE
;
106 // Status is EFI_SUCCESS, process the received frame.
108 RxData
= RxToken
->Packet
.RxData
;
112 if (RxData
->DataLength
< sizeof (ARP_HEAD
)) {
114 // Restart the receiving if packet size is not correct.
116 goto RESTART_RECEIVE
;
120 // Convert the byte order of the multi-byte fields.
122 Head
= (ARP_HEAD
*) RxData
->PacketData
;
123 Head
->HwType
= NTOHS (Head
->HwType
);
124 Head
->ProtoType
= NTOHS (Head
->ProtoType
);
125 Head
->OpCode
= NTOHS (Head
->OpCode
);
127 if (RxData
->DataLength
< (sizeof (ARP_HEAD
) + 2 * Head
->HwAddrLen
+ 2 * Head
->ProtoAddrLen
)) {
128 goto RESTART_RECEIVE
;
131 if ((Head
->HwType
!= ArpService
->SnpMode
.IfType
) ||
132 (Head
->HwAddrLen
!= ArpService
->SnpMode
.HwAddressSize
) ||
133 (RxData
->ProtocolType
!= ARP_ETHER_PROTO_TYPE
)) {
135 // The hardware type or the hardware address length doesn't match.
136 // There is a sanity check for the protocol type too.
142 // Set the pointers to the addresses contained in the arp packet.
144 ArpAddress
.SenderHwAddr
= (UINT8
*)(Head
+ 1);
145 ArpAddress
.SenderProtoAddr
= ArpAddress
.SenderHwAddr
+ Head
->HwAddrLen
;
146 ArpAddress
.TargetHwAddr
= ArpAddress
.SenderProtoAddr
+ Head
->ProtoAddrLen
;
147 ArpAddress
.TargetProtoAddr
= ArpAddress
.TargetHwAddr
+ Head
->HwAddrLen
;
149 SenderAddress
[Hardware
].Type
= Head
->HwType
;
150 SenderAddress
[Hardware
].Length
= Head
->HwAddrLen
;
151 SenderAddress
[Hardware
].AddressPtr
= ArpAddress
.SenderHwAddr
;
153 SenderAddress
[Protocol
].Type
= Head
->ProtoType
;
154 SenderAddress
[Protocol
].Length
= Head
->ProtoAddrLen
;
155 SenderAddress
[Protocol
].AddressPtr
= ArpAddress
.SenderProtoAddr
;
158 // First, check the denied cache table.
160 CacheEntry
= ArpFindDeniedCacheEntry (
162 &SenderAddress
[Protocol
],
163 &SenderAddress
[Hardware
]
165 if (CacheEntry
!= NULL
) {
167 // This address (either hardware or protocol address, or both) is configured to
168 // be a deny entry, silently skip the normal process.
173 ProtoMatched
= FALSE
;
176 NET_LIST_FOR_EACH (Entry
, &ArpService
->ChildrenList
) {
178 // Iterate all the children.
180 Instance
= NET_LIST_USER_STRUCT (Entry
, ARP_INSTANCE_DATA
, List
);
181 NET_CHECK_SIGNATURE (Instance
, ARP_INSTANCE_DATA_SIGNATURE
);
182 ConfigData
= &Instance
->ConfigData
;
184 if ((Instance
->Configured
) &&
185 (Head
->ProtoType
== ConfigData
->SwAddressType
) &&
186 (Head
->ProtoAddrLen
== ConfigData
->SwAddressLength
)) {
188 // The protocol type is matched for the received arp packet.
191 if (0 == CompareMem (
192 (VOID
*)ArpAddress
.TargetProtoAddr
,
193 ConfigData
->StationAddress
,
194 ConfigData
->SwAddressLength
197 // The arp driver has the target address required by the received arp packet.
207 // Protocol type unmatchable, skip.
213 // Check whether the sender's address information is already in the cache.
216 CacheEntry
= ArpFindNextCacheEntryInTable (
217 &ArpService
->ResolvedCacheTable
,
220 &SenderAddress
[Protocol
],
223 if (CacheEntry
!= NULL
) {
225 // Update the entry with the new information.
227 ArpFillAddressInCacheEntry (CacheEntry
, &SenderAddress
[Hardware
], NULL
);
228 CacheEntry
->DecayTime
= CacheEntry
->DefaultDecayTime
;
234 // This arp packet isn't targeted to us, skip now.
241 // Add the triplet <protocol type, sender protocol address, sender hardware address>
242 // to the translation table.
244 CacheEntry
= ArpFindNextCacheEntryInTable (
245 &ArpService
->PendingRequestTable
,
248 &SenderAddress
[Protocol
],
251 if (CacheEntry
== NULL
) {
253 // Allocate a new CacheEntry.
255 CacheEntry
= ArpAllocCacheEntry (NULL
);
256 if (CacheEntry
== NULL
) {
261 if (!IsListEmpty (&CacheEntry
->List
)) {
262 RemoveEntryList (&CacheEntry
->List
);
266 // Fill the addresses into the CacheEntry.
268 ArpFillAddressInCacheEntry (
270 &SenderAddress
[Hardware
],
271 &SenderAddress
[Protocol
]
277 ArpAddressResolved (CacheEntry
, NULL
, NULL
);
280 // Add this entry into the ResolvedCacheTable
282 InsertHeadList (&ArpService
->ResolvedCacheTable
, &CacheEntry
->List
);
285 if (Head
->OpCode
== ARP_OPCODE_REQUEST
) {
287 // Send back the ARP Reply. If we reach here, Instance is not NULL and CacheEntry
290 ArpSendFrame (Instance
, CacheEntry
, ARP_OPCODE_REPLY
);
296 // Signal Mnp to recycle the RxData.
298 gBS
->SignalEvent (RxData
->RecycleEvent
);
303 // Continue to receive packets from Mnp.
305 Status
= ArpService
->Mnp
->Receive (ArpService
->Mnp
, RxToken
);
308 if (EFI_ERROR (Status
)) {
309 DEBUG ((EFI_D_ERROR
, "ArpOnFrameRcvd: ArpService->Mnp->Receive "
310 "failed, %r\n.", Status
));
316 Queue ArpOnFrameRcvdDpc as a DPC at TPL_CALLBACK.
318 @param[in] Event The Event this notify function registered to.
319 @param[in] Context Pointer to the context data registerd to the
333 // Request ArpOnFrameRcvdDpc as a DPC at TPL_CALLBACK
335 QueueDpc (TPL_CALLBACK
, ArpOnFrameRcvdDpc
, Context
);
339 Process the already sent arp packets.
341 @param[in] Context Pointer to the context data registerd to the
353 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TxToken
;
354 EFI_MANAGED_NETWORK_TRANSMIT_DATA
*TxData
;
356 ASSERT (Context
!= NULL
);
358 TxToken
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*)Context
;
359 TxData
= TxToken
->Packet
.TxData
;
362 if (EFI_ERROR (TxToken
->Status
)) {
363 DEBUG ((EFI_D_ERROR
, "ArpOnFrameSent: TxToken->Status, %r.\n", TxToken
->Status
));
368 // Free the allocated memory and close the event.
370 FreePool (TxData
->FragmentTable
[0].FragmentBuffer
);
372 gBS
->CloseEvent (TxToken
->Event
);
377 Request ArpOnFrameSentDpc as a DPC at TPL_CALLBACK.
379 @param[in] Event The Event this notify function registered to.
380 @param[in] Context Pointer to the context data registerd to the
394 // Request ArpOnFrameSentDpc as a DPC at TPL_CALLBACK
396 QueueDpc (TPL_CALLBACK
, ArpOnFrameSentDpc
, Context
);
401 Process the arp cache olding and drive the retrying arp requests.
403 @param[in] Event The Event this notify function registered to.
404 @param[in] Context Pointer to the context data registerd to the
417 ARP_SERVICE_DATA
*ArpService
;
419 LIST_ENTRY
*NextEntry
;
420 LIST_ENTRY
*ContextEntry
;
421 ARP_CACHE_ENTRY
*CacheEntry
;
422 USER_REQUEST_CONTEXT
*RequestContext
;
424 ASSERT (Context
!= NULL
);
425 ArpService
= (ARP_SERVICE_DATA
*)Context
;
428 // Iterate all the pending requests to see whether a retry is needed to send out
429 // or the request finally fails because the retry time reaches the limitation.
431 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &ArpService
->PendingRequestTable
) {
432 CacheEntry
= NET_LIST_USER_STRUCT (Entry
, ARP_CACHE_ENTRY
, List
);
434 if (CacheEntry
->NextRetryTime
<= ARP_PERIODIC_TIMER_INTERVAL
) {
436 // Timeout, if we can retry more, send out the request again, otherwise abort
439 if (CacheEntry
->RetryCount
== 0) {
441 // Abort this request.
443 ArpAddressResolved (CacheEntry
, NULL
, NULL
);
444 ASSERT (IsListEmpty (&CacheEntry
->UserRequestList
));
446 RemoveEntryList (&CacheEntry
->List
);
447 FreePool (CacheEntry
);
450 // resend the ARP request.
452 ASSERT (!IsListEmpty(&CacheEntry
->UserRequestList
));
454 ContextEntry
= CacheEntry
->UserRequestList
.ForwardLink
;
455 RequestContext
= NET_LIST_USER_STRUCT (ContextEntry
, USER_REQUEST_CONTEXT
, List
);
457 ArpSendFrame (RequestContext
->Instance
, CacheEntry
, ARP_OPCODE_REQUEST
);
459 CacheEntry
->RetryCount
--;
460 CacheEntry
->NextRetryTime
= RequestContext
->Instance
->ConfigData
.RetryTimeOut
;
464 // Update the NextRetryTime.
466 CacheEntry
->NextRetryTime
-= ARP_PERIODIC_TIMER_INTERVAL
;
471 // Check the timeouts for the DeniedCacheTable.
473 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &ArpService
->DeniedCacheTable
) {
474 CacheEntry
= NET_LIST_USER_STRUCT (Entry
, ARP_CACHE_ENTRY
, List
);
475 ASSERT (IsListEmpty (&CacheEntry
->UserRequestList
));
477 if (CacheEntry
->DefaultDecayTime
== 0) {
479 // It's a static entry, skip it.
484 if (CacheEntry
->DecayTime
<= ARP_PERIODIC_TIMER_INTERVAL
) {
486 // Time out, remove it.
488 RemoveEntryList (&CacheEntry
->List
);
489 FreePool (CacheEntry
);
492 // Update the DecayTime.
494 CacheEntry
->DecayTime
-= ARP_PERIODIC_TIMER_INTERVAL
;
499 // Check the timeouts for the ResolvedCacheTable.
501 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &ArpService
->ResolvedCacheTable
) {
502 CacheEntry
= NET_LIST_USER_STRUCT (Entry
, ARP_CACHE_ENTRY
, List
);
503 ASSERT (IsListEmpty (&CacheEntry
->UserRequestList
));
505 if (CacheEntry
->DefaultDecayTime
== 0) {
507 // It's a static entry, skip it.
512 if (CacheEntry
->DecayTime
<= ARP_PERIODIC_TIMER_INTERVAL
) {
514 // Time out, remove it.
516 RemoveEntryList (&CacheEntry
->List
);
517 FreePool (CacheEntry
);
520 // Update the DecayTime.
522 CacheEntry
->DecayTime
-= ARP_PERIODIC_TIMER_INTERVAL
;
529 Match the two NET_ARP_ADDRESSes.
531 @param[in] AddressOne Pointer to the first address to match.
532 @param[in] AddressTwo Pointer to the second address to match.
534 @return The two addresses match or not.
539 IN NET_ARP_ADDRESS
*AddressOne
,
540 IN NET_ARP_ADDRESS
*AddressTwo
543 ASSERT (AddressOne
!= NULL
&& AddressTwo
!= NULL
);
545 if ((AddressOne
->Type
!= AddressTwo
->Type
) ||
546 (AddressOne
->Length
!= AddressTwo
->Length
)) {
548 // Either Type or Length doesn't match.
553 if ((AddressOne
->AddressPtr
!= NULL
) &&
555 AddressOne
->AddressPtr
,
556 AddressTwo
->AddressPtr
,
560 // The address is not the same.
570 Find the CacheEntry which matches the requirements in the specified CacheTable.
572 @param[in] CacheTable Pointer to the arp cache table.
573 @param[in] StartEntry Pointer to the start entry this search begins with
575 @param[in] FindOpType The search type.
576 @param[in] ProtocolAddress Pointer to the protocol address to match.
577 @param[in] HardwareAddress Pointer to the hardware address to match.
579 @return Pointer to the matched arp cache entry, if NULL, no match is found.
583 ArpFindNextCacheEntryInTable (
584 IN LIST_ENTRY
*CacheTable
,
585 IN LIST_ENTRY
*StartEntry
,
586 IN FIND_OPTYPE FindOpType
,
587 IN NET_ARP_ADDRESS
*ProtocolAddress OPTIONAL
,
588 IN NET_ARP_ADDRESS
*HardwareAddress OPTIONAL
592 ARP_CACHE_ENTRY
*CacheEntry
;
594 if (StartEntry
== NULL
) {
596 // Start from the beginning of the table if no StartEntry is specified.
598 StartEntry
= CacheTable
;
601 for (Entry
= StartEntry
->ForwardLink
; Entry
!= CacheTable
; Entry
= Entry
->ForwardLink
) {
602 CacheEntry
= NET_LIST_USER_STRUCT (Entry
, ARP_CACHE_ENTRY
, List
);
604 if ((FindOpType
& MATCH_SW_ADDRESS
) != 0) {
606 // Find by the software address.
608 if (!ArpMatchAddress (ProtocolAddress
, &CacheEntry
->Addresses
[Protocol
])) {
610 // The ProtocolAddress doesn't match, continue to the next cache entry.
616 if ((FindOpType
& MATCH_HW_ADDRESS
) != 0) {
618 // Find by the hardware address.
620 if (!ArpMatchAddress (HardwareAddress
, &CacheEntry
->Addresses
[Hardware
])) {
622 // The HardwareAddress doesn't match, continue to the next cache entry.
629 // The CacheEntry meets the requirements now, return this entry.
642 Find the CacheEntry, using ProtocolAddress or HardwareAddress or both, as the keyword,
643 in the DeniedCacheTable.
645 @param[in] ArpService Pointer to the arp service context data.
646 @param[in] ProtocolAddress Pointer to the protocol address.
647 @param[in] HardwareAddress Pointer to the hardware address.
649 @return Pointer to the matched cache entry, if NULL no match is found.
653 ArpFindDeniedCacheEntry (
654 IN ARP_SERVICE_DATA
*ArpService
,
655 IN NET_ARP_ADDRESS
*ProtocolAddress OPTIONAL
,
656 IN NET_ARP_ADDRESS
*HardwareAddress OPTIONAL
659 ARP_CACHE_ENTRY
*CacheEntry
;
661 ASSERT ((ProtocolAddress
!= NULL
) || (HardwareAddress
!= NULL
));
662 NET_CHECK_SIGNATURE (ArpService
, ARP_SERVICE_DATA_SIGNATURE
);
666 if ((ProtocolAddress
!= NULL
) && (ProtocolAddress
->AddressPtr
!= NULL
)) {
668 // Find the cache entry in the DeniedCacheTable by the protocol address.
670 CacheEntry
= ArpFindNextCacheEntryInTable (
671 &ArpService
->DeniedCacheTable
,
677 if (CacheEntry
!= NULL
) {
685 if ((HardwareAddress
!= NULL
) && (HardwareAddress
->AddressPtr
!= NULL
)) {
687 // Find the cache entry in the DeniedCacheTable by the hardware address.
689 CacheEntry
= ArpFindNextCacheEntryInTable (
690 &ArpService
->DeniedCacheTable
,
703 Allocate a cache entry and initialize it.
705 @param[in] Instance Pointer to the instance context data.
707 @return Pointer to the new created cache entry.
712 IN ARP_INSTANCE_DATA
*Instance
715 ARP_CACHE_ENTRY
*CacheEntry
;
716 NET_ARP_ADDRESS
*Address
;
720 // Allocate memory for the cache entry.
722 CacheEntry
= AllocatePool (sizeof (ARP_CACHE_ENTRY
));
723 if (CacheEntry
== NULL
) {
730 InitializeListHead (&CacheEntry
->List
);
731 InitializeListHead (&CacheEntry
->UserRequestList
);
733 for (Index
= 0; Index
< 2; Index
++) {
735 // Init the address pointers to point to the concrete buffer.
737 Address
= &CacheEntry
->Addresses
[Index
];
738 Address
->AddressPtr
= Address
->Buffer
.ProtoAddress
;
742 // Zero the hardware address first.
744 ZeroMem (CacheEntry
->Addresses
[Hardware
].AddressPtr
, ARP_MAX_HARDWARE_ADDRESS_LEN
);
746 if (Instance
!= NULL
) {
748 // Inherit the parameters from the instance configuration.
750 CacheEntry
->RetryCount
= Instance
->ConfigData
.RetryCount
;
751 CacheEntry
->NextRetryTime
= Instance
->ConfigData
.RetryTimeOut
;
752 CacheEntry
->DefaultDecayTime
= Instance
->ConfigData
.EntryTimeOut
;
753 CacheEntry
->DecayTime
= Instance
->ConfigData
.EntryTimeOut
;
756 // Use the default parameters if this cache entry isn't allocate in a
759 CacheEntry
->RetryCount
= ARP_DEFAULT_RETRY_COUNT
;
760 CacheEntry
->NextRetryTime
= ARP_DEFAULT_RETRY_INTERVAL
;
761 CacheEntry
->DefaultDecayTime
= ARP_DEFAULT_TIMEOUT_VALUE
;
762 CacheEntry
->DecayTime
= ARP_DEFAULT_TIMEOUT_VALUE
;
770 Turn the CacheEntry into the resolved status.
772 @param[in] CacheEntry Pointer to the resolved cache entry.
773 @param[in] Instance Pointer to the instance context data.
774 @param[in] UserEvent Pointer to the UserEvent to notify.
776 @return The count of notifications sent to the instance.
781 IN ARP_CACHE_ENTRY
*CacheEntry
,
782 IN ARP_INSTANCE_DATA
*Instance OPTIONAL
,
783 IN EFI_EVENT UserEvent OPTIONAL
787 LIST_ENTRY
*NextEntry
;
788 USER_REQUEST_CONTEXT
*Context
;
794 // Iterate all the linked user requests to notify them.
796 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &CacheEntry
->UserRequestList
) {
797 Context
= NET_LIST_USER_STRUCT (Entry
, USER_REQUEST_CONTEXT
, List
);
799 if (((Instance
== NULL
) || (Context
->Instance
== Instance
)) &&
800 ((UserEvent
== NULL
) || (Context
->UserRequestEvent
== UserEvent
))) {
802 // Copy the address to the user-provided buffer and notify the user.
805 Context
->UserHwAddrBuffer
,
806 CacheEntry
->Addresses
[Hardware
].AddressPtr
,
807 CacheEntry
->Addresses
[Hardware
].Length
809 gBS
->SignalEvent (Context
->UserRequestEvent
);
812 // Remove this user request and free the context data.
814 RemoveEntryList (&Context
->List
);
822 // Dispatch the DPCs queued by the NotifyFunction of the Context->UserRequestEvent.
831 Fill the addresses in the CacheEntry using the information passed in by
834 @param[in] CacheEntry Pointer to the cache entry.
835 @param[in] HwAddr Pointer to the software address.
836 @param[in] SwAddr Pointer to the hardware address.
842 ArpFillAddressInCacheEntry (
843 IN ARP_CACHE_ENTRY
*CacheEntry
,
844 IN NET_ARP_ADDRESS
*HwAddr OPTIONAL
,
845 IN NET_ARP_ADDRESS
*SwAddr OPTIONAL
848 NET_ARP_ADDRESS
*Address
[2];
849 NET_ARP_ADDRESS
*CacheAddress
;
852 Address
[Hardware
] = HwAddr
;
853 Address
[Protocol
] = SwAddr
;
855 for (Index
= 0; Index
< 2; Index
++) {
856 if (Address
[Index
] != NULL
) {
858 // Fill the address if the passed in pointer is not NULL.
860 CacheAddress
= &CacheEntry
->Addresses
[Index
];
862 CacheAddress
->Type
= Address
[Index
]->Type
;
863 CacheAddress
->Length
= Address
[Index
]->Length
;
865 if (Address
[Index
]->AddressPtr
!= NULL
) {
867 // Copy it if the AddressPtr points to some buffer.
870 CacheAddress
->AddressPtr
,
871 Address
[Index
]->AddressPtr
,
876 // Zero the corresponding address buffer in the CacheEntry.
878 ZeroMem (CacheAddress
->AddressPtr
, CacheAddress
->Length
);
886 Configure the instance using the ConfigData. ConfigData is already validated.
888 @param[in] Instance Pointer to the instance context data to be
890 @param[in] ConfigData Pointer to the configuration data used to
891 configure the instance.
893 @retval EFI_SUCCESS The instance is configured with the ConfigData.
894 @retval EFI_ACCESS_DENIED The instance is already configured and the
895 ConfigData tries to reset some unchangeable
897 @retval EFI_INVALID_PARAMETER The ConfigData provides a non-unicast IPv4 address
898 when the SwAddressType is IPv4.
899 @retval EFI_OUT_OF_RESOURCES The instance fails to configure due to memory
904 ArpConfigureInstance (
905 IN ARP_INSTANCE_DATA
*Instance
,
906 IN EFI_ARP_CONFIG_DATA
*ConfigData OPTIONAL
909 EFI_ARP_CONFIG_DATA
*OldConfigData
;
912 OldConfigData
= &Instance
->ConfigData
;
914 if (ConfigData
!= NULL
) {
916 if (Instance
->Configured
) {
918 // The instance is configured, check the unchangeable fields.
920 if ((OldConfigData
->SwAddressType
!= ConfigData
->SwAddressType
) ||
921 (OldConfigData
->SwAddressLength
!= ConfigData
->SwAddressLength
) ||
923 OldConfigData
->StationAddress
,
924 ConfigData
->StationAddress
,
925 OldConfigData
->SwAddressLength
928 // Deny the unallowed changes.
930 return EFI_ACCESS_DENIED
;
934 // The instance is not configured.
937 if (ConfigData
->SwAddressType
== IPV4_ETHER_PROTO_TYPE
) {
938 CopyMem (&Ip
, ConfigData
->StationAddress
, sizeof (IP4_ADDR
));
940 if (IP4_IS_UNSPECIFIED (Ip
) || IP4_IS_LOCAL_BROADCAST (Ip
)) {
942 // The station address should not be zero or broadcast address.
944 return EFI_INVALID_PARAMETER
;
949 // Save the configuration.
951 CopyMem (OldConfigData
, ConfigData
, sizeof (*OldConfigData
));
953 OldConfigData
->StationAddress
= AllocatePool (OldConfigData
->SwAddressLength
);
954 if (OldConfigData
->StationAddress
== NULL
) {
955 DEBUG ((EFI_D_ERROR
, "ArpConfigInstance: AllocatePool for the StationAddress "
957 return EFI_OUT_OF_RESOURCES
;
961 // Save the StationAddress.
964 OldConfigData
->StationAddress
,
965 ConfigData
->StationAddress
,
966 OldConfigData
->SwAddressLength
970 // Set the state to configured.
972 Instance
->Configured
= TRUE
;
976 // Use the implementation specific values if the following field is zero.
978 OldConfigData
->EntryTimeOut
= (ConfigData
->EntryTimeOut
== 0) ?
979 ARP_DEFAULT_TIMEOUT_VALUE
: ConfigData
->EntryTimeOut
;
981 OldConfigData
->RetryCount
= (ConfigData
->RetryCount
== 0) ?
982 ARP_DEFAULT_RETRY_COUNT
: ConfigData
->RetryCount
;
984 OldConfigData
->RetryTimeOut
= (ConfigData
->RetryTimeOut
== 0) ?
985 ARP_DEFAULT_RETRY_INTERVAL
: ConfigData
->RetryTimeOut
;
988 // Reset the configuration.
991 if (Instance
->Configured
) {
993 // Cancel the arp requests issued by this instance.
995 Instance
->ArpProto
.Cancel (&Instance
->ArpProto
, NULL
, NULL
);
998 // Free the buffer previously allocated to hold the station address.
1000 FreePool (OldConfigData
->StationAddress
);
1003 Instance
->Configured
= FALSE
;
1011 Send out an arp frame using the CachEntry and the ArpOpCode.
1013 @param[in] Instance Pointer to the instance context data.
1014 @param[in] CacheEntry Pointer to the configuration data used to
1015 configure the instance.
1016 @param[in] ArpOpCode The opcode used to send out this Arp frame, either
1024 IN ARP_INSTANCE_DATA
*Instance
,
1025 IN ARP_CACHE_ENTRY
*CacheEntry
,
1030 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TxToken
;
1031 EFI_MANAGED_NETWORK_TRANSMIT_DATA
*TxData
;
1034 ARP_SERVICE_DATA
*ArpService
;
1035 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
1036 EFI_ARP_CONFIG_DATA
*ConfigData
;
1040 ASSERT ((Instance
!= NULL
) && (CacheEntry
!= NULL
));
1043 // Allocate memory for the TxToken.
1045 TxToken
= AllocatePool (sizeof(EFI_MANAGED_NETWORK_COMPLETION_TOKEN
));
1046 if (TxToken
== NULL
) {
1047 DEBUG ((EFI_D_ERROR
, "ArpSendFrame: Allocate memory for TxToken failed.\n"));
1051 TxToken
->Event
= NULL
;
1056 // Create the event for this TxToken.
1058 Status
= gBS
->CreateEvent (
1065 if (EFI_ERROR (Status
)) {
1066 DEBUG ((EFI_D_ERROR
, "ArpSendFrame: CreateEvent failed for TxToken->Event.\n"));
1071 // Allocate memory for the TxData used in the TxToken.
1073 TxData
= AllocatePool (sizeof(EFI_MANAGED_NETWORK_TRANSMIT_DATA
));
1074 if (TxData
== NULL
) {
1075 DEBUG ((EFI_D_ERROR
, "ArpSendFrame: Allocate memory for TxData failed.\n"));
1079 ArpService
= Instance
->ArpService
;
1080 SnpMode
= &ArpService
->SnpMode
;
1081 ConfigData
= &Instance
->ConfigData
;
1084 // Calculate the buffer length for this arp frame.
1086 TotalLength
= SnpMode
->MediaHeaderSize
+ sizeof (ARP_HEAD
) +
1087 2 * (ConfigData
->SwAddressLength
+ SnpMode
->HwAddressSize
);
1090 // Allocate buffer for the arp frame.
1092 Packet
= AllocatePool (TotalLength
);
1093 if (Packet
== NULL
) {
1094 DEBUG ((EFI_D_ERROR
, "ArpSendFrame: Allocate memory for Packet failed.\n"));
1095 ASSERT (Packet
!= NULL
);
1101 // The destination MAC address.
1103 if (ArpOpCode
== ARP_OPCODE_REQUEST
) {
1104 CopyMem (TmpPtr
, &SnpMode
->BroadcastAddress
, SnpMode
->HwAddressSize
);
1108 CacheEntry
->Addresses
[Hardware
].AddressPtr
,
1109 SnpMode
->HwAddressSize
1112 TmpPtr
+= SnpMode
->HwAddressSize
;
1115 // The source MAC address.
1117 CopyMem (TmpPtr
, &SnpMode
->CurrentAddress
, SnpMode
->HwAddressSize
);
1118 TmpPtr
+= SnpMode
->HwAddressSize
;
1121 // The ethernet protocol type.
1123 *(UINT16
*)TmpPtr
= HTONS (ARP_ETHER_PROTO_TYPE
);
1129 ArpHead
= (ARP_HEAD
*) TmpPtr
;
1130 ArpHead
->HwType
= HTONS ((UINT16
)SnpMode
->IfType
);
1131 ArpHead
->ProtoType
= HTONS (ConfigData
->SwAddressType
);
1132 ArpHead
->HwAddrLen
= (UINT8
)SnpMode
->HwAddressSize
;
1133 ArpHead
->ProtoAddrLen
= ConfigData
->SwAddressLength
;
1134 ArpHead
->OpCode
= HTONS (ArpOpCode
);
1135 TmpPtr
+= sizeof (ARP_HEAD
);
1138 // The sender hardware address.
1140 CopyMem (TmpPtr
, &SnpMode
->CurrentAddress
, SnpMode
->HwAddressSize
);
1141 TmpPtr
+= SnpMode
->HwAddressSize
;
1144 // The sender protocol address.
1146 CopyMem (TmpPtr
, ConfigData
->StationAddress
, ConfigData
->SwAddressLength
);
1147 TmpPtr
+= ConfigData
->SwAddressLength
;
1150 // The target hardware address.
1154 CacheEntry
->Addresses
[Hardware
].AddressPtr
,
1155 SnpMode
->HwAddressSize
1157 TmpPtr
+= SnpMode
->HwAddressSize
;
1160 // The target protocol address.
1164 CacheEntry
->Addresses
[Protocol
].AddressPtr
,
1165 ConfigData
->SwAddressLength
1169 // Set all the fields of the TxData.
1171 TxData
->DestinationAddress
= NULL
;
1172 TxData
->SourceAddress
= NULL
;
1173 TxData
->ProtocolType
= 0;
1174 TxData
->DataLength
= TotalLength
- SnpMode
->MediaHeaderSize
;
1175 TxData
->HeaderLength
= (UINT16
) SnpMode
->MediaHeaderSize
;
1176 TxData
->FragmentCount
= 1;
1178 TxData
->FragmentTable
[0].FragmentBuffer
= Packet
;
1179 TxData
->FragmentTable
[0].FragmentLength
= TotalLength
;
1182 // Associate the TxData with the TxToken.
1184 TxToken
->Packet
.TxData
= TxData
;
1185 TxToken
->Status
= EFI_NOT_READY
;
1188 // Send out this arp packet by Mnp.
1190 Status
= ArpService
->Mnp
->Transmit (ArpService
->Mnp
, TxToken
);
1191 if (EFI_ERROR (Status
)) {
1192 DEBUG ((EFI_D_ERROR
, "Mnp->Transmit failed, %r.\n", Status
));
1200 if (Packet
!= NULL
) {
1204 if (TxData
!= NULL
) {
1208 if (TxToken
->Event
!= NULL
) {
1209 gBS
->CloseEvent (TxToken
->Event
);
1217 Delete the cache entries in the specified CacheTable, using the BySwAddress,
1218 SwAddressType, AddressBuffer combination as the matching key, if Force is TRUE,
1219 the cache is deleted event it's a static entry.
1221 @param[in] CacheTable Pointer to the cache table to do the deletion.
1222 @param[in] BySwAddress Delete the cache entry by software address or by
1224 @param[in] SwAddressType The software address used to do the deletion.
1225 @param[in] AddressBuffer Pointer to the buffer containing the address to
1226 match for the deletion.
1227 @param[in] Force This deletion is forced or not.
1229 @return The count of the deleted cache entries.
1233 ArpDeleteCacheEntryInTable (
1234 IN LIST_ENTRY
*CacheTable
,
1235 IN BOOLEAN BySwAddress
,
1236 IN UINT16 SwAddressType
,
1237 IN UINT8
*AddressBuffer OPTIONAL
,
1242 LIST_ENTRY
*NextEntry
;
1243 ARP_CACHE_ENTRY
*CacheEntry
;
1248 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, CacheTable
) {
1249 CacheEntry
= NET_LIST_USER_STRUCT (Entry
, ARP_CACHE_ENTRY
, List
);
1251 if ((CacheEntry
->DefaultDecayTime
== 0) && !Force
) {
1253 // It's a static entry and we are not forced to delete it, skip.
1259 if (SwAddressType
== CacheEntry
->Addresses
[Protocol
].Type
) {
1261 // Protocol address type matched. Check the address.
1263 if ((AddressBuffer
== NULL
) ||
1266 CacheEntry
->Addresses
[Protocol
].AddressPtr
,
1267 CacheEntry
->Addresses
[Protocol
].Length
1276 if ((AddressBuffer
== NULL
) ||
1279 CacheEntry
->Addresses
[Hardware
].AddressPtr
,
1280 CacheEntry
->Addresses
[Hardware
].Length
1294 // Delete this entry.
1296 RemoveEntryList (&CacheEntry
->List
);
1297 ASSERT (IsListEmpty (&CacheEntry
->UserRequestList
));
1298 FreePool (CacheEntry
);
1308 Delete cache entries in all the cache tables.
1310 @param[in] Instance Pointer to the instance context data.
1311 @param[in] BySwAddress Delete the cache entry by software address or by
1313 @param[in] AddressBuffer Pointer to the buffer containing the address to
1314 match for the deletion.
1315 @param[in] Force This deletion is forced or not.
1317 @return The count of the deleted cache entries.
1321 ArpDeleteCacheEntry (
1322 IN ARP_INSTANCE_DATA
*Instance
,
1323 IN BOOLEAN BySwAddress
,
1324 IN UINT8
*AddressBuffer OPTIONAL
,
1328 ARP_SERVICE_DATA
*ArpService
;
1331 NET_CHECK_SIGNATURE (Instance
, ARP_INSTANCE_DATA_SIGNATURE
);
1333 ArpService
= Instance
->ArpService
;
1336 // Delete the cache entries in the DeniedCacheTable.
1338 Count
= ArpDeleteCacheEntryInTable (
1339 &ArpService
->DeniedCacheTable
,
1341 Instance
->ConfigData
.SwAddressType
,
1347 // Delete the cache entries inthe ResolvedCacheTable.
1349 Count
+= ArpDeleteCacheEntryInTable (
1350 &ArpService
->ResolvedCacheTable
,
1352 Instance
->ConfigData
.SwAddressType
,
1362 Cancel the arp request.
1364 @param[in] Instance Pointer to the instance context data.
1365 @param[in] TargetSwAddress Pointer to the buffer containing the target
1366 software address to match the arp request.
1367 @param[in] UserEvent The user event used to notify this request
1370 @return The count of the cancelled requests.
1375 IN ARP_INSTANCE_DATA
*Instance
,
1376 IN VOID
*TargetSwAddress OPTIONAL
,
1377 IN EFI_EVENT UserEvent OPTIONAL
1380 ARP_SERVICE_DATA
*ArpService
;
1382 LIST_ENTRY
*NextEntry
;
1383 ARP_CACHE_ENTRY
*CacheEntry
;
1386 NET_CHECK_SIGNATURE (Instance
, ARP_INSTANCE_DATA_SIGNATURE
);
1388 ArpService
= Instance
->ArpService
;
1391 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &ArpService
->PendingRequestTable
) {
1392 CacheEntry
= NET_LIST_USER_STRUCT (Entry
, ARP_CACHE_ENTRY
, List
);
1394 if ((TargetSwAddress
== NULL
) ||
1397 CacheEntry
->Addresses
[Protocol
].AddressPtr
,
1398 CacheEntry
->Addresses
[Protocol
].Length
1401 // This request entry matches the TargetSwAddress or all requests are to be
1402 // cancelled as TargetSwAddress is NULL.
1404 Count
+= ArpAddressResolved (CacheEntry
, Instance
, UserEvent
);
1406 if (IsListEmpty (&CacheEntry
->UserRequestList
)) {
1408 // No user requests any more, remove this request cache entry.
1410 RemoveEntryList (&CacheEntry
->List
);
1411 FreePool (CacheEntry
);
1421 Find the cache entry in the cache table.
1423 @param[in] Instance Pointer to the instance context data.
1424 @param[in] BySwAddress Set to TRUE to look for matching software protocol
1425 addresses. Set to FALSE to look for matching
1426 hardware protocol addresses.
1427 @param[in] AddressBuffer Pointer to address buffer. Set to NULL to match
1429 @param[out] EntryLength The size of an entry in the entries buffer.
1430 @param[out] EntryCount The number of ARP cache entries that are found by
1431 the specified criteria.
1432 @param[out] Entries Pointer to the buffer that will receive the ARP
1434 @param[in] Refresh Set to TRUE to refresh the timeout value of the
1435 matching ARP cache entry.
1437 @retval EFI_SUCCESS The requested ARP cache entries are copied into
1439 @retval EFI_NOT_FOUND No matching entries found.
1440 @retval EFI_OUT_OF_RESOURCE There is a memory allocation failure.
1445 IN ARP_INSTANCE_DATA
*Instance
,
1446 IN BOOLEAN BySwAddress
,
1447 IN VOID
*AddressBuffer OPTIONAL
,
1448 OUT UINT32
*EntryLength OPTIONAL
,
1449 OUT UINT32
*EntryCount OPTIONAL
,
1450 OUT EFI_ARP_FIND_DATA
**Entries OPTIONAL
,
1455 ARP_SERVICE_DATA
*ArpService
;
1456 NET_ARP_ADDRESS MatchAddress
;
1457 FIND_OPTYPE FindOpType
;
1458 LIST_ENTRY
*StartEntry
;
1459 ARP_CACHE_ENTRY
*CacheEntry
;
1460 NET_MAP FoundEntries
;
1462 EFI_ARP_FIND_DATA
*FindData
;
1463 LIST_ENTRY
*CacheTable
;
1464 UINT32 FoundEntryLength
;
1466 ArpService
= Instance
->ArpService
;
1469 // Init the FounEntries used to hold the found cache entries.
1471 NetMapInit (&FoundEntries
);
1474 // Set the MatchAddress.
1477 MatchAddress
.Type
= Instance
->ConfigData
.SwAddressType
;
1478 MatchAddress
.Length
= Instance
->ConfigData
.SwAddressLength
;
1479 FindOpType
= ByProtoAddress
;
1481 MatchAddress
.Type
= ArpService
->SnpMode
.IfType
;
1482 MatchAddress
.Length
= (UINT8
)ArpService
->SnpMode
.HwAddressSize
;
1483 FindOpType
= ByHwAddress
;
1486 MatchAddress
.AddressPtr
= AddressBuffer
;
1489 // Search the DeniedCacheTable
1494 // Try to find the matched entries in the DeniedCacheTable.
1496 CacheEntry
= ArpFindNextCacheEntryInTable (
1497 &ArpService
->DeniedCacheTable
,
1503 if (CacheEntry
== NULL
) {
1505 // Once the CacheEntry is NULL, there are no more matches.
1511 // Insert the found entry into the map.
1516 (VOID
*)&ArpService
->DeniedCacheTable
1520 // Let the next search start from this cache entry.
1522 StartEntry
= &CacheEntry
->List
;
1526 // Refresh the DecayTime if needed.
1528 CacheEntry
->DecayTime
= CacheEntry
->DefaultDecayTime
;
1533 // Search the ResolvedCacheTable
1537 CacheEntry
= ArpFindNextCacheEntryInTable (
1538 &ArpService
->ResolvedCacheTable
,
1544 if (CacheEntry
== NULL
) {
1546 // Once the CacheEntry is NULL, there are no more matches.
1552 // Insert the found entry into the map.
1557 (VOID
*)&ArpService
->ResolvedCacheTable
1561 // Let the next search start from this cache entry.
1563 StartEntry
= &CacheEntry
->List
;
1567 // Refresh the DecayTime if needed.
1569 CacheEntry
->DecayTime
= CacheEntry
->DefaultDecayTime
;
1573 Status
= EFI_SUCCESS
;
1575 FoundCount
= (UINT32
) NetMapGetCount (&FoundEntries
);
1576 if (FoundCount
== 0) {
1577 Status
= EFI_NOT_FOUND
;
1582 // Found the entry length, make sure its 8 bytes alignment.
1584 FoundEntryLength
= (((sizeof (EFI_ARP_FIND_DATA
) + Instance
->ConfigData
.SwAddressLength
+
1585 ArpService
->SnpMode
.HwAddressSize
) + 3) & ~(0x3));
1587 if (EntryLength
!= NULL
) {
1588 *EntryLength
= FoundEntryLength
;
1591 if (EntryCount
!= NULL
) {
1593 // Return the found entry count.
1595 *EntryCount
= FoundCount
;
1598 if (Entries
== NULL
) {
1603 // Allocate buffer to copy the found entries.
1605 FindData
= AllocatePool (FoundCount
* FoundEntryLength
);
1606 if (FindData
== NULL
) {
1607 DEBUG ((EFI_D_ERROR
, "ArpFindCacheEntry: Failed to allocate memory.\n"));
1608 Status
= EFI_OUT_OF_RESOURCES
;
1613 // Return the address to the user.
1615 *Entries
= FindData
;
1618 // Dump the entries.
1620 while (!NetMapIsEmpty (&FoundEntries
)) {
1622 // Get a cache entry from the map.
1624 CacheEntry
= NetMapRemoveHead (&FoundEntries
, (VOID
**)&CacheTable
);
1627 // Set the fields in FindData.
1629 FindData
->Size
= FoundEntryLength
;
1630 FindData
->DenyFlag
= (BOOLEAN
)(CacheTable
== &ArpService
->DeniedCacheTable
);
1631 FindData
->StaticFlag
= (BOOLEAN
)(CacheEntry
->DefaultDecayTime
== 0);
1632 FindData
->HwAddressType
= ArpService
->SnpMode
.IfType
;
1633 FindData
->SwAddressType
= Instance
->ConfigData
.SwAddressType
;
1634 FindData
->HwAddressLength
= (UINT8
)ArpService
->SnpMode
.HwAddressSize
;
1635 FindData
->SwAddressLength
= Instance
->ConfigData
.SwAddressLength
;
1638 // Copy the software address.
1642 CacheEntry
->Addresses
[Protocol
].AddressPtr
,
1643 FindData
->SwAddressLength
1647 // Copy the hardware address.
1650 (UINT8
*)(FindData
+ 1) + FindData
->SwAddressLength
,
1651 CacheEntry
->Addresses
[Hardware
].AddressPtr
,
1652 FindData
->HwAddressLength
1656 // Slip to the next FindData.
1658 FindData
= (EFI_ARP_FIND_DATA
*)((UINT8
*)FindData
+ FoundEntryLength
);
1663 NetMapClean (&FoundEntries
);