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