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