Ip6Input.c 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813
  1. /** @file
  2. IP6 internal functions to process the incoming packets.
  3. Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
  4. (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include "Ip6Impl.h"
  8. /**
  9. Create an empty assemble entry for the packet identified by
  10. (Dst, Src, Id). The default life for the packet is 60 seconds.
  11. @param[in] Dst The destination address.
  12. @param[in] Src The source address.
  13. @param[in] Id The ID field in the IP header.
  14. @return NULL if failed to allocate memory for the entry. Otherwise,
  15. the pointer to the just created reassemble entry.
  16. **/
  17. IP6_ASSEMBLE_ENTRY *
  18. Ip6CreateAssembleEntry (
  19. IN EFI_IPv6_ADDRESS *Dst,
  20. IN EFI_IPv6_ADDRESS *Src,
  21. IN UINT32 Id
  22. )
  23. {
  24. IP6_ASSEMBLE_ENTRY *Assemble;
  25. Assemble = AllocatePool (sizeof (IP6_ASSEMBLE_ENTRY));
  26. if (Assemble == NULL) {
  27. return NULL;
  28. }
  29. IP6_COPY_ADDRESS (&Assemble->Dst, Dst);
  30. IP6_COPY_ADDRESS (&Assemble->Src, Src);
  31. InitializeListHead (&Assemble->Fragments);
  32. Assemble->Id = Id;
  33. Assemble->Life = IP6_FRAGMENT_LIFE + 1;
  34. Assemble->TotalLen = 0;
  35. Assemble->CurLen = 0;
  36. Assemble->Head = NULL;
  37. Assemble->Info = NULL;
  38. Assemble->Packet = NULL;
  39. return Assemble;
  40. }
  41. /**
  42. Release all the fragments of a packet, then free the assemble entry.
  43. @param[in] Assemble The assemble entry to free.
  44. **/
  45. VOID
  46. Ip6FreeAssembleEntry (
  47. IN IP6_ASSEMBLE_ENTRY *Assemble
  48. )
  49. {
  50. LIST_ENTRY *Entry;
  51. LIST_ENTRY *Next;
  52. NET_BUF *Fragment;
  53. NET_LIST_FOR_EACH_SAFE (Entry, Next, &Assemble->Fragments) {
  54. Fragment = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
  55. RemoveEntryList (Entry);
  56. NetbufFree (Fragment);
  57. }
  58. if (Assemble->Packet != NULL) {
  59. NetbufFree (Assemble->Packet);
  60. }
  61. FreePool (Assemble);
  62. }
  63. /**
  64. Release all the fragments of the packet. This is the callback for
  65. the assembled packet's OnFree. It will free the assemble entry,
  66. which in turn frees all the fragments of the packet.
  67. @param[in] Arg The assemble entry to free.
  68. **/
  69. VOID
  70. EFIAPI
  71. Ip6OnFreeFragments (
  72. IN VOID *Arg
  73. )
  74. {
  75. Ip6FreeAssembleEntry ((IP6_ASSEMBLE_ENTRY *)Arg);
  76. }
  77. /**
  78. Trim the packet to fit in [Start, End), and update per the
  79. packet information.
  80. @param[in, out] Packet Packet to trim.
  81. @param[in] Start The sequence of the first byte to fit in.
  82. @param[in] End One beyond the sequence of last byte to fit in.
  83. **/
  84. VOID
  85. Ip6TrimPacket (
  86. IN OUT NET_BUF *Packet,
  87. IN INTN Start,
  88. IN INTN End
  89. )
  90. {
  91. IP6_CLIP_INFO *Info;
  92. INTN Len;
  93. Info = IP6_GET_CLIP_INFO (Packet);
  94. ASSERT (Info->Start + Info->Length == Info->End);
  95. ASSERT ((Info->Start < End) && (Start < Info->End));
  96. if (Info->Start < Start) {
  97. Len = Start - Info->Start;
  98. NetbufTrim (Packet, (UINT32)Len, NET_BUF_HEAD);
  99. Info->Start = (UINT32)Start;
  100. Info->Length -= (UINT32)Len;
  101. }
  102. if (End < Info->End) {
  103. Len = End - Info->End;
  104. NetbufTrim (Packet, (UINT32)Len, NET_BUF_TAIL);
  105. Info->End = (UINT32)End;
  106. Info->Length -= (UINT32)Len;
  107. }
  108. }
  109. /**
  110. Reassemble the IP fragments. If all the fragments of the packet
  111. have been received, it will wrap the packet in a net buffer then
  112. return it to caller. If the packet can't be assembled, NULL is
  113. returned.
  114. @param[in, out] Table The assemble table used. A new assemble entry will be created
  115. if the Packet is from a new chain of fragments.
  116. @param[in] Packet The fragment to assemble. It might be freed if the fragment
  117. can't be re-assembled.
  118. @return NULL if the packet can't be reassembled. The pointer to the just assembled
  119. packet if all the fragments of the packet have arrived.
  120. **/
  121. NET_BUF *
  122. Ip6Reassemble (
  123. IN OUT IP6_ASSEMBLE_TABLE *Table,
  124. IN NET_BUF *Packet
  125. )
  126. {
  127. EFI_IP6_HEADER *Head;
  128. IP6_CLIP_INFO *This;
  129. IP6_CLIP_INFO *Node;
  130. IP6_ASSEMBLE_ENTRY *Assemble;
  131. IP6_ASSEMBLE_ENTRY *Entry;
  132. LIST_ENTRY *ListHead;
  133. LIST_ENTRY *Prev;
  134. LIST_ENTRY *Cur;
  135. NET_BUF *Fragment;
  136. NET_BUF *TmpPacket;
  137. NET_BUF *NewPacket;
  138. NET_BUF *Duplicate;
  139. UINT8 *DupHead;
  140. INTN Index;
  141. UINT16 UnFragmentLen;
  142. UINT8 *NextHeader;
  143. Head = Packet->Ip.Ip6;
  144. This = IP6_GET_CLIP_INFO (Packet);
  145. ASSERT (Head != NULL);
  146. //
  147. // Find the corresponding assemble entry by (Dst, Src, Id)
  148. //
  149. Assemble = NULL;
  150. Index = IP6_ASSEMBLE_HASH (&Head->DestinationAddress, &Head->SourceAddress, This->Id);
  151. NET_LIST_FOR_EACH (Cur, &Table->Bucket[Index]) {
  152. Entry = NET_LIST_USER_STRUCT (Cur, IP6_ASSEMBLE_ENTRY, Link);
  153. if ((Entry->Id == This->Id) &&
  154. EFI_IP6_EQUAL (&Entry->Src, &Head->SourceAddress) &&
  155. EFI_IP6_EQUAL (&Entry->Dst, &Head->DestinationAddress)
  156. )
  157. {
  158. Assemble = Entry;
  159. break;
  160. }
  161. }
  162. //
  163. // Create a new entry if can not find an existing one, insert it to assemble table
  164. //
  165. if (Assemble == NULL) {
  166. Assemble = Ip6CreateAssembleEntry (
  167. &Head->DestinationAddress,
  168. &Head->SourceAddress,
  169. This->Id
  170. );
  171. if (Assemble == NULL) {
  172. goto Error;
  173. }
  174. InsertHeadList (&Table->Bucket[Index], &Assemble->Link);
  175. }
  176. //
  177. // Find the point to insert the packet: before the first
  178. // fragment with THIS.Start < CUR.Start. the previous one
  179. // has PREV.Start <= THIS.Start < CUR.Start.
  180. //
  181. ListHead = &Assemble->Fragments;
  182. NET_LIST_FOR_EACH (Cur, ListHead) {
  183. Fragment = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);
  184. if (This->Start < IP6_GET_CLIP_INFO (Fragment)->Start) {
  185. break;
  186. }
  187. }
  188. //
  189. // Check whether the current fragment overlaps with the previous one.
  190. // It holds that: PREV.Start <= THIS.Start < THIS.End. Only need to
  191. // check whether THIS.Start < PREV.End for overlap. If two fragments
  192. // overlaps, trim the overlapped part off THIS fragment.
  193. //
  194. if ((Prev = Cur->BackLink) != ListHead) {
  195. Fragment = NET_LIST_USER_STRUCT (Prev, NET_BUF, List);
  196. Node = IP6_GET_CLIP_INFO (Fragment);
  197. if (This->Start < Node->End) {
  198. if (This->End <= Node->End) {
  199. goto Error;
  200. }
  201. //
  202. // Trim the previous fragment from tail.
  203. //
  204. Ip6TrimPacket (Fragment, Node->Start, This->Start);
  205. }
  206. }
  207. //
  208. // Insert the fragment into the packet. The fragment may be removed
  209. // from the list by the following checks.
  210. //
  211. NetListInsertBefore (Cur, &Packet->List);
  212. //
  213. // Check the packets after the insert point. It holds that:
  214. // THIS.Start <= NODE.Start < NODE.End. The equality holds
  215. // if PREV and NEXT are continuous. THIS fragment may fill
  216. // several holes. Remove the completely overlapped fragments
  217. //
  218. while (Cur != ListHead) {
  219. Fragment = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);
  220. Node = IP6_GET_CLIP_INFO (Fragment);
  221. //
  222. // Remove fragments completely overlapped by this fragment
  223. //
  224. if (Node->End <= This->End) {
  225. Cur = Cur->ForwardLink;
  226. RemoveEntryList (&Fragment->List);
  227. Assemble->CurLen -= Node->Length;
  228. NetbufFree (Fragment);
  229. continue;
  230. }
  231. //
  232. // The conditions are: THIS.Start <= NODE.Start, and THIS.End <
  233. // NODE.End. Two fragments overlaps if NODE.Start < THIS.End.
  234. // If two fragments start at the same offset, remove THIS fragment
  235. // because ((THIS.Start == NODE.Start) && (THIS.End < NODE.End)).
  236. //
  237. if (Node->Start < This->End) {
  238. if (This->Start == Node->Start) {
  239. RemoveEntryList (&Packet->List);
  240. goto Error;
  241. }
  242. Ip6TrimPacket (Packet, This->Start, Node->Start);
  243. }
  244. break;
  245. }
  246. //
  247. // Update the assemble info: increase the current length. If it is
  248. // the frist fragment, update the packet's IP head and per packet
  249. // info. If it is the last fragment, update the total length.
  250. //
  251. Assemble->CurLen += This->Length;
  252. if (This->Start == 0) {
  253. //
  254. // Once the first fragment is enqueued, it can't be removed
  255. // from the fragment list. So, Assemble->Head always point
  256. // to valid memory area.
  257. //
  258. if ((Assemble->Head != NULL) || (Assemble->Packet != NULL)) {
  259. goto Error;
  260. }
  261. //
  262. // Backup the first fragment in case the reassembly of that packet fail.
  263. //
  264. Duplicate = NetbufDuplicate (Packet, NULL, sizeof (EFI_IP6_HEADER));
  265. if (Duplicate == NULL) {
  266. goto Error;
  267. }
  268. //
  269. // Revert IP head to network order.
  270. //
  271. DupHead = NetbufGetByte (Duplicate, 0, NULL);
  272. ASSERT (DupHead != NULL);
  273. Duplicate->Ip.Ip6 = Ip6NtohHead ((EFI_IP6_HEADER *)DupHead);
  274. Assemble->Packet = Duplicate;
  275. //
  276. // Adjust the unfragmentable part in first fragment
  277. //
  278. UnFragmentLen = (UINT16)(This->HeadLen - sizeof (EFI_IP6_HEADER));
  279. if (UnFragmentLen == 0) {
  280. //
  281. // There is not any unfragmentable extension header.
  282. //
  283. ASSERT (Head->NextHeader == IP6_FRAGMENT);
  284. Head->NextHeader = This->NextHeader;
  285. } else {
  286. NextHeader = NetbufGetByte (
  287. Packet,
  288. This->FormerNextHeader + sizeof (EFI_IP6_HEADER),
  289. 0
  290. );
  291. if (NextHeader == NULL) {
  292. goto Error;
  293. }
  294. *NextHeader = This->NextHeader;
  295. }
  296. Assemble->Head = Head;
  297. Assemble->Info = IP6_GET_CLIP_INFO (Packet);
  298. }
  299. //
  300. // Don't update the length more than once.
  301. //
  302. if ((This->LastFrag != 0) && (Assemble->TotalLen == 0)) {
  303. Assemble->TotalLen = This->End;
  304. }
  305. //
  306. // Deliver the whole packet if all the fragments received.
  307. // All fragments received if:
  308. // 1. received the last one, so, the total length is known
  309. // 2. received all the data. If the last fragment on the
  310. // queue ends at the total length, all data is received.
  311. //
  312. if ((Assemble->TotalLen != 0) && (Assemble->CurLen >= Assemble->TotalLen)) {
  313. RemoveEntryList (&Assemble->Link);
  314. //
  315. // If the packet is properly formatted, the last fragment's End
  316. // equals to the packet's total length. Otherwise, the packet
  317. // is a fake, drop it now.
  318. //
  319. Fragment = NET_LIST_USER_STRUCT (ListHead->BackLink, NET_BUF, List);
  320. if (IP6_GET_CLIP_INFO (Fragment)->End != (INTN)Assemble->TotalLen) {
  321. Ip6FreeAssembleEntry (Assemble);
  322. goto Error;
  323. }
  324. Fragment = NET_LIST_HEAD (ListHead, NET_BUF, List);
  325. This = Assemble->Info;
  326. //
  327. // This TmpPacket is used to hold the unfragmentable part, i.e.,
  328. // the IPv6 header and the unfragmentable extension headers. Be noted that
  329. // the Fragment Header is excluded.
  330. //
  331. TmpPacket = NetbufGetFragment (Fragment, 0, This->HeadLen, 0);
  332. ASSERT (TmpPacket != NULL);
  333. NET_LIST_FOR_EACH (Cur, ListHead) {
  334. //
  335. // Trim off the unfragment part plus the fragment header from all fragments.
  336. //
  337. Fragment = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);
  338. NetbufTrim (Fragment, This->HeadLen + sizeof (IP6_FRAGMENT_HEADER), TRUE);
  339. }
  340. InsertHeadList (ListHead, &TmpPacket->List);
  341. //
  342. // Wrap the packet in a net buffer then deliver it up
  343. //
  344. NewPacket = NetbufFromBufList (
  345. &Assemble->Fragments,
  346. 0,
  347. 0,
  348. Ip6OnFreeFragments,
  349. Assemble
  350. );
  351. if (NewPacket == NULL) {
  352. Ip6FreeAssembleEntry (Assemble);
  353. goto Error;
  354. }
  355. NewPacket->Ip.Ip6 = Assemble->Head;
  356. CopyMem (IP6_GET_CLIP_INFO (NewPacket), Assemble->Info, sizeof (IP6_CLIP_INFO));
  357. return NewPacket;
  358. }
  359. return NULL;
  360. Error:
  361. NetbufFree (Packet);
  362. return NULL;
  363. }
  364. /**
  365. The callback function for the net buffer that wraps the packet processed by
  366. IPsec. It releases the wrap packet and also signals IPsec to free the resources.
  367. @param[in] Arg The wrap context.
  368. **/
  369. VOID
  370. EFIAPI
  371. Ip6IpSecFree (
  372. IN VOID *Arg
  373. )
  374. {
  375. IP6_IPSEC_WRAP *Wrap;
  376. Wrap = (IP6_IPSEC_WRAP *)Arg;
  377. if (Wrap->IpSecRecycleSignal != NULL) {
  378. gBS->SignalEvent (Wrap->IpSecRecycleSignal);
  379. }
  380. NetbufFree (Wrap->Packet);
  381. FreePool (Wrap);
  382. return;
  383. }
  384. /**
  385. The work function to locate the IPsec protocol to process the inbound or
  386. outbound IP packets. The process routine handles the packet with the following
  387. actions: bypass the packet, discard the packet, or protect the packet.
  388. @param[in] IpSb The IP6 service instance.
  389. @param[in, out] Head The caller-supplied IP6 header.
  390. @param[in, out] LastHead The next header field of last IP header.
  391. @param[in, out] Netbuf The IP6 packet to be processed by IPsec.
  392. @param[in, out] ExtHdrs The caller-supplied options.
  393. @param[in, out] ExtHdrsLen The length of the option.
  394. @param[in] Direction The directionality in an SPD entry,
  395. EfiIPsecInBound, or EfiIPsecOutBound.
  396. @param[in] Context The token's wrap.
  397. @retval EFI_SUCCESS The IPsec protocol is not available or disabled.
  398. @retval EFI_SUCCESS The packet was bypassed, and all buffers remain the same.
  399. @retval EFI_SUCCESS The packet was protected.
  400. @retval EFI_ACCESS_DENIED The packet was discarded.
  401. @retval EFI_OUT_OF_RESOURCES There are not sufficient resources to complete the operation.
  402. @retval EFI_BUFFER_TOO_SMALL The number of non-empty blocks is bigger than the
  403. number of input data blocks when building a fragment table.
  404. **/
  405. EFI_STATUS
  406. Ip6IpSecProcessPacket (
  407. IN IP6_SERVICE *IpSb,
  408. IN OUT EFI_IP6_HEADER **Head,
  409. IN OUT UINT8 *LastHead,
  410. IN OUT NET_BUF **Netbuf,
  411. IN OUT UINT8 **ExtHdrs,
  412. IN OUT UINT32 *ExtHdrsLen,
  413. IN EFI_IPSEC_TRAFFIC_DIR Direction,
  414. IN VOID *Context
  415. )
  416. {
  417. NET_FRAGMENT *FragmentTable;
  418. NET_FRAGMENT *OriginalFragmentTable;
  419. UINT32 FragmentCount;
  420. UINT32 OriginalFragmentCount;
  421. EFI_EVENT RecycleEvent;
  422. NET_BUF *Packet;
  423. IP6_TXTOKEN_WRAP *TxWrap;
  424. IP6_IPSEC_WRAP *IpSecWrap;
  425. EFI_STATUS Status;
  426. EFI_IP6_HEADER *PacketHead;
  427. UINT8 *Buf;
  428. EFI_IP6_HEADER ZeroHead;
  429. Status = EFI_SUCCESS;
  430. if (!mIpSec2Installed) {
  431. goto ON_EXIT;
  432. }
  433. ASSERT (mIpSec != NULL);
  434. Packet = *Netbuf;
  435. RecycleEvent = NULL;
  436. IpSecWrap = NULL;
  437. FragmentTable = NULL;
  438. PacketHead = NULL;
  439. Buf = NULL;
  440. TxWrap = (IP6_TXTOKEN_WRAP *)Context;
  441. FragmentCount = Packet->BlockOpNum;
  442. ZeroMem (&ZeroHead, sizeof (EFI_IP6_HEADER));
  443. //
  444. // Check whether the ipsec enable variable is set.
  445. //
  446. if (mIpSec->DisabledFlag) {
  447. //
  448. // If IPsec is disabled, restore the original MTU
  449. //
  450. IpSb->MaxPacketSize = IpSb->OldMaxPacketSize;
  451. goto ON_EXIT;
  452. } else {
  453. //
  454. // If IPsec is enabled, use the MTU which reduce the IPsec header length.
  455. //
  456. IpSb->MaxPacketSize = IpSb->OldMaxPacketSize - IP6_MAX_IPSEC_HEADLEN;
  457. }
  458. //
  459. // Bypass all multicast inbound or outbound traffic.
  460. //
  461. if (IP6_IS_MULTICAST (&(*Head)->DestinationAddress) || IP6_IS_MULTICAST (&(*Head)->SourceAddress)) {
  462. goto ON_EXIT;
  463. }
  464. //
  465. // Rebuild fragment table from netbuf to ease ipsec process.
  466. //
  467. FragmentTable = AllocateZeroPool (FragmentCount * sizeof (NET_FRAGMENT));
  468. if (FragmentTable == NULL) {
  469. Status = EFI_OUT_OF_RESOURCES;
  470. goto ON_EXIT;
  471. }
  472. Status = NetbufBuildExt (Packet, FragmentTable, &FragmentCount);
  473. OriginalFragmentTable = FragmentTable;
  474. OriginalFragmentCount = FragmentCount;
  475. if (EFI_ERROR (Status)) {
  476. FreePool (FragmentTable);
  477. goto ON_EXIT;
  478. }
  479. //
  480. // Convert host byte order to network byte order
  481. //
  482. Ip6NtohHead (*Head);
  483. Status = mIpSec->ProcessExt (
  484. mIpSec,
  485. IpSb->Controller,
  486. IP_VERSION_6,
  487. (VOID *)(*Head),
  488. LastHead,
  489. (VOID **)ExtHdrs,
  490. ExtHdrsLen,
  491. (EFI_IPSEC_FRAGMENT_DATA **)(&FragmentTable),
  492. &FragmentCount,
  493. Direction,
  494. &RecycleEvent
  495. );
  496. //
  497. // Convert back to host byte order
  498. //
  499. Ip6NtohHead (*Head);
  500. if (EFI_ERROR (Status)) {
  501. FreePool (OriginalFragmentTable);
  502. goto ON_EXIT;
  503. }
  504. if ((OriginalFragmentCount == FragmentCount) && (OriginalFragmentTable == FragmentTable)) {
  505. //
  506. // For ByPass Packet
  507. //
  508. FreePool (FragmentTable);
  509. goto ON_EXIT;
  510. } else {
  511. //
  512. // Free the FragmentTable which allocated before calling the IPsec.
  513. //
  514. FreePool (OriginalFragmentTable);
  515. }
  516. if ((Direction == EfiIPsecOutBound) && (TxWrap != NULL)) {
  517. TxWrap->IpSecRecycleSignal = RecycleEvent;
  518. TxWrap->Packet = NetbufFromExt (
  519. FragmentTable,
  520. FragmentCount,
  521. IP6_MAX_HEADLEN,
  522. 0,
  523. Ip6FreeTxToken,
  524. TxWrap
  525. );
  526. if (TxWrap->Packet == NULL) {
  527. TxWrap->Packet = *Netbuf;
  528. Status = EFI_OUT_OF_RESOURCES;
  529. goto ON_EXIT;
  530. }
  531. CopyMem (
  532. IP6_GET_CLIP_INFO (TxWrap->Packet),
  533. IP6_GET_CLIP_INFO (Packet),
  534. sizeof (IP6_CLIP_INFO)
  535. );
  536. NetIpSecNetbufFree (Packet);
  537. *Netbuf = TxWrap->Packet;
  538. } else {
  539. IpSecWrap = AllocateZeroPool (sizeof (IP6_IPSEC_WRAP));
  540. if (IpSecWrap == NULL) {
  541. Status = EFI_OUT_OF_RESOURCES;
  542. gBS->SignalEvent (RecycleEvent);
  543. goto ON_EXIT;
  544. }
  545. IpSecWrap->IpSecRecycleSignal = RecycleEvent;
  546. IpSecWrap->Packet = Packet;
  547. Packet = NetbufFromExt (
  548. FragmentTable,
  549. FragmentCount,
  550. IP6_MAX_HEADLEN,
  551. 0,
  552. Ip6IpSecFree,
  553. IpSecWrap
  554. );
  555. if (Packet == NULL) {
  556. Packet = IpSecWrap->Packet;
  557. gBS->SignalEvent (RecycleEvent);
  558. FreePool (IpSecWrap);
  559. Status = EFI_OUT_OF_RESOURCES;
  560. goto ON_EXIT;
  561. }
  562. if ((Direction == EfiIPsecInBound) && (0 != CompareMem (&ZeroHead, *Head, sizeof (EFI_IP6_HEADER)))) {
  563. PacketHead = (EFI_IP6_HEADER *)NetbufAllocSpace (
  564. Packet,
  565. sizeof (EFI_IP6_HEADER) + *ExtHdrsLen,
  566. NET_BUF_HEAD
  567. );
  568. if (PacketHead == NULL) {
  569. *Netbuf = Packet;
  570. Status = EFI_OUT_OF_RESOURCES;
  571. goto ON_EXIT;
  572. }
  573. CopyMem (PacketHead, *Head, sizeof (EFI_IP6_HEADER));
  574. *Head = PacketHead;
  575. Packet->Ip.Ip6 = PacketHead;
  576. if (*ExtHdrs != NULL) {
  577. Buf = (UINT8 *)(PacketHead + 1);
  578. CopyMem (Buf, *ExtHdrs, *ExtHdrsLen);
  579. }
  580. NetbufTrim (Packet, sizeof (EFI_IP6_HEADER) + *ExtHdrsLen, TRUE);
  581. CopyMem (
  582. IP6_GET_CLIP_INFO (Packet),
  583. IP6_GET_CLIP_INFO (IpSecWrap->Packet),
  584. sizeof (IP6_CLIP_INFO)
  585. );
  586. }
  587. *Netbuf = Packet;
  588. }
  589. ON_EXIT:
  590. return Status;
  591. }
  592. /**
  593. Pre-process the IPv6 packet. First validates the IPv6 packet, and
  594. then reassembles packet if it is necessary.
  595. @param[in] IpSb The IP6 service instance.
  596. @param[in, out] Packet The received IP6 packet to be processed.
  597. @param[in] Flag The link layer flag for the packet received, such
  598. as multicast.
  599. @param[out] Payload The pointer to the payload of the received packet.
  600. it starts from the first byte of the extension header.
  601. @param[out] LastHead The pointer of NextHeader of the last extension
  602. header processed by IP6.
  603. @param[out] ExtHdrsLen The length of the whole option.
  604. @param[out] UnFragmentLen The length of unfragmented length of extension headers.
  605. @param[out] Fragmented Indicate whether the packet is fragmented.
  606. @param[out] Head The pointer to the EFI_IP6_Header.
  607. @retval EFI_SUCCESS The received packet is well format.
  608. @retval EFI_INVALID_PARAMETER The received packet is malformed.
  609. **/
  610. EFI_STATUS
  611. Ip6PreProcessPacket (
  612. IN IP6_SERVICE *IpSb,
  613. IN OUT NET_BUF **Packet,
  614. IN UINT32 Flag,
  615. OUT UINT8 **Payload,
  616. OUT UINT8 **LastHead,
  617. OUT UINT32 *ExtHdrsLen,
  618. OUT UINT32 *UnFragmentLen,
  619. OUT BOOLEAN *Fragmented,
  620. OUT EFI_IP6_HEADER **Head
  621. )
  622. {
  623. UINT16 PayloadLen;
  624. UINT16 TotalLen;
  625. UINT32 FormerHeadOffset;
  626. UINT32 HeadLen;
  627. IP6_FRAGMENT_HEADER *FragmentHead;
  628. UINT16 FragmentOffset;
  629. IP6_CLIP_INFO *Info;
  630. EFI_IPv6_ADDRESS Loopback;
  631. HeadLen = 0;
  632. PayloadLen = 0;
  633. //
  634. // Check whether the input packet is a valid packet
  635. //
  636. if ((*Packet)->TotalSize < IP6_MIN_HEADLEN) {
  637. return EFI_INVALID_PARAMETER;
  638. }
  639. //
  640. // Get header information of the packet.
  641. //
  642. *Head = (EFI_IP6_HEADER *)NetbufGetByte (*Packet, 0, NULL);
  643. if (*Head == NULL) {
  644. return EFI_INVALID_PARAMETER;
  645. }
  646. //
  647. // Multicast addresses must not be used as source addresses in IPv6 packets.
  648. //
  649. if (((*Head)->Version != 6) || (IP6_IS_MULTICAST (&(*Head)->SourceAddress))) {
  650. return EFI_INVALID_PARAMETER;
  651. }
  652. //
  653. // A packet with a destination address of loopback ::1/128 or unspecified must be dropped.
  654. //
  655. ZeroMem (&Loopback, sizeof (EFI_IPv6_ADDRESS));
  656. Loopback.Addr[15] = 0x1;
  657. if ((CompareMem (&Loopback, &(*Head)->DestinationAddress, sizeof (EFI_IPv6_ADDRESS)) == 0) ||
  658. (NetIp6IsUnspecifiedAddr (&(*Head)->DestinationAddress)))
  659. {
  660. return EFI_INVALID_PARAMETER;
  661. }
  662. //
  663. // Convert the IP header to host byte order.
  664. //
  665. (*Packet)->Ip.Ip6 = Ip6NtohHead (*Head);
  666. //
  667. // Get the per packet info.
  668. //
  669. Info = IP6_GET_CLIP_INFO (*Packet);
  670. Info->LinkFlag = Flag;
  671. Info->CastType = 0;
  672. if (IpSb->MnpConfigData.EnablePromiscuousReceive) {
  673. Info->CastType = Ip6Promiscuous;
  674. }
  675. if (Ip6IsOneOfSetAddress (IpSb, &(*Head)->DestinationAddress, NULL, NULL)) {
  676. Info->CastType = Ip6Unicast;
  677. } else if (IP6_IS_MULTICAST (&(*Head)->DestinationAddress)) {
  678. if (Ip6FindMldEntry (IpSb, &(*Head)->DestinationAddress) != NULL) {
  679. Info->CastType = Ip6Multicast;
  680. }
  681. }
  682. //
  683. // Drop the packet that is not delivered to us.
  684. //
  685. if (Info->CastType == 0) {
  686. return EFI_INVALID_PARAMETER;
  687. }
  688. PayloadLen = (*Head)->PayloadLength;
  689. Info->Start = 0;
  690. Info->Length = PayloadLen;
  691. Info->End = Info->Start + Info->Length;
  692. Info->HeadLen = (UINT16)sizeof (EFI_IP6_HEADER);
  693. Info->Status = EFI_SUCCESS;
  694. Info->LastFrag = FALSE;
  695. TotalLen = (UINT16)(PayloadLen + sizeof (EFI_IP6_HEADER));
  696. //
  697. // Mnp may deliver frame trailer sequence up, trim it off.
  698. //
  699. if (TotalLen < (*Packet)->TotalSize) {
  700. NetbufTrim (*Packet, (*Packet)->TotalSize - TotalLen, FALSE);
  701. }
  702. if (TotalLen != (*Packet)->TotalSize) {
  703. return EFI_INVALID_PARAMETER;
  704. }
  705. //
  706. // Check the extension headers, if exist validate them
  707. //
  708. if (PayloadLen != 0) {
  709. *Payload = AllocatePool ((UINTN)PayloadLen);
  710. if (*Payload == NULL) {
  711. return EFI_INVALID_PARAMETER;
  712. }
  713. NetbufCopy (*Packet, sizeof (EFI_IP6_HEADER), PayloadLen, *Payload);
  714. }
  715. if (!Ip6IsExtsValid (
  716. IpSb,
  717. *Packet,
  718. &(*Head)->NextHeader,
  719. *Payload,
  720. (UINT32)PayloadLen,
  721. TRUE,
  722. &FormerHeadOffset,
  723. LastHead,
  724. ExtHdrsLen,
  725. UnFragmentLen,
  726. Fragmented
  727. ))
  728. {
  729. return EFI_INVALID_PARAMETER;
  730. }
  731. HeadLen = sizeof (EFI_IP6_HEADER) + *UnFragmentLen;
  732. if (*Fragmented) {
  733. //
  734. // Get the fragment offset from the Fragment header
  735. //
  736. FragmentHead = (IP6_FRAGMENT_HEADER *)NetbufGetByte (*Packet, HeadLen, NULL);
  737. if (FragmentHead == NULL) {
  738. return EFI_INVALID_PARAMETER;
  739. }
  740. FragmentOffset = NTOHS (FragmentHead->FragmentOffset);
  741. if ((FragmentOffset & 0x1) == 0) {
  742. Info->LastFrag = TRUE;
  743. }
  744. FragmentOffset &= (~0x1);
  745. //
  746. // This is the first fragment of the packet
  747. //
  748. if (FragmentOffset == 0) {
  749. Info->NextHeader = FragmentHead->NextHeader;
  750. }
  751. Info->HeadLen = (UINT16)HeadLen;
  752. HeadLen += sizeof (IP6_FRAGMENT_HEADER);
  753. Info->Start = FragmentOffset;
  754. Info->Length = TotalLen - (UINT16)HeadLen;
  755. Info->End = Info->Start + Info->Length;
  756. Info->Id = FragmentHead->Identification;
  757. Info->FormerNextHeader = FormerHeadOffset;
  758. //
  759. // Fragments should in the unit of 8 octets long except the last one.
  760. //
  761. if ((Info->LastFrag == 0) && (Info->Length % 8 != 0)) {
  762. return EFI_INVALID_PARAMETER;
  763. }
  764. //
  765. // Reassemble the packet.
  766. //
  767. *Packet = Ip6Reassemble (&IpSb->Assemble, *Packet);
  768. if (*Packet == NULL) {
  769. return EFI_INVALID_PARAMETER;
  770. }
  771. //
  772. // Re-check the assembled packet to get the right values.
  773. //
  774. *Head = (*Packet)->Ip.Ip6;
  775. PayloadLen = (*Head)->PayloadLength;
  776. if (PayloadLen != 0) {
  777. if (*Payload != NULL) {
  778. FreePool (*Payload);
  779. }
  780. *Payload = AllocatePool ((UINTN)PayloadLen);
  781. if (*Payload == NULL) {
  782. return EFI_INVALID_PARAMETER;
  783. }
  784. NetbufCopy (*Packet, sizeof (EFI_IP6_HEADER), PayloadLen, *Payload);
  785. }
  786. if (!Ip6IsExtsValid (
  787. IpSb,
  788. *Packet,
  789. &(*Head)->NextHeader,
  790. *Payload,
  791. (UINT32)PayloadLen,
  792. TRUE,
  793. NULL,
  794. LastHead,
  795. ExtHdrsLen,
  796. UnFragmentLen,
  797. Fragmented
  798. ))
  799. {
  800. return EFI_INVALID_PARAMETER;
  801. }
  802. }
  803. //
  804. // Trim the head off, after this point, the packet is headless.
  805. // and Packet->TotalLen == Info->Length.
  806. //
  807. NetbufTrim (*Packet, sizeof (EFI_IP6_HEADER) + *ExtHdrsLen, TRUE);
  808. return EFI_SUCCESS;
  809. }
  810. /**
  811. The IP6 input routine. It is called by the IP6_INTERFACE when an
  812. IP6 fragment is received from MNP.
  813. @param[in] Packet The IP6 packet received.
  814. @param[in] IoStatus The return status of receive request.
  815. @param[in] Flag The link layer flag for the packet received, such
  816. as multicast.
  817. @param[in] Context The IP6 service instance that owns the MNP.
  818. **/
  819. VOID
  820. Ip6AcceptFrame (
  821. IN NET_BUF *Packet,
  822. IN EFI_STATUS IoStatus,
  823. IN UINT32 Flag,
  824. IN VOID *Context
  825. )
  826. {
  827. IP6_SERVICE *IpSb;
  828. EFI_IP6_HEADER *Head;
  829. UINT8 *Payload;
  830. UINT8 *LastHead;
  831. UINT32 UnFragmentLen;
  832. UINT32 ExtHdrsLen;
  833. BOOLEAN Fragmented;
  834. EFI_STATUS Status;
  835. EFI_IP6_HEADER ZeroHead;
  836. IpSb = (IP6_SERVICE *)Context;
  837. NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
  838. Payload = NULL;
  839. LastHead = NULL;
  840. //
  841. // Check input parameters
  842. //
  843. if (EFI_ERROR (IoStatus) || (IpSb->State == IP6_SERVICE_DESTROY)) {
  844. goto Drop;
  845. }
  846. //
  847. // Pre-Process the Ipv6 Packet and then reassemble if it is necessary.
  848. //
  849. Status = Ip6PreProcessPacket (
  850. IpSb,
  851. &Packet,
  852. Flag,
  853. &Payload,
  854. &LastHead,
  855. &ExtHdrsLen,
  856. &UnFragmentLen,
  857. &Fragmented,
  858. &Head
  859. );
  860. if (EFI_ERROR (Status)) {
  861. goto Restart;
  862. }
  863. //
  864. // After trim off, the packet is a esp/ah/udp/tcp/icmp6 net buffer,
  865. // and no need consider any other ahead ext headers.
  866. //
  867. Status = Ip6IpSecProcessPacket (
  868. IpSb,
  869. &Head,
  870. LastHead, // need get the lasthead value for input
  871. &Packet,
  872. &Payload,
  873. &ExtHdrsLen,
  874. EfiIPsecInBound,
  875. NULL
  876. );
  877. if (EFI_ERROR (Status)) {
  878. goto Restart;
  879. }
  880. //
  881. // If the packet is protected by IPsec Tunnel Mode, Check the Inner Ip Packet.
  882. //
  883. ZeroMem (&ZeroHead, sizeof (EFI_IP6_HEADER));
  884. if (0 == CompareMem (Head, &ZeroHead, sizeof (EFI_IP6_HEADER))) {
  885. Status = Ip6PreProcessPacket (
  886. IpSb,
  887. &Packet,
  888. Flag,
  889. &Payload,
  890. &LastHead,
  891. &ExtHdrsLen,
  892. &UnFragmentLen,
  893. &Fragmented,
  894. &Head
  895. );
  896. if (EFI_ERROR (Status)) {
  897. goto Restart;
  898. }
  899. }
  900. //
  901. // Check the Packet again.
  902. //
  903. if (Packet == NULL) {
  904. goto Restart;
  905. }
  906. //
  907. // Packet may have been changed. The ownership of the packet
  908. // is transferred to the packet process logic.
  909. //
  910. Head = Packet->Ip.Ip6;
  911. IP6_GET_CLIP_INFO (Packet)->Status = EFI_SUCCESS;
  912. switch (*LastHead) {
  913. case IP6_ICMP:
  914. Ip6IcmpHandle (IpSb, Head, Packet);
  915. break;
  916. default:
  917. Ip6Demultiplex (IpSb, Head, Packet);
  918. }
  919. Packet = NULL;
  920. //
  921. // Dispatch the DPCs queued by the NotifyFunction of the rx token's events
  922. // which are signaled with received data.
  923. //
  924. DispatchDpc ();
  925. Restart:
  926. if (Payload != NULL) {
  927. FreePool (Payload);
  928. }
  929. Ip6ReceiveFrame (Ip6AcceptFrame, IpSb);
  930. Drop:
  931. if (Packet != NULL) {
  932. NetbufFree (Packet);
  933. }
  934. return;
  935. }
  936. /**
  937. Initialize an already allocated assemble table. This is generally
  938. the assemble table embedded in the IP6 service instance.
  939. @param[in, out] Table The assemble table to initialize.
  940. **/
  941. VOID
  942. Ip6CreateAssembleTable (
  943. IN OUT IP6_ASSEMBLE_TABLE *Table
  944. )
  945. {
  946. UINT32 Index;
  947. for (Index = 0; Index < IP6_ASSEMLE_HASH_SIZE; Index++) {
  948. InitializeListHead (&Table->Bucket[Index]);
  949. }
  950. }
  951. /**
  952. Clean up the assemble table by removing all of the fragments
  953. and assemble entries.
  954. @param[in, out] Table The assemble table to clean up.
  955. **/
  956. VOID
  957. Ip6CleanAssembleTable (
  958. IN OUT IP6_ASSEMBLE_TABLE *Table
  959. )
  960. {
  961. LIST_ENTRY *Entry;
  962. LIST_ENTRY *Next;
  963. IP6_ASSEMBLE_ENTRY *Assemble;
  964. UINT32 Index;
  965. for (Index = 0; Index < IP6_ASSEMLE_HASH_SIZE; Index++) {
  966. NET_LIST_FOR_EACH_SAFE (Entry, Next, &Table->Bucket[Index]) {
  967. Assemble = NET_LIST_USER_STRUCT (Entry, IP6_ASSEMBLE_ENTRY, Link);
  968. RemoveEntryList (Entry);
  969. Ip6FreeAssembleEntry (Assemble);
  970. }
  971. }
  972. }
  973. /**
  974. The signal handle of IP6's recycle event. It is called back
  975. when the upper layer releases the packet.
  976. @param[in] Event The IP6's recycle event.
  977. @param[in] Context The context of the handle, which is a IP6_RXDATA_WRAP.
  978. **/
  979. VOID
  980. EFIAPI
  981. Ip6OnRecyclePacket (
  982. IN EFI_EVENT Event,
  983. IN VOID *Context
  984. )
  985. {
  986. IP6_RXDATA_WRAP *Wrap;
  987. Wrap = (IP6_RXDATA_WRAP *)Context;
  988. EfiAcquireLockOrFail (&Wrap->IpInstance->RecycleLock);
  989. RemoveEntryList (&Wrap->Link);
  990. EfiReleaseLock (&Wrap->IpInstance->RecycleLock);
  991. ASSERT (!NET_BUF_SHARED (Wrap->Packet));
  992. NetbufFree (Wrap->Packet);
  993. gBS->CloseEvent (Wrap->RxData.RecycleSignal);
  994. FreePool (Wrap);
  995. }
  996. /**
  997. Wrap the received packet to a IP6_RXDATA_WRAP, which will be
  998. delivered to the upper layer. Each IP6 child that accepts the
  999. packet will get a not-shared copy of the packet which is wrapped
  1000. in the IP6_RXDATA_WRAP. The IP6_RXDATA_WRAP->RxData is passed
  1001. to the upper layer. The upper layer will signal the recycle event in
  1002. it when it is done with the packet.
  1003. @param[in] IpInstance The IP6 child to receive the packet.
  1004. @param[in] Packet The packet to deliver up.
  1005. @return NULL if it failed to wrap the packet; otherwise, the wrapper.
  1006. **/
  1007. IP6_RXDATA_WRAP *
  1008. Ip6WrapRxData (
  1009. IN IP6_PROTOCOL *IpInstance,
  1010. IN NET_BUF *Packet
  1011. )
  1012. {
  1013. IP6_RXDATA_WRAP *Wrap;
  1014. EFI_IP6_RECEIVE_DATA *RxData;
  1015. EFI_STATUS Status;
  1016. Wrap = AllocatePool (IP6_RXDATA_WRAP_SIZE (Packet->BlockOpNum));
  1017. if (Wrap == NULL) {
  1018. return NULL;
  1019. }
  1020. InitializeListHead (&Wrap->Link);
  1021. Wrap->IpInstance = IpInstance;
  1022. Wrap->Packet = Packet;
  1023. RxData = &Wrap->RxData;
  1024. ZeroMem (&RxData->TimeStamp, sizeof (EFI_TIME));
  1025. Status = gBS->CreateEvent (
  1026. EVT_NOTIFY_SIGNAL,
  1027. TPL_NOTIFY,
  1028. Ip6OnRecyclePacket,
  1029. Wrap,
  1030. &RxData->RecycleSignal
  1031. );
  1032. if (EFI_ERROR (Status)) {
  1033. FreePool (Wrap);
  1034. return NULL;
  1035. }
  1036. ASSERT (Packet->Ip.Ip6 != NULL);
  1037. //
  1038. // The application expects a network byte order header.
  1039. //
  1040. RxData->HeaderLength = sizeof (EFI_IP6_HEADER);
  1041. RxData->Header = (EFI_IP6_HEADER *)Ip6NtohHead (Packet->Ip.Ip6);
  1042. RxData->DataLength = Packet->TotalSize;
  1043. //
  1044. // Build the fragment table to be delivered up.
  1045. //
  1046. RxData->FragmentCount = Packet->BlockOpNum;
  1047. NetbufBuildExt (Packet, (NET_FRAGMENT *)RxData->FragmentTable, &RxData->FragmentCount);
  1048. return Wrap;
  1049. }
  1050. /**
  1051. Check whether this IP child accepts the packet.
  1052. @param[in] IpInstance The IP child to check.
  1053. @param[in] Head The IP header of the packet.
  1054. @param[in] Packet The data of the packet.
  1055. @retval TRUE The child wants to receive the packet.
  1056. @retval FALSE The child does not want to receive the packet.
  1057. **/
  1058. BOOLEAN
  1059. Ip6InstanceFrameAcceptable (
  1060. IN IP6_PROTOCOL *IpInstance,
  1061. IN EFI_IP6_HEADER *Head,
  1062. IN NET_BUF *Packet
  1063. )
  1064. {
  1065. IP6_ICMP_ERROR_HEAD Icmp;
  1066. EFI_IP6_CONFIG_DATA *Config;
  1067. IP6_CLIP_INFO *Info;
  1068. UINT8 *Proto;
  1069. UINT32 Index;
  1070. UINT8 *ExtHdrs;
  1071. UINT16 ErrMsgPayloadLen;
  1072. UINT8 *ErrMsgPayload;
  1073. Config = &IpInstance->ConfigData;
  1074. Proto = NULL;
  1075. //
  1076. // Dirty trick for the Tiano UEFI network stack implementation. If
  1077. // ReceiveTimeout == -1, the receive of the packet for this instance
  1078. // is disabled. The UEFI spec don't have such captibility. We add
  1079. // this to improve the performance because IP will make a copy of
  1080. // the received packet for each accepting instance. Some IP instances
  1081. // used by UDP/TCP only send packets, they don't wants to receive.
  1082. //
  1083. if (Config->ReceiveTimeout == (UINT32)(-1)) {
  1084. return FALSE;
  1085. }
  1086. if (Config->AcceptPromiscuous) {
  1087. return TRUE;
  1088. }
  1089. //
  1090. // Check whether the protocol is acceptable.
  1091. //
  1092. ExtHdrs = NetbufGetByte (Packet, 0, NULL);
  1093. if (!Ip6IsExtsValid (
  1094. IpInstance->Service,
  1095. Packet,
  1096. &Head->NextHeader,
  1097. ExtHdrs,
  1098. (UINT32)Head->PayloadLength,
  1099. TRUE,
  1100. NULL,
  1101. &Proto,
  1102. NULL,
  1103. NULL,
  1104. NULL
  1105. ))
  1106. {
  1107. return FALSE;
  1108. }
  1109. //
  1110. // The upper layer driver may want to receive the ICMPv6 error packet
  1111. // invoked by its packet, like UDP.
  1112. //
  1113. if ((*Proto == IP6_ICMP) && (!Config->AcceptAnyProtocol) && (*Proto != Config->DefaultProtocol)) {
  1114. NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *)&Icmp);
  1115. if (Icmp.Head.Type <= ICMP_V6_ERROR_MAX) {
  1116. if (!Config->AcceptIcmpErrors) {
  1117. return FALSE;
  1118. }
  1119. //
  1120. // Get the protocol of the invoking packet of ICMPv6 error packet.
  1121. //
  1122. ErrMsgPayloadLen = NTOHS (Icmp.IpHead.PayloadLength);
  1123. ErrMsgPayload = NetbufGetByte (Packet, sizeof (Icmp), NULL);
  1124. if (!Ip6IsExtsValid (
  1125. NULL,
  1126. NULL,
  1127. &Icmp.IpHead.NextHeader,
  1128. ErrMsgPayload,
  1129. ErrMsgPayloadLen,
  1130. TRUE,
  1131. NULL,
  1132. &Proto,
  1133. NULL,
  1134. NULL,
  1135. NULL
  1136. ))
  1137. {
  1138. return FALSE;
  1139. }
  1140. }
  1141. }
  1142. //
  1143. // Match the protocol
  1144. //
  1145. if (!Config->AcceptAnyProtocol && (*Proto != Config->DefaultProtocol)) {
  1146. return FALSE;
  1147. }
  1148. //
  1149. // Check for broadcast, the caller has computed the packet's
  1150. // cast type for this child's interface.
  1151. //
  1152. Info = IP6_GET_CLIP_INFO (Packet);
  1153. //
  1154. // If it is a multicast packet, check whether we are in the group.
  1155. //
  1156. if (Info->CastType == Ip6Multicast) {
  1157. //
  1158. // Receive the multicast if the instance wants to receive all packets.
  1159. //
  1160. if (NetIp6IsUnspecifiedAddr (&IpInstance->ConfigData.StationAddress)) {
  1161. return TRUE;
  1162. }
  1163. for (Index = 0; Index < IpInstance->GroupCount; Index++) {
  1164. if (EFI_IP6_EQUAL (IpInstance->GroupList + Index, &Head->DestinationAddress)) {
  1165. break;
  1166. }
  1167. }
  1168. return (BOOLEAN)(Index < IpInstance->GroupCount);
  1169. }
  1170. return TRUE;
  1171. }
  1172. /**
  1173. Enqueue a shared copy of the packet to the IP6 child if the
  1174. packet is acceptable to it. Here the data of the packet is
  1175. shared, but the net buffer isn't.
  1176. @param IpInstance The IP6 child to enqueue the packet to.
  1177. @param Head The IP header of the received packet.
  1178. @param Packet The data of the received packet.
  1179. @retval EFI_NOT_STARTED The IP child hasn't been configured.
  1180. @retval EFI_INVALID_PARAMETER The child doesn't want to receive the packet.
  1181. @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources
  1182. @retval EFI_SUCCESS A shared copy the packet is enqueued to the child.
  1183. **/
  1184. EFI_STATUS
  1185. Ip6InstanceEnquePacket (
  1186. IN IP6_PROTOCOL *IpInstance,
  1187. IN EFI_IP6_HEADER *Head,
  1188. IN NET_BUF *Packet
  1189. )
  1190. {
  1191. IP6_CLIP_INFO *Info;
  1192. NET_BUF *Clone;
  1193. //
  1194. // Check whether the packet is acceptable to this instance.
  1195. //
  1196. if (IpInstance->State != IP6_STATE_CONFIGED) {
  1197. return EFI_NOT_STARTED;
  1198. }
  1199. if (!Ip6InstanceFrameAcceptable (IpInstance, Head, Packet)) {
  1200. return EFI_INVALID_PARAMETER;
  1201. }
  1202. //
  1203. // Enqueue a shared copy of the packet.
  1204. //
  1205. Clone = NetbufClone (Packet);
  1206. if (Clone == NULL) {
  1207. return EFI_OUT_OF_RESOURCES;
  1208. }
  1209. //
  1210. // Set the receive time out for the assembled packet. If it expires,
  1211. // packet will be removed from the queue.
  1212. //
  1213. Info = IP6_GET_CLIP_INFO (Clone);
  1214. Info->Life = IP6_US_TO_SEC (IpInstance->ConfigData.ReceiveTimeout);
  1215. InsertTailList (&IpInstance->Received, &Clone->List);
  1216. return EFI_SUCCESS;
  1217. }
  1218. /**
  1219. Deliver the received packets to the upper layer if there are both received
  1220. requests and enqueued packets. If the enqueued packet is shared, it will
  1221. duplicate it to a non-shared packet, release the shared packet, then
  1222. deliver the non-shared packet up.
  1223. @param[in] IpInstance The IP child to deliver the packet up.
  1224. @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to deliver the
  1225. packets.
  1226. @retval EFI_SUCCESS All the enqueued packets that can be delivered
  1227. are delivered up.
  1228. **/
  1229. EFI_STATUS
  1230. Ip6InstanceDeliverPacket (
  1231. IN IP6_PROTOCOL *IpInstance
  1232. )
  1233. {
  1234. EFI_IP6_COMPLETION_TOKEN *Token;
  1235. IP6_RXDATA_WRAP *Wrap;
  1236. NET_BUF *Packet;
  1237. NET_BUF *Dup;
  1238. UINT8 *Head;
  1239. //
  1240. // Deliver a packet if there are both a packet and a receive token.
  1241. //
  1242. while (!IsListEmpty (&IpInstance->Received) && !NetMapIsEmpty (&IpInstance->RxTokens)) {
  1243. Packet = NET_LIST_HEAD (&IpInstance->Received, NET_BUF, List);
  1244. if (!NET_BUF_SHARED (Packet)) {
  1245. //
  1246. // If this is the only instance that wants the packet, wrap it up.
  1247. //
  1248. Wrap = Ip6WrapRxData (IpInstance, Packet);
  1249. if (Wrap == NULL) {
  1250. return EFI_OUT_OF_RESOURCES;
  1251. }
  1252. RemoveEntryList (&Packet->List);
  1253. } else {
  1254. //
  1255. // Create a duplicated packet if this packet is shared
  1256. //
  1257. Dup = NetbufDuplicate (Packet, NULL, sizeof (EFI_IP6_HEADER));
  1258. if (Dup == NULL) {
  1259. return EFI_OUT_OF_RESOURCES;
  1260. }
  1261. //
  1262. // Copy the IP head over. The packet to deliver up is
  1263. // headless. Trim the head off after copy. The IP head
  1264. // may be not continuous before the data.
  1265. //
  1266. Head = NetbufAllocSpace (Dup, sizeof (EFI_IP6_HEADER), NET_BUF_HEAD);
  1267. ASSERT (Head != NULL);
  1268. Dup->Ip.Ip6 = (EFI_IP6_HEADER *)Head;
  1269. CopyMem (Head, Packet->Ip.Ip6, sizeof (EFI_IP6_HEADER));
  1270. NetbufTrim (Dup, sizeof (EFI_IP6_HEADER), TRUE);
  1271. Wrap = Ip6WrapRxData (IpInstance, Dup);
  1272. if (Wrap == NULL) {
  1273. NetbufFree (Dup);
  1274. return EFI_OUT_OF_RESOURCES;
  1275. }
  1276. RemoveEntryList (&Packet->List);
  1277. NetbufFree (Packet);
  1278. Packet = Dup;
  1279. }
  1280. //
  1281. // Insert it into the delivered packet, then get a user's
  1282. // receive token, pass the wrapped packet up.
  1283. //
  1284. EfiAcquireLockOrFail (&IpInstance->RecycleLock);
  1285. InsertHeadList (&IpInstance->Delivered, &Wrap->Link);
  1286. EfiReleaseLock (&IpInstance->RecycleLock);
  1287. Token = NetMapRemoveHead (&IpInstance->RxTokens, NULL);
  1288. Token->Status = IP6_GET_CLIP_INFO (Packet)->Status;
  1289. Token->Packet.RxData = &Wrap->RxData;
  1290. gBS->SignalEvent (Token->Event);
  1291. }
  1292. return EFI_SUCCESS;
  1293. }
  1294. /**
  1295. Enqueue a received packet to all the IP children that share
  1296. the same interface.
  1297. @param[in] IpSb The IP6 service instance that receive the packet.
  1298. @param[in] Head The header of the received packet.
  1299. @param[in] Packet The data of the received packet.
  1300. @param[in] IpIf The interface to enqueue the packet to.
  1301. @return The number of the IP6 children that accepts the packet.
  1302. **/
  1303. INTN
  1304. Ip6InterfaceEnquePacket (
  1305. IN IP6_SERVICE *IpSb,
  1306. IN EFI_IP6_HEADER *Head,
  1307. IN NET_BUF *Packet,
  1308. IN IP6_INTERFACE *IpIf
  1309. )
  1310. {
  1311. IP6_PROTOCOL *IpInstance;
  1312. IP6_CLIP_INFO *Info;
  1313. LIST_ENTRY *Entry;
  1314. INTN Enqueued;
  1315. INTN LocalType;
  1316. INTN SavedType;
  1317. //
  1318. // First, check that the packet is acceptable to this interface
  1319. // and find the local cast type for the interface.
  1320. //
  1321. LocalType = 0;
  1322. Info = IP6_GET_CLIP_INFO (Packet);
  1323. if (IpIf->PromiscRecv) {
  1324. LocalType = Ip6Promiscuous;
  1325. } else {
  1326. LocalType = Info->CastType;
  1327. }
  1328. //
  1329. // Iterate through the ip instances on the interface, enqueue
  1330. // the packet if filter passed. Save the original cast type,
  1331. // and pass the local cast type to the IP children on the
  1332. // interface. The global cast type will be restored later.
  1333. //
  1334. SavedType = Info->CastType;
  1335. Info->CastType = (UINT32)LocalType;
  1336. Enqueued = 0;
  1337. NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) {
  1338. IpInstance = NET_LIST_USER_STRUCT (Entry, IP6_PROTOCOL, AddrLink);
  1339. NET_CHECK_SIGNATURE (IpInstance, IP6_PROTOCOL_SIGNATURE);
  1340. if (Ip6InstanceEnquePacket (IpInstance, Head, Packet) == EFI_SUCCESS) {
  1341. Enqueued++;
  1342. }
  1343. }
  1344. Info->CastType = (UINT32)SavedType;
  1345. return Enqueued;
  1346. }
  1347. /**
  1348. Deliver the packet for each IP6 child on the interface.
  1349. @param[in] IpSb The IP6 service instance that received the packet.
  1350. @param[in] IpIf The IP6 interface to deliver the packet.
  1351. **/
  1352. VOID
  1353. Ip6InterfaceDeliverPacket (
  1354. IN IP6_SERVICE *IpSb,
  1355. IN IP6_INTERFACE *IpIf
  1356. )
  1357. {
  1358. IP6_PROTOCOL *IpInstance;
  1359. LIST_ENTRY *Entry;
  1360. NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) {
  1361. IpInstance = NET_LIST_USER_STRUCT (Entry, IP6_PROTOCOL, AddrLink);
  1362. Ip6InstanceDeliverPacket (IpInstance);
  1363. }
  1364. }
  1365. /**
  1366. De-multiplex the packet. the packet delivery is processed in two
  1367. passes. The first pass will enqueue a shared copy of the packet
  1368. to each IP6 child that accepts the packet. The second pass will
  1369. deliver a non-shared copy of the packet to each IP6 child that
  1370. has pending receive requests. Data is copied if more than one
  1371. child wants to consume the packet, because each IP child needs
  1372. its own copy of the packet to make changes.
  1373. @param[in] IpSb The IP6 service instance that received the packet.
  1374. @param[in] Head The header of the received packet.
  1375. @param[in] Packet The data of the received packet.
  1376. @retval EFI_NOT_FOUND No IP child accepts the packet.
  1377. @retval EFI_SUCCESS The packet is enqueued or delivered to some IP
  1378. children.
  1379. **/
  1380. EFI_STATUS
  1381. Ip6Demultiplex (
  1382. IN IP6_SERVICE *IpSb,
  1383. IN EFI_IP6_HEADER *Head,
  1384. IN NET_BUF *Packet
  1385. )
  1386. {
  1387. LIST_ENTRY *Entry;
  1388. IP6_INTERFACE *IpIf;
  1389. INTN Enqueued;
  1390. //
  1391. // Two pass delivery: first, enqueue a shared copy of the packet
  1392. // to each instance that accept the packet.
  1393. //
  1394. Enqueued = 0;
  1395. NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
  1396. IpIf = NET_LIST_USER_STRUCT (Entry, IP6_INTERFACE, Link);
  1397. if (IpIf->Configured) {
  1398. Enqueued += Ip6InterfaceEnquePacket (IpSb, Head, Packet, IpIf);
  1399. }
  1400. }
  1401. //
  1402. // Second: deliver a duplicate of the packet to each instance.
  1403. // Release the local reference first, so that the last instance
  1404. // getting the packet will not copy the data.
  1405. //
  1406. NetbufFree (Packet);
  1407. Packet = NULL;
  1408. if (Enqueued == 0) {
  1409. return EFI_NOT_FOUND;
  1410. }
  1411. NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
  1412. IpIf = NET_LIST_USER_STRUCT (Entry, IP6_INTERFACE, Link);
  1413. if (IpIf->Configured) {
  1414. Ip6InterfaceDeliverPacket (IpSb, IpIf);
  1415. }
  1416. }
  1417. return EFI_SUCCESS;
  1418. }
  1419. /**
  1420. Decrease the life of the transmitted packets. If it is
  1421. decreased to zero, cancel the packet. This function is
  1422. called by Ip6packetTimerTicking that provides timeout for both the
  1423. received-but-not-delivered and transmitted-but-not-recycle
  1424. packets.
  1425. @param[in] Map The IP6 child's transmit map.
  1426. @param[in] Item Current transmitted packet.
  1427. @param[in] Context Not used.
  1428. @retval EFI_SUCCESS Always returns EFI_SUCCESS.
  1429. **/
  1430. EFI_STATUS
  1431. EFIAPI
  1432. Ip6SentPacketTicking (
  1433. IN NET_MAP *Map,
  1434. IN NET_MAP_ITEM *Item,
  1435. IN VOID *Context
  1436. )
  1437. {
  1438. IP6_TXTOKEN_WRAP *Wrap;
  1439. Wrap = (IP6_TXTOKEN_WRAP *)Item->Value;
  1440. ASSERT (Wrap != NULL);
  1441. if ((Wrap->Life > 0) && (--Wrap->Life == 0)) {
  1442. Ip6CancelPacket (Wrap->IpInstance->Interface, Wrap->Packet, EFI_ABORTED);
  1443. }
  1444. return EFI_SUCCESS;
  1445. }
  1446. /**
  1447. Timeout the fragments, and the enqueued, and transmitted packets.
  1448. @param[in] IpSb The IP6 service instance to timeout.
  1449. **/
  1450. VOID
  1451. Ip6PacketTimerTicking (
  1452. IN IP6_SERVICE *IpSb
  1453. )
  1454. {
  1455. LIST_ENTRY *InstanceEntry;
  1456. LIST_ENTRY *Entry;
  1457. LIST_ENTRY *Next;
  1458. IP6_PROTOCOL *IpInstance;
  1459. IP6_ASSEMBLE_ENTRY *Assemble;
  1460. NET_BUF *Packet;
  1461. IP6_CLIP_INFO *Info;
  1462. UINT32 Index;
  1463. //
  1464. // First, time out the fragments. The packet's life is counting down
  1465. // once the first-arriving fragment of that packet was received.
  1466. //
  1467. for (Index = 0; Index < IP6_ASSEMLE_HASH_SIZE; Index++) {
  1468. NET_LIST_FOR_EACH_SAFE (Entry, Next, &(IpSb->Assemble.Bucket[Index])) {
  1469. Assemble = NET_LIST_USER_STRUCT (Entry, IP6_ASSEMBLE_ENTRY, Link);
  1470. if ((Assemble->Life > 0) && (--Assemble->Life == 0)) {
  1471. //
  1472. // If the first fragment (the one with a Fragment Offset of zero)
  1473. // has been received, an ICMP Time Exceeded - Fragment Reassembly
  1474. // Time Exceeded message should be sent to the source of that fragment.
  1475. //
  1476. if ((Assemble->Packet != NULL) &&
  1477. !IP6_IS_MULTICAST (&Assemble->Head->DestinationAddress))
  1478. {
  1479. Ip6SendIcmpError (
  1480. IpSb,
  1481. Assemble->Packet,
  1482. NULL,
  1483. &Assemble->Head->SourceAddress,
  1484. ICMP_V6_TIME_EXCEEDED,
  1485. ICMP_V6_TIMEOUT_REASSEMBLE,
  1486. NULL
  1487. );
  1488. }
  1489. //
  1490. // If reassembly of a packet is not completed within 60 seconds of
  1491. // the reception of the first-arriving fragment of that packet, the
  1492. // reassembly must be abandoned and all the fragments that have been
  1493. // received for that packet must be discarded.
  1494. //
  1495. RemoveEntryList (Entry);
  1496. Ip6FreeAssembleEntry (Assemble);
  1497. }
  1498. }
  1499. }
  1500. NET_LIST_FOR_EACH (InstanceEntry, &IpSb->Children) {
  1501. IpInstance = NET_LIST_USER_STRUCT (InstanceEntry, IP6_PROTOCOL, Link);
  1502. //
  1503. // Second, time out the assembled packets enqueued on each IP child.
  1504. //
  1505. NET_LIST_FOR_EACH_SAFE (Entry, Next, &IpInstance->Received) {
  1506. Packet = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
  1507. Info = IP6_GET_CLIP_INFO (Packet);
  1508. if ((Info->Life > 0) && (--Info->Life == 0)) {
  1509. RemoveEntryList (Entry);
  1510. NetbufFree (Packet);
  1511. }
  1512. }
  1513. //
  1514. // Third: time out the transmitted packets.
  1515. //
  1516. NetMapIterate (&IpInstance->TxTokens, Ip6SentPacketTicking, NULL);
  1517. }
  1518. }