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