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