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