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