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