]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/ArpDxe/ArpImpl.c
797ebd0ba08528805d3c6225c2e0b3715b6d86a3
[mirror_edk2.git] / MdeModulePkg / Universal / Network / ArpDxe / ArpImpl.c
1 /** @file
2
3 Copyright (c) 2006 - 2007, 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 STATIC
535 BOOLEAN
536 ArpMatchAddress (
537 IN NET_ARP_ADDRESS *AddressOne,
538 IN NET_ARP_ADDRESS *AddressTwo
539 )
540 {
541 if ((AddressOne->Type != AddressTwo->Type) ||
542 (AddressOne->Length != AddressTwo->Length)) {
543 //
544 // Either Type or Length doesn't match.
545 //
546 return FALSE;
547 }
548
549 if ((AddressOne->AddressPtr != NULL) &&
550 (CompareMem (
551 AddressOne->AddressPtr,
552 AddressTwo->AddressPtr,
553 AddressOne->Length
554 ) != 0)) {
555 //
556 // The address is not the same.
557 //
558 return FALSE;
559 }
560
561 return TRUE;
562 }
563
564
565 /**
566 Find the CacheEntry which matches the requirements in the specified CacheTable.
567
568 @param CacheTable Pointer to the arp cache table.
569 @param StartEntry Pointer to the start entry this search begins with
570 in the cache table.
571 @param FindOpType The search type.
572 @param ProtocolAddress Pointer to the protocol address to match.
573 @param HardwareAddress Pointer to the hardware address to match.
574
575 @return Pointer to the matched arp cache entry, if NULL, no match is found.
576
577 **/
578 ARP_CACHE_ENTRY *
579 ArpFindNextCacheEntryInTable (
580 IN LIST_ENTRY *CacheTable,
581 IN LIST_ENTRY *StartEntry,
582 IN FIND_OPTYPE FindOpType,
583 IN NET_ARP_ADDRESS *ProtocolAddress OPTIONAL,
584 IN NET_ARP_ADDRESS *HardwareAddress OPTIONAL
585 )
586 {
587 LIST_ENTRY *Entry;
588 ARP_CACHE_ENTRY *CacheEntry;
589
590 if (StartEntry == NULL) {
591 //
592 // Start from the beginning of the table if no StartEntry is specified.
593 //
594 StartEntry = CacheTable;
595 }
596
597 for (Entry = StartEntry->ForwardLink; Entry != CacheTable; Entry = Entry->ForwardLink) {
598 CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
599
600 if (FindOpType & MATCH_SW_ADDRESS) {
601 //
602 // Find by the software address.
603 //
604 if (!ArpMatchAddress (ProtocolAddress, &CacheEntry->Addresses[Protocol])) {
605 //
606 // The ProtocolAddress doesn't match, continue to the next cache entry.
607 //
608 continue;
609 }
610 }
611
612 if (FindOpType & MATCH_HW_ADDRESS) {
613 //
614 // Find by the hardware address.
615 //
616 if (!ArpMatchAddress (HardwareAddress, &CacheEntry->Addresses[Hardware])) {
617 //
618 // The HardwareAddress doesn't match, continue to the next cache entry.
619 //
620 continue;
621 }
622 }
623
624 //
625 // The CacheEntry meets the requirements now, return this entry.
626 //
627 return CacheEntry;
628 }
629
630 //
631 // No matching.
632 //
633 return NULL;
634 }
635
636
637 /**
638 Find the CacheEntry, using ProtocolAddress or HardwareAddress or both, as the keyword,
639 in the DeniedCacheTable.
640
641 @param ArpService Pointer to the arp service context data.
642 @param ProtocolAddress Pointer to the protocol address.
643 @param HardwareAddress Pointer to the hardware address.
644
645 @return Pointer to the matched cache entry, if NULL no match is found.
646
647 **/
648 ARP_CACHE_ENTRY *
649 ArpFindDeniedCacheEntry (
650 IN ARP_SERVICE_DATA *ArpService,
651 IN NET_ARP_ADDRESS *ProtocolAddress OPTIONAL,
652 IN NET_ARP_ADDRESS *HardwareAddress OPTIONAL
653 )
654 {
655 ARP_CACHE_ENTRY *CacheEntry;
656
657 ASSERT ((ProtocolAddress != NULL) || (HardwareAddress != NULL));
658 NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);
659
660 CacheEntry = NULL;
661
662 if ((ProtocolAddress != NULL) && (ProtocolAddress->AddressPtr != NULL)) {
663 //
664 // Find the cache entry in the DeniedCacheTable by the protocol address.
665 //
666 CacheEntry = ArpFindNextCacheEntryInTable (
667 &ArpService->DeniedCacheTable,
668 NULL,
669 ByProtoAddress,
670 ProtocolAddress,
671 NULL
672 );
673 if (CacheEntry != NULL) {
674 //
675 // There is a match.
676 //
677 return CacheEntry;
678 }
679 }
680
681 if ((HardwareAddress != NULL) && (HardwareAddress->AddressPtr != NULL)) {
682 //
683 // Find the cache entry in the DeniedCacheTable by the hardware address.
684 //
685 CacheEntry = ArpFindNextCacheEntryInTable (
686 &ArpService->DeniedCacheTable,
687 NULL,
688 ByHwAddress,
689 NULL,
690 HardwareAddress
691 );
692 }
693
694 return CacheEntry;
695 }
696
697
698 /**
699 Allocate a cache entry and initialize it.
700
701 @param Instance Pointer to the instance context data.
702
703 @return Pointer to the new created cache entry.
704
705 **/
706 ARP_CACHE_ENTRY *
707 ArpAllocCacheEntry (
708 IN ARP_INSTANCE_DATA *Instance
709 )
710 {
711 ARP_CACHE_ENTRY *CacheEntry;
712 NET_ARP_ADDRESS *Address;
713 UINT16 Index;
714
715 //
716 // Allocate memory for the cache entry.
717 //
718 CacheEntry = AllocatePool (sizeof (ARP_CACHE_ENTRY));
719 if (CacheEntry == NULL) {
720 return NULL;
721 }
722
723 //
724 // Init the lists.
725 //
726 InitializeListHead (&CacheEntry->List);
727 InitializeListHead (&CacheEntry->UserRequestList);
728
729 for (Index = 0; Index < 2; Index++) {
730 //
731 // Init the address pointers to point to the concrete buffer.
732 //
733 Address = &CacheEntry->Addresses[Index];
734 Address->AddressPtr = Address->Buffer.ProtoAddress;
735 }
736
737 //
738 // Zero the hardware address first.
739 //
740 ZeroMem (CacheEntry->Addresses[Hardware].AddressPtr, ARP_MAX_HARDWARE_ADDRESS_LEN);
741
742 if (Instance != NULL) {
743 //
744 // Inherit the parameters from the instance configuration.
745 //
746 CacheEntry->RetryCount = Instance->ConfigData.RetryCount;
747 CacheEntry->NextRetryTime = Instance->ConfigData.RetryTimeOut;
748 CacheEntry->DefaultDecayTime = Instance->ConfigData.EntryTimeOut;
749 CacheEntry->DecayTime = Instance->ConfigData.EntryTimeOut;
750 } else {
751 //
752 // Use the default parameters if this cache entry isn't allocate in a
753 // instance's scope.
754 //
755 CacheEntry->RetryCount = ARP_DEFAULT_RETRY_COUNT;
756 CacheEntry->NextRetryTime = ARP_DEFAULT_RETRY_INTERVAL;
757 CacheEntry->DefaultDecayTime = ARP_DEFAULT_TIMEOUT_VALUE;
758 CacheEntry->DecayTime = ARP_DEFAULT_TIMEOUT_VALUE;
759 }
760
761 return CacheEntry;
762 }
763
764
765 /**
766 Turn the CacheEntry into the resolved status.
767
768 @param CacheEntry Pointer to the resolved cache entry.
769 @param Instance Pointer to the instance context data.
770 @param UserEvent Pointer to the UserEvent to notify.
771
772 @return The count of notifications sent to the instance.
773
774 **/
775 UINTN
776 ArpAddressResolved (
777 IN ARP_CACHE_ENTRY *CacheEntry,
778 IN ARP_INSTANCE_DATA *Instance OPTIONAL,
779 IN EFI_EVENT UserEvent OPTIONAL
780 )
781 {
782 LIST_ENTRY *Entry;
783 LIST_ENTRY *NextEntry;
784 USER_REQUEST_CONTEXT *Context;
785 UINTN Count;
786
787 Count = 0;
788
789 //
790 // Iterate all the linked user requests to notify them.
791 //
792 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &CacheEntry->UserRequestList) {
793 Context = NET_LIST_USER_STRUCT (Entry, USER_REQUEST_CONTEXT, List);
794
795 if (((Instance == NULL) || (Context->Instance == Instance)) &&
796 ((UserEvent == NULL) || (Context->UserRequestEvent == UserEvent))) {
797 //
798 // Copy the address to the user-provided buffer and notify the user.
799 //
800 CopyMem (
801 Context->UserHwAddrBuffer,
802 CacheEntry->Addresses[Hardware].AddressPtr,
803 CacheEntry->Addresses[Hardware].Length
804 );
805 gBS->SignalEvent (Context->UserRequestEvent);
806
807 //
808 // Remove this user request and free the context data.
809 //
810 RemoveEntryList (&Context->List);
811 gBS->FreePool (Context);
812
813 Count++;
814 }
815 }
816
817 //
818 // Dispatch the DPCs queued by the NotifyFunction of the Context->UserRequestEvent.
819 //
820 NetLibDispatchDpc ();
821
822 return Count;
823 }
824
825
826 /**
827 Fill the addresses in the CacheEntry using the information passed in by
828 HwAddr and SwAddr.
829
830 @param CacheEntry Pointer to the cache entry.
831 @param HwAddr Pointer to the software address.
832 @param SwAddr Pointer to the hardware address.
833
834 @return None.
835
836 **/
837 VOID
838 ArpFillAddressInCacheEntry (
839 IN ARP_CACHE_ENTRY *CacheEntry,
840 IN NET_ARP_ADDRESS *HwAddr OPTIONAL,
841 IN NET_ARP_ADDRESS *SwAddr OPTIONAL
842 )
843 {
844 NET_ARP_ADDRESS *Address[2];
845 NET_ARP_ADDRESS *CacheAddress;
846 UINT32 Index;
847
848 Address[Hardware] = HwAddr;
849 Address[Protocol] = SwAddr;
850
851 for (Index = 0; Index < 2; Index++) {
852 if (Address[Index] != NULL) {
853 //
854 // Fill the address if the passed in pointer is not NULL.
855 //
856 CacheAddress = &CacheEntry->Addresses[Index];
857
858 CacheAddress->Type = Address[Index]->Type;
859 CacheAddress->Length = Address[Index]->Length;
860
861 if (Address[Index]->AddressPtr != NULL) {
862 //
863 // Copy it if the AddressPtr points to some buffer.
864 //
865 CopyMem (
866 CacheAddress->AddressPtr,
867 Address[Index]->AddressPtr,
868 CacheAddress->Length
869 );
870 } else {
871 //
872 // Zero the corresponding address buffer in the CacheEntry.
873 //
874 ZeroMem (CacheAddress->AddressPtr, CacheAddress->Length);
875 }
876 }
877 }
878 }
879
880
881 /**
882 Configure the instance using the ConfigData. ConfigData is already validated.
883
884 @param Instance Pointer to the instance context data to be
885 configured.
886 @param ConfigData Pointer to the configuration data used to
887 configure the instance.
888
889 @retval EFI_SUCCESS The instance is configured with the ConfigData.
890 @retval EFI_ACCESS_DENIED The instance is already configured and the
891 ConfigData tries to reset some unchangeable
892 fields.
893 @retval EFI_INVALID_PARAMETER The ConfigData provides a non-unicast IPv4 address
894 when the SwAddressType is IPv4.
895 @retval EFI_OUT_OF_RESOURCES The instance fails to configure due to memory
896 limitation.
897
898 **/
899 EFI_STATUS
900 ArpConfigureInstance (
901 IN ARP_INSTANCE_DATA *Instance,
902 IN EFI_ARP_CONFIG_DATA *ConfigData OPTIONAL
903 )
904 {
905 EFI_ARP_CONFIG_DATA *OldConfigData;
906 IP4_ADDR Ip;
907
908 OldConfigData = &Instance->ConfigData;
909
910 if (ConfigData != NULL) {
911
912 if (Instance->Configured) {
913 //
914 // The instance is configured, check the unchangeable fields.
915 //
916 if ((OldConfigData->SwAddressType != ConfigData->SwAddressType) ||
917 (OldConfigData->SwAddressLength != ConfigData->SwAddressLength) ||
918 (CompareMem (
919 OldConfigData->StationAddress,
920 ConfigData->StationAddress,
921 OldConfigData->SwAddressLength
922 ) != 0)) {
923 //
924 // Deny the unallowed changes.
925 //
926 return EFI_ACCESS_DENIED;
927 }
928 } else {
929 //
930 // The instance is not configured.
931 //
932
933 if (ConfigData->SwAddressType == IPv4_ETHER_PROTO_TYPE) {
934 CopyMem (&Ip, ConfigData->StationAddress, sizeof (IP4_ADDR));
935
936 if (!Ip4IsUnicast (NTOHL (Ip), 0)) {
937 //
938 // The station address is not a valid IPv4 unicast address.
939 //
940 return EFI_INVALID_PARAMETER;
941 }
942 }
943
944 //
945 // Save the configuration.
946 //
947 CopyMem (OldConfigData, ConfigData, sizeof (*OldConfigData));
948
949 OldConfigData->StationAddress = AllocatePool (OldConfigData->SwAddressLength);
950 if (OldConfigData->StationAddress == NULL) {
951 DEBUG ((EFI_D_ERROR, "ArpConfigInstance: AllocatePool for the StationAddress "
952 "failed.\n"));
953 return EFI_OUT_OF_RESOURCES;
954 }
955
956 //
957 // Save the StationAddress.
958 //
959 CopyMem (
960 OldConfigData->StationAddress,
961 ConfigData->StationAddress,
962 OldConfigData->SwAddressLength
963 );
964
965 //
966 // Set the state to configured.
967 //
968 Instance->Configured = TRUE;
969 }
970
971 //
972 // Use the implementation specific values if the following field is zero.
973 //
974 OldConfigData->EntryTimeOut = (ConfigData->EntryTimeOut == 0) ?
975 ARP_DEFAULT_TIMEOUT_VALUE : ConfigData->EntryTimeOut;
976
977 OldConfigData->RetryCount = (ConfigData->RetryCount == 0) ?
978 ARP_DEFAULT_RETRY_COUNT : ConfigData->RetryCount;
979
980 OldConfigData->RetryTimeOut = (ConfigData->RetryTimeOut == 0) ?
981 ARP_DEFAULT_RETRY_INTERVAL : ConfigData->RetryTimeOut;
982 } else {
983 //
984 // Reset the configuration.
985 //
986
987 if (Instance->Configured) {
988 //
989 // Cancel the arp requests issued by this instance.
990 //
991 Instance->ArpProto.Cancel (&Instance->ArpProto, NULL, NULL);
992
993 //
994 // Free the buffer previously allocated to hold the station address.
995 //
996 gBS->FreePool (OldConfigData->StationAddress);
997 }
998
999 Instance->Configured = FALSE;
1000 }
1001
1002 return EFI_SUCCESS;
1003 }
1004
1005
1006 /**
1007 Send out an arp frame using the CachEntry and the ArpOpCode.
1008
1009 @param Instance Pointer to the instance context data.
1010 @param CacheEntry Pointer to the configuration data used to
1011 configure the instance.
1012 @param ArpOpCode The opcode used to send out this Arp frame, either
1013 request or reply.
1014
1015 @return None.
1016
1017 **/
1018 VOID
1019 ArpSendFrame (
1020 IN ARP_INSTANCE_DATA *Instance,
1021 IN ARP_CACHE_ENTRY *CacheEntry,
1022 IN UINT16 ArpOpCode
1023 )
1024 {
1025 EFI_STATUS Status;
1026 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TxToken;
1027 EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData;
1028 UINT32 TotalLength;
1029 UINT8 *Packet;
1030 ARP_SERVICE_DATA *ArpService;
1031 EFI_SIMPLE_NETWORK_MODE *SnpMode;
1032 EFI_ARP_CONFIG_DATA *ConfigData;
1033 UINT8 *TmpPtr;
1034 ARP_HEAD *ArpHead;
1035
1036 ASSERT ((Instance != NULL) && (CacheEntry != NULL));
1037
1038 //
1039 // Allocate memory for the TxToken.
1040 //
1041 TxToken = AllocatePool (sizeof(EFI_MANAGED_NETWORK_COMPLETION_TOKEN));
1042 if (TxToken == NULL) {
1043 DEBUG ((EFI_D_ERROR, "ArpSendFrame: Allocate memory for TxToken failed.\n"));
1044 return;
1045 }
1046
1047 TxToken->Event = NULL;
1048 TxData = NULL;
1049 Packet = NULL;
1050
1051 //
1052 // Create the event for this TxToken.
1053 //
1054 Status = gBS->CreateEvent (
1055 EVT_NOTIFY_SIGNAL,
1056 TPL_NOTIFY,
1057 ArpOnFrameSent,
1058 (VOID *)TxToken,
1059 &TxToken->Event
1060 );
1061 if (EFI_ERROR (Status)) {
1062 DEBUG ((EFI_D_ERROR, "ArpSendFrame: CreateEvent failed for TxToken->Event.\n"));
1063 goto CLEAN_EXIT;
1064 }
1065
1066 //
1067 // Allocate memory for the TxData used in the TxToken.
1068 //
1069 TxData = AllocatePool (sizeof(EFI_MANAGED_NETWORK_TRANSMIT_DATA));
1070 if (TxData == NULL) {
1071 DEBUG ((EFI_D_ERROR, "ArpSendFrame: Allocate memory for TxData failed.\n"));
1072 goto CLEAN_EXIT;
1073 }
1074
1075 ArpService = Instance->ArpService;
1076 SnpMode = &ArpService->SnpMode;
1077 ConfigData = &Instance->ConfigData;
1078
1079 //
1080 // Calculate the buffer length for this arp frame.
1081 //
1082 TotalLength = SnpMode->MediaHeaderSize + sizeof (ARP_HEAD) +
1083 2 * (ConfigData->SwAddressLength + SnpMode->HwAddressSize);
1084
1085 //
1086 // Allocate buffer for the arp frame.
1087 //
1088 Packet = AllocatePool (TotalLength);
1089 if (Packet == NULL) {
1090 DEBUG ((EFI_D_ERROR, "ArpSendFrame: Allocate memory for Packet failed.\n"));
1091 }
1092
1093 TmpPtr = Packet;
1094
1095 //
1096 // The destination MAC address.
1097 //
1098 if (ArpOpCode == ARP_OPCODE_REQUEST) {
1099 CopyMem (TmpPtr, &SnpMode->BroadcastAddress, SnpMode->HwAddressSize);
1100 } else {
1101 CopyMem (
1102 TmpPtr,
1103 CacheEntry->Addresses[Hardware].AddressPtr,
1104 SnpMode->HwAddressSize
1105 );
1106 }
1107 TmpPtr += SnpMode->HwAddressSize;
1108
1109 //
1110 // The source MAC address.
1111 //
1112 CopyMem (TmpPtr, &SnpMode->CurrentAddress, SnpMode->HwAddressSize);
1113 TmpPtr += SnpMode->HwAddressSize;
1114
1115 //
1116 // The ethernet protocol type.
1117 //
1118 *(UINT16 *)TmpPtr = HTONS (ARP_ETHER_PROTO_TYPE);
1119 TmpPtr += 2;
1120
1121 //
1122 // The ARP Head.
1123 //
1124 ArpHead = (ARP_HEAD *) TmpPtr;
1125 ArpHead->HwType = HTONS ((UINT16)SnpMode->IfType);
1126 ArpHead->ProtoType = HTONS (ConfigData->SwAddressType);
1127 ArpHead->HwAddrLen = (UINT8)SnpMode->HwAddressSize;
1128 ArpHead->ProtoAddrLen = ConfigData->SwAddressLength;
1129 ArpHead->OpCode = HTONS (ArpOpCode);
1130 TmpPtr += sizeof (ARP_HEAD);
1131
1132 //
1133 // The sender hardware address.
1134 //
1135 CopyMem (TmpPtr, &SnpMode->CurrentAddress, SnpMode->HwAddressSize);
1136 TmpPtr += SnpMode->HwAddressSize;
1137
1138 //
1139 // The sender protocol address.
1140 //
1141 CopyMem (TmpPtr, ConfigData->StationAddress, ConfigData->SwAddressLength);
1142 TmpPtr += ConfigData->SwAddressLength;
1143
1144 //
1145 // The target hardware address.
1146 //
1147 CopyMem (
1148 TmpPtr,
1149 CacheEntry->Addresses[Hardware].AddressPtr,
1150 SnpMode->HwAddressSize
1151 );
1152 TmpPtr += SnpMode->HwAddressSize;
1153
1154 //
1155 // The target protocol address.
1156 //
1157 CopyMem (
1158 TmpPtr,
1159 CacheEntry->Addresses[Protocol].AddressPtr,
1160 ConfigData->SwAddressLength
1161 );
1162
1163 //
1164 // Set all the fields of the TxData.
1165 //
1166 TxData->DestinationAddress = NULL;
1167 TxData->SourceAddress = NULL;
1168 TxData->ProtocolType = 0;
1169 TxData->DataLength = TotalLength - SnpMode->MediaHeaderSize;
1170 TxData->HeaderLength = (UINT16) SnpMode->MediaHeaderSize;
1171 TxData->FragmentCount = 1;
1172
1173 TxData->FragmentTable[0].FragmentBuffer = Packet;
1174 TxData->FragmentTable[0].FragmentLength = TotalLength;
1175
1176 //
1177 // Associate the TxData with the TxToken.
1178 //
1179 TxToken->Packet.TxData = TxData;
1180 TxToken->Status = EFI_NOT_READY;
1181
1182 //
1183 // Send out this arp packet by Mnp.
1184 //
1185 Status = ArpService->Mnp->Transmit (ArpService->Mnp, TxToken);
1186 if (EFI_ERROR (Status)) {
1187 DEBUG ((EFI_D_ERROR, "Mnp->Transmit failed, %r.\n", Status));
1188 goto CLEAN_EXIT;
1189 }
1190
1191 return;
1192
1193 CLEAN_EXIT:
1194
1195 if (Packet != NULL) {
1196 gBS->FreePool (Packet);
1197 }
1198
1199 if (TxData != NULL) {
1200 gBS->FreePool (TxData);
1201 }
1202
1203 if (TxToken->Event != NULL) {
1204 gBS->CloseEvent (TxToken->Event);
1205 }
1206
1207 gBS->FreePool (TxToken);
1208 }
1209
1210
1211 /**
1212 Delete the cache entries in the specified CacheTable, using the BySwAddress,
1213 SwAddressType, AddressBuffer combination as the matching key, if Force is TRUE,
1214 the cache is deleted event it's a static entry.
1215
1216 @param CacheTable Pointer to the cache table to do the deletion.
1217 @param BySwAddress Delete the cache entry by software address or by
1218 hardware address.
1219 @param SwAddressType The software address used to do the deletion.
1220 @param AddressBuffer Pointer to the buffer containing the address to
1221 match for the deletion.
1222 @param Force This deletion is forced or not.
1223
1224 @return The count of the deleted cache entries.
1225
1226 **/
1227 STATIC
1228 UINTN
1229 ArpDeleteCacheEntryInTable (
1230 IN LIST_ENTRY *CacheTable,
1231 IN BOOLEAN BySwAddress,
1232 IN UINT16 SwAddressType,
1233 IN UINT8 *AddressBuffer OPTIONAL,
1234 IN BOOLEAN Force
1235 )
1236 {
1237 LIST_ENTRY *Entry;
1238 LIST_ENTRY *NextEntry;
1239 ARP_CACHE_ENTRY *CacheEntry;
1240 UINTN Count;
1241
1242 Count = 0;
1243
1244 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, CacheTable) {
1245 CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
1246
1247 if ((CacheEntry->DefaultDecayTime == 0) && !Force) {
1248 //
1249 // It's a static entry and we are not forced to delete it, skip.
1250 //
1251 continue;
1252 }
1253
1254 if (BySwAddress) {
1255 if (SwAddressType == CacheEntry->Addresses[Protocol].Type) {
1256 //
1257 // Protocol address type matched. Check the address.
1258 //
1259 if ((AddressBuffer == NULL) ||
1260 (CompareMem (
1261 AddressBuffer,
1262 CacheEntry->Addresses[Protocol].AddressPtr,
1263 CacheEntry->Addresses[Protocol].Length
1264 ) == 0)) {
1265 //
1266 // Address matched.
1267 //
1268 goto MATCHED;
1269 }
1270 }
1271 } else {
1272 if ((AddressBuffer == NULL) ||
1273 (CompareMem (
1274 AddressBuffer,
1275 CacheEntry->Addresses[Hardware].AddressPtr,
1276 CacheEntry->Addresses[Hardware].Length
1277 ) == 0)) {
1278 //
1279 // Address matched.
1280 //
1281 goto MATCHED;
1282 }
1283 }
1284
1285 continue;
1286
1287 MATCHED:
1288
1289 //
1290 // Delete this entry.
1291 //
1292 RemoveEntryList (&CacheEntry->List);
1293 ASSERT (IsListEmpty (&CacheEntry->UserRequestList));
1294 gBS->FreePool (CacheEntry);
1295
1296 Count++;
1297 }
1298
1299 return Count;
1300 }
1301
1302
1303 /**
1304 Delete cache entries in all the cache tables.
1305
1306 @param Instance Pointer to the instance context data.
1307 @param BySwAddress Delete the cache entry by software address or by
1308 hardware address.
1309 @param AddressBuffer Pointer to the buffer containing the address to
1310 match for the deletion.
1311 @param Force This deletion is forced or not.
1312
1313 @return The count of the deleted cache entries.
1314
1315 **/
1316 UINTN
1317 ArpDeleteCacheEntry (
1318 IN ARP_INSTANCE_DATA *Instance,
1319 IN BOOLEAN BySwAddress,
1320 IN UINT8 *AddressBuffer OPTIONAL,
1321 IN BOOLEAN Force
1322 )
1323 {
1324 ARP_SERVICE_DATA *ArpService;
1325 UINTN Count;
1326
1327 NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE);
1328
1329 ArpService = Instance->ArpService;
1330
1331 //
1332 // Delete the cache entries in the DeniedCacheTable.
1333 //
1334 Count = ArpDeleteCacheEntryInTable (
1335 &ArpService->DeniedCacheTable,
1336 BySwAddress,
1337 Instance->ConfigData.SwAddressType,
1338 AddressBuffer,
1339 Force
1340 );
1341
1342 //
1343 // Delete the cache entries inthe ResolvedCacheTable.
1344 //
1345 Count += ArpDeleteCacheEntryInTable (
1346 &ArpService->ResolvedCacheTable,
1347 BySwAddress,
1348 Instance->ConfigData.SwAddressType,
1349 AddressBuffer,
1350 Force
1351 );
1352
1353 return Count;
1354 }
1355
1356
1357 /**
1358 Cancel the arp request.
1359
1360 @param Instance Pointer to the instance context data.
1361 @param TargetSwAddress Pointer to the buffer containing the target
1362 software address to match the arp request.
1363 @param UserEvent The user event used to notify this request
1364 cancellation.
1365
1366 @return The count of the cancelled requests.
1367
1368 **/
1369 UINTN
1370 ArpCancelRequest (
1371 IN ARP_INSTANCE_DATA *Instance,
1372 IN VOID *TargetSwAddress OPTIONAL,
1373 IN EFI_EVENT UserEvent OPTIONAL
1374 )
1375 {
1376 ARP_SERVICE_DATA *ArpService;
1377 LIST_ENTRY *Entry;
1378 LIST_ENTRY *NextEntry;
1379 ARP_CACHE_ENTRY *CacheEntry;
1380 UINTN Count;
1381
1382 NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE);
1383
1384 ArpService = Instance->ArpService;
1385
1386 Count = 0;
1387 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->PendingRequestTable) {
1388 CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
1389
1390 if ((TargetSwAddress == NULL) ||
1391 (CompareMem (
1392 TargetSwAddress,
1393 CacheEntry->Addresses[Protocol].AddressPtr,
1394 CacheEntry->Addresses[Protocol].Length
1395 ) == 0)) {
1396 //
1397 // This request entry matches the TargetSwAddress or all requests are to be
1398 // cancelled as TargetSwAddress is NULL.
1399 //
1400 Count += ArpAddressResolved (CacheEntry, Instance, UserEvent);
1401
1402 if (IsListEmpty (&CacheEntry->UserRequestList)) {
1403 //
1404 // No user requests any more, remove this request cache entry.
1405 //
1406 RemoveEntryList (&CacheEntry->List);
1407 gBS->FreePool (CacheEntry);
1408 }
1409 }
1410 }
1411
1412 return Count;
1413 }
1414
1415
1416 /**
1417 Find the cache entry in the cache table.
1418
1419 @param Instance Pointer to the instance context data.
1420 @param BySwAddress Set to TRUE to look for matching software protocol
1421 addresses. Set to FALSE to look for matching
1422 hardware protocol addresses.
1423 @param AddressBuffer Pointer to address buffer. Set to NULL to match
1424 all addresses.
1425 @param EntryLength The size of an entry in the entries buffer.
1426 @param EntryCount The number of ARP cache entries that are found by
1427 the specified criteria.
1428 @param Entries Pointer to the buffer that will receive the ARP
1429 cache entries.
1430 @param Refresh Set to TRUE to refresh the timeout value of the
1431 matching ARP cache entry.
1432
1433 @retval EFI_SUCCESS The requested ARP cache entries are copied into
1434 the buffer.
1435 @retval EFI_NOT_FOUND No matching entries found.
1436 @retval EFI_OUT_OF_RESOURCE There is a memory allocation failure.
1437
1438 **/
1439 EFI_STATUS
1440 ArpFindCacheEntry (
1441 IN ARP_INSTANCE_DATA *Instance,
1442 IN BOOLEAN BySwAddress,
1443 IN VOID *AddressBuffer OPTIONAL,
1444 OUT UINT32 *EntryLength OPTIONAL,
1445 OUT UINT32 *EntryCount OPTIONAL,
1446 OUT EFI_ARP_FIND_DATA **Entries OPTIONAL,
1447 IN BOOLEAN Refresh
1448 )
1449 {
1450 EFI_STATUS Status;
1451 ARP_SERVICE_DATA *ArpService;
1452 NET_ARP_ADDRESS MatchAddress;
1453 FIND_OPTYPE FindOpType;
1454 LIST_ENTRY *StartEntry;
1455 ARP_CACHE_ENTRY *CacheEntry;
1456 NET_MAP FoundEntries;
1457 UINT32 FoundCount;
1458 EFI_ARP_FIND_DATA *FindData;
1459 LIST_ENTRY *CacheTable;
1460
1461 ArpService = Instance->ArpService;
1462
1463 //
1464 // Init the FounEntries used to hold the found cache entries.
1465 //
1466 NetMapInit (&FoundEntries);
1467
1468 //
1469 // Set the MatchAddress.
1470 //
1471 if (BySwAddress) {
1472 MatchAddress.Type = Instance->ConfigData.SwAddressType;
1473 MatchAddress.Length = Instance->ConfigData.SwAddressLength;
1474 FindOpType = ByProtoAddress;
1475 } else {
1476 MatchAddress.Type = ArpService->SnpMode.IfType;
1477 MatchAddress.Length = (UINT8)ArpService->SnpMode.HwAddressSize;
1478 FindOpType = ByHwAddress;
1479 }
1480
1481 MatchAddress.AddressPtr = AddressBuffer;
1482
1483 //
1484 // Search the DeniedCacheTable
1485 //
1486 StartEntry = NULL;
1487 while (TRUE) {
1488 //
1489 // Try to find the matched entries in the DeniedCacheTable.
1490 //
1491 CacheEntry = ArpFindNextCacheEntryInTable (
1492 &ArpService->DeniedCacheTable,
1493 StartEntry,
1494 FindOpType,
1495 &MatchAddress,
1496 &MatchAddress
1497 );
1498 if (CacheEntry == NULL) {
1499 //
1500 // Once the CacheEntry is NULL, there are no more matches.
1501 //
1502 break;
1503 }
1504
1505 //
1506 // Insert the found entry into the map.
1507 //
1508 NetMapInsertTail (
1509 &FoundEntries,
1510 (VOID *)CacheEntry,
1511 (VOID *)&ArpService->DeniedCacheTable
1512 );
1513
1514 //
1515 // Let the next search start from this cache entry.
1516 //
1517 StartEntry = &CacheEntry->List;
1518
1519 if (Refresh) {
1520 //
1521 // Refresh the DecayTime if needed.
1522 //
1523 CacheEntry->DecayTime = CacheEntry->DefaultDecayTime;
1524 }
1525 }
1526
1527 //
1528 // Search the ResolvedCacheTable
1529 //
1530 StartEntry = NULL;
1531 while (TRUE) {
1532 CacheEntry = ArpFindNextCacheEntryInTable (
1533 &ArpService->ResolvedCacheTable,
1534 StartEntry,
1535 FindOpType,
1536 &MatchAddress,
1537 &MatchAddress
1538 );
1539 if (CacheEntry == NULL) {
1540 //
1541 // Once the CacheEntry is NULL, there are no more matches.
1542 //
1543 break;
1544 }
1545
1546 //
1547 // Insert the found entry into the map.
1548 //
1549 NetMapInsertTail (
1550 &FoundEntries,
1551 (VOID *)CacheEntry,
1552 (VOID *)&ArpService->ResolvedCacheTable
1553 );
1554
1555 //
1556 // Let the next search start from this cache entry.
1557 //
1558 StartEntry = &CacheEntry->List;
1559
1560 if (Refresh) {
1561 //
1562 // Refresh the DecayTime if needed.
1563 //
1564 CacheEntry->DecayTime = CacheEntry->DefaultDecayTime;
1565 }
1566 }
1567
1568 Status = EFI_SUCCESS;
1569
1570 FoundCount = (UINT32) NetMapGetCount (&FoundEntries);
1571 if (FoundCount == 0) {
1572 Status = EFI_NOT_FOUND;
1573 goto CLEAN_EXIT;
1574 }
1575
1576 if (EntryLength != NULL) {
1577 //
1578 // Return the entry length, make sure its 8 bytes alignment.
1579 //
1580 *EntryLength = (((sizeof (EFI_ARP_FIND_DATA) + Instance->ConfigData.SwAddressLength +
1581 ArpService->SnpMode.HwAddressSize) + 3) & ~(0x3));
1582 }
1583
1584 if (EntryCount != NULL) {
1585 //
1586 // Return the found entry count.
1587 //
1588 *EntryCount = FoundCount;
1589 }
1590
1591 if (Entries == NULL) {
1592 goto CLEAN_EXIT;
1593 }
1594
1595 //
1596 // Allocate buffer to copy the found entries.
1597 //
1598 FindData = AllocatePool (FoundCount * (*EntryLength));
1599 if (FindData == NULL) {
1600 DEBUG ((EFI_D_ERROR, "ArpFindCacheEntry: Failed to allocate memory.\n"));
1601 Status = EFI_OUT_OF_RESOURCES;
1602 goto CLEAN_EXIT;
1603 }
1604
1605 //
1606 // Return the address to the user.
1607 //
1608 *Entries = FindData;
1609
1610 //
1611 // Dump the entries.
1612 //
1613 while (!NetMapIsEmpty (&FoundEntries)) {
1614 //
1615 // Get a cache entry from the map.
1616 //
1617 CacheEntry = NetMapRemoveHead (&FoundEntries, (VOID **)&CacheTable);
1618
1619 //
1620 // Set the fields in FindData.
1621 //
1622 FindData->Size = *EntryLength;
1623 FindData->DenyFlag = (BOOLEAN)(CacheTable == &ArpService->DeniedCacheTable);
1624 FindData->StaticFlag = (BOOLEAN)(CacheEntry->DefaultDecayTime == 0);
1625 FindData->HwAddressType = ArpService->SnpMode.IfType;
1626 FindData->SwAddressType = Instance->ConfigData.SwAddressType;
1627 FindData->HwAddressLength = (UINT8)ArpService->SnpMode.HwAddressSize;
1628 FindData->SwAddressLength = Instance->ConfigData.SwAddressLength;
1629
1630 //
1631 // Copy the software address.
1632 //
1633 CopyMem (
1634 FindData + 1,
1635 CacheEntry->Addresses[Protocol].AddressPtr,
1636 FindData->SwAddressLength
1637 );
1638
1639 //
1640 // Copy the hardware address.
1641 //
1642 CopyMem (
1643 (UINT8 *)(FindData + 1) + FindData->SwAddressLength,
1644 CacheEntry->Addresses[Hardware].AddressPtr,
1645 FindData->HwAddressLength
1646 );
1647
1648 //
1649 // Slip to the next FindData.
1650 //
1651 FindData = (EFI_ARP_FIND_DATA *)((UINT8 *)FindData + *EntryLength);
1652 }
1653
1654 CLEAN_EXIT:
1655
1656 NetMapClean (&FoundEntries);
1657
1658 return Status;
1659 }
1660