2 The implementation of the ARP protocol.
4 Copyright (c) 2006 - 2008, Intel Corporation.<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at<BR>
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 // Global variable of EFI ARP Protocol Interface.
20 EFI_ARP_PROTOCOL mEfiArpProtocolTemplate
= {
32 Initialize the instance context data.
34 @param[in] ArpService Pointer to the arp service context data this
36 @param[out] Instance Pointer to the instance context data.
43 IN ARP_SERVICE_DATA
*ArpService
,
44 OUT ARP_INSTANCE_DATA
*Instance
47 NET_CHECK_SIGNATURE (ArpService
, ARP_SERVICE_DATA_SIGNATURE
);
49 Instance
->Signature
= ARP_INSTANCE_DATA_SIGNATURE
;
50 Instance
->ArpService
= ArpService
;
52 CopyMem (&Instance
->ArpProto
, &mEfiArpProtocolTemplate
, sizeof (Instance
->ArpProto
));
54 Instance
->Configured
= FALSE
;
55 Instance
->Destroyed
= FALSE
;
57 InitializeListHead (&Instance
->List
);
62 Process the Arp packets received from Mnp, the procedure conforms to RFC826.
64 @param[in] Context Pointer to the context data registerd to the
77 ARP_SERVICE_DATA
*ArpService
;
78 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*RxToken
;
79 EFI_MANAGED_NETWORK_RECEIVE_DATA
*RxData
;
81 ARP_ADDRESS ArpAddress
;
82 ARP_CACHE_ENTRY
*CacheEntry
;
84 ARP_INSTANCE_DATA
*Instance
;
85 EFI_ARP_CONFIG_DATA
*ConfigData
;
86 NET_ARP_ADDRESS SenderAddress
[2];
91 ArpService
= (ARP_SERVICE_DATA
*)Context
;
92 NET_CHECK_SIGNATURE (ArpService
, ARP_SERVICE_DATA_SIGNATURE
);
94 RxToken
= &ArpService
->RxToken
;
96 if (RxToken
->Status
== EFI_ABORTED
) {
98 // The Token is aborted, possibly by arp itself, just return and the receiving
99 // process is stopped.
104 if (EFI_ERROR (RxToken
->Status
)) {
106 // Restart the receiving if any other error Status occurs.
108 goto RESTART_RECEIVE
;
112 // Status is EFI_SUCCESS, process the received frame.
114 RxData
= RxToken
->Packet
.RxData
;
115 Head
= (ARP_HEAD
*) RxData
->PacketData
;
118 // Convert the byte order of the multi-byte fields.
120 Head
->HwType
= NTOHS (Head
->HwType
);
121 Head
->ProtoType
= NTOHS (Head
->ProtoType
);
122 Head
->OpCode
= NTOHS (Head
->OpCode
);
124 if ((Head
->HwType
!= ArpService
->SnpMode
.IfType
) ||
125 (Head
->HwAddrLen
!= ArpService
->SnpMode
.HwAddressSize
) ||
126 (RxData
->ProtocolType
!= ARP_ETHER_PROTO_TYPE
)) {
128 // The hardware type or the hardware address length doesn't match.
129 // There is a sanity check for the protocol type too.
135 // Set the pointers to the addresses contained in the arp packet.
137 ArpAddress
.SenderHwAddr
= (UINT8
*)(Head
+ 1);
138 ArpAddress
.SenderProtoAddr
= ArpAddress
.SenderHwAddr
+ Head
->HwAddrLen
;
139 ArpAddress
.TargetHwAddr
= ArpAddress
.SenderProtoAddr
+ Head
->ProtoAddrLen
;
140 ArpAddress
.TargetProtoAddr
= ArpAddress
.TargetHwAddr
+ Head
->HwAddrLen
;
142 SenderAddress
[Hardware
].Type
= Head
->HwType
;
143 SenderAddress
[Hardware
].Length
= Head
->HwAddrLen
;
144 SenderAddress
[Hardware
].AddressPtr
= ArpAddress
.SenderHwAddr
;
146 SenderAddress
[Protocol
].Type
= Head
->ProtoType
;
147 SenderAddress
[Protocol
].Length
= Head
->ProtoAddrLen
;
148 SenderAddress
[Protocol
].AddressPtr
= ArpAddress
.SenderProtoAddr
;
151 // First, check the denied cache table.
153 CacheEntry
= ArpFindDeniedCacheEntry (
155 &SenderAddress
[Protocol
],
156 &SenderAddress
[Hardware
]
158 if (CacheEntry
!= NULL
) {
160 // This address (either hardware or protocol address, or both) is configured to
161 // be a deny entry, silently skip the normal process.
166 ProtoMatched
= FALSE
;
169 NET_LIST_FOR_EACH (Entry
, &ArpService
->ChildrenList
) {
171 // Iterate all the children.
173 Instance
= NET_LIST_USER_STRUCT (Entry
, ARP_INSTANCE_DATA
, List
);
174 NET_CHECK_SIGNATURE (Instance
, ARP_INSTANCE_DATA_SIGNATURE
);
175 ConfigData
= &Instance
->ConfigData
;
177 if ((Instance
->Configured
) &&
178 (Head
->ProtoType
== ConfigData
->SwAddressType
) &&
179 (Head
->ProtoAddrLen
== ConfigData
->SwAddressLength
)) {
181 // The protocol type is matched for the received arp packet.
184 if (0 == CompareMem (
185 (VOID
*)ArpAddress
.TargetProtoAddr
,
186 ConfigData
->StationAddress
,
187 ConfigData
->SwAddressLength
190 // The arp driver has the target address required by the received arp packet.
200 // Protocol type unmatchable, skip.
206 // Check whether the sender's address information is already in the cache.
209 CacheEntry
= ArpFindNextCacheEntryInTable (
210 &ArpService
->ResolvedCacheTable
,
213 &SenderAddress
[Protocol
],
216 if (CacheEntry
!= NULL
) {
218 // Update the entry with the new information.
220 ArpFillAddressInCacheEntry (CacheEntry
, &SenderAddress
[Hardware
], NULL
);
221 CacheEntry
->DecayTime
= CacheEntry
->DefaultDecayTime
;
227 // This arp packet isn't targeted to us, skip now.
234 // Add the triplet <protocol type, sender protocol address, sender hardware address>
235 // to the translation table.
237 CacheEntry
= ArpFindNextCacheEntryInTable (
238 &ArpService
->PendingRequestTable
,
241 &SenderAddress
[Protocol
],
244 if (CacheEntry
== NULL
) {
246 // Allocate a new CacheEntry.
248 CacheEntry
= ArpAllocCacheEntry (NULL
);
249 if (CacheEntry
== NULL
) {
254 if (!IsListEmpty (&CacheEntry
->List
)) {
255 RemoveEntryList (&CacheEntry
->List
);
259 // Fill the addresses into the CacheEntry.
261 ArpFillAddressInCacheEntry (
263 &SenderAddress
[Hardware
],
264 &SenderAddress
[Protocol
]
270 ArpAddressResolved (CacheEntry
, NULL
, NULL
);
273 // Add this entry into the ResolvedCacheTable
275 InsertHeadList (&ArpService
->ResolvedCacheTable
, &CacheEntry
->List
);
278 if (Head
->OpCode
== ARP_OPCODE_REQUEST
) {
280 // Send back the ARP Reply. If we reach here, Instance is not NULL and CacheEntry
283 ArpSendFrame (Instance
, CacheEntry
, ARP_OPCODE_REPLY
);
289 // Signal Mnp to recycle the RxData.
291 gBS
->SignalEvent (RxData
->RecycleEvent
);
296 // Continue to receive packets from Mnp.
298 Status
= ArpService
->Mnp
->Receive (ArpService
->Mnp
, RxToken
);
301 if (EFI_ERROR (Status
)) {
302 DEBUG ((EFI_D_ERROR
, "ArpOnFrameRcvd: ArpService->Mnp->Receive "
303 "failed, %r\n.", Status
));
309 Queue ArpOnFrameRcvdDpc as a DPC at TPL_CALLBACK.
311 @param[in] Event The Event this notify function registered to.
312 @param[in] Context Pointer to the context data registerd to the
326 // Request ArpOnFrameRcvdDpc as a DPC at TPL_CALLBACK
328 NetLibQueueDpc (TPL_CALLBACK
, ArpOnFrameRcvdDpc
, Context
);
332 Process the already sent arp packets.
334 @param[in] Context Pointer to the context data registerd to the
346 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TxToken
;
347 EFI_MANAGED_NETWORK_TRANSMIT_DATA
*TxData
;
349 ASSERT (Context
!= NULL
);
351 TxToken
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*)Context
;
352 TxData
= TxToken
->Packet
.TxData
;
355 if (EFI_ERROR (TxToken
->Status
)) {
356 DEBUG ((EFI_D_ERROR
, "ArpOnFrameSent: TxToken->Status, %r.\n", TxToken
->Status
));
361 // Free the allocated memory and close the event.
363 gBS
->FreePool (TxData
->FragmentTable
[0].FragmentBuffer
);
364 gBS
->FreePool (TxData
);
365 gBS
->CloseEvent (TxToken
->Event
);
366 gBS
->FreePool (TxToken
);
370 Request ArpOnFrameSentDpc as a DPC at TPL_CALLBACK.
372 @param[in] Event The Event this notify function registered to.
373 @param[in] Context Pointer to the context data registerd to the
387 // Request ArpOnFrameSentDpc as a DPC at TPL_CALLBACK
389 NetLibQueueDpc (TPL_CALLBACK
, ArpOnFrameSentDpc
, Context
);
394 Process the arp cache olding and drive the retrying arp requests.
396 @param[in] Event The Event this notify function registered to.
397 @param[in] Context Pointer to the context data registerd to the
410 ARP_SERVICE_DATA
*ArpService
;
412 LIST_ENTRY
*NextEntry
;
413 LIST_ENTRY
*ContextEntry
;
414 ARP_CACHE_ENTRY
*CacheEntry
;
415 USER_REQUEST_CONTEXT
*RequestContext
;
417 ASSERT (Context
!= NULL
);
418 ArpService
= (ARP_SERVICE_DATA
*)Context
;
421 // Iterate all the pending requests to see whether a retry is needed to send out
422 // or the request finally fails because the retry time reaches the limitation.
424 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &ArpService
->PendingRequestTable
) {
425 CacheEntry
= NET_LIST_USER_STRUCT (Entry
, ARP_CACHE_ENTRY
, List
);
427 if (CacheEntry
->NextRetryTime
<= ARP_PERIODIC_TIMER_INTERVAL
) {
429 // Timeout, if we can retry more, send out the request again, otherwise abort
432 if (CacheEntry
->RetryCount
== 0) {
434 // Abort this request.
436 ArpAddressResolved (CacheEntry
, NULL
, NULL
);
437 ASSERT (IsListEmpty (&CacheEntry
->UserRequestList
));
439 RemoveEntryList (&CacheEntry
->List
);
440 gBS
->FreePool (CacheEntry
);
443 // resend the ARP request.
445 ASSERT (!IsListEmpty(&CacheEntry
->UserRequestList
));
447 ContextEntry
= CacheEntry
->UserRequestList
.ForwardLink
;
448 RequestContext
= NET_LIST_USER_STRUCT (ContextEntry
, USER_REQUEST_CONTEXT
, List
);
450 ArpSendFrame (RequestContext
->Instance
, CacheEntry
, ARP_OPCODE_REQUEST
);
452 CacheEntry
->RetryCount
--;
453 CacheEntry
->NextRetryTime
= RequestContext
->Instance
->ConfigData
.RetryTimeOut
;
457 // Update the NextRetryTime.
459 CacheEntry
->NextRetryTime
-= ARP_PERIODIC_TIMER_INTERVAL
;
464 // Check the timeouts for the DeniedCacheTable.
466 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &ArpService
->DeniedCacheTable
) {
467 CacheEntry
= NET_LIST_USER_STRUCT (Entry
, ARP_CACHE_ENTRY
, List
);
468 ASSERT (IsListEmpty (&CacheEntry
->UserRequestList
));
470 if (CacheEntry
->DefaultDecayTime
== 0) {
472 // It's a static entry, skip it.
477 if (CacheEntry
->DecayTime
<= ARP_PERIODIC_TIMER_INTERVAL
) {
479 // Time out, remove it.
481 RemoveEntryList (&CacheEntry
->List
);
482 gBS
->FreePool (CacheEntry
);
485 // Update the DecayTime.
487 CacheEntry
->DecayTime
-= ARP_PERIODIC_TIMER_INTERVAL
;
492 // Check the timeouts for the ResolvedCacheTable.
494 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &ArpService
->ResolvedCacheTable
) {
495 CacheEntry
= NET_LIST_USER_STRUCT (Entry
, ARP_CACHE_ENTRY
, List
);
496 ASSERT (IsListEmpty (&CacheEntry
->UserRequestList
));
498 if (CacheEntry
->DefaultDecayTime
== 0) {
500 // It's a static entry, skip it.
505 if (CacheEntry
->DecayTime
<= ARP_PERIODIC_TIMER_INTERVAL
) {
507 // Time out, remove it.
509 RemoveEntryList (&CacheEntry
->List
);
510 gBS
->FreePool (CacheEntry
);
513 // Update the DecayTime.
515 CacheEntry
->DecayTime
-= ARP_PERIODIC_TIMER_INTERVAL
;
522 Match the two NET_ARP_ADDRESSes.
524 @param[in] AddressOne Pointer to the first address to match.
525 @param[in] AddressTwo Pointer to the second address to match.
527 @return The two addresses match or not.
532 IN NET_ARP_ADDRESS
*AddressOne
,
533 IN NET_ARP_ADDRESS
*AddressTwo
536 if ((AddressOne
->Type
!= AddressTwo
->Type
) ||
537 (AddressOne
->Length
!= AddressTwo
->Length
)) {
539 // Either Type or Length doesn't match.
544 if ((AddressOne
->AddressPtr
!= NULL
) &&
546 AddressOne
->AddressPtr
,
547 AddressTwo
->AddressPtr
,
551 // The address is not the same.
561 Find the CacheEntry which matches the requirements in the specified CacheTable.
563 @param[in] CacheTable Pointer to the arp cache table.
564 @param[in] StartEntry Pointer to the start entry this search begins with
566 @param[in] FindOpType The search type.
567 @param[in] ProtocolAddress Pointer to the protocol address to match.
568 @param[in] HardwareAddress Pointer to the hardware address to match.
570 @return Pointer to the matched arp cache entry, if NULL, no match is found.
574 ArpFindNextCacheEntryInTable (
575 IN LIST_ENTRY
*CacheTable
,
576 IN LIST_ENTRY
*StartEntry
,
577 IN FIND_OPTYPE FindOpType
,
578 IN NET_ARP_ADDRESS
*ProtocolAddress OPTIONAL
,
579 IN NET_ARP_ADDRESS
*HardwareAddress OPTIONAL
583 ARP_CACHE_ENTRY
*CacheEntry
;
585 if (StartEntry
== NULL
) {
587 // Start from the beginning of the table if no StartEntry is specified.
589 StartEntry
= CacheTable
;
592 for (Entry
= StartEntry
->ForwardLink
; Entry
!= CacheTable
; Entry
= Entry
->ForwardLink
) {
593 CacheEntry
= NET_LIST_USER_STRUCT (Entry
, ARP_CACHE_ENTRY
, List
);
595 if ((FindOpType
& MATCH_SW_ADDRESS
) != 0) {
597 // Find by the software address.
599 if (!ArpMatchAddress (ProtocolAddress
, &CacheEntry
->Addresses
[Protocol
])) {
601 // The ProtocolAddress doesn't match, continue to the next cache entry.
607 if ((FindOpType
& MATCH_HW_ADDRESS
) != 0) {
609 // Find by the hardware address.
611 if (!ArpMatchAddress (HardwareAddress
, &CacheEntry
->Addresses
[Hardware
])) {
613 // The HardwareAddress doesn't match, continue to the next cache entry.
620 // The CacheEntry meets the requirements now, return this entry.
633 Find the CacheEntry, using ProtocolAddress or HardwareAddress or both, as the keyword,
634 in the DeniedCacheTable.
636 @param[in] ArpService Pointer to the arp service context data.
637 @param[in] ProtocolAddress Pointer to the protocol address.
638 @param[in] HardwareAddress Pointer to the hardware address.
640 @return Pointer to the matched cache entry, if NULL no match is found.
644 ArpFindDeniedCacheEntry (
645 IN ARP_SERVICE_DATA
*ArpService
,
646 IN NET_ARP_ADDRESS
*ProtocolAddress OPTIONAL
,
647 IN NET_ARP_ADDRESS
*HardwareAddress OPTIONAL
650 ARP_CACHE_ENTRY
*CacheEntry
;
652 ASSERT ((ProtocolAddress
!= NULL
) || (HardwareAddress
!= NULL
));
653 NET_CHECK_SIGNATURE (ArpService
, ARP_SERVICE_DATA_SIGNATURE
);
657 if ((ProtocolAddress
!= NULL
) && (ProtocolAddress
->AddressPtr
!= NULL
)) {
659 // Find the cache entry in the DeniedCacheTable by the protocol address.
661 CacheEntry
= ArpFindNextCacheEntryInTable (
662 &ArpService
->DeniedCacheTable
,
668 if (CacheEntry
!= NULL
) {
676 if ((HardwareAddress
!= NULL
) && (HardwareAddress
->AddressPtr
!= NULL
)) {
678 // Find the cache entry in the DeniedCacheTable by the hardware address.
680 CacheEntry
= ArpFindNextCacheEntryInTable (
681 &ArpService
->DeniedCacheTable
,
694 Allocate a cache entry and initialize it.
696 @param[in] Instance Pointer to the instance context data.
698 @return Pointer to the new created cache entry.
703 IN ARP_INSTANCE_DATA
*Instance
706 ARP_CACHE_ENTRY
*CacheEntry
;
707 NET_ARP_ADDRESS
*Address
;
711 // Allocate memory for the cache entry.
713 CacheEntry
= AllocatePool (sizeof (ARP_CACHE_ENTRY
));
714 if (CacheEntry
== NULL
) {
721 InitializeListHead (&CacheEntry
->List
);
722 InitializeListHead (&CacheEntry
->UserRequestList
);
724 for (Index
= 0; Index
< 2; Index
++) {
726 // Init the address pointers to point to the concrete buffer.
728 Address
= &CacheEntry
->Addresses
[Index
];
729 Address
->AddressPtr
= Address
->Buffer
.ProtoAddress
;
733 // Zero the hardware address first.
735 ZeroMem (CacheEntry
->Addresses
[Hardware
].AddressPtr
, ARP_MAX_HARDWARE_ADDRESS_LEN
);
737 if (Instance
!= NULL
) {
739 // Inherit the parameters from the instance configuration.
741 CacheEntry
->RetryCount
= Instance
->ConfigData
.RetryCount
;
742 CacheEntry
->NextRetryTime
= Instance
->ConfigData
.RetryTimeOut
;
743 CacheEntry
->DefaultDecayTime
= Instance
->ConfigData
.EntryTimeOut
;
744 CacheEntry
->DecayTime
= Instance
->ConfigData
.EntryTimeOut
;
747 // Use the default parameters if this cache entry isn't allocate in a
750 CacheEntry
->RetryCount
= ARP_DEFAULT_RETRY_COUNT
;
751 CacheEntry
->NextRetryTime
= ARP_DEFAULT_RETRY_INTERVAL
;
752 CacheEntry
->DefaultDecayTime
= ARP_DEFAULT_TIMEOUT_VALUE
;
753 CacheEntry
->DecayTime
= ARP_DEFAULT_TIMEOUT_VALUE
;
761 Turn the CacheEntry into the resolved status.
763 @param[in] CacheEntry Pointer to the resolved cache entry.
764 @param[in] Instance Pointer to the instance context data.
765 @param[in] UserEvent Pointer to the UserEvent to notify.
767 @return The count of notifications sent to the instance.
772 IN ARP_CACHE_ENTRY
*CacheEntry
,
773 IN ARP_INSTANCE_DATA
*Instance OPTIONAL
,
774 IN EFI_EVENT UserEvent OPTIONAL
778 LIST_ENTRY
*NextEntry
;
779 USER_REQUEST_CONTEXT
*Context
;
785 // Iterate all the linked user requests to notify them.
787 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &CacheEntry
->UserRequestList
) {
788 Context
= NET_LIST_USER_STRUCT (Entry
, USER_REQUEST_CONTEXT
, List
);
790 if (((Instance
== NULL
) || (Context
->Instance
== Instance
)) &&
791 ((UserEvent
== NULL
) || (Context
->UserRequestEvent
== UserEvent
))) {
793 // Copy the address to the user-provided buffer and notify the user.
796 Context
->UserHwAddrBuffer
,
797 CacheEntry
->Addresses
[Hardware
].AddressPtr
,
798 CacheEntry
->Addresses
[Hardware
].Length
800 gBS
->SignalEvent (Context
->UserRequestEvent
);
803 // Remove this user request and free the context data.
805 RemoveEntryList (&Context
->List
);
806 gBS
->FreePool (Context
);
813 // Dispatch the DPCs queued by the NotifyFunction of the Context->UserRequestEvent.
815 NetLibDispatchDpc ();
822 Fill the addresses in the CacheEntry using the information passed in by
825 @param[in] CacheEntry Pointer to the cache entry.
826 @param[in] HwAddr Pointer to the software address.
827 @param[in] SwAddr Pointer to the hardware address.
833 ArpFillAddressInCacheEntry (
834 IN ARP_CACHE_ENTRY
*CacheEntry
,
835 IN NET_ARP_ADDRESS
*HwAddr OPTIONAL
,
836 IN NET_ARP_ADDRESS
*SwAddr OPTIONAL
839 NET_ARP_ADDRESS
*Address
[2];
840 NET_ARP_ADDRESS
*CacheAddress
;
843 Address
[Hardware
] = HwAddr
;
844 Address
[Protocol
] = SwAddr
;
846 for (Index
= 0; Index
< 2; Index
++) {
847 if (Address
[Index
] != NULL
) {
849 // Fill the address if the passed in pointer is not NULL.
851 CacheAddress
= &CacheEntry
->Addresses
[Index
];
853 CacheAddress
->Type
= Address
[Index
]->Type
;
854 CacheAddress
->Length
= Address
[Index
]->Length
;
856 if (Address
[Index
]->AddressPtr
!= NULL
) {
858 // Copy it if the AddressPtr points to some buffer.
861 CacheAddress
->AddressPtr
,
862 Address
[Index
]->AddressPtr
,
867 // Zero the corresponding address buffer in the CacheEntry.
869 ZeroMem (CacheAddress
->AddressPtr
, CacheAddress
->Length
);
877 Configure the instance using the ConfigData. ConfigData is already validated.
879 @param[in] Instance Pointer to the instance context data to be
881 @param[in] ConfigData Pointer to the configuration data used to
882 configure the instance.
884 @retval EFI_SUCCESS The instance is configured with the ConfigData.
885 @retval EFI_ACCESS_DENIED The instance is already configured and the
886 ConfigData tries to reset some unchangeable
888 @retval EFI_INVALID_PARAMETER The ConfigData provides a non-unicast IPv4 address
889 when the SwAddressType is IPv4.
890 @retval EFI_OUT_OF_RESOURCES The instance fails to configure due to memory
895 ArpConfigureInstance (
896 IN ARP_INSTANCE_DATA
*Instance
,
897 IN EFI_ARP_CONFIG_DATA
*ConfigData OPTIONAL
900 EFI_ARP_CONFIG_DATA
*OldConfigData
;
903 OldConfigData
= &Instance
->ConfigData
;
905 if (ConfigData
!= NULL
) {
907 if (Instance
->Configured
) {
909 // The instance is configured, check the unchangeable fields.
911 if ((OldConfigData
->SwAddressType
!= ConfigData
->SwAddressType
) ||
912 (OldConfigData
->SwAddressLength
!= ConfigData
->SwAddressLength
) ||
914 OldConfigData
->StationAddress
,
915 ConfigData
->StationAddress
,
916 OldConfigData
->SwAddressLength
919 // Deny the unallowed changes.
921 return EFI_ACCESS_DENIED
;
925 // The instance is not configured.
928 if (ConfigData
->SwAddressType
== IPV4_ETHER_PROTO_TYPE
) {
929 CopyMem (&Ip
, ConfigData
->StationAddress
, sizeof (IP4_ADDR
));
931 if (!Ip4IsUnicast (NTOHL (Ip
), 0)) {
933 // The station address is not a valid IPv4 unicast address.
935 return EFI_INVALID_PARAMETER
;
940 // Save the configuration.
942 CopyMem (OldConfigData
, ConfigData
, sizeof (*OldConfigData
));
944 OldConfigData
->StationAddress
= AllocatePool (OldConfigData
->SwAddressLength
);
945 if (OldConfigData
->StationAddress
== NULL
) {
946 DEBUG ((EFI_D_ERROR
, "ArpConfigInstance: AllocatePool for the StationAddress "
948 return EFI_OUT_OF_RESOURCES
;
952 // Save the StationAddress.
955 OldConfigData
->StationAddress
,
956 ConfigData
->StationAddress
,
957 OldConfigData
->SwAddressLength
961 // Set the state to configured.
963 Instance
->Configured
= TRUE
;
967 // Use the implementation specific values if the following field is zero.
969 OldConfigData
->EntryTimeOut
= (ConfigData
->EntryTimeOut
== 0) ?
970 ARP_DEFAULT_TIMEOUT_VALUE
: ConfigData
->EntryTimeOut
;
972 OldConfigData
->RetryCount
= (ConfigData
->RetryCount
== 0) ?
973 ARP_DEFAULT_RETRY_COUNT
: ConfigData
->RetryCount
;
975 OldConfigData
->RetryTimeOut
= (ConfigData
->RetryTimeOut
== 0) ?
976 ARP_DEFAULT_RETRY_INTERVAL
: ConfigData
->RetryTimeOut
;
979 // Reset the configuration.
982 if (Instance
->Configured
) {
984 // Cancel the arp requests issued by this instance.
986 Instance
->ArpProto
.Cancel (&Instance
->ArpProto
, NULL
, NULL
);
989 // Free the buffer previously allocated to hold the station address.
991 gBS
->FreePool (OldConfigData
->StationAddress
);
994 Instance
->Configured
= FALSE
;
1002 Send out an arp frame using the CachEntry and the ArpOpCode.
1004 @param[in] Instance Pointer to the instance context data.
1005 @param[in] CacheEntry Pointer to the configuration data used to
1006 configure the instance.
1007 @param[in] ArpOpCode The opcode used to send out this Arp frame, either
1015 IN ARP_INSTANCE_DATA
*Instance
,
1016 IN ARP_CACHE_ENTRY
*CacheEntry
,
1021 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TxToken
;
1022 EFI_MANAGED_NETWORK_TRANSMIT_DATA
*TxData
;
1025 ARP_SERVICE_DATA
*ArpService
;
1026 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
1027 EFI_ARP_CONFIG_DATA
*ConfigData
;
1031 ASSERT ((Instance
!= NULL
) && (CacheEntry
!= NULL
));
1034 // Allocate memory for the TxToken.
1036 TxToken
= AllocatePool (sizeof(EFI_MANAGED_NETWORK_COMPLETION_TOKEN
));
1037 if (TxToken
== NULL
) {
1038 DEBUG ((EFI_D_ERROR
, "ArpSendFrame: Allocate memory for TxToken failed.\n"));
1042 TxToken
->Event
= NULL
;
1047 // Create the event for this TxToken.
1049 Status
= gBS
->CreateEvent (
1056 if (EFI_ERROR (Status
)) {
1057 DEBUG ((EFI_D_ERROR
, "ArpSendFrame: CreateEvent failed for TxToken->Event.\n"));
1062 // Allocate memory for the TxData used in the TxToken.
1064 TxData
= AllocatePool (sizeof(EFI_MANAGED_NETWORK_TRANSMIT_DATA
));
1065 if (TxData
== NULL
) {
1066 DEBUG ((EFI_D_ERROR
, "ArpSendFrame: Allocate memory for TxData failed.\n"));
1070 ArpService
= Instance
->ArpService
;
1071 SnpMode
= &ArpService
->SnpMode
;
1072 ConfigData
= &Instance
->ConfigData
;
1075 // Calculate the buffer length for this arp frame.
1077 TotalLength
= SnpMode
->MediaHeaderSize
+ sizeof (ARP_HEAD
) +
1078 2 * (ConfigData
->SwAddressLength
+ SnpMode
->HwAddressSize
);
1081 // Allocate buffer for the arp frame.
1083 Packet
= AllocatePool (TotalLength
);
1084 if (Packet
== NULL
) {
1085 DEBUG ((EFI_D_ERROR
, "ArpSendFrame: Allocate memory for Packet failed.\n"));
1091 // The destination MAC address.
1093 if (ArpOpCode
== ARP_OPCODE_REQUEST
) {
1094 CopyMem (TmpPtr
, &SnpMode
->BroadcastAddress
, SnpMode
->HwAddressSize
);
1098 CacheEntry
->Addresses
[Hardware
].AddressPtr
,
1099 SnpMode
->HwAddressSize
1102 TmpPtr
+= SnpMode
->HwAddressSize
;
1105 // The source MAC address.
1107 CopyMem (TmpPtr
, &SnpMode
->CurrentAddress
, SnpMode
->HwAddressSize
);
1108 TmpPtr
+= SnpMode
->HwAddressSize
;
1111 // The ethernet protocol type.
1113 *(UINT16
*)TmpPtr
= HTONS (ARP_ETHER_PROTO_TYPE
);
1119 ArpHead
= (ARP_HEAD
*) TmpPtr
;
1120 ArpHead
->HwType
= HTONS ((UINT16
)SnpMode
->IfType
);
1121 ArpHead
->ProtoType
= HTONS (ConfigData
->SwAddressType
);
1122 ArpHead
->HwAddrLen
= (UINT8
)SnpMode
->HwAddressSize
;
1123 ArpHead
->ProtoAddrLen
= ConfigData
->SwAddressLength
;
1124 ArpHead
->OpCode
= HTONS (ArpOpCode
);
1125 TmpPtr
+= sizeof (ARP_HEAD
);
1128 // The sender hardware address.
1130 CopyMem (TmpPtr
, &SnpMode
->CurrentAddress
, SnpMode
->HwAddressSize
);
1131 TmpPtr
+= SnpMode
->HwAddressSize
;
1134 // The sender protocol address.
1136 CopyMem (TmpPtr
, ConfigData
->StationAddress
, ConfigData
->SwAddressLength
);
1137 TmpPtr
+= ConfigData
->SwAddressLength
;
1140 // The target hardware address.
1144 CacheEntry
->Addresses
[Hardware
].AddressPtr
,
1145 SnpMode
->HwAddressSize
1147 TmpPtr
+= SnpMode
->HwAddressSize
;
1150 // The target protocol address.
1154 CacheEntry
->Addresses
[Protocol
].AddressPtr
,
1155 ConfigData
->SwAddressLength
1159 // Set all the fields of the TxData.
1161 TxData
->DestinationAddress
= NULL
;
1162 TxData
->SourceAddress
= NULL
;
1163 TxData
->ProtocolType
= 0;
1164 TxData
->DataLength
= TotalLength
- SnpMode
->MediaHeaderSize
;
1165 TxData
->HeaderLength
= (UINT16
) SnpMode
->MediaHeaderSize
;
1166 TxData
->FragmentCount
= 1;
1168 TxData
->FragmentTable
[0].FragmentBuffer
= Packet
;
1169 TxData
->FragmentTable
[0].FragmentLength
= TotalLength
;
1172 // Associate the TxData with the TxToken.
1174 TxToken
->Packet
.TxData
= TxData
;
1175 TxToken
->Status
= EFI_NOT_READY
;
1178 // Send out this arp packet by Mnp.
1180 Status
= ArpService
->Mnp
->Transmit (ArpService
->Mnp
, TxToken
);
1181 if (EFI_ERROR (Status
)) {
1182 DEBUG ((EFI_D_ERROR
, "Mnp->Transmit failed, %r.\n", Status
));
1190 if (Packet
!= NULL
) {
1191 gBS
->FreePool (Packet
);
1194 if (TxData
!= NULL
) {
1195 gBS
->FreePool (TxData
);
1198 if (TxToken
->Event
!= NULL
) {
1199 gBS
->CloseEvent (TxToken
->Event
);
1202 gBS
->FreePool (TxToken
);
1207 Delete the cache entries in the specified CacheTable, using the BySwAddress,
1208 SwAddressType, AddressBuffer combination as the matching key, if Force is TRUE,
1209 the cache is deleted event it's a static entry.
1211 @param[in] CacheTable Pointer to the cache table to do the deletion.
1212 @param[in] BySwAddress Delete the cache entry by software address or by
1214 @param[in] SwAddressType The software address used to do the deletion.
1215 @param[in] AddressBuffer Pointer to the buffer containing the address to
1216 match for the deletion.
1217 @param[in] Force This deletion is forced or not.
1219 @return The count of the deleted cache entries.
1223 ArpDeleteCacheEntryInTable (
1224 IN LIST_ENTRY
*CacheTable
,
1225 IN BOOLEAN BySwAddress
,
1226 IN UINT16 SwAddressType
,
1227 IN UINT8
*AddressBuffer OPTIONAL
,
1232 LIST_ENTRY
*NextEntry
;
1233 ARP_CACHE_ENTRY
*CacheEntry
;
1238 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, CacheTable
) {
1239 CacheEntry
= NET_LIST_USER_STRUCT (Entry
, ARP_CACHE_ENTRY
, List
);
1241 if ((CacheEntry
->DefaultDecayTime
== 0) && !Force
) {
1243 // It's a static entry and we are not forced to delete it, skip.
1249 if (SwAddressType
== CacheEntry
->Addresses
[Protocol
].Type
) {
1251 // Protocol address type matched. Check the address.
1253 if ((AddressBuffer
== NULL
) ||
1256 CacheEntry
->Addresses
[Protocol
].AddressPtr
,
1257 CacheEntry
->Addresses
[Protocol
].Length
1266 if ((AddressBuffer
== NULL
) ||
1269 CacheEntry
->Addresses
[Hardware
].AddressPtr
,
1270 CacheEntry
->Addresses
[Hardware
].Length
1284 // Delete this entry.
1286 RemoveEntryList (&CacheEntry
->List
);
1287 ASSERT (IsListEmpty (&CacheEntry
->UserRequestList
));
1288 gBS
->FreePool (CacheEntry
);
1298 Delete cache entries in all the cache tables.
1300 @param[in] Instance Pointer to the instance context data.
1301 @param[in] BySwAddress Delete the cache entry by software address or by
1303 @param[in] AddressBuffer Pointer to the buffer containing the address to
1304 match for the deletion.
1305 @param[in] Force This deletion is forced or not.
1307 @return The count of the deleted cache entries.
1311 ArpDeleteCacheEntry (
1312 IN ARP_INSTANCE_DATA
*Instance
,
1313 IN BOOLEAN BySwAddress
,
1314 IN UINT8
*AddressBuffer OPTIONAL
,
1318 ARP_SERVICE_DATA
*ArpService
;
1321 NET_CHECK_SIGNATURE (Instance
, ARP_INSTANCE_DATA_SIGNATURE
);
1323 ArpService
= Instance
->ArpService
;
1326 // Delete the cache entries in the DeniedCacheTable.
1328 Count
= ArpDeleteCacheEntryInTable (
1329 &ArpService
->DeniedCacheTable
,
1331 Instance
->ConfigData
.SwAddressType
,
1337 // Delete the cache entries inthe ResolvedCacheTable.
1339 Count
+= ArpDeleteCacheEntryInTable (
1340 &ArpService
->ResolvedCacheTable
,
1342 Instance
->ConfigData
.SwAddressType
,
1352 Cancel the arp request.
1354 @param[in] Instance Pointer to the instance context data.
1355 @param[in] TargetSwAddress Pointer to the buffer containing the target
1356 software address to match the arp request.
1357 @param[in] UserEvent The user event used to notify this request
1360 @return The count of the cancelled requests.
1365 IN ARP_INSTANCE_DATA
*Instance
,
1366 IN VOID
*TargetSwAddress OPTIONAL
,
1367 IN EFI_EVENT UserEvent OPTIONAL
1370 ARP_SERVICE_DATA
*ArpService
;
1372 LIST_ENTRY
*NextEntry
;
1373 ARP_CACHE_ENTRY
*CacheEntry
;
1376 NET_CHECK_SIGNATURE (Instance
, ARP_INSTANCE_DATA_SIGNATURE
);
1378 ArpService
= Instance
->ArpService
;
1381 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &ArpService
->PendingRequestTable
) {
1382 CacheEntry
= NET_LIST_USER_STRUCT (Entry
, ARP_CACHE_ENTRY
, List
);
1384 if ((TargetSwAddress
== NULL
) ||
1387 CacheEntry
->Addresses
[Protocol
].AddressPtr
,
1388 CacheEntry
->Addresses
[Protocol
].Length
1391 // This request entry matches the TargetSwAddress or all requests are to be
1392 // cancelled as TargetSwAddress is NULL.
1394 Count
+= ArpAddressResolved (CacheEntry
, Instance
, UserEvent
);
1396 if (IsListEmpty (&CacheEntry
->UserRequestList
)) {
1398 // No user requests any more, remove this request cache entry.
1400 RemoveEntryList (&CacheEntry
->List
);
1401 gBS
->FreePool (CacheEntry
);
1411 Find the cache entry in the cache table.
1413 @param[in] Instance Pointer to the instance context data.
1414 @param[in] BySwAddress Set to TRUE to look for matching software protocol
1415 addresses. Set to FALSE to look for matching
1416 hardware protocol addresses.
1417 @param[in] AddressBuffer Pointer to address buffer. Set to NULL to match
1419 @param[out] EntryLength The size of an entry in the entries buffer.
1420 @param[out] EntryCount The number of ARP cache entries that are found by
1421 the specified criteria.
1422 @param[out] Entries Pointer to the buffer that will receive the ARP
1424 @param[in] Refresh Set to TRUE to refresh the timeout value of the
1425 matching ARP cache entry.
1427 @retval EFI_SUCCESS The requested ARP cache entries are copied into
1429 @retval EFI_NOT_FOUND No matching entries found.
1430 @retval EFI_OUT_OF_RESOURCE There is a memory allocation failure.
1435 IN ARP_INSTANCE_DATA
*Instance
,
1436 IN BOOLEAN BySwAddress
,
1437 IN VOID
*AddressBuffer OPTIONAL
,
1438 OUT UINT32
*EntryLength OPTIONAL
,
1439 OUT UINT32
*EntryCount OPTIONAL
,
1440 OUT EFI_ARP_FIND_DATA
**Entries OPTIONAL
,
1445 ARP_SERVICE_DATA
*ArpService
;
1446 NET_ARP_ADDRESS MatchAddress
;
1447 FIND_OPTYPE FindOpType
;
1448 LIST_ENTRY
*StartEntry
;
1449 ARP_CACHE_ENTRY
*CacheEntry
;
1450 NET_MAP FoundEntries
;
1452 EFI_ARP_FIND_DATA
*FindData
;
1453 LIST_ENTRY
*CacheTable
;
1455 ArpService
= Instance
->ArpService
;
1458 // Init the FounEntries used to hold the found cache entries.
1460 NetMapInit (&FoundEntries
);
1463 // Set the MatchAddress.
1466 MatchAddress
.Type
= Instance
->ConfigData
.SwAddressType
;
1467 MatchAddress
.Length
= Instance
->ConfigData
.SwAddressLength
;
1468 FindOpType
= ByProtoAddress
;
1470 MatchAddress
.Type
= ArpService
->SnpMode
.IfType
;
1471 MatchAddress
.Length
= (UINT8
)ArpService
->SnpMode
.HwAddressSize
;
1472 FindOpType
= ByHwAddress
;
1475 MatchAddress
.AddressPtr
= AddressBuffer
;
1478 // Search the DeniedCacheTable
1483 // Try to find the matched entries in the DeniedCacheTable.
1485 CacheEntry
= ArpFindNextCacheEntryInTable (
1486 &ArpService
->DeniedCacheTable
,
1492 if (CacheEntry
== NULL
) {
1494 // Once the CacheEntry is NULL, there are no more matches.
1500 // Insert the found entry into the map.
1505 (VOID
*)&ArpService
->DeniedCacheTable
1509 // Let the next search start from this cache entry.
1511 StartEntry
= &CacheEntry
->List
;
1515 // Refresh the DecayTime if needed.
1517 CacheEntry
->DecayTime
= CacheEntry
->DefaultDecayTime
;
1522 // Search the ResolvedCacheTable
1526 CacheEntry
= ArpFindNextCacheEntryInTable (
1527 &ArpService
->ResolvedCacheTable
,
1533 if (CacheEntry
== NULL
) {
1535 // Once the CacheEntry is NULL, there are no more matches.
1541 // Insert the found entry into the map.
1546 (VOID
*)&ArpService
->ResolvedCacheTable
1550 // Let the next search start from this cache entry.
1552 StartEntry
= &CacheEntry
->List
;
1556 // Refresh the DecayTime if needed.
1558 CacheEntry
->DecayTime
= CacheEntry
->DefaultDecayTime
;
1562 Status
= EFI_SUCCESS
;
1564 FoundCount
= (UINT32
) NetMapGetCount (&FoundEntries
);
1565 if (FoundCount
== 0) {
1566 Status
= EFI_NOT_FOUND
;
1570 if (EntryLength
!= NULL
) {
1572 // Return the entry length, make sure its 8 bytes alignment.
1574 *EntryLength
= (((sizeof (EFI_ARP_FIND_DATA
) + Instance
->ConfigData
.SwAddressLength
+
1575 ArpService
->SnpMode
.HwAddressSize
) + 3) & ~(0x3));
1578 if (EntryCount
!= NULL
) {
1580 // Return the found entry count.
1582 *EntryCount
= FoundCount
;
1585 if (Entries
== NULL
) {
1590 // Allocate buffer to copy the found entries.
1592 FindData
= AllocatePool (FoundCount
* (*EntryLength
));
1593 if (FindData
== NULL
) {
1594 DEBUG ((EFI_D_ERROR
, "ArpFindCacheEntry: Failed to allocate memory.\n"));
1595 Status
= EFI_OUT_OF_RESOURCES
;
1600 // Return the address to the user.
1602 *Entries
= FindData
;
1605 // Dump the entries.
1607 while (!NetMapIsEmpty (&FoundEntries
)) {
1609 // Get a cache entry from the map.
1611 CacheEntry
= NetMapRemoveHead (&FoundEntries
, (VOID
**)&CacheTable
);
1614 // Set the fields in FindData.
1616 FindData
->Size
= *EntryLength
;
1617 FindData
->DenyFlag
= (BOOLEAN
)(CacheTable
== &ArpService
->DeniedCacheTable
);
1618 FindData
->StaticFlag
= (BOOLEAN
)(CacheEntry
->DefaultDecayTime
== 0);
1619 FindData
->HwAddressType
= ArpService
->SnpMode
.IfType
;
1620 FindData
->SwAddressType
= Instance
->ConfigData
.SwAddressType
;
1621 FindData
->HwAddressLength
= (UINT8
)ArpService
->SnpMode
.HwAddressSize
;
1622 FindData
->SwAddressLength
= Instance
->ConfigData
.SwAddressLength
;
1625 // Copy the software address.
1629 CacheEntry
->Addresses
[Protocol
].AddressPtr
,
1630 FindData
->SwAddressLength
1634 // Copy the hardware address.
1637 (UINT8
*)(FindData
+ 1) + FindData
->SwAddressLength
,
1638 CacheEntry
->Addresses
[Hardware
].AddressPtr
,
1639 FindData
->HwAddressLength
1643 // Slip to the next FindData.
1645 FindData
= (EFI_ARP_FIND_DATA
*)((UINT8
*)FindData
+ *EntryLength
);
1650 NetMapClean (&FoundEntries
);