ArpImpl.c 45 KB

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