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