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