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