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
ArpInitInstance(IN ARP_SERVICE_DATA * ArpService,OUT ARP_INSTANCE_DATA * Instance)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
ArpOnFrameRcvdDpc(IN VOID * Context)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
ArpOnFrameRcvd(IN EFI_EVENT Event,IN VOID * Context)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
ArpOnFrameSentDpc(IN VOID * Context)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
ArpOnFrameSent(IN EFI_EVENT Event,IN VOID * Context)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
ArpTimerHandler(IN EFI_EVENT Event,IN VOID * Context)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
ArpMatchAddress(IN NET_ARP_ADDRESS * AddressOne,IN NET_ARP_ADDRESS * AddressTwo)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 *
ArpFindNextCacheEntryInTable(IN LIST_ENTRY * CacheTable,IN LIST_ENTRY * StartEntry,IN FIND_OPTYPE FindOpType,IN NET_ARP_ADDRESS * ProtocolAddress OPTIONAL,IN NET_ARP_ADDRESS * HardwareAddress OPTIONAL)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 *
ArpFindDeniedCacheEntry(IN ARP_SERVICE_DATA * ArpService,IN NET_ARP_ADDRESS * ProtocolAddress OPTIONAL,IN NET_ARP_ADDRESS * HardwareAddress OPTIONAL)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 *
ArpAllocCacheEntry(IN ARP_INSTANCE_DATA * Instance)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
ArpAddressResolved(IN ARP_CACHE_ENTRY * CacheEntry,IN ARP_INSTANCE_DATA * Instance OPTIONAL,IN EFI_EVENT UserEvent OPTIONAL)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
ArpFillAddressInCacheEntry(IN ARP_CACHE_ENTRY * CacheEntry,IN NET_ARP_ADDRESS * HwAddr OPTIONAL,IN NET_ARP_ADDRESS * SwAddr OPTIONAL)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
ArpConfigureInstance(IN ARP_INSTANCE_DATA * Instance,IN EFI_ARP_CONFIG_DATA * ConfigData OPTIONAL)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
ArpSendFrame(IN ARP_INSTANCE_DATA * Instance,IN ARP_CACHE_ENTRY * CacheEntry,IN UINT16 ArpOpCode)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
ArpDeleteCacheEntryInTable(IN LIST_ENTRY * CacheTable,IN BOOLEAN BySwAddress,IN UINT16 SwAddressType,IN UINT8 * AddressBuffer OPTIONAL,IN BOOLEAN Force)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
ArpDeleteCacheEntry(IN ARP_INSTANCE_DATA * Instance,IN BOOLEAN BySwAddress,IN UINT8 * AddressBuffer OPTIONAL,IN BOOLEAN Force)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
ArpCancelRequest(IN ARP_INSTANCE_DATA * Instance,IN VOID * TargetSwAddress OPTIONAL,IN EFI_EVENT UserEvent OPTIONAL)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
ArpFindCacheEntry(IN ARP_INSTANCE_DATA * Instance,IN BOOLEAN BySwAddress,IN VOID * AddressBuffer OPTIONAL,OUT UINT32 * EntryLength OPTIONAL,OUT UINT32 * EntryCount OPTIONAL,OUT EFI_ARP_FIND_DATA ** Entries OPTIONAL,IN BOOLEAN Refresh)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 
1661