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