]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/ArpDxe/ArpImpl.c
[Change summary]:
[mirror_edk2.git] / MdeModulePkg / Universal / Network / ArpDxe / ArpImpl.c
1 /** @file
2 The implementation of the ARP protocol.
3
4 Copyright (c) 2006 - 2009, 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
9
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.
12
13 **/
14
15 #include "ArpImpl.h"
16
17 //
18 // Global variable of EFI ARP Protocol Interface.
19 //
20 EFI_ARP_PROTOCOL mEfiArpProtocolTemplate = {
21 ArpConfigure,
22 ArpAdd,
23 ArpFind,
24 ArpDelete,
25 ArpFlush,
26 ArpRequest,
27 ArpCancel
28 };
29
30
31 /**
32 Initialize the instance context data.
33
34 @param[in] ArpService Pointer to the arp service context data this
35 instance belongs to.
36 @param[out] Instance Pointer to the instance context data.
37
38 @return None.
39
40 **/
41 VOID
42 ArpInitInstance (
43 IN ARP_SERVICE_DATA *ArpService,
44 OUT ARP_INSTANCE_DATA *Instance
45 )
46 {
47 NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);
48
49 Instance->Signature = ARP_INSTANCE_DATA_SIGNATURE;
50 Instance->ArpService = ArpService;
51
52 CopyMem (&Instance->ArpProto, &mEfiArpProtocolTemplate, sizeof (Instance->ArpProto));
53
54 Instance->Configured = FALSE;
55 Instance->Destroyed = FALSE;
56
57 InitializeListHead (&Instance->List);
58 }
59
60
61 /**
62 Process the Arp packets received from Mnp, the procedure conforms to RFC826.
63
64 @param[in] Context Pointer to the context data registerd to the
65 Event.
66
67 @return None.
68
69 **/
70 VOID
71 EFIAPI
72 ArpOnFrameRcvdDpc (
73 IN VOID *Context
74 )
75 {
76 EFI_STATUS Status;
77 ARP_SERVICE_DATA *ArpService;
78 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *RxToken;
79 EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData;
80 ARP_HEAD *Head;
81 ARP_ADDRESS ArpAddress;
82 ARP_CACHE_ENTRY *CacheEntry;
83 LIST_ENTRY *Entry;
84 ARP_INSTANCE_DATA *Instance;
85 EFI_ARP_CONFIG_DATA *ConfigData;
86 NET_ARP_ADDRESS SenderAddress[2];
87 BOOLEAN ProtoMatched;
88 BOOLEAN IsTarget;
89 BOOLEAN MergeFlag;
90
91 ArpService = (ARP_SERVICE_DATA *)Context;
92 NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);
93
94 RxToken = &ArpService->RxToken;
95
96 if (RxToken->Status == EFI_ABORTED) {
97 //
98 // The Token is aborted, possibly by arp itself, just return and the receiving
99 // process is stopped.
100 //
101 return;
102 }
103
104 if (EFI_ERROR (RxToken->Status)) {
105 //
106 // Restart the receiving if any other error Status occurs.
107 //
108 goto RESTART_RECEIVE;
109 }
110
111 //
112 // Status is EFI_SUCCESS, process the received frame.
113 //
114 RxData = RxToken->Packet.RxData;
115 Head = (ARP_HEAD *) RxData->PacketData;
116
117 //
118 // Convert the byte order of the multi-byte fields.
119 //
120 Head->HwType = NTOHS (Head->HwType);
121 Head->ProtoType = NTOHS (Head->ProtoType);
122 Head->OpCode = NTOHS (Head->OpCode);
123
124 if ((Head->HwType != ArpService->SnpMode.IfType) ||
125 (Head->HwAddrLen != ArpService->SnpMode.HwAddressSize) ||
126 (RxData->ProtocolType != ARP_ETHER_PROTO_TYPE)) {
127 //
128 // The hardware type or the hardware address length doesn't match.
129 // There is a sanity check for the protocol type too.
130 //
131 goto RECYCLE_RXDATA;
132 }
133
134 //
135 // Set the pointers to the addresses contained in the arp packet.
136 //
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;
141
142 SenderAddress[Hardware].Type = Head->HwType;
143 SenderAddress[Hardware].Length = Head->HwAddrLen;
144 SenderAddress[Hardware].AddressPtr = ArpAddress.SenderHwAddr;
145
146 SenderAddress[Protocol].Type = Head->ProtoType;
147 SenderAddress[Protocol].Length = Head->ProtoAddrLen;
148 SenderAddress[Protocol].AddressPtr = ArpAddress.SenderProtoAddr;
149
150 //
151 // First, check the denied cache table.
152 //
153 CacheEntry = ArpFindDeniedCacheEntry (
154 ArpService,
155 &SenderAddress[Protocol],
156 &SenderAddress[Hardware]
157 );
158 if (CacheEntry != NULL) {
159 //
160 // This address (either hardware or protocol address, or both) is configured to
161 // be a deny entry, silently skip the normal process.
162 //
163 goto RECYCLE_RXDATA;
164 }
165
166 ProtoMatched = FALSE;
167 IsTarget = FALSE;
168 Instance = NULL;
169 NET_LIST_FOR_EACH (Entry, &ArpService->ChildrenList) {
170 //
171 // Iterate all the children.
172 //
173 Instance = NET_LIST_USER_STRUCT (Entry, ARP_INSTANCE_DATA, List);
174 NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE);
175 ConfigData = &Instance->ConfigData;
176
177 if ((Instance->Configured) &&
178 (Head->ProtoType == ConfigData->SwAddressType) &&
179 (Head->ProtoAddrLen == ConfigData->SwAddressLength)) {
180 //
181 // The protocol type is matched for the received arp packet.
182 //
183 ProtoMatched = TRUE;
184 if (0 == CompareMem (
185 (VOID *)ArpAddress.TargetProtoAddr,
186 ConfigData->StationAddress,
187 ConfigData->SwAddressLength
188 )) {
189 //
190 // The arp driver has the target address required by the received arp packet.
191 //
192 IsTarget = TRUE;
193 break;
194 }
195 }
196 }
197
198 if (!ProtoMatched) {
199 //
200 // Protocol type unmatchable, skip.
201 //
202 goto RECYCLE_RXDATA;
203 }
204
205 //
206 // Check whether the sender's address information is already in the cache.
207 //
208 MergeFlag = FALSE;
209 CacheEntry = ArpFindNextCacheEntryInTable (
210 &ArpService->ResolvedCacheTable,
211 NULL,
212 ByProtoAddress,
213 &SenderAddress[Protocol],
214 NULL
215 );
216 if (CacheEntry != NULL) {
217 //
218 // Update the entry with the new information.
219 //
220 ArpFillAddressInCacheEntry (CacheEntry, &SenderAddress[Hardware], NULL);
221 CacheEntry->DecayTime = CacheEntry->DefaultDecayTime;
222 MergeFlag = TRUE;
223 }
224
225 if (!IsTarget) {
226 //
227 // This arp packet isn't targeted to us, skip now.
228 //
229 goto RECYCLE_RXDATA;
230 }
231
232 if (!MergeFlag) {
233 //
234 // Add the triplet <protocol type, sender protocol address, sender hardware address>
235 // to the translation table.
236 //
237 CacheEntry = ArpFindNextCacheEntryInTable (
238 &ArpService->PendingRequestTable,
239 NULL,
240 ByProtoAddress,
241 &SenderAddress[Protocol],
242 NULL
243 );
244 if (CacheEntry == NULL) {
245 //
246 // Allocate a new CacheEntry.
247 //
248 CacheEntry = ArpAllocCacheEntry (NULL);
249 if (CacheEntry == NULL) {
250 goto RECYCLE_RXDATA;
251 }
252 }
253
254 if (!IsListEmpty (&CacheEntry->List)) {
255 RemoveEntryList (&CacheEntry->List);
256 }
257
258 //
259 // Fill the addresses into the CacheEntry.
260 //
261 ArpFillAddressInCacheEntry (
262 CacheEntry,
263 &SenderAddress[Hardware],
264 &SenderAddress[Protocol]
265 );
266
267 //
268 // Inform the user.
269 //
270 ArpAddressResolved (CacheEntry, NULL, NULL);
271
272 //
273 // Add this entry into the ResolvedCacheTable
274 //
275 InsertHeadList (&ArpService->ResolvedCacheTable, &CacheEntry->List);
276 }
277
278 if (Head->OpCode == ARP_OPCODE_REQUEST) {
279 //
280 // Send back the ARP Reply. If we reach here, Instance is not NULL and CacheEntry
281 // is not NULL.
282 //
283 ArpSendFrame (Instance, CacheEntry, ARP_OPCODE_REPLY);
284 }
285
286 RECYCLE_RXDATA:
287
288 //
289 // Signal Mnp to recycle the RxData.
290 //
291 gBS->SignalEvent (RxData->RecycleEvent);
292
293 RESTART_RECEIVE:
294
295 //
296 // Continue to receive packets from Mnp.
297 //
298 Status = ArpService->Mnp->Receive (ArpService->Mnp, RxToken);
299
300 DEBUG_CODE (
301 if (EFI_ERROR (Status)) {
302 DEBUG ((EFI_D_ERROR, "ArpOnFrameRcvd: ArpService->Mnp->Receive "
303 "failed, %r\n.", Status));
304 }
305 );
306 }
307
308 /**
309 Queue ArpOnFrameRcvdDpc as a DPC at TPL_CALLBACK.
310
311 @param[in] Event The Event this notify function registered to.
312 @param[in] Context Pointer to the context data registerd to the
313 Event.
314
315 @return None.
316
317 **/
318 VOID
319 EFIAPI
320 ArpOnFrameRcvd (
321 IN EFI_EVENT Event,
322 IN VOID *Context
323 )
324 {
325 //
326 // Request ArpOnFrameRcvdDpc as a DPC at TPL_CALLBACK
327 //
328 QueueDpc (TPL_CALLBACK, ArpOnFrameRcvdDpc, Context);
329 }
330
331 /**
332 Process the already sent arp packets.
333
334 @param[in] Context Pointer to the context data registerd to the
335 Event.
336
337 @return None.
338
339 **/
340 VOID
341 EFIAPI
342 ArpOnFrameSentDpc (
343 IN VOID *Context
344 )
345 {
346 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TxToken;
347 EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData;
348
349 ASSERT (Context != NULL);
350
351 TxToken = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *)Context;
352 TxData = TxToken->Packet.TxData;
353
354 DEBUG_CODE (
355 if (EFI_ERROR (TxToken->Status)) {
356 DEBUG ((EFI_D_ERROR, "ArpOnFrameSent: TxToken->Status, %r.\n", TxToken->Status));
357 }
358 );
359
360 //
361 // Free the allocated memory and close the event.
362 //
363 gBS->FreePool (TxData->FragmentTable[0].FragmentBuffer);
364 gBS->FreePool (TxData);
365 gBS->CloseEvent (TxToken->Event);
366 gBS->FreePool (TxToken);
367 }
368
369 /**
370 Request ArpOnFrameSentDpc as a DPC at TPL_CALLBACK.
371
372 @param[in] Event The Event this notify function registered to.
373 @param[in] Context Pointer to the context data registerd to the
374 Event.
375
376 @return None.
377
378 **/
379 VOID
380 EFIAPI
381 ArpOnFrameSent (
382 IN EFI_EVENT Event,
383 IN VOID *Context
384 )
385 {
386 //
387 // Request ArpOnFrameSentDpc as a DPC at TPL_CALLBACK
388 //
389 QueueDpc (TPL_CALLBACK, ArpOnFrameSentDpc, Context);
390 }
391
392
393 /**
394 Process the arp cache olding and drive the retrying arp requests.
395
396 @param[in] Event The Event this notify function registered to.
397 @param[in] Context Pointer to the context data registerd to the
398 Event.
399
400 @return None.
401
402 **/
403 VOID
404 EFIAPI
405 ArpTimerHandler (
406 IN EFI_EVENT Event,
407 IN VOID *Context
408 )
409 {
410 ARP_SERVICE_DATA *ArpService;
411 LIST_ENTRY *Entry;
412 LIST_ENTRY *NextEntry;
413 LIST_ENTRY *ContextEntry;
414 ARP_CACHE_ENTRY *CacheEntry;
415 USER_REQUEST_CONTEXT *RequestContext;
416
417 ASSERT (Context != NULL);
418 ArpService = (ARP_SERVICE_DATA *)Context;
419
420 //
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.
423 //
424 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->PendingRequestTable) {
425 CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
426
427 if (CacheEntry->NextRetryTime <= ARP_PERIODIC_TIMER_INTERVAL) {
428 //
429 // Timeout, if we can retry more, send out the request again, otherwise abort
430 // this request.
431 //
432 if (CacheEntry->RetryCount == 0) {
433 //
434 // Abort this request.
435 //
436 ArpAddressResolved (CacheEntry, NULL, NULL);
437 ASSERT (IsListEmpty (&CacheEntry->UserRequestList));
438
439 RemoveEntryList (&CacheEntry->List);
440 gBS->FreePool (CacheEntry);
441 } else {
442 //
443 // resend the ARP request.
444 //
445 ASSERT (!IsListEmpty(&CacheEntry->UserRequestList));
446
447 ContextEntry = CacheEntry->UserRequestList.ForwardLink;
448 RequestContext = NET_LIST_USER_STRUCT (ContextEntry, USER_REQUEST_CONTEXT, List);
449
450 ArpSendFrame (RequestContext->Instance, CacheEntry, ARP_OPCODE_REQUEST);
451
452 CacheEntry->RetryCount--;
453 CacheEntry->NextRetryTime = RequestContext->Instance->ConfigData.RetryTimeOut;
454 }
455 } else {
456 //
457 // Update the NextRetryTime.
458 //
459 CacheEntry->NextRetryTime -= ARP_PERIODIC_TIMER_INTERVAL;
460 }
461 }
462
463 //
464 // Check the timeouts for the DeniedCacheTable.
465 //
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));
469
470 if (CacheEntry->DefaultDecayTime == 0) {
471 //
472 // It's a static entry, skip it.
473 //
474 continue;
475 }
476
477 if (CacheEntry->DecayTime <= ARP_PERIODIC_TIMER_INTERVAL) {
478 //
479 // Time out, remove it.
480 //
481 RemoveEntryList (&CacheEntry->List);
482 gBS->FreePool (CacheEntry);
483 } else {
484 //
485 // Update the DecayTime.
486 //
487 CacheEntry->DecayTime -= ARP_PERIODIC_TIMER_INTERVAL;
488 }
489 }
490
491 //
492 // Check the timeouts for the ResolvedCacheTable.
493 //
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));
497
498 if (CacheEntry->DefaultDecayTime == 0) {
499 //
500 // It's a static entry, skip it.
501 //
502 continue;
503 }
504
505 if (CacheEntry->DecayTime <= ARP_PERIODIC_TIMER_INTERVAL) {
506 //
507 // Time out, remove it.
508 //
509 RemoveEntryList (&CacheEntry->List);
510 gBS->FreePool (CacheEntry);
511 } else {
512 //
513 // Update the DecayTime.
514 //
515 CacheEntry->DecayTime -= ARP_PERIODIC_TIMER_INTERVAL;
516 }
517 }
518 }
519
520
521 /**
522 Match the two NET_ARP_ADDRESSes.
523
524 @param[in] AddressOne Pointer to the first address to match.
525 @param[in] AddressTwo Pointer to the second address to match.
526
527 @return The two addresses match or not.
528
529 **/
530 BOOLEAN
531 ArpMatchAddress (
532 IN NET_ARP_ADDRESS *AddressOne,
533 IN NET_ARP_ADDRESS *AddressTwo
534 )
535 {
536 if ((AddressOne->Type != AddressTwo->Type) ||
537 (AddressOne->Length != AddressTwo->Length)) {
538 //
539 // Either Type or Length doesn't match.
540 //
541 return FALSE;
542 }
543
544 if ((AddressOne->AddressPtr != NULL) &&
545 (CompareMem (
546 AddressOne->AddressPtr,
547 AddressTwo->AddressPtr,
548 AddressOne->Length
549 ) != 0)) {
550 //
551 // The address is not the same.
552 //
553 return FALSE;
554 }
555
556 return TRUE;
557 }
558
559
560 /**
561 Find the CacheEntry which matches the requirements in the specified CacheTable.
562
563 @param[in] CacheTable Pointer to the arp cache table.
564 @param[in] StartEntry Pointer to the start entry this search begins with
565 in the cache table.
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.
569
570 @return Pointer to the matched arp cache entry, if NULL, no match is found.
571
572 **/
573 ARP_CACHE_ENTRY *
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
580 )
581 {
582 LIST_ENTRY *Entry;
583 ARP_CACHE_ENTRY *CacheEntry;
584
585 if (StartEntry == NULL) {
586 //
587 // Start from the beginning of the table if no StartEntry is specified.
588 //
589 StartEntry = CacheTable;
590 }
591
592 for (Entry = StartEntry->ForwardLink; Entry != CacheTable; Entry = Entry->ForwardLink) {
593 CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
594
595 if ((FindOpType & MATCH_SW_ADDRESS) != 0) {
596 //
597 // Find by the software address.
598 //
599 if (!ArpMatchAddress (ProtocolAddress, &CacheEntry->Addresses[Protocol])) {
600 //
601 // The ProtocolAddress doesn't match, continue to the next cache entry.
602 //
603 continue;
604 }
605 }
606
607 if ((FindOpType & MATCH_HW_ADDRESS) != 0) {
608 //
609 // Find by the hardware address.
610 //
611 if (!ArpMatchAddress (HardwareAddress, &CacheEntry->Addresses[Hardware])) {
612 //
613 // The HardwareAddress doesn't match, continue to the next cache entry.
614 //
615 continue;
616 }
617 }
618
619 //
620 // The CacheEntry meets the requirements now, return this entry.
621 //
622 return CacheEntry;
623 }
624
625 //
626 // No matching.
627 //
628 return NULL;
629 }
630
631
632 /**
633 Find the CacheEntry, using ProtocolAddress or HardwareAddress or both, as the keyword,
634 in the DeniedCacheTable.
635
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.
639
640 @return Pointer to the matched cache entry, if NULL no match is found.
641
642 **/
643 ARP_CACHE_ENTRY *
644 ArpFindDeniedCacheEntry (
645 IN ARP_SERVICE_DATA *ArpService,
646 IN NET_ARP_ADDRESS *ProtocolAddress OPTIONAL,
647 IN NET_ARP_ADDRESS *HardwareAddress OPTIONAL
648 )
649 {
650 ARP_CACHE_ENTRY *CacheEntry;
651
652 ASSERT ((ProtocolAddress != NULL) || (HardwareAddress != NULL));
653 NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);
654
655 CacheEntry = NULL;
656
657 if ((ProtocolAddress != NULL) && (ProtocolAddress->AddressPtr != NULL)) {
658 //
659 // Find the cache entry in the DeniedCacheTable by the protocol address.
660 //
661 CacheEntry = ArpFindNextCacheEntryInTable (
662 &ArpService->DeniedCacheTable,
663 NULL,
664 ByProtoAddress,
665 ProtocolAddress,
666 NULL
667 );
668 if (CacheEntry != NULL) {
669 //
670 // There is a match.
671 //
672 return CacheEntry;
673 }
674 }
675
676 if ((HardwareAddress != NULL) && (HardwareAddress->AddressPtr != NULL)) {
677 //
678 // Find the cache entry in the DeniedCacheTable by the hardware address.
679 //
680 CacheEntry = ArpFindNextCacheEntryInTable (
681 &ArpService->DeniedCacheTable,
682 NULL,
683 ByHwAddress,
684 NULL,
685 HardwareAddress
686 );
687 }
688
689 return CacheEntry;
690 }
691
692
693 /**
694 Allocate a cache entry and initialize it.
695
696 @param[in] Instance Pointer to the instance context data.
697
698 @return Pointer to the new created cache entry.
699
700 **/
701 ARP_CACHE_ENTRY *
702 ArpAllocCacheEntry (
703 IN ARP_INSTANCE_DATA *Instance
704 )
705 {
706 ARP_CACHE_ENTRY *CacheEntry;
707 NET_ARP_ADDRESS *Address;
708 UINT16 Index;
709
710 //
711 // Allocate memory for the cache entry.
712 //
713 CacheEntry = AllocatePool (sizeof (ARP_CACHE_ENTRY));
714 if (CacheEntry == NULL) {
715 return NULL;
716 }
717
718 //
719 // Init the lists.
720 //
721 InitializeListHead (&CacheEntry->List);
722 InitializeListHead (&CacheEntry->UserRequestList);
723
724 for (Index = 0; Index < 2; Index++) {
725 //
726 // Init the address pointers to point to the concrete buffer.
727 //
728 Address = &CacheEntry->Addresses[Index];
729 Address->AddressPtr = Address->Buffer.ProtoAddress;
730 }
731
732 //
733 // Zero the hardware address first.
734 //
735 ZeroMem (CacheEntry->Addresses[Hardware].AddressPtr, ARP_MAX_HARDWARE_ADDRESS_LEN);
736
737 if (Instance != NULL) {
738 //
739 // Inherit the parameters from the instance configuration.
740 //
741 CacheEntry->RetryCount = Instance->ConfigData.RetryCount;
742 CacheEntry->NextRetryTime = Instance->ConfigData.RetryTimeOut;
743 CacheEntry->DefaultDecayTime = Instance->ConfigData.EntryTimeOut;
744 CacheEntry->DecayTime = Instance->ConfigData.EntryTimeOut;
745 } else {
746 //
747 // Use the default parameters if this cache entry isn't allocate in a
748 // instance's scope.
749 //
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;
754 }
755
756 return CacheEntry;
757 }
758
759
760 /**
761 Turn the CacheEntry into the resolved status.
762
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.
766
767 @return The count of notifications sent to the instance.
768
769 **/
770 UINTN
771 ArpAddressResolved (
772 IN ARP_CACHE_ENTRY *CacheEntry,
773 IN ARP_INSTANCE_DATA *Instance OPTIONAL,
774 IN EFI_EVENT UserEvent OPTIONAL
775 )
776 {
777 LIST_ENTRY *Entry;
778 LIST_ENTRY *NextEntry;
779 USER_REQUEST_CONTEXT *Context;
780 UINTN Count;
781
782 Count = 0;
783
784 //
785 // Iterate all the linked user requests to notify them.
786 //
787 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &CacheEntry->UserRequestList) {
788 Context = NET_LIST_USER_STRUCT (Entry, USER_REQUEST_CONTEXT, List);
789
790 if (((Instance == NULL) || (Context->Instance == Instance)) &&
791 ((UserEvent == NULL) || (Context->UserRequestEvent == UserEvent))) {
792 //
793 // Copy the address to the user-provided buffer and notify the user.
794 //
795 CopyMem (
796 Context->UserHwAddrBuffer,
797 CacheEntry->Addresses[Hardware].AddressPtr,
798 CacheEntry->Addresses[Hardware].Length
799 );
800 gBS->SignalEvent (Context->UserRequestEvent);
801
802 //
803 // Remove this user request and free the context data.
804 //
805 RemoveEntryList (&Context->List);
806 gBS->FreePool (Context);
807
808 Count++;
809 }
810 }
811
812 //
813 // Dispatch the DPCs queued by the NotifyFunction of the Context->UserRequestEvent.
814 //
815 DispatchDpc ();
816
817 return Count;
818 }
819
820
821 /**
822 Fill the addresses in the CacheEntry using the information passed in by
823 HwAddr and SwAddr.
824
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.
828
829 @return None.
830
831 **/
832 VOID
833 ArpFillAddressInCacheEntry (
834 IN ARP_CACHE_ENTRY *CacheEntry,
835 IN NET_ARP_ADDRESS *HwAddr OPTIONAL,
836 IN NET_ARP_ADDRESS *SwAddr OPTIONAL
837 )
838 {
839 NET_ARP_ADDRESS *Address[2];
840 NET_ARP_ADDRESS *CacheAddress;
841 UINT32 Index;
842
843 Address[Hardware] = HwAddr;
844 Address[Protocol] = SwAddr;
845
846 for (Index = 0; Index < 2; Index++) {
847 if (Address[Index] != NULL) {
848 //
849 // Fill the address if the passed in pointer is not NULL.
850 //
851 CacheAddress = &CacheEntry->Addresses[Index];
852
853 CacheAddress->Type = Address[Index]->Type;
854 CacheAddress->Length = Address[Index]->Length;
855
856 if (Address[Index]->AddressPtr != NULL) {
857 //
858 // Copy it if the AddressPtr points to some buffer.
859 //
860 CopyMem (
861 CacheAddress->AddressPtr,
862 Address[Index]->AddressPtr,
863 CacheAddress->Length
864 );
865 } else {
866 //
867 // Zero the corresponding address buffer in the CacheEntry.
868 //
869 ZeroMem (CacheAddress->AddressPtr, CacheAddress->Length);
870 }
871 }
872 }
873 }
874
875
876 /**
877 Configure the instance using the ConfigData. ConfigData is already validated.
878
879 @param[in] Instance Pointer to the instance context data to be
880 configured.
881 @param[in] ConfigData Pointer to the configuration data used to
882 configure the instance.
883
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
887 fields.
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
891 limitation.
892
893 **/
894 EFI_STATUS
895 ArpConfigureInstance (
896 IN ARP_INSTANCE_DATA *Instance,
897 IN EFI_ARP_CONFIG_DATA *ConfigData OPTIONAL
898 )
899 {
900 EFI_ARP_CONFIG_DATA *OldConfigData;
901 IP4_ADDR Ip;
902
903 OldConfigData = &Instance->ConfigData;
904
905 if (ConfigData != NULL) {
906
907 if (Instance->Configured) {
908 //
909 // The instance is configured, check the unchangeable fields.
910 //
911 if ((OldConfigData->SwAddressType != ConfigData->SwAddressType) ||
912 (OldConfigData->SwAddressLength != ConfigData->SwAddressLength) ||
913 (CompareMem (
914 OldConfigData->StationAddress,
915 ConfigData->StationAddress,
916 OldConfigData->SwAddressLength
917 ) != 0)) {
918 //
919 // Deny the unallowed changes.
920 //
921 return EFI_ACCESS_DENIED;
922 }
923 } else {
924 //
925 // The instance is not configured.
926 //
927
928 if (ConfigData->SwAddressType == IPV4_ETHER_PROTO_TYPE) {
929 CopyMem (&Ip, ConfigData->StationAddress, sizeof (IP4_ADDR));
930
931 if (!NetIp4IsUnicast (NTOHL (Ip), 0)) {
932 //
933 // The station address is not a valid IPv4 unicast address.
934 //
935 return EFI_INVALID_PARAMETER;
936 }
937 }
938
939 //
940 // Save the configuration.
941 //
942 CopyMem (OldConfigData, ConfigData, sizeof (*OldConfigData));
943
944 OldConfigData->StationAddress = AllocatePool (OldConfigData->SwAddressLength);
945 if (OldConfigData->StationAddress == NULL) {
946 DEBUG ((EFI_D_ERROR, "ArpConfigInstance: AllocatePool for the StationAddress "
947 "failed.\n"));
948 return EFI_OUT_OF_RESOURCES;
949 }
950
951 //
952 // Save the StationAddress.
953 //
954 CopyMem (
955 OldConfigData->StationAddress,
956 ConfigData->StationAddress,
957 OldConfigData->SwAddressLength
958 );
959
960 //
961 // Set the state to configured.
962 //
963 Instance->Configured = TRUE;
964 }
965
966 //
967 // Use the implementation specific values if the following field is zero.
968 //
969 OldConfigData->EntryTimeOut = (ConfigData->EntryTimeOut == 0) ?
970 ARP_DEFAULT_TIMEOUT_VALUE : ConfigData->EntryTimeOut;
971
972 OldConfigData->RetryCount = (ConfigData->RetryCount == 0) ?
973 ARP_DEFAULT_RETRY_COUNT : ConfigData->RetryCount;
974
975 OldConfigData->RetryTimeOut = (ConfigData->RetryTimeOut == 0) ?
976 ARP_DEFAULT_RETRY_INTERVAL : ConfigData->RetryTimeOut;
977 } else {
978 //
979 // Reset the configuration.
980 //
981
982 if (Instance->Configured) {
983 //
984 // Cancel the arp requests issued by this instance.
985 //
986 Instance->ArpProto.Cancel (&Instance->ArpProto, NULL, NULL);
987
988 //
989 // Free the buffer previously allocated to hold the station address.
990 //
991 gBS->FreePool (OldConfigData->StationAddress);
992 }
993
994 Instance->Configured = FALSE;
995 }
996
997 return EFI_SUCCESS;
998 }
999
1000
1001 /**
1002 Send out an arp frame using the CachEntry and the ArpOpCode.
1003
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
1008 request or reply.
1009
1010 @return None.
1011
1012 **/
1013 VOID
1014 ArpSendFrame (
1015 IN ARP_INSTANCE_DATA *Instance,
1016 IN ARP_CACHE_ENTRY *CacheEntry,
1017 IN UINT16 ArpOpCode
1018 )
1019 {
1020 EFI_STATUS Status;
1021 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TxToken;
1022 EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData;
1023 UINT32 TotalLength;
1024 UINT8 *Packet;
1025 ARP_SERVICE_DATA *ArpService;
1026 EFI_SIMPLE_NETWORK_MODE *SnpMode;
1027 EFI_ARP_CONFIG_DATA *ConfigData;
1028 UINT8 *TmpPtr;
1029 ARP_HEAD *ArpHead;
1030
1031 ASSERT ((Instance != NULL) && (CacheEntry != NULL));
1032
1033 //
1034 // Allocate memory for the TxToken.
1035 //
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"));
1039 return;
1040 }
1041
1042 TxToken->Event = NULL;
1043 TxData = NULL;
1044 Packet = NULL;
1045
1046 //
1047 // Create the event for this TxToken.
1048 //
1049 Status = gBS->CreateEvent (
1050 EVT_NOTIFY_SIGNAL,
1051 TPL_NOTIFY,
1052 ArpOnFrameSent,
1053 (VOID *)TxToken,
1054 &TxToken->Event
1055 );
1056 if (EFI_ERROR (Status)) {
1057 DEBUG ((EFI_D_ERROR, "ArpSendFrame: CreateEvent failed for TxToken->Event.\n"));
1058 goto CLEAN_EXIT;
1059 }
1060
1061 //
1062 // Allocate memory for the TxData used in the TxToken.
1063 //
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"));
1067 goto CLEAN_EXIT;
1068 }
1069
1070 ArpService = Instance->ArpService;
1071 SnpMode = &ArpService->SnpMode;
1072 ConfigData = &Instance->ConfigData;
1073
1074 //
1075 // Calculate the buffer length for this arp frame.
1076 //
1077 TotalLength = SnpMode->MediaHeaderSize + sizeof (ARP_HEAD) +
1078 2 * (ConfigData->SwAddressLength + SnpMode->HwAddressSize);
1079
1080 //
1081 // Allocate buffer for the arp frame.
1082 //
1083 Packet = AllocatePool (TotalLength);
1084 if (Packet == NULL) {
1085 DEBUG ((EFI_D_ERROR, "ArpSendFrame: Allocate memory for Packet failed.\n"));
1086 ASSERT (Packet != NULL);
1087 }
1088
1089 TmpPtr = Packet;
1090
1091 //
1092 // The destination MAC address.
1093 //
1094 if (ArpOpCode == ARP_OPCODE_REQUEST) {
1095 CopyMem (TmpPtr, &SnpMode->BroadcastAddress, SnpMode->HwAddressSize);
1096 } else {
1097 CopyMem (
1098 TmpPtr,
1099 CacheEntry->Addresses[Hardware].AddressPtr,
1100 SnpMode->HwAddressSize
1101 );
1102 }
1103 TmpPtr += SnpMode->HwAddressSize;
1104
1105 //
1106 // The source MAC address.
1107 //
1108 CopyMem (TmpPtr, &SnpMode->CurrentAddress, SnpMode->HwAddressSize);
1109 TmpPtr += SnpMode->HwAddressSize;
1110
1111 //
1112 // The ethernet protocol type.
1113 //
1114 *(UINT16 *)TmpPtr = HTONS (ARP_ETHER_PROTO_TYPE);
1115 TmpPtr += 2;
1116
1117 //
1118 // The ARP Head.
1119 //
1120 ArpHead = (ARP_HEAD *) TmpPtr;
1121 ArpHead->HwType = HTONS ((UINT16)SnpMode->IfType);
1122 ArpHead->ProtoType = HTONS (ConfigData->SwAddressType);
1123 ArpHead->HwAddrLen = (UINT8)SnpMode->HwAddressSize;
1124 ArpHead->ProtoAddrLen = ConfigData->SwAddressLength;
1125 ArpHead->OpCode = HTONS (ArpOpCode);
1126 TmpPtr += sizeof (ARP_HEAD);
1127
1128 //
1129 // The sender hardware address.
1130 //
1131 CopyMem (TmpPtr, &SnpMode->CurrentAddress, SnpMode->HwAddressSize);
1132 TmpPtr += SnpMode->HwAddressSize;
1133
1134 //
1135 // The sender protocol address.
1136 //
1137 CopyMem (TmpPtr, ConfigData->StationAddress, ConfigData->SwAddressLength);
1138 TmpPtr += ConfigData->SwAddressLength;
1139
1140 //
1141 // The target hardware address.
1142 //
1143 CopyMem (
1144 TmpPtr,
1145 CacheEntry->Addresses[Hardware].AddressPtr,
1146 SnpMode->HwAddressSize
1147 );
1148 TmpPtr += SnpMode->HwAddressSize;
1149
1150 //
1151 // The target protocol address.
1152 //
1153 CopyMem (
1154 TmpPtr,
1155 CacheEntry->Addresses[Protocol].AddressPtr,
1156 ConfigData->SwAddressLength
1157 );
1158
1159 //
1160 // Set all the fields of the TxData.
1161 //
1162 TxData->DestinationAddress = NULL;
1163 TxData->SourceAddress = NULL;
1164 TxData->ProtocolType = 0;
1165 TxData->DataLength = TotalLength - SnpMode->MediaHeaderSize;
1166 TxData->HeaderLength = (UINT16) SnpMode->MediaHeaderSize;
1167 TxData->FragmentCount = 1;
1168
1169 TxData->FragmentTable[0].FragmentBuffer = Packet;
1170 TxData->FragmentTable[0].FragmentLength = TotalLength;
1171
1172 //
1173 // Associate the TxData with the TxToken.
1174 //
1175 TxToken->Packet.TxData = TxData;
1176 TxToken->Status = EFI_NOT_READY;
1177
1178 //
1179 // Send out this arp packet by Mnp.
1180 //
1181 Status = ArpService->Mnp->Transmit (ArpService->Mnp, TxToken);
1182 if (EFI_ERROR (Status)) {
1183 DEBUG ((EFI_D_ERROR, "Mnp->Transmit failed, %r.\n", Status));
1184 goto CLEAN_EXIT;
1185 }
1186
1187 return;
1188
1189 CLEAN_EXIT:
1190
1191 if (Packet != NULL) {
1192 gBS->FreePool (Packet);
1193 }
1194
1195 if (TxData != NULL) {
1196 gBS->FreePool (TxData);
1197 }
1198
1199 if (TxToken->Event != NULL) {
1200 gBS->CloseEvent (TxToken->Event);
1201 }
1202
1203 gBS->FreePool (TxToken);
1204 }
1205
1206
1207 /**
1208 Delete the cache entries in the specified CacheTable, using the BySwAddress,
1209 SwAddressType, AddressBuffer combination as the matching key, if Force is TRUE,
1210 the cache is deleted event it's a static entry.
1211
1212 @param[in] CacheTable Pointer to the cache table to do the deletion.
1213 @param[in] BySwAddress Delete the cache entry by software address or by
1214 hardware address.
1215 @param[in] SwAddressType The software address used to do the deletion.
1216 @param[in] AddressBuffer Pointer to the buffer containing the address to
1217 match for the deletion.
1218 @param[in] Force This deletion is forced or not.
1219
1220 @return The count of the deleted cache entries.
1221
1222 **/
1223 UINTN
1224 ArpDeleteCacheEntryInTable (
1225 IN LIST_ENTRY *CacheTable,
1226 IN BOOLEAN BySwAddress,
1227 IN UINT16 SwAddressType,
1228 IN UINT8 *AddressBuffer OPTIONAL,
1229 IN BOOLEAN Force
1230 )
1231 {
1232 LIST_ENTRY *Entry;
1233 LIST_ENTRY *NextEntry;
1234 ARP_CACHE_ENTRY *CacheEntry;
1235 UINTN Count;
1236
1237 Count = 0;
1238
1239 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, CacheTable) {
1240 CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
1241
1242 if ((CacheEntry->DefaultDecayTime == 0) && !Force) {
1243 //
1244 // It's a static entry and we are not forced to delete it, skip.
1245 //
1246 continue;
1247 }
1248
1249 if (BySwAddress) {
1250 if (SwAddressType == CacheEntry->Addresses[Protocol].Type) {
1251 //
1252 // Protocol address type matched. Check the address.
1253 //
1254 if ((AddressBuffer == NULL) ||
1255 (CompareMem (
1256 AddressBuffer,
1257 CacheEntry->Addresses[Protocol].AddressPtr,
1258 CacheEntry->Addresses[Protocol].Length
1259 ) == 0)) {
1260 //
1261 // Address matched.
1262 //
1263 goto MATCHED;
1264 }
1265 }
1266 } else {
1267 if ((AddressBuffer == NULL) ||
1268 (CompareMem (
1269 AddressBuffer,
1270 CacheEntry->Addresses[Hardware].AddressPtr,
1271 CacheEntry->Addresses[Hardware].Length
1272 ) == 0)) {
1273 //
1274 // Address matched.
1275 //
1276 goto MATCHED;
1277 }
1278 }
1279
1280 continue;
1281
1282 MATCHED:
1283
1284 //
1285 // Delete this entry.
1286 //
1287 RemoveEntryList (&CacheEntry->List);
1288 ASSERT (IsListEmpty (&CacheEntry->UserRequestList));
1289 gBS->FreePool (CacheEntry);
1290
1291 Count++;
1292 }
1293
1294 return Count;
1295 }
1296
1297
1298 /**
1299 Delete cache entries in all the cache tables.
1300
1301 @param[in] Instance Pointer to the instance context data.
1302 @param[in] BySwAddress Delete the cache entry by software address or by
1303 hardware address.
1304 @param[in] AddressBuffer Pointer to the buffer containing the address to
1305 match for the deletion.
1306 @param[in] Force This deletion is forced or not.
1307
1308 @return The count of the deleted cache entries.
1309
1310 **/
1311 UINTN
1312 ArpDeleteCacheEntry (
1313 IN ARP_INSTANCE_DATA *Instance,
1314 IN BOOLEAN BySwAddress,
1315 IN UINT8 *AddressBuffer OPTIONAL,
1316 IN BOOLEAN Force
1317 )
1318 {
1319 ARP_SERVICE_DATA *ArpService;
1320 UINTN Count;
1321
1322 NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE);
1323
1324 ArpService = Instance->ArpService;
1325
1326 //
1327 // Delete the cache entries in the DeniedCacheTable.
1328 //
1329 Count = ArpDeleteCacheEntryInTable (
1330 &ArpService->DeniedCacheTable,
1331 BySwAddress,
1332 Instance->ConfigData.SwAddressType,
1333 AddressBuffer,
1334 Force
1335 );
1336
1337 //
1338 // Delete the cache entries inthe ResolvedCacheTable.
1339 //
1340 Count += ArpDeleteCacheEntryInTable (
1341 &ArpService->ResolvedCacheTable,
1342 BySwAddress,
1343 Instance->ConfigData.SwAddressType,
1344 AddressBuffer,
1345 Force
1346 );
1347
1348 return Count;
1349 }
1350
1351
1352 /**
1353 Cancel the arp request.
1354
1355 @param[in] Instance Pointer to the instance context data.
1356 @param[in] TargetSwAddress Pointer to the buffer containing the target
1357 software address to match the arp request.
1358 @param[in] UserEvent The user event used to notify this request
1359 cancellation.
1360
1361 @return The count of the cancelled requests.
1362
1363 **/
1364 UINTN
1365 ArpCancelRequest (
1366 IN ARP_INSTANCE_DATA *Instance,
1367 IN VOID *TargetSwAddress OPTIONAL,
1368 IN EFI_EVENT UserEvent OPTIONAL
1369 )
1370 {
1371 ARP_SERVICE_DATA *ArpService;
1372 LIST_ENTRY *Entry;
1373 LIST_ENTRY *NextEntry;
1374 ARP_CACHE_ENTRY *CacheEntry;
1375 UINTN Count;
1376
1377 NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE);
1378
1379 ArpService = Instance->ArpService;
1380
1381 Count = 0;
1382 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->PendingRequestTable) {
1383 CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
1384
1385 if ((TargetSwAddress == NULL) ||
1386 (CompareMem (
1387 TargetSwAddress,
1388 CacheEntry->Addresses[Protocol].AddressPtr,
1389 CacheEntry->Addresses[Protocol].Length
1390 ) == 0)) {
1391 //
1392 // This request entry matches the TargetSwAddress or all requests are to be
1393 // cancelled as TargetSwAddress is NULL.
1394 //
1395 Count += ArpAddressResolved (CacheEntry, Instance, UserEvent);
1396
1397 if (IsListEmpty (&CacheEntry->UserRequestList)) {
1398 //
1399 // No user requests any more, remove this request cache entry.
1400 //
1401 RemoveEntryList (&CacheEntry->List);
1402 gBS->FreePool (CacheEntry);
1403 }
1404 }
1405 }
1406
1407 return Count;
1408 }
1409
1410
1411 /**
1412 Find the cache entry in the cache table.
1413
1414 @param[in] Instance Pointer to the instance context data.
1415 @param[in] BySwAddress Set to TRUE to look for matching software protocol
1416 addresses. Set to FALSE to look for matching
1417 hardware protocol addresses.
1418 @param[in] AddressBuffer Pointer to address buffer. Set to NULL to match
1419 all addresses.
1420 @param[out] EntryLength The size of an entry in the entries buffer.
1421 @param[out] EntryCount The number of ARP cache entries that are found by
1422 the specified criteria.
1423 @param[out] Entries Pointer to the buffer that will receive the ARP
1424 cache entries.
1425 @param[in] Refresh Set to TRUE to refresh the timeout value of the
1426 matching ARP cache entry.
1427
1428 @retval EFI_SUCCESS The requested ARP cache entries are copied into
1429 the buffer.
1430 @retval EFI_NOT_FOUND No matching entries found.
1431 @retval EFI_OUT_OF_RESOURCE There is a memory allocation failure.
1432
1433 **/
1434 EFI_STATUS
1435 ArpFindCacheEntry (
1436 IN ARP_INSTANCE_DATA *Instance,
1437 IN BOOLEAN BySwAddress,
1438 IN VOID *AddressBuffer OPTIONAL,
1439 OUT UINT32 *EntryLength OPTIONAL,
1440 OUT UINT32 *EntryCount OPTIONAL,
1441 OUT EFI_ARP_FIND_DATA **Entries OPTIONAL,
1442 IN BOOLEAN Refresh
1443 )
1444 {
1445 EFI_STATUS Status;
1446 ARP_SERVICE_DATA *ArpService;
1447 NET_ARP_ADDRESS MatchAddress;
1448 FIND_OPTYPE FindOpType;
1449 LIST_ENTRY *StartEntry;
1450 ARP_CACHE_ENTRY *CacheEntry;
1451 NET_MAP FoundEntries;
1452 UINT32 FoundCount;
1453 EFI_ARP_FIND_DATA *FindData;
1454 LIST_ENTRY *CacheTable;
1455 UINT32 FoundEntryLength;
1456
1457 ArpService = Instance->ArpService;
1458
1459 //
1460 // Init the FounEntries used to hold the found cache entries.
1461 //
1462 NetMapInit (&FoundEntries);
1463
1464 //
1465 // Set the MatchAddress.
1466 //
1467 if (BySwAddress) {
1468 MatchAddress.Type = Instance->ConfigData.SwAddressType;
1469 MatchAddress.Length = Instance->ConfigData.SwAddressLength;
1470 FindOpType = ByProtoAddress;
1471 } else {
1472 MatchAddress.Type = ArpService->SnpMode.IfType;
1473 MatchAddress.Length = (UINT8)ArpService->SnpMode.HwAddressSize;
1474 FindOpType = ByHwAddress;
1475 }
1476
1477 MatchAddress.AddressPtr = AddressBuffer;
1478
1479 //
1480 // Search the DeniedCacheTable
1481 //
1482 StartEntry = NULL;
1483 while (TRUE) {
1484 //
1485 // Try to find the matched entries in the DeniedCacheTable.
1486 //
1487 CacheEntry = ArpFindNextCacheEntryInTable (
1488 &ArpService->DeniedCacheTable,
1489 StartEntry,
1490 FindOpType,
1491 &MatchAddress,
1492 &MatchAddress
1493 );
1494 if (CacheEntry == NULL) {
1495 //
1496 // Once the CacheEntry is NULL, there are no more matches.
1497 //
1498 break;
1499 }
1500
1501 //
1502 // Insert the found entry into the map.
1503 //
1504 NetMapInsertTail (
1505 &FoundEntries,
1506 (VOID *)CacheEntry,
1507 (VOID *)&ArpService->DeniedCacheTable
1508 );
1509
1510 //
1511 // Let the next search start from this cache entry.
1512 //
1513 StartEntry = &CacheEntry->List;
1514
1515 if (Refresh) {
1516 //
1517 // Refresh the DecayTime if needed.
1518 //
1519 CacheEntry->DecayTime = CacheEntry->DefaultDecayTime;
1520 }
1521 }
1522
1523 //
1524 // Search the ResolvedCacheTable
1525 //
1526 StartEntry = NULL;
1527 while (TRUE) {
1528 CacheEntry = ArpFindNextCacheEntryInTable (
1529 &ArpService->ResolvedCacheTable,
1530 StartEntry,
1531 FindOpType,
1532 &MatchAddress,
1533 &MatchAddress
1534 );
1535 if (CacheEntry == NULL) {
1536 //
1537 // Once the CacheEntry is NULL, there are no more matches.
1538 //
1539 break;
1540 }
1541
1542 //
1543 // Insert the found entry into the map.
1544 //
1545 NetMapInsertTail (
1546 &FoundEntries,
1547 (VOID *)CacheEntry,
1548 (VOID *)&ArpService->ResolvedCacheTable
1549 );
1550
1551 //
1552 // Let the next search start from this cache entry.
1553 //
1554 StartEntry = &CacheEntry->List;
1555
1556 if (Refresh) {
1557 //
1558 // Refresh the DecayTime if needed.
1559 //
1560 CacheEntry->DecayTime = CacheEntry->DefaultDecayTime;
1561 }
1562 }
1563
1564 Status = EFI_SUCCESS;
1565
1566 FoundCount = (UINT32) NetMapGetCount (&FoundEntries);
1567 if (FoundCount == 0) {
1568 Status = EFI_NOT_FOUND;
1569 goto CLEAN_EXIT;
1570 }
1571
1572 //
1573 // Found the entry length, make sure its 8 bytes alignment.
1574 //
1575 FoundEntryLength = (((sizeof (EFI_ARP_FIND_DATA) + Instance->ConfigData.SwAddressLength +
1576 ArpService->SnpMode.HwAddressSize) + 3) & ~(0x3));
1577
1578 if (EntryLength != NULL) {
1579 *EntryLength = FoundEntryLength;
1580 }
1581
1582 if (EntryCount != NULL) {
1583 //
1584 // Return the found entry count.
1585 //
1586 *EntryCount = FoundCount;
1587 }
1588
1589 if (Entries == NULL) {
1590 goto CLEAN_EXIT;
1591 }
1592
1593 //
1594 // Allocate buffer to copy the found entries.
1595 //
1596 FindData = AllocatePool (FoundCount * FoundEntryLength);
1597 if (FindData == NULL) {
1598 DEBUG ((EFI_D_ERROR, "ArpFindCacheEntry: Failed to allocate memory.\n"));
1599 Status = EFI_OUT_OF_RESOURCES;
1600 goto CLEAN_EXIT;
1601 }
1602
1603 //
1604 // Return the address to the user.
1605 //
1606 *Entries = FindData;
1607
1608 //
1609 // Dump the entries.
1610 //
1611 while (!NetMapIsEmpty (&FoundEntries)) {
1612 //
1613 // Get a cache entry from the map.
1614 //
1615 CacheEntry = NetMapRemoveHead (&FoundEntries, (VOID **)&CacheTable);
1616
1617 //
1618 // Set the fields in FindData.
1619 //
1620 FindData->Size = FoundEntryLength;
1621 FindData->DenyFlag = (BOOLEAN)(CacheTable == &ArpService->DeniedCacheTable);
1622 FindData->StaticFlag = (BOOLEAN)(CacheEntry->DefaultDecayTime == 0);
1623 FindData->HwAddressType = ArpService->SnpMode.IfType;
1624 FindData->SwAddressType = Instance->ConfigData.SwAddressType;
1625 FindData->HwAddressLength = (UINT8)ArpService->SnpMode.HwAddressSize;
1626 FindData->SwAddressLength = Instance->ConfigData.SwAddressLength;
1627
1628 //
1629 // Copy the software address.
1630 //
1631 CopyMem (
1632 FindData + 1,
1633 CacheEntry->Addresses[Protocol].AddressPtr,
1634 FindData->SwAddressLength
1635 );
1636
1637 //
1638 // Copy the hardware address.
1639 //
1640 CopyMem (
1641 (UINT8 *)(FindData + 1) + FindData->SwAddressLength,
1642 CacheEntry->Addresses[Hardware].AddressPtr,
1643 FindData->HwAddressLength
1644 );
1645
1646 //
1647 // Slip to the next FindData.
1648 //
1649 FindData = (EFI_ARP_FIND_DATA *)((UINT8 *)FindData + FoundEntryLength);
1650 }
1651
1652 CLEAN_EXIT:
1653
1654 NetMapClean (&FoundEntries);
1655
1656 return Status;
1657 }
1658