]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/ArpDxe/ArpMain.c
1. Sync the latest network stack. Add NetLibCreateIPv4DPathNode () in netlib library.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / ArpDxe / ArpMain.c
CommitLineData
772db4bb 1/** @file\r
2\r
3Copyright (c) 2006, 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 ArpMain.c\r
15\r
16Abstract:\r
17\r
18\r
19**/\r
20\r
21#include "ArpImpl.h"\r
22\r
23\r
24/**\r
25 This function is used to assign a station address to the ARP cache for this instance\r
26 of the ARP driver. A call to this function with the ConfigData field set to NULL\r
27 will reset this ARP instance.\r
28\r
29 @param This Pointer to the EFI_ARP_PROTOCOL instance.\r
30 @param ConfigData Pointer to the EFI_ARP_CONFIG_DATA structure.\r
31\r
32 @retval EFI_SUCCESS The new station address was successfully\r
33 registered.\r
34 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
35 This is NULL. SwAddressLength is zero when\r
36 ConfigData is not NULL. StationAddress is NULL\r
37 when ConfigData is not NULL.\r
38 @retval EFI_ACCESS_DENIED The SwAddressType, SwAddressLength, or\r
39 StationAddress is different from the one that is\r
40 already registered.\r
41 @retval EFI_OUT_OF_RESOURCES Storage for the new StationAddress could not be\r
42 allocated.\r
43\r
44**/\r
45EFI_STATUS\r
46EFIAPI\r
47ArpConfigure (\r
48 IN EFI_ARP_PROTOCOL *This,\r
49 IN EFI_ARP_CONFIG_DATA *ConfigData OPTIONAL\r
50 )\r
51{\r
52 EFI_STATUS Status;\r
53 ARP_INSTANCE_DATA *Instance;\r
54\r
55 if (This == NULL) {\r
56 return EFI_INVALID_PARAMETER;\r
57 }\r
58\r
59 if ((ConfigData != NULL) &&\r
60 ((ConfigData->SwAddressLength == 0) ||\r
61 (ConfigData->StationAddress == NULL) ||\r
62 (ConfigData->SwAddressType <= 1500))) {\r
63 return EFI_INVALID_PARAMETER;\r
64 }\r
65\r
66 Instance = ARP_INSTANCE_DATA_FROM_THIS (This);\r
67\r
68 if (EFI_ERROR (NET_TRYLOCK (&Instance->ArpService->Lock))) {\r
69 return EFI_ACCESS_DENIED;\r
70 }\r
71\r
72 //\r
73 // Configure this instance, the ConfigData has already passed the basic checks.\r
74 //\r
75 Status = ArpConfigureInstance (Instance, ConfigData);\r
76\r
77 NET_UNLOCK (&Instance->ArpService->Lock);\r
78\r
79 return Status;\r
80}\r
81\r
82\r
83/**\r
84 This function is used to insert entries into the ARP cache.\r
85\r
86 @param This Pointer to the EFI_ARP_PROTOCOL instance.\r
87 @param DenyFlag Set to TRUE if this entry is a deny entry. Set to\r
88 FALSE if this entry is a normal entry.\r
89 @param TargetSwAddress Pointer to a protocol address to add (or deny).\r
90 May be set to NULL if DenyFlag is TRUE.\r
91 @param TargetHwAddress Pointer to a hardware address to add (or deny).\r
92 May be set to NULL if DenyFlag is TRUE.\r
93 @param TimeoutValue Time in 100-ns units that this entry will remain\r
94 in the ARP cache. A value of zero means that the\r
95 entry is permanent. A nonzero value will override\r
96 the one given by Configure() if the entry to be\r
97 added is a dynamic entry.\r
98 @param Overwrite If TRUE, the matching cache entry will be\r
99 overwritten with the supplied parameters. If\r
100 FALSE, EFI_ACCESS_DENIED is returned if the\r
101 corresponding cache entry already exists.\r
102\r
103 @retval EFI_SUCCESS The entry has been added or updated.\r
104 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
105 This is NULL. DenyFlag is FALSE and\r
106 TargetHwAddress is NULL. DenyFlag is FALSE and\r
107 TargetSwAddress is NULL. TargetHwAddress is NULL\r
108 and TargetSwAddress is NULL. Both TargetSwAddress\r
109 and TargetHwAddress are not NULL when DenyFlag is\r
110 TRUE.\r
111 @retval EFI_OUT_OF_RESOURCES The new ARP cache entry could not be allocated.\r
112 @retval EFI_ACCESS_DENIED The ARP cache entry already exists and Overwrite\r
113 is not true.\r
114 @retval EFI_NOT_STARTED The ARP driver instance has not been configured.\r
115\r
116**/\r
117EFI_STATUS\r
118EFIAPI\r
119ArpAdd (\r
120 IN EFI_ARP_PROTOCOL *This,\r
121 IN BOOLEAN DenyFlag,\r
122 IN VOID *TargetSwAddress OPTIONAL,\r
123 IN VOID *TargetHwAddress OPTIONAL,\r
124 IN UINT32 TimeoutValue,\r
125 IN BOOLEAN Overwrite\r
126 )\r
127{\r
128 EFI_STATUS Status;\r
129 ARP_INSTANCE_DATA *Instance;\r
130 ARP_SERVICE_DATA *ArpService;\r
131 ARP_CACHE_ENTRY *CacheEntry;\r
132 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
133 NET_ARP_ADDRESS MatchAddress[2];\r
134\r
135 if (This == NULL) {\r
136 return EFI_INVALID_PARAMETER;\r
137 }\r
138\r
139 if (((!DenyFlag) && ((TargetHwAddress == NULL) || (TargetSwAddress == NULL))) ||\r
140 (DenyFlag && (TargetHwAddress != NULL) && (TargetSwAddress != NULL)) ||\r
141 ((TargetHwAddress == NULL) && (TargetSwAddress == NULL))) {\r
142 return EFI_INVALID_PARAMETER;\r
143 }\r
144\r
145 Instance = ARP_INSTANCE_DATA_FROM_THIS (This);\r
146\r
147 if (!Instance->Configured) {\r
148 return EFI_NOT_STARTED;\r
149 }\r
150\r
151 Status = EFI_SUCCESS;\r
152 ArpService = Instance->ArpService;\r
153 SnpMode = &Instance->ArpService->SnpMode;\r
154\r
155 //\r
156 // Fill the hardware address part in the MatchAddress.\r
157 //\r
158 MatchAddress[Hardware].Type = SnpMode->IfType;\r
159 MatchAddress[Hardware].Length = (UINT8) SnpMode->HwAddressSize;\r
160 MatchAddress[Hardware].AddressPtr = TargetHwAddress;\r
161\r
162 //\r
163 // Fill the software address part in the MatchAddress.\r
164 //\r
165 MatchAddress[Protocol].Type = Instance->ConfigData.SwAddressType;\r
166 MatchAddress[Protocol].Length = Instance->ConfigData.SwAddressLength;\r
167 MatchAddress[Protocol].AddressPtr = TargetSwAddress;\r
168\r
169 if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {\r
170 return EFI_ACCESS_DENIED;\r
171 }\r
172\r
173 //\r
174 // See whether the entry to add exists. Check the DeinedCacheTable first.\r
175 //\r
176 CacheEntry = ArpFindDeniedCacheEntry (\r
177 ArpService,\r
178 &MatchAddress[Protocol],\r
179 &MatchAddress[Hardware]\r
180 );\r
181\r
182 if (CacheEntry == NULL) {\r
183 //\r
184 // Check the ResolvedCacheTable\r
185 //\r
186 CacheEntry = ArpFindNextCacheEntryInTable (\r
187 &ArpService->ResolvedCacheTable,\r
188 NULL,\r
189 ByBoth,\r
190 &MatchAddress[Protocol],\r
191 &MatchAddress[Hardware]\r
192 );\r
193 }\r
194\r
195 if ((CacheEntry != NULL) && !Overwrite) {\r
196 //\r
197 // The entry to add exists, if not Overwirte, deny this add request.\r
198 //\r
199 Status = EFI_ACCESS_DENIED;\r
200 goto UNLOCK_EXIT;\r
201 }\r
202\r
203 if ((CacheEntry == NULL) && (TargetSwAddress != NULL)) {\r
204 //\r
205 // Check whether there are pending requests matching the entry to be added.\r
206 //\r
207 CacheEntry = ArpFindNextCacheEntryInTable (\r
208 &ArpService->PendingRequestTable,\r
209 NULL,\r
210 ByProtoAddress,\r
211 &MatchAddress[Protocol],\r
212 NULL\r
213 );\r
214 }\r
215\r
216 if (CacheEntry != NULL) {\r
217 //\r
218 // Remove it from the Table.\r
219 //\r
220 NetListRemoveEntry (&CacheEntry->List);\r
221 } else {\r
222 //\r
223 // It's a new entry, allocate memory for the entry.\r
224 //\r
225 CacheEntry = ArpAllocCacheEntry (Instance);\r
226\r
227 if (CacheEntry == NULL) {\r
228 ARP_DEBUG_ERROR (("ArpAdd: Failed to allocate pool for CacheEntry.\n"));\r
229 Status = EFI_OUT_OF_RESOURCES;\r
230 goto UNLOCK_EXIT;\r
231 }\r
232 }\r
233\r
234 //\r
235 // Overwrite these parameters.\r
236 //\r
237 CacheEntry->DefaultDecayTime = TimeoutValue;\r
238 CacheEntry->DecayTime = TimeoutValue;\r
239\r
240 //\r
241 // Fill in the addresses.\r
242 //\r
243 ArpFillAddressInCacheEntry (\r
244 CacheEntry,\r
245 &MatchAddress[Hardware],\r
246 &MatchAddress[Protocol]\r
247 );\r
248\r
249 //\r
250 // Inform the user if there is any.\r
251 //\r
252 ArpAddressResolved (CacheEntry, NULL, NULL);\r
253\r
254 //\r
255 // Add this CacheEntry to the corresponding CacheTable.\r
256 //\r
257 if (DenyFlag) {\r
258 NetListInsertHead (&ArpService->DeniedCacheTable, &CacheEntry->List);\r
259 } else {\r
260 NetListInsertHead (&ArpService->ResolvedCacheTable, &CacheEntry->List);\r
261 }\r
262\r
263UNLOCK_EXIT:\r
264\r
265 NET_UNLOCK (&ArpService->Lock);\r
266\r
267 return Status;\r
268}\r
269\r
270\r
271/**\r
272 This function searches the ARP cache for matching entries and allocates a buffer into\r
273 which those entries are copied.\r
274\r
275 @param This Pointer to the EFI_ARP_PROTOCOL instance.\r
276 @param BySwAddress Set to TRUE to look for matching software protocol\r
277 addresses. Set to FALSE to look for matching\r
278 hardware protocol addresses.\r
279 @param AddressBuffer Pointer to address buffer. Set to NULL to match\r
280 all addresses.\r
281 @param EntryLength The size of an entry in the entries buffer.\r
282 @param EntryCount The number of ARP cache entries that are found by\r
283 the specified criteria.\r
284 @param Entries Pointer to the buffer that will receive the ARP\r
285 cache entries.\r
286 @param Refresh Set to TRUE to refresh the timeout value of the\r
287 matching ARP cache entry.\r
288\r
289 @retval EFI_SUCCESS The requested ARP cache entries were copied into\r
290 the buffer.\r
291 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
292 This is NULL. Both EntryCount and EntryLength are\r
293 NULL, when Refresh is FALSE.\r
294 @retval EFI_NOT_FOUND No matching entries were found.\r
295 @retval EFI_NOT_STARTED The ARP driver instance has not been configured.\r
296\r
297**/\r
298EFI_STATUS\r
299EFIAPI\r
300ArpFind (\r
301 IN EFI_ARP_PROTOCOL *This,\r
302 IN BOOLEAN BySwAddress,\r
303 IN VOID *AddressBuffer OPTIONAL,\r
304 OUT UINT32 *EntryLength OPTIONAL,\r
305 OUT UINT32 *EntryCount OPTIONAL,\r
306 OUT EFI_ARP_FIND_DATA **Entries OPTIONAL,\r
307 IN BOOLEAN Refresh\r
308 )\r
309{\r
310 EFI_STATUS Status;\r
311 ARP_INSTANCE_DATA *Instance;\r
312 ARP_SERVICE_DATA *ArpService;\r
313\r
314 if ((This == NULL) ||\r
315 (!Refresh && (EntryCount == NULL) && (EntryLength == NULL)) ||\r
316 ((Entries != NULL) && ((EntryLength == NULL) || (EntryCount == NULL)))) {\r
317 return EFI_INVALID_PARAMETER;\r
318 }\r
319\r
320 Instance = ARP_INSTANCE_DATA_FROM_THIS (This);\r
321 ArpService = Instance->ArpService;\r
322\r
323 if (!Instance->Configured) {\r
324 return EFI_NOT_STARTED;\r
325 }\r
326\r
327 if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {\r
328 return EFI_ACCESS_DENIED;\r
329 }\r
330\r
331 //\r
332 // All the check passed, find the cache entries now.\r
333 //\r
334 Status = ArpFindCacheEntry (\r
335 Instance,\r
336 BySwAddress,\r
337 AddressBuffer,\r
338 EntryLength,\r
339 EntryCount,\r
340 Entries,\r
341 Refresh\r
342 );\r
343\r
344 NET_UNLOCK (&ArpService->Lock);\r
345\r
346 return Status;\r
347}\r
348\r
349\r
350/**\r
351 This function removes specified ARP cache entries.\r
352\r
353 @param This Pointer to the EFI_ARP_PROTOCOL instance.\r
354 @param BySwAddress Set to TRUE to delete matching protocol addresses.\r
355 Set to FALSE to delete matching hardware\r
356 addresses.\r
357 @param AddressBuffer Pointer to the address buffer that is used as a\r
358 key to look for the cache entry. Set to NULL to\r
359 delete all entries.\r
360\r
361 @retval EFI_SUCCESS The entry was removed from the ARP cache.\r
362 @retval EFI_INVALID_PARAMETER This is NULL.\r
363 @retval EFI_NOT_FOUND The specified deletion key was not found.\r
364 @retval EFI_NOT_STARTED The ARP driver instance has not been configured.\r
365\r
366**/\r
367EFI_STATUS\r
368EFIAPI\r
369ArpDelete (\r
370 IN EFI_ARP_PROTOCOL *This,\r
371 IN BOOLEAN BySwAddress,\r
372 IN VOID *AddressBuffer OPTIONAL\r
373 )\r
374{\r
375 ARP_INSTANCE_DATA *Instance;\r
376 ARP_SERVICE_DATA *ArpService;\r
377 UINTN Count;\r
378\r
379 if (This == NULL) {\r
380 return EFI_INVALID_PARAMETER;\r
381 }\r
382\r
383 Instance = ARP_INSTANCE_DATA_FROM_THIS (This);\r
384\r
385 if (!Instance->Configured) {\r
386 return EFI_NOT_STARTED;\r
387 }\r
388\r
389 ArpService = Instance->ArpService;\r
390\r
391 if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {\r
392 return EFI_ACCESS_DENIED;\r
393 }\r
394\r
395 //\r
396 // Delete the specified cache entries.\r
397 //\r
398 Count = ArpDeleteCacheEntry (Instance, BySwAddress, AddressBuffer, TRUE);\r
399\r
400 NET_UNLOCK (&ArpService->Lock);\r
401\r
402 return (Count == 0) ? EFI_NOT_FOUND : EFI_SUCCESS;\r
403}\r
404\r
405\r
406/**\r
407 This function delete all dynamic entries from the ARP cache that match the specified\r
408 software protocol type.\r
409\r
410 @param This Pointer to the EFI_ARP_PROTOCOL instance.\r
411\r
412 @retval EFI_SUCCESS The cache has been flushed.\r
413 @retval EFI_INVALID_PARAMETER This is NULL.\r
414 @retval EFI_NOT_FOUND There are no matching dynamic cache entries.\r
415 @retval EFI_NOT_STARTED The ARP driver instance has not been configured.\r
416\r
417**/\r
418EFI_STATUS\r
419EFIAPI\r
420ArpFlush (\r
421 IN EFI_ARP_PROTOCOL *This\r
422 )\r
423{\r
424 ARP_INSTANCE_DATA *Instance;\r
425 ARP_SERVICE_DATA *ArpService;\r
426 UINTN Count;\r
427\r
428 if (This == NULL) {\r
429 return EFI_INVALID_PARAMETER;\r
430 }\r
431\r
432 Instance = ARP_INSTANCE_DATA_FROM_THIS (This);\r
433\r
434 if (!Instance->Configured) {\r
435 return EFI_NOT_STARTED;\r
436 }\r
437\r
438 ArpService = Instance->ArpService;\r
439\r
440 if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {\r
441 return EFI_ACCESS_DENIED;\r
442 }\r
443\r
444 //\r
445 // Delete the dynamic entries from the cache table.\r
446 //\r
447 Count = ArpDeleteCacheEntry (Instance, FALSE, NULL, FALSE);\r
448\r
449 NET_UNLOCK (&ArpService->Lock);\r
450\r
451 return (Count == 0) ? EFI_NOT_FOUND : EFI_SUCCESS;\r
452}\r
453\r
454\r
455/**\r
456 This function tries to resolve the TargetSwAddress and optionally returns a\r
457 TargetHwAddress if it already exists in the ARP cache.\r
458\r
459 @param This Pointer to the EFI_ARP_PROTOCOL instance.\r
460 @param TargetSwAddress Pointer to the protocol address to resolve.\r
461 @param ResolvedEvent Pointer to the event that will be signaled when\r
462 the address is resolved or some error occurs.\r
463 @param TargetHwAddress Pointer to the buffer for the resolved hardware\r
464 address in network byte order.\r
465\r
466 @retval EFI_SUCCESS The data is copied from the ARP cache into the\r
467 TargetHwAddress buffer.\r
468 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
469 This is NULL. TargetHwAddress is NULL.\r
470 @retval EFI_ACCESS_DENIED The requested address is not present in the normal\r
471 ARP cache but is present in the deny address list.\r
472 Outgoing traffic to that address is forbidden.\r
473 @retval EFI_NOT_STARTED The ARP driver instance has not been configured.\r
474 @retval EFI_NOT_READY The request has been started and is not finished.\r
475\r
476**/\r
477EFI_STATUS\r
478EFIAPI\r
479ArpRequest (\r
480 IN EFI_ARP_PROTOCOL *This,\r
481 IN VOID *TargetSwAddress OPTIONAL,\r
482 IN EFI_EVENT ResolvedEvent OPTIONAL,\r
483 OUT VOID *TargetHwAddress\r
484 )\r
485{\r
486 EFI_STATUS Status;\r
487 ARP_INSTANCE_DATA *Instance;\r
488 ARP_SERVICE_DATA *ArpService;\r
489 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
490 ARP_CACHE_ENTRY *CacheEntry;\r
491 NET_ARP_ADDRESS HardwareAddress;\r
492 NET_ARP_ADDRESS ProtocolAddress;\r
493 USER_REQUEST_CONTEXT *RequestContext;\r
494\r
495 if ((This == NULL) || (TargetHwAddress == NULL)) {\r
496 return EFI_INVALID_PARAMETER;\r
497 }\r
498\r
499 Instance = ARP_INSTANCE_DATA_FROM_THIS (This);\r
500\r
501 if (!Instance->Configured) {\r
502 return EFI_NOT_STARTED;\r
503 }\r
504\r
505 Status = EFI_SUCCESS;\r
506 ArpService = Instance->ArpService;\r
507 SnpMode = &ArpService->SnpMode;\r
508\r
509 if ((TargetSwAddress == NULL) ||\r
510 ((Instance->ConfigData.SwAddressType == IPv4_ETHER_PROTO_TYPE) &&\r
511 IP4_IS_LOCAL_BROADCAST (*((UINT32 *)TargetSwAddress)))) {\r
512 //\r
513 // Return the hardware broadcast address.\r
514 //\r
515 NetCopyMem (TargetHwAddress, &SnpMode->BroadcastAddress, SnpMode->HwAddressSize);\r
516\r
517 goto SIGNAL_USER;\r
518 }\r
519\r
520 if ((Instance->ConfigData.SwAddressType == IPv4_ETHER_PROTO_TYPE) &&\r
521 IP4_IS_MULTICAST (NTOHL (*((UINT32 *)TargetSwAddress)))) {\r
522 //\r
523 // If the software address is an IPv4 multicast address, invoke Mnp to\r
524 // resolve the address.\r
525 //\r
526 Status = ArpService->Mnp->McastIpToMac (\r
527 ArpService->Mnp,\r
528 FALSE,\r
529 TargetSwAddress,\r
530 TargetHwAddress\r
531 );\r
532 goto SIGNAL_USER;\r
533 }\r
534\r
535 HardwareAddress.Type = SnpMode->IfType;\r
536 HardwareAddress.Length = (UINT8)SnpMode->HwAddressSize;\r
537 HardwareAddress.AddressPtr = NULL;\r
538\r
539 ProtocolAddress.Type = Instance->ConfigData.SwAddressType;\r
540 ProtocolAddress.Length = Instance->ConfigData.SwAddressLength;\r
541 ProtocolAddress.AddressPtr = TargetSwAddress;\r
542\r
543 //\r
544 // Initialize the TargetHwAddrss to a zero address.\r
545 //\r
546 NetZeroMem (TargetHwAddress, SnpMode->HwAddressSize);\r
547\r
548 if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {\r
549 return EFI_ACCESS_DENIED;\r
550 }\r
551\r
552 //\r
553 // Check whether the software address is in the denied table.\r
554 //\r
555 CacheEntry = ArpFindDeniedCacheEntry (ArpService, &ProtocolAddress, NULL);\r
556 if (CacheEntry != NULL) {\r
557 Status = EFI_ACCESS_DENIED;\r
558 goto UNLOCK_EXIT;\r
559 }\r
560\r
561 //\r
562 // Check whether the software address is already resolved.\r
563 //\r
564 CacheEntry = ArpFindNextCacheEntryInTable (\r
565 &ArpService->ResolvedCacheTable,\r
566 NULL,\r
567 ByProtoAddress,\r
568 &ProtocolAddress,\r
569 NULL\r
570 );\r
571 if (CacheEntry != NULL) {\r
572 //\r
573 // Resolved, copy the address into the user buffer.\r
574 //\r
575 NetCopyMem (\r
576 TargetHwAddress,\r
577 CacheEntry->Addresses[Hardware].AddressPtr,\r
578 CacheEntry->Addresses[Hardware].Length\r
579 );\r
580\r
581 goto UNLOCK_EXIT;\r
582 }\r
583\r
584 if (ResolvedEvent == NULL) {\r
585 Status = EFI_NOT_READY;\r
586 goto UNLOCK_EXIT;\r
587 }\r
588\r
589 //\r
590 // Create a request context for this arp request.\r
591 //\r
592 RequestContext = NetAllocatePool (sizeof(USER_REQUEST_CONTEXT));\r
593 if (RequestContext == NULL) {\r
594 ARP_DEBUG_ERROR (("ArpRequest: Allocate memory for RequestContext failed.\n"));\r
595\r
596 Status = EFI_OUT_OF_RESOURCES;\r
597 goto UNLOCK_EXIT;\r
598 }\r
599\r
600 RequestContext->Instance = Instance;\r
601 RequestContext->UserRequestEvent = ResolvedEvent;\r
602 RequestContext->UserHwAddrBuffer = TargetHwAddress;\r
603 NetListInit (&RequestContext->List);\r
604\r
605 //\r
606 // Check whether there is a same request.\r
607 //\r
608 CacheEntry = ArpFindNextCacheEntryInTable (\r
609 &ArpService->PendingRequestTable,\r
610 NULL,\r
611 ByProtoAddress,\r
612 &ProtocolAddress,\r
613 NULL\r
614 );\r
615 if (CacheEntry != NULL) {\r
616\r
617 CacheEntry->NextRetryTime = Instance->ConfigData.RetryTimeOut;\r
618 CacheEntry->RetryCount = Instance->ConfigData.RetryCount;\r
619 } else {\r
620 //\r
621 // Allocate a cache entry for this request.\r
622 //\r
623 CacheEntry = ArpAllocCacheEntry (Instance);\r
624 if (CacheEntry == NULL) {\r
625 ARP_DEBUG_ERROR (("ArpRequest: Allocate memory for CacheEntry failed.\n"));\r
626 NetFreePool (RequestContext);\r
627\r
628 Status = EFI_OUT_OF_RESOURCES;\r
629 goto UNLOCK_EXIT;\r
630 }\r
631\r
632 //\r
633 // Fill the software address.\r
634 //\r
635 ArpFillAddressInCacheEntry (CacheEntry, &HardwareAddress, &ProtocolAddress);\r
636\r
637 //\r
638 // Add this entry into the PendingRequestTable.\r
639 //\r
640 NetListInsertTail (&ArpService->PendingRequestTable, &CacheEntry->List);\r
641 }\r
642\r
643 //\r
644 // Link this request context into the cache entry.\r
645 //\r
646 NetListInsertHead (&CacheEntry->UserRequestList, &RequestContext->List);\r
647\r
648 //\r
649 // Send out the ARP Request frame.\r
650 //\r
651 ArpSendFrame (Instance, CacheEntry, ARP_OPCODE_REQUEST);\r
652 Status = EFI_NOT_READY;\r
653\r
654UNLOCK_EXIT:\r
655\r
656 NET_UNLOCK (&ArpService->Lock);\r
657\r
658SIGNAL_USER:\r
659\r
660 if ((ResolvedEvent != NULL) && (Status == EFI_SUCCESS)) {\r
661 gBS->SignalEvent (ResolvedEvent);\r
662 }\r
663\r
664 return Status;\r
665}\r
666\r
667\r
668/**\r
669 This function aborts the previous ARP request (identified by This, TargetSwAddress\r
670 and ResolvedEvent) that is issued by EFI_ARP_PROTOCOL.Request().\r
671\r
672 @param This Pointer to the EFI_ARP_PROTOCOL instance.\r
673 @param TargetSwAddress Pointer to the protocol address in previous\r
674 request session.\r
675 @param ResolvedEvent Pointer to the event that is used as the\r
676 notification event in previous request session.\r
677\r
678 @retval EFI_SUCCESS The pending request session(s) is/are aborted and\r
679 corresponding event(s) is/are signaled.\r
680 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
681 This is NULL. TargetSwAddress is not NULL and\r
682 ResolvedEvent is NULL. TargetSwAddress is NULL and\r
683 ResolvedEvent is not NULL.\r
684 @retval EFI_NOT_STARTED The ARP driver instance has not been configured.\r
685 @retval EFI_NOT_FOUND The request is not issued by\r
686 EFI_ARP_PROTOCOL.Request().\r
687\r
688**/\r
689EFI_STATUS\r
690EFIAPI\r
691ArpCancel (\r
692 IN EFI_ARP_PROTOCOL *This,\r
693 IN VOID *TargetSwAddress OPTIONAL,\r
694 IN EFI_EVENT ResolvedEvent OPTIONAL\r
695 )\r
696{\r
697 ARP_INSTANCE_DATA *Instance;\r
698 ARP_SERVICE_DATA *ArpService;\r
699 UINTN Count;\r
700\r
701 if ((This == NULL) ||\r
702 ((TargetSwAddress != NULL) && (ResolvedEvent == NULL)) ||\r
703 ((TargetSwAddress == NULL) && (ResolvedEvent != NULL))) {\r
704 return EFI_INVALID_PARAMETER;\r
705 }\r
706\r
707 Instance = ARP_INSTANCE_DATA_FROM_THIS (This);\r
708\r
709 if (!Instance->Configured) {\r
710 return EFI_NOT_STARTED;\r
711 }\r
712\r
713 ArpService = Instance->ArpService;\r
714\r
715 if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {\r
716 return EFI_ACCESS_DENIED;\r
717 }\r
718\r
719 //\r
720 // Cancel the specified request.\r
721 //\r
722 Count = ArpCancelRequest (Instance, TargetSwAddress, ResolvedEvent);\r
723\r
724 NET_UNLOCK (&ArpService->Lock);\r
725\r
726 return (Count == 0) ? EFI_NOT_FOUND : EFI_SUCCESS;\r
727}\r