Ip6Nd.c 99 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173
  1. /** @file
  2. Implementation of Neighbor Discovery support routines.
  3. Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "Ip6Impl.h"
  7. EFI_MAC_ADDRESS mZeroMacAddress;
  8. /**
  9. Update the ReachableTime in IP6 service binding instance data, in milliseconds.
  10. @param[in, out] IpSb Points to the IP6_SERVICE.
  11. **/
  12. VOID
  13. Ip6UpdateReachableTime (
  14. IN OUT IP6_SERVICE *IpSb
  15. )
  16. {
  17. UINT32 Random;
  18. Random = (NetRandomInitSeed () / 4294967295UL) * IP6_RANDOM_FACTOR_SCALE;
  19. Random = Random + IP6_MIN_RANDOM_FACTOR_SCALED;
  20. IpSb->ReachableTime = (IpSb->BaseReachableTime * Random) / IP6_RANDOM_FACTOR_SCALE;
  21. }
  22. /**
  23. Build a array of EFI_IP6_NEIGHBOR_CACHE to be returned to the caller. The number
  24. of EFI_IP6_NEIGHBOR_CACHE is also returned.
  25. @param[in] IpInstance The pointer to IP6_PROTOCOL instance.
  26. @param[out] NeighborCount The number of returned neighbor cache entries.
  27. @param[out] NeighborCache The pointer to the array of EFI_IP6_NEIGHBOR_CACHE.
  28. @retval EFI_SUCCESS The EFI_IP6_NEIGHBOR_CACHE successfully built.
  29. @retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the route table.
  30. **/
  31. EFI_STATUS
  32. Ip6BuildEfiNeighborCache (
  33. IN IP6_PROTOCOL *IpInstance,
  34. OUT UINT32 *NeighborCount,
  35. OUT EFI_IP6_NEIGHBOR_CACHE **NeighborCache
  36. )
  37. {
  38. IP6_NEIGHBOR_ENTRY *Neighbor;
  39. LIST_ENTRY *Entry;
  40. IP6_SERVICE *IpSb;
  41. UINT32 Count;
  42. EFI_IP6_NEIGHBOR_CACHE *EfiNeighborCache;
  43. EFI_IP6_NEIGHBOR_CACHE *NeighborCacheTmp;
  44. NET_CHECK_SIGNATURE (IpInstance, IP6_PROTOCOL_SIGNATURE);
  45. ASSERT (NeighborCount != NULL && NeighborCache != NULL);
  46. IpSb = IpInstance->Service;
  47. Count = 0;
  48. NET_LIST_FOR_EACH (Entry, &IpSb->NeighborTable) {
  49. Count++;
  50. }
  51. if (Count == 0) {
  52. return EFI_SUCCESS;
  53. }
  54. NeighborCacheTmp = AllocatePool (Count * sizeof (EFI_IP6_NEIGHBOR_CACHE));
  55. if (NeighborCacheTmp == NULL) {
  56. return EFI_OUT_OF_RESOURCES;
  57. }
  58. *NeighborCount = Count;
  59. Count = 0;
  60. NET_LIST_FOR_EACH (Entry, &IpSb->NeighborTable) {
  61. Neighbor = NET_LIST_USER_STRUCT (Entry, IP6_NEIGHBOR_ENTRY, Link);
  62. EfiNeighborCache = NeighborCacheTmp + Count;
  63. EfiNeighborCache->State = Neighbor->State;
  64. IP6_COPY_ADDRESS (&EfiNeighborCache->Neighbor, &Neighbor->Neighbor);
  65. IP6_COPY_LINK_ADDRESS (&EfiNeighborCache->LinkAddress, &Neighbor->LinkAddress);
  66. Count++;
  67. }
  68. ASSERT (*NeighborCount == Count);
  69. *NeighborCache = NeighborCacheTmp;
  70. return EFI_SUCCESS;
  71. }
  72. /**
  73. Build a array of EFI_IP6_ADDRESS_INFO to be returned to the caller. The number
  74. of prefix entries is also returned.
  75. @param[in] IpInstance The pointer to IP6_PROTOCOL instance.
  76. @param[out] PrefixCount The number of returned prefix entries.
  77. @param[out] PrefixTable The pointer to the array of PrefixTable.
  78. @retval EFI_SUCCESS The prefix table successfully built.
  79. @retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the prefix table.
  80. **/
  81. EFI_STATUS
  82. Ip6BuildPrefixTable (
  83. IN IP6_PROTOCOL *IpInstance,
  84. OUT UINT32 *PrefixCount,
  85. OUT EFI_IP6_ADDRESS_INFO **PrefixTable
  86. )
  87. {
  88. LIST_ENTRY *Entry;
  89. IP6_SERVICE *IpSb;
  90. UINT32 Count;
  91. IP6_PREFIX_LIST_ENTRY *PrefixList;
  92. EFI_IP6_ADDRESS_INFO *EfiPrefix;
  93. EFI_IP6_ADDRESS_INFO *PrefixTableTmp;
  94. NET_CHECK_SIGNATURE (IpInstance, IP6_PROTOCOL_SIGNATURE);
  95. ASSERT (PrefixCount != NULL && PrefixTable != NULL);
  96. IpSb = IpInstance->Service;
  97. Count = 0;
  98. NET_LIST_FOR_EACH (Entry, &IpSb->OnlinkPrefix) {
  99. Count++;
  100. }
  101. if (Count == 0) {
  102. return EFI_SUCCESS;
  103. }
  104. PrefixTableTmp = AllocatePool (Count * sizeof (EFI_IP6_ADDRESS_INFO));
  105. if (PrefixTableTmp == NULL) {
  106. return EFI_OUT_OF_RESOURCES;
  107. }
  108. *PrefixCount = Count;
  109. Count = 0;
  110. NET_LIST_FOR_EACH (Entry, &IpSb->OnlinkPrefix) {
  111. PrefixList = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
  112. EfiPrefix = PrefixTableTmp + Count;
  113. IP6_COPY_ADDRESS (&EfiPrefix->Address, &PrefixList->Prefix);
  114. EfiPrefix->PrefixLength = PrefixList->PrefixLength;
  115. Count++;
  116. }
  117. ASSERT (*PrefixCount == Count);
  118. *PrefixTable = PrefixTableTmp;
  119. return EFI_SUCCESS;
  120. }
  121. /**
  122. Allocate and initialize a IP6 prefix list entry.
  123. @param[in] IpSb The pointer to IP6_SERVICE instance.
  124. @param[in] OnLinkOrAuto If TRUE, the entry is created for the on link prefix list.
  125. Otherwise, it is created for the autoconfiguration prefix list.
  126. @param[in] ValidLifetime The length of time in seconds that the prefix
  127. is valid for the purpose of on-link determination.
  128. @param[in] PreferredLifetime The length of time in seconds that addresses
  129. generated from the prefix via stateless address
  130. autoconfiguration remain preferred.
  131. @param[in] PrefixLength The prefix length of the Prefix.
  132. @param[in] Prefix The prefix address.
  133. @return NULL if it failed to allocate memory for the prefix node. Otherwise, point
  134. to the created or existing prefix list entry.
  135. **/
  136. IP6_PREFIX_LIST_ENTRY *
  137. Ip6CreatePrefixListEntry (
  138. IN IP6_SERVICE *IpSb,
  139. IN BOOLEAN OnLinkOrAuto,
  140. IN UINT32 ValidLifetime,
  141. IN UINT32 PreferredLifetime,
  142. IN UINT8 PrefixLength,
  143. IN EFI_IPv6_ADDRESS *Prefix
  144. )
  145. {
  146. IP6_PREFIX_LIST_ENTRY *PrefixEntry;
  147. IP6_ROUTE_ENTRY *RtEntry;
  148. LIST_ENTRY *ListHead;
  149. LIST_ENTRY *Entry;
  150. IP6_PREFIX_LIST_ENTRY *TmpPrefixEntry;
  151. if ((Prefix == NULL) || (PreferredLifetime > ValidLifetime) || (PrefixLength > IP6_PREFIX_MAX)) {
  152. return NULL;
  153. }
  154. NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
  155. PrefixEntry = Ip6FindPrefixListEntry (
  156. IpSb,
  157. OnLinkOrAuto,
  158. PrefixLength,
  159. Prefix
  160. );
  161. if (PrefixEntry != NULL) {
  162. PrefixEntry->RefCnt++;
  163. return PrefixEntry;
  164. }
  165. PrefixEntry = AllocatePool (sizeof (IP6_PREFIX_LIST_ENTRY));
  166. if (PrefixEntry == NULL) {
  167. return NULL;
  168. }
  169. PrefixEntry->RefCnt = 1;
  170. PrefixEntry->ValidLifetime = ValidLifetime;
  171. PrefixEntry->PreferredLifetime = PreferredLifetime;
  172. PrefixEntry->PrefixLength = PrefixLength;
  173. IP6_COPY_ADDRESS (&PrefixEntry->Prefix, Prefix);
  174. ListHead = OnLinkOrAuto ? &IpSb->OnlinkPrefix : &IpSb->AutonomousPrefix;
  175. //
  176. // Create a direct route entry for on-link prefix and insert to route area.
  177. //
  178. if (OnLinkOrAuto) {
  179. RtEntry = Ip6CreateRouteEntry (Prefix, PrefixLength, NULL);
  180. if (RtEntry == NULL) {
  181. FreePool (PrefixEntry);
  182. return NULL;
  183. }
  184. RtEntry->Flag = IP6_DIRECT_ROUTE;
  185. InsertHeadList (&IpSb->RouteTable->RouteArea[PrefixLength], &RtEntry->Link);
  186. IpSb->RouteTable->TotalNum++;
  187. }
  188. //
  189. // Insert the prefix entry in the order that a prefix with longer prefix length
  190. // is put ahead in the list.
  191. //
  192. NET_LIST_FOR_EACH (Entry, ListHead) {
  193. TmpPrefixEntry = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
  194. if (TmpPrefixEntry->PrefixLength < PrefixEntry->PrefixLength) {
  195. break;
  196. }
  197. }
  198. NetListInsertBefore (Entry, &PrefixEntry->Link);
  199. return PrefixEntry;
  200. }
  201. /**
  202. Destroy a IP6 prefix list entry.
  203. @param[in] IpSb The pointer to IP6_SERVICE instance.
  204. @param[in] PrefixEntry The to be destroyed prefix list entry.
  205. @param[in] OnLinkOrAuto If TRUE, the entry is removed from on link prefix list.
  206. Otherwise remove from autoconfiguration prefix list.
  207. @param[in] ImmediateDelete If TRUE, remove the entry directly.
  208. Otherwise, check the reference count to see whether
  209. it should be removed.
  210. **/
  211. VOID
  212. Ip6DestroyPrefixListEntry (
  213. IN IP6_SERVICE *IpSb,
  214. IN IP6_PREFIX_LIST_ENTRY *PrefixEntry,
  215. IN BOOLEAN OnLinkOrAuto,
  216. IN BOOLEAN ImmediateDelete
  217. )
  218. {
  219. LIST_ENTRY *Entry;
  220. IP6_INTERFACE *IpIf;
  221. EFI_STATUS Status;
  222. if ((!ImmediateDelete) && (PrefixEntry->RefCnt > 0) && ((--PrefixEntry->RefCnt) > 0)) {
  223. return;
  224. }
  225. if (OnLinkOrAuto) {
  226. //
  227. // Remove the direct route for onlink prefix from route table.
  228. //
  229. do {
  230. Status = Ip6DelRoute (
  231. IpSb->RouteTable,
  232. &PrefixEntry->Prefix,
  233. PrefixEntry->PrefixLength,
  234. NULL
  235. );
  236. } while (Status != EFI_NOT_FOUND);
  237. } else {
  238. //
  239. // Remove the corresponding addresses generated from this autonomous prefix.
  240. //
  241. NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
  242. IpIf = NET_LIST_USER_STRUCT_S (Entry, IP6_INTERFACE, Link, IP6_INTERFACE_SIGNATURE);
  243. Ip6RemoveAddr (IpSb, &IpIf->AddressList, &IpIf->AddressCount, &PrefixEntry->Prefix, PrefixEntry->PrefixLength);
  244. }
  245. }
  246. RemoveEntryList (&PrefixEntry->Link);
  247. FreePool (PrefixEntry);
  248. }
  249. /**
  250. Search the list array to find an IP6 prefix list entry.
  251. @param[in] IpSb The pointer to IP6_SERVICE instance.
  252. @param[in] OnLinkOrAuto If TRUE, the search the link prefix list,
  253. Otherwise search the autoconfiguration prefix list.
  254. @param[in] PrefixLength The prefix length of the Prefix
  255. @param[in] Prefix The prefix address.
  256. @return NULL if cannot find the IP6 prefix list entry. Otherwise, return the
  257. pointer to the IP6 prefix list entry.
  258. **/
  259. IP6_PREFIX_LIST_ENTRY *
  260. Ip6FindPrefixListEntry (
  261. IN IP6_SERVICE *IpSb,
  262. IN BOOLEAN OnLinkOrAuto,
  263. IN UINT8 PrefixLength,
  264. IN EFI_IPv6_ADDRESS *Prefix
  265. )
  266. {
  267. IP6_PREFIX_LIST_ENTRY *PrefixList;
  268. LIST_ENTRY *Entry;
  269. LIST_ENTRY *ListHead;
  270. NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
  271. ASSERT (Prefix != NULL);
  272. if (OnLinkOrAuto) {
  273. ListHead = &IpSb->OnlinkPrefix;
  274. } else {
  275. ListHead = &IpSb->AutonomousPrefix;
  276. }
  277. NET_LIST_FOR_EACH (Entry, ListHead) {
  278. PrefixList = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
  279. if (PrefixLength != 255) {
  280. //
  281. // Perform exactly prefix match.
  282. //
  283. if ((PrefixList->PrefixLength == PrefixLength) &&
  284. NetIp6IsNetEqual (&PrefixList->Prefix, Prefix, PrefixLength))
  285. {
  286. return PrefixList;
  287. }
  288. } else {
  289. //
  290. // Perform the longest prefix match. The list is already sorted with
  291. // the longest length prefix put at the head of the list.
  292. //
  293. if (NetIp6IsNetEqual (&PrefixList->Prefix, Prefix, PrefixList->PrefixLength)) {
  294. return PrefixList;
  295. }
  296. }
  297. }
  298. return NULL;
  299. }
  300. /**
  301. Release the resource in the prefix list table, and destroy the list entry and
  302. corresponding addresses or route entries.
  303. @param[in] IpSb The pointer to the IP6_SERVICE instance.
  304. @param[in] ListHead The list entry head of the prefix list table.
  305. **/
  306. VOID
  307. Ip6CleanPrefixListTable (
  308. IN IP6_SERVICE *IpSb,
  309. IN LIST_ENTRY *ListHead
  310. )
  311. {
  312. IP6_PREFIX_LIST_ENTRY *PrefixList;
  313. BOOLEAN OnLink;
  314. OnLink = (BOOLEAN)(ListHead == &IpSb->OnlinkPrefix);
  315. while (!IsListEmpty (ListHead)) {
  316. PrefixList = NET_LIST_HEAD (ListHead, IP6_PREFIX_LIST_ENTRY, Link);
  317. Ip6DestroyPrefixListEntry (IpSb, PrefixList, OnLink, TRUE);
  318. }
  319. }
  320. /**
  321. Callback function when address resolution is finished. It will cancel
  322. all the queued frames if the address resolution failed, or transmit them
  323. if the request succeeded.
  324. @param[in] Context The context of the callback, a pointer to IP6_NEIGHBOR_ENTRY.
  325. **/
  326. VOID
  327. Ip6OnArpResolved (
  328. IN VOID *Context
  329. )
  330. {
  331. LIST_ENTRY *Entry;
  332. LIST_ENTRY *Next;
  333. IP6_NEIGHBOR_ENTRY *ArpQue;
  334. IP6_SERVICE *IpSb;
  335. IP6_LINK_TX_TOKEN *Token;
  336. EFI_STATUS Status;
  337. BOOLEAN Sent;
  338. ArpQue = (IP6_NEIGHBOR_ENTRY *)Context;
  339. if ((ArpQue == NULL) || (ArpQue->Interface == NULL)) {
  340. return;
  341. }
  342. IpSb = ArpQue->Interface->Service;
  343. if ((IpSb == NULL) || (IpSb->Signature != IP6_SERVICE_SIGNATURE)) {
  344. return;
  345. }
  346. //
  347. // ARP resolve failed for some reason. Release all the frame
  348. // and ARP queue itself. Ip6FreeArpQue will call the frame's
  349. // owner back.
  350. //
  351. if (NET_MAC_EQUAL (&ArpQue->LinkAddress, &mZeroMacAddress, IpSb->SnpMode.HwAddressSize)) {
  352. Ip6FreeNeighborEntry (IpSb, ArpQue, FALSE, TRUE, EFI_NO_MAPPING, NULL, NULL);
  353. return;
  354. }
  355. //
  356. // ARP resolve succeeded, Transmit all the frame.
  357. //
  358. Sent = FALSE;
  359. NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {
  360. RemoveEntryList (Entry);
  361. Token = NET_LIST_USER_STRUCT (Entry, IP6_LINK_TX_TOKEN, Link);
  362. IP6_COPY_LINK_ADDRESS (&Token->DstMac, &ArpQue->LinkAddress);
  363. //
  364. // Insert the tx token before transmitting it via MNP as the FrameSentDpc
  365. // may be called before Mnp->Transmit returns which will remove this tx
  366. // token from the SentFrames list. Remove it from the list if the returned
  367. // Status of Mnp->Transmit is not EFI_SUCCESS as in this case the
  368. // FrameSentDpc won't be queued.
  369. //
  370. InsertTailList (&ArpQue->Interface->SentFrames, &Token->Link);
  371. Status = IpSb->Mnp->Transmit (IpSb->Mnp, &Token->MnpToken);
  372. if (EFI_ERROR (Status)) {
  373. RemoveEntryList (&Token->Link);
  374. Token->CallBack (Token->Packet, Status, 0, Token->Context);
  375. Ip6FreeLinkTxToken (Token);
  376. continue;
  377. } else {
  378. Sent = TRUE;
  379. }
  380. }
  381. //
  382. // Free the ArpQue only but not the whole neighbor entry.
  383. //
  384. Ip6FreeNeighborEntry (IpSb, ArpQue, FALSE, FALSE, EFI_SUCCESS, NULL, NULL);
  385. if (Sent && (ArpQue->State == EfiNeighborStale)) {
  386. ArpQue->State = EfiNeighborDelay;
  387. ArpQue->Ticks = (UINT32)IP6_GET_TICKS (IP6_DELAY_FIRST_PROBE_TIME);
  388. }
  389. }
  390. /**
  391. Allocate and initialize an IP6 neighbor cache entry.
  392. @param[in] IpSb The pointer to the IP6_SERVICE instance.
  393. @param[in] CallBack The callback function to be called when
  394. address resolution is finished.
  395. @param[in] Ip6Address Points to the IPv6 address of the neighbor.
  396. @param[in] LinkAddress Points to the MAC address of the neighbor.
  397. Ignored if NULL.
  398. @return NULL if failed to allocate memory for the neighbor cache entry.
  399. Otherwise, point to the created neighbor cache entry.
  400. **/
  401. IP6_NEIGHBOR_ENTRY *
  402. Ip6CreateNeighborEntry (
  403. IN IP6_SERVICE *IpSb,
  404. IN IP6_ARP_CALLBACK CallBack,
  405. IN EFI_IPv6_ADDRESS *Ip6Address,
  406. IN EFI_MAC_ADDRESS *LinkAddress OPTIONAL
  407. )
  408. {
  409. IP6_NEIGHBOR_ENTRY *Entry;
  410. IP6_DEFAULT_ROUTER *DefaultRouter;
  411. NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
  412. ASSERT (Ip6Address != NULL);
  413. Entry = AllocateZeroPool (sizeof (IP6_NEIGHBOR_ENTRY));
  414. if (Entry == NULL) {
  415. return NULL;
  416. }
  417. Entry->RefCnt = 1;
  418. Entry->IsRouter = FALSE;
  419. Entry->ArpFree = FALSE;
  420. Entry->Dynamic = FALSE;
  421. Entry->State = EfiNeighborInComplete;
  422. Entry->Transmit = IP6_MAX_MULTICAST_SOLICIT + 1;
  423. Entry->CallBack = CallBack;
  424. Entry->Interface = NULL;
  425. InitializeListHead (&Entry->Frames);
  426. IP6_COPY_ADDRESS (&Entry->Neighbor, Ip6Address);
  427. if (LinkAddress != NULL) {
  428. IP6_COPY_LINK_ADDRESS (&Entry->LinkAddress, LinkAddress);
  429. } else {
  430. IP6_COPY_LINK_ADDRESS (&Entry->LinkAddress, &mZeroMacAddress);
  431. }
  432. InsertHeadList (&IpSb->NeighborTable, &Entry->Link);
  433. //
  434. // If corresponding default router entry exists, establish the relationship.
  435. //
  436. DefaultRouter = Ip6FindDefaultRouter (IpSb, Ip6Address);
  437. if (DefaultRouter != NULL) {
  438. DefaultRouter->NeighborCache = Entry;
  439. }
  440. return Entry;
  441. }
  442. /**
  443. Search a IP6 neighbor cache entry.
  444. @param[in] IpSb The pointer to the IP6_SERVICE instance.
  445. @param[in] Ip6Address Points to the IPv6 address of the neighbor.
  446. @return NULL if it failed to find the matching neighbor cache entry.
  447. Otherwise, point to the found neighbor cache entry.
  448. **/
  449. IP6_NEIGHBOR_ENTRY *
  450. Ip6FindNeighborEntry (
  451. IN IP6_SERVICE *IpSb,
  452. IN EFI_IPv6_ADDRESS *Ip6Address
  453. )
  454. {
  455. LIST_ENTRY *Entry;
  456. LIST_ENTRY *Next;
  457. IP6_NEIGHBOR_ENTRY *Neighbor;
  458. NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
  459. ASSERT (Ip6Address != NULL);
  460. NET_LIST_FOR_EACH_SAFE (Entry, Next, &IpSb->NeighborTable) {
  461. Neighbor = NET_LIST_USER_STRUCT (Entry, IP6_NEIGHBOR_ENTRY, Link);
  462. if (EFI_IP6_EQUAL (Ip6Address, &Neighbor->Neighbor)) {
  463. RemoveEntryList (Entry);
  464. InsertHeadList (&IpSb->NeighborTable, Entry);
  465. return Neighbor;
  466. }
  467. }
  468. return NULL;
  469. }
  470. /**
  471. Free a IP6 neighbor cache entry and remove all the frames on the address
  472. resolution queue that pass the FrameToCancel. That is, either FrameToCancel
  473. is NULL, or it returns true for the frame.
  474. @param[in] IpSb The pointer to the IP6_SERVICE instance.
  475. @param[in] NeighborCache The to be free neighbor cache entry.
  476. @param[in] SendIcmpError If TRUE, send out ICMP error.
  477. @param[in] FullFree If TRUE, remove the neighbor cache entry.
  478. Otherwise remove the pending frames.
  479. @param[in] IoStatus The status returned to the cancelled frames'
  480. callback function.
  481. @param[in] FrameToCancel Function to select which frame to cancel.
  482. This is an optional parameter that may be NULL.
  483. @param[in] Context Opaque parameter to the FrameToCancel.
  484. Ignored if FrameToCancel is NULL.
  485. @retval EFI_INVALID_PARAMETER The input parameter is invalid.
  486. @retval EFI_SUCCESS The operation finished successfully.
  487. **/
  488. EFI_STATUS
  489. Ip6FreeNeighborEntry (
  490. IN IP6_SERVICE *IpSb,
  491. IN IP6_NEIGHBOR_ENTRY *NeighborCache,
  492. IN BOOLEAN SendIcmpError,
  493. IN BOOLEAN FullFree,
  494. IN EFI_STATUS IoStatus,
  495. IN IP6_FRAME_TO_CANCEL FrameToCancel OPTIONAL,
  496. IN VOID *Context OPTIONAL
  497. )
  498. {
  499. IP6_LINK_TX_TOKEN *TxToken;
  500. LIST_ENTRY *Entry;
  501. LIST_ENTRY *Next;
  502. IP6_DEFAULT_ROUTER *DefaultRouter;
  503. //
  504. // If FrameToCancel fails, the token will not be released.
  505. // To avoid the memory leak, stop this usage model.
  506. //
  507. if (FullFree && (FrameToCancel != NULL)) {
  508. return EFI_INVALID_PARAMETER;
  509. }
  510. NET_LIST_FOR_EACH_SAFE (Entry, Next, &NeighborCache->Frames) {
  511. TxToken = NET_LIST_USER_STRUCT (Entry, IP6_LINK_TX_TOKEN, Link);
  512. if (SendIcmpError && !IP6_IS_MULTICAST (&TxToken->Packet->Ip.Ip6->DestinationAddress)) {
  513. Ip6SendIcmpError (
  514. IpSb,
  515. TxToken->Packet,
  516. NULL,
  517. &TxToken->Packet->Ip.Ip6->SourceAddress,
  518. ICMP_V6_DEST_UNREACHABLE,
  519. ICMP_V6_ADDR_UNREACHABLE,
  520. NULL
  521. );
  522. }
  523. if ((FrameToCancel == NULL) || FrameToCancel (TxToken, Context)) {
  524. RemoveEntryList (Entry);
  525. TxToken->CallBack (TxToken->Packet, IoStatus, 0, TxToken->Context);
  526. Ip6FreeLinkTxToken (TxToken);
  527. }
  528. }
  529. if (NeighborCache->ArpFree && IsListEmpty (&NeighborCache->Frames)) {
  530. RemoveEntryList (&NeighborCache->ArpList);
  531. NeighborCache->ArpFree = FALSE;
  532. }
  533. if (FullFree) {
  534. if (NeighborCache->IsRouter) {
  535. DefaultRouter = Ip6FindDefaultRouter (IpSb, &NeighborCache->Neighbor);
  536. if (DefaultRouter != NULL) {
  537. Ip6DestroyDefaultRouter (IpSb, DefaultRouter);
  538. }
  539. }
  540. RemoveEntryList (&NeighborCache->Link);
  541. FreePool (NeighborCache);
  542. }
  543. return EFI_SUCCESS;
  544. }
  545. /**
  546. Allocate and initialize an IP6 default router entry.
  547. @param[in] IpSb The pointer to the IP6_SERVICE instance.
  548. @param[in] Ip6Address The IPv6 address of the default router.
  549. @param[in] RouterLifetime The lifetime associated with the default
  550. router, in units of seconds.
  551. @return NULL if it failed to allocate memory for the default router node.
  552. Otherwise, point to the created default router node.
  553. **/
  554. IP6_DEFAULT_ROUTER *
  555. Ip6CreateDefaultRouter (
  556. IN IP6_SERVICE *IpSb,
  557. IN EFI_IPv6_ADDRESS *Ip6Address,
  558. IN UINT16 RouterLifetime
  559. )
  560. {
  561. IP6_DEFAULT_ROUTER *Entry;
  562. IP6_ROUTE_ENTRY *RtEntry;
  563. NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
  564. ASSERT (Ip6Address != NULL);
  565. Entry = AllocatePool (sizeof (IP6_DEFAULT_ROUTER));
  566. if (Entry == NULL) {
  567. return NULL;
  568. }
  569. Entry->RefCnt = 1;
  570. Entry->Lifetime = RouterLifetime;
  571. Entry->NeighborCache = Ip6FindNeighborEntry (IpSb, Ip6Address);
  572. IP6_COPY_ADDRESS (&Entry->Router, Ip6Address);
  573. //
  574. // Add a default route into route table with both Destination and PrefixLength set to zero.
  575. //
  576. RtEntry = Ip6CreateRouteEntry (NULL, 0, Ip6Address);
  577. if (RtEntry == NULL) {
  578. FreePool (Entry);
  579. return NULL;
  580. }
  581. InsertHeadList (&IpSb->RouteTable->RouteArea[0], &RtEntry->Link);
  582. IpSb->RouteTable->TotalNum++;
  583. InsertTailList (&IpSb->DefaultRouterList, &Entry->Link);
  584. return Entry;
  585. }
  586. /**
  587. Destroy an IP6 default router entry.
  588. @param[in] IpSb The pointer to the IP6_SERVICE instance.
  589. @param[in] DefaultRouter The to be destroyed IP6_DEFAULT_ROUTER.
  590. **/
  591. VOID
  592. Ip6DestroyDefaultRouter (
  593. IN IP6_SERVICE *IpSb,
  594. IN IP6_DEFAULT_ROUTER *DefaultRouter
  595. )
  596. {
  597. EFI_STATUS Status;
  598. RemoveEntryList (&DefaultRouter->Link);
  599. //
  600. // Update the Destination Cache - all entries using the time-out router as next-hop
  601. // should perform next-hop determination again.
  602. //
  603. do {
  604. Status = Ip6DelRoute (IpSb->RouteTable, NULL, 0, &DefaultRouter->Router);
  605. } while (Status != EFI_NOT_FOUND);
  606. FreePool (DefaultRouter);
  607. }
  608. /**
  609. Clean an IP6 default router list.
  610. @param[in] IpSb The pointer to the IP6_SERVICE instance.
  611. **/
  612. VOID
  613. Ip6CleanDefaultRouterList (
  614. IN IP6_SERVICE *IpSb
  615. )
  616. {
  617. IP6_DEFAULT_ROUTER *DefaultRouter;
  618. while (!IsListEmpty (&IpSb->DefaultRouterList)) {
  619. DefaultRouter = NET_LIST_HEAD (&IpSb->DefaultRouterList, IP6_DEFAULT_ROUTER, Link);
  620. Ip6DestroyDefaultRouter (IpSb, DefaultRouter);
  621. }
  622. }
  623. /**
  624. Search a default router node from an IP6 default router list.
  625. @param[in] IpSb The pointer to the IP6_SERVICE instance.
  626. @param[in] Ip6Address The IPv6 address of the to be searched default router node.
  627. @return NULL if it failed to find the matching default router node.
  628. Otherwise, point to the found default router node.
  629. **/
  630. IP6_DEFAULT_ROUTER *
  631. Ip6FindDefaultRouter (
  632. IN IP6_SERVICE *IpSb,
  633. IN EFI_IPv6_ADDRESS *Ip6Address
  634. )
  635. {
  636. LIST_ENTRY *Entry;
  637. IP6_DEFAULT_ROUTER *DefaultRouter;
  638. NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
  639. ASSERT (Ip6Address != NULL);
  640. NET_LIST_FOR_EACH (Entry, &IpSb->DefaultRouterList) {
  641. DefaultRouter = NET_LIST_USER_STRUCT (Entry, IP6_DEFAULT_ROUTER, Link);
  642. if (EFI_IP6_EQUAL (Ip6Address, &DefaultRouter->Router)) {
  643. return DefaultRouter;
  644. }
  645. }
  646. return NULL;
  647. }
  648. /**
  649. The function to be called after DAD (Duplicate Address Detection) is performed.
  650. @param[in] IsDadPassed If TRUE, the DAD operation succeed. Otherwise, the DAD operation failed.
  651. @param[in] IpIf Points to the IP6_INTERFACE.
  652. @param[in] DadEntry The DAD entry which already performed DAD.
  653. **/
  654. VOID
  655. Ip6OnDADFinished (
  656. IN BOOLEAN IsDadPassed,
  657. IN IP6_INTERFACE *IpIf,
  658. IN IP6_DAD_ENTRY *DadEntry
  659. )
  660. {
  661. IP6_SERVICE *IpSb;
  662. IP6_ADDRESS_INFO *AddrInfo;
  663. EFI_DHCP6_PROTOCOL *Dhcp6;
  664. UINT16 OptBuf[4];
  665. EFI_DHCP6_PACKET_OPTION *Oro;
  666. EFI_DHCP6_RETRANSMISSION InfoReqReXmit;
  667. EFI_IPv6_ADDRESS AllNodes;
  668. IpSb = IpIf->Service;
  669. AddrInfo = DadEntry->AddressInfo;
  670. if (IsDadPassed) {
  671. //
  672. // DAD succeed.
  673. //
  674. if (NetIp6IsLinkLocalAddr (&AddrInfo->Address)) {
  675. ASSERT (!IpSb->LinkLocalOk);
  676. IP6_COPY_ADDRESS (&IpSb->LinkLocalAddr, &AddrInfo->Address);
  677. IpSb->LinkLocalOk = TRUE;
  678. IpIf->Configured = TRUE;
  679. //
  680. // Check whether DHCP6 need to be started.
  681. //
  682. Dhcp6 = IpSb->Ip6ConfigInstance.Dhcp6;
  683. if (IpSb->Dhcp6NeedStart) {
  684. Dhcp6->Start (Dhcp6);
  685. IpSb->Dhcp6NeedStart = FALSE;
  686. }
  687. if (IpSb->Dhcp6NeedInfoRequest) {
  688. //
  689. // Set the exta options to send. Here we only want the option request option
  690. // with DNS SERVERS.
  691. //
  692. Oro = (EFI_DHCP6_PACKET_OPTION *)OptBuf;
  693. Oro->OpCode = HTONS (DHCP6_OPT_ORO);
  694. Oro->OpLen = HTONS (2);
  695. *((UINT16 *)&Oro->Data[0]) = HTONS (DHCP6_OPT_DNS_SERVERS);
  696. InfoReqReXmit.Irt = 4;
  697. InfoReqReXmit.Mrc = 64;
  698. InfoReqReXmit.Mrt = 60;
  699. InfoReqReXmit.Mrd = 0;
  700. Dhcp6->InfoRequest (
  701. Dhcp6,
  702. TRUE,
  703. Oro,
  704. 0,
  705. NULL,
  706. &InfoReqReXmit,
  707. IpSb->Ip6ConfigInstance.Dhcp6Event,
  708. Ip6ConfigOnDhcp6Reply,
  709. &IpSb->Ip6ConfigInstance
  710. );
  711. }
  712. //
  713. // Add an on-link prefix for link-local address.
  714. //
  715. Ip6CreatePrefixListEntry (
  716. IpSb,
  717. TRUE,
  718. (UINT32)IP6_INFINIT_LIFETIME,
  719. (UINT32)IP6_INFINIT_LIFETIME,
  720. IP6_LINK_LOCAL_PREFIX_LENGTH,
  721. &IpSb->LinkLocalAddr
  722. );
  723. } else {
  724. //
  725. // Global scope unicast address.
  726. //
  727. Ip6AddAddr (IpIf, AddrInfo);
  728. //
  729. // Add an on-link prefix for this address.
  730. //
  731. Ip6CreatePrefixListEntry (
  732. IpSb,
  733. TRUE,
  734. AddrInfo->ValidLifetime,
  735. AddrInfo->PreferredLifetime,
  736. AddrInfo->PrefixLength,
  737. &AddrInfo->Address
  738. );
  739. IpIf->Configured = TRUE;
  740. }
  741. } else {
  742. //
  743. // Leave the group we joined before.
  744. //
  745. Ip6LeaveGroup (IpSb, &DadEntry->Destination);
  746. }
  747. if (DadEntry->Callback != NULL) {
  748. DadEntry->Callback (IsDadPassed, &AddrInfo->Address, DadEntry->Context);
  749. }
  750. if (!IsDadPassed && NetIp6IsLinkLocalAddr (&AddrInfo->Address)) {
  751. FreePool (AddrInfo);
  752. RemoveEntryList (&DadEntry->Link);
  753. FreePool (DadEntry);
  754. //
  755. // Leave link-scope all-nodes multicast address (FF02::1)
  756. //
  757. Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &AllNodes);
  758. Ip6LeaveGroup (IpSb, &AllNodes);
  759. //
  760. // Disable IP operation since link-local address is a duplicate address.
  761. //
  762. IpSb->LinkLocalDadFail = TRUE;
  763. IpSb->Mnp->Configure (IpSb->Mnp, NULL);
  764. gBS->SetTimer (IpSb->Timer, TimerCancel, 0);
  765. gBS->SetTimer (IpSb->FasterTimer, TimerCancel, 0);
  766. return;
  767. }
  768. if (!IsDadPassed || NetIp6IsLinkLocalAddr (&AddrInfo->Address)) {
  769. //
  770. // Free the AddressInfo we hold if DAD fails or it is a link-local address.
  771. //
  772. FreePool (AddrInfo);
  773. }
  774. RemoveEntryList (&DadEntry->Link);
  775. FreePool (DadEntry);
  776. }
  777. /**
  778. Create a DAD (Duplicate Address Detection) entry and queue it to be performed.
  779. @param[in] IpIf Points to the IP6_INTERFACE.
  780. @param[in] AddressInfo The address information which needs DAD performed.
  781. @param[in] Callback The callback routine that will be called after DAD
  782. is performed. This is an optional parameter that
  783. may be NULL.
  784. @param[in] Context The opaque parameter for a DAD callback routine.
  785. This is an optional parameter that may be NULL.
  786. @retval EFI_SUCCESS The DAD entry was created and queued.
  787. @retval EFI_OUT_OF_RESOURCES Failed to allocate the memory to complete the
  788. operation.
  789. **/
  790. EFI_STATUS
  791. Ip6InitDADProcess (
  792. IN IP6_INTERFACE *IpIf,
  793. IN IP6_ADDRESS_INFO *AddressInfo,
  794. IN IP6_DAD_CALLBACK Callback OPTIONAL,
  795. IN VOID *Context OPTIONAL
  796. )
  797. {
  798. IP6_DAD_ENTRY *Entry;
  799. EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS *DadXmits;
  800. IP6_SERVICE *IpSb;
  801. EFI_STATUS Status;
  802. UINT32 MaxDelayTick;
  803. NET_CHECK_SIGNATURE (IpIf, IP6_INTERFACE_SIGNATURE);
  804. ASSERT (AddressInfo != NULL);
  805. //
  806. // Do nothing if we have already started DAD on the address.
  807. //
  808. if (Ip6FindDADEntry (IpIf->Service, &AddressInfo->Address, NULL) != NULL) {
  809. return EFI_SUCCESS;
  810. }
  811. Status = EFI_SUCCESS;
  812. IpSb = IpIf->Service;
  813. DadXmits = &IpSb->Ip6ConfigInstance.DadXmits;
  814. //
  815. // Allocate the resources and insert info
  816. //
  817. Entry = AllocatePool (sizeof (IP6_DAD_ENTRY));
  818. if (Entry == NULL) {
  819. return EFI_OUT_OF_RESOURCES;
  820. }
  821. //
  822. // Map the incoming unicast address to solicited-node multicast address
  823. //
  824. Ip6CreateSNMulticastAddr (&AddressInfo->Address, &Entry->Destination);
  825. //
  826. // Join in the solicited-node multicast address.
  827. //
  828. Status = Ip6JoinGroup (IpSb, IpIf, &Entry->Destination);
  829. if (EFI_ERROR (Status)) {
  830. FreePool (Entry);
  831. return Status;
  832. }
  833. Entry->Signature = IP6_DAD_ENTRY_SIGNATURE;
  834. Entry->MaxTransmit = DadXmits->DupAddrDetectTransmits;
  835. Entry->Transmit = 0;
  836. Entry->Receive = 0;
  837. MaxDelayTick = IP6_MAX_RTR_SOLICITATION_DELAY / IP6_TIMER_INTERVAL_IN_MS;
  838. Entry->RetransTick = (MaxDelayTick * ((NET_RANDOM (NetRandomInitSeed ()) % 5) + 1)) / 5;
  839. Entry->AddressInfo = AddressInfo;
  840. Entry->Callback = Callback;
  841. Entry->Context = Context;
  842. InsertTailList (&IpIf->DupAddrDetectList, &Entry->Link);
  843. if (Entry->MaxTransmit == 0) {
  844. //
  845. // DAD is disabled on this interface, immediately mark this DAD successful.
  846. //
  847. Ip6OnDADFinished (TRUE, IpIf, Entry);
  848. }
  849. return EFI_SUCCESS;
  850. }
  851. /**
  852. Search IP6_DAD_ENTRY from the Duplicate Address Detection List.
  853. @param[in] IpSb The pointer to the IP6_SERVICE instance.
  854. @param[in] Target The address information which needs DAD performed .
  855. @param[out] Interface If not NULL, output the IP6 interface that configures
  856. the tentative address.
  857. @return NULL if failed to find the matching DAD entry.
  858. Otherwise, point to the found DAD entry.
  859. **/
  860. IP6_DAD_ENTRY *
  861. Ip6FindDADEntry (
  862. IN IP6_SERVICE *IpSb,
  863. IN EFI_IPv6_ADDRESS *Target,
  864. OUT IP6_INTERFACE **Interface OPTIONAL
  865. )
  866. {
  867. LIST_ENTRY *Entry;
  868. LIST_ENTRY *Entry2;
  869. IP6_INTERFACE *IpIf;
  870. IP6_DAD_ENTRY *DupAddrDetect;
  871. IP6_ADDRESS_INFO *AddrInfo;
  872. NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
  873. IpIf = NET_LIST_USER_STRUCT (Entry, IP6_INTERFACE, Link);
  874. NET_LIST_FOR_EACH (Entry2, &IpIf->DupAddrDetectList) {
  875. DupAddrDetect = NET_LIST_USER_STRUCT_S (Entry2, IP6_DAD_ENTRY, Link, IP6_DAD_ENTRY_SIGNATURE);
  876. AddrInfo = DupAddrDetect->AddressInfo;
  877. if (EFI_IP6_EQUAL (&AddrInfo->Address, Target)) {
  878. if (Interface != NULL) {
  879. *Interface = IpIf;
  880. }
  881. return DupAddrDetect;
  882. }
  883. }
  884. }
  885. return NULL;
  886. }
  887. /**
  888. Generate router solicit message and send it out to Destination Address or
  889. All Router Link Local scope multicast address.
  890. @param[in] IpSb The IP service to send the packet.
  891. @param[in] Interface If not NULL, points to the IP6 interface to send
  892. the packet.
  893. @param[in] SourceAddress If not NULL, the source address of the message.
  894. @param[in] DestinationAddress If not NULL, the destination address of the message.
  895. @param[in] SourceLinkAddress If not NULL, the MAC address of the source.
  896. A source link-layer address option will be appended
  897. to the message.
  898. @retval EFI_OUT_OF_RESOURCES Insufficient resources to complete the
  899. operation.
  900. @retval EFI_SUCCESS The router solicit message was successfully sent.
  901. **/
  902. EFI_STATUS
  903. Ip6SendRouterSolicit (
  904. IN IP6_SERVICE *IpSb,
  905. IN IP6_INTERFACE *Interface OPTIONAL,
  906. IN EFI_IPv6_ADDRESS *SourceAddress OPTIONAL,
  907. IN EFI_IPv6_ADDRESS *DestinationAddress OPTIONAL,
  908. IN EFI_MAC_ADDRESS *SourceLinkAddress OPTIONAL
  909. )
  910. {
  911. NET_BUF *Packet;
  912. EFI_IP6_HEADER Head;
  913. IP6_ICMP_INFORMATION_HEAD *IcmpHead;
  914. IP6_ETHER_ADDR_OPTION *LinkLayerOption;
  915. UINT16 PayloadLen;
  916. IP6_INTERFACE *IpIf;
  917. NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
  918. IpIf = Interface;
  919. if ((IpIf == NULL) && (IpSb->DefaultInterface != NULL)) {
  920. IpIf = IpSb->DefaultInterface;
  921. }
  922. //
  923. // Generate the packet to be sent
  924. //
  925. PayloadLen = (UINT16)sizeof (IP6_ICMP_INFORMATION_HEAD);
  926. if (SourceLinkAddress != NULL) {
  927. PayloadLen += sizeof (IP6_ETHER_ADDR_OPTION);
  928. }
  929. Packet = NetbufAlloc (sizeof (EFI_IP6_HEADER) + (UINT32)PayloadLen);
  930. if (Packet == NULL) {
  931. return EFI_OUT_OF_RESOURCES;
  932. }
  933. //
  934. // Create the basic IPv6 header.
  935. //
  936. Head.FlowLabelL = 0;
  937. Head.FlowLabelH = 0;
  938. Head.PayloadLength = HTONS (PayloadLen);
  939. Head.NextHeader = IP6_ICMP;
  940. Head.HopLimit = IP6_HOP_LIMIT;
  941. if (SourceAddress != NULL) {
  942. IP6_COPY_ADDRESS (&Head.SourceAddress, SourceAddress);
  943. } else {
  944. ZeroMem (&Head.SourceAddress, sizeof (EFI_IPv6_ADDRESS));
  945. }
  946. if (DestinationAddress != NULL) {
  947. IP6_COPY_ADDRESS (&Head.DestinationAddress, DestinationAddress);
  948. } else {
  949. Ip6SetToAllNodeMulticast (TRUE, IP6_LINK_LOCAL_SCOPE, &Head.DestinationAddress);
  950. }
  951. NetbufReserve (Packet, sizeof (EFI_IP6_HEADER));
  952. //
  953. // Fill in the ICMP header, and Source link-layer address if contained.
  954. //
  955. IcmpHead = (IP6_ICMP_INFORMATION_HEAD *)NetbufAllocSpace (Packet, sizeof (IP6_ICMP_INFORMATION_HEAD), FALSE);
  956. ASSERT (IcmpHead != NULL);
  957. ZeroMem (IcmpHead, sizeof (IP6_ICMP_INFORMATION_HEAD));
  958. IcmpHead->Head.Type = ICMP_V6_ROUTER_SOLICIT;
  959. IcmpHead->Head.Code = 0;
  960. LinkLayerOption = NULL;
  961. if (SourceLinkAddress != NULL) {
  962. LinkLayerOption = (IP6_ETHER_ADDR_OPTION *)NetbufAllocSpace (
  963. Packet,
  964. sizeof (IP6_ETHER_ADDR_OPTION),
  965. FALSE
  966. );
  967. ASSERT (LinkLayerOption != NULL);
  968. LinkLayerOption->Type = Ip6OptionEtherSource;
  969. LinkLayerOption->Length = (UINT8)sizeof (IP6_ETHER_ADDR_OPTION);
  970. CopyMem (LinkLayerOption->EtherAddr, SourceLinkAddress, 6);
  971. }
  972. //
  973. // Transmit the packet
  974. //
  975. return Ip6Output (IpSb, IpIf, NULL, Packet, &Head, NULL, 0, Ip6SysPacketSent, NULL);
  976. }
  977. /**
  978. Generate a Neighbor Advertisement message and send it out to Destination Address.
  979. @param[in] IpSb The IP service to send the packet.
  980. @param[in] SourceAddress The source address of the message.
  981. @param[in] DestinationAddress The destination address of the message.
  982. @param[in] TargetIp6Address The target address field in the Neighbor Solicitation
  983. message that prompted this advertisement.
  984. @param[in] TargetLinkAddress The MAC address for the target, i.e. the sender
  985. of the advertisement.
  986. @param[in] IsRouter If TRUE, indicates the sender is a router.
  987. @param[in] Override If TRUE, indicates the advertisement should override
  988. an existing cache entry and update the MAC address.
  989. @param[in] Solicited If TRUE, indicates the advertisement was sent
  990. in response to a Neighbor Solicitation from
  991. the Destination address.
  992. @retval EFI_OUT_OF_RESOURCES Insufficient resources to complete the
  993. operation.
  994. @retval EFI_SUCCESS The Neighbor Advertise message was successfully sent.
  995. **/
  996. EFI_STATUS
  997. Ip6SendNeighborAdvertise (
  998. IN IP6_SERVICE *IpSb,
  999. IN EFI_IPv6_ADDRESS *SourceAddress,
  1000. IN EFI_IPv6_ADDRESS *DestinationAddress,
  1001. IN EFI_IPv6_ADDRESS *TargetIp6Address,
  1002. IN EFI_MAC_ADDRESS *TargetLinkAddress,
  1003. IN BOOLEAN IsRouter,
  1004. IN BOOLEAN Override,
  1005. IN BOOLEAN Solicited
  1006. )
  1007. {
  1008. NET_BUF *Packet;
  1009. EFI_IP6_HEADER Head;
  1010. IP6_ICMP_INFORMATION_HEAD *IcmpHead;
  1011. IP6_ETHER_ADDR_OPTION *LinkLayerOption;
  1012. EFI_IPv6_ADDRESS *Target;
  1013. UINT16 PayloadLen;
  1014. NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
  1015. //
  1016. // The Neighbor Advertisement message must include a Target link-layer address option
  1017. // when responding to multicast solicitation and should include such option when
  1018. // responding to unicast solicitation. It also must include such option as unsolicited
  1019. // advertisement.
  1020. //
  1021. ASSERT (DestinationAddress != NULL && TargetIp6Address != NULL && TargetLinkAddress != NULL);
  1022. PayloadLen = (UINT16)(sizeof (IP6_ICMP_INFORMATION_HEAD) + sizeof (EFI_IPv6_ADDRESS) + sizeof (IP6_ETHER_ADDR_OPTION));
  1023. //
  1024. // Generate the packet to be sent
  1025. //
  1026. Packet = NetbufAlloc (sizeof (EFI_IP6_HEADER) + (UINT32)PayloadLen);
  1027. if (Packet == NULL) {
  1028. return EFI_OUT_OF_RESOURCES;
  1029. }
  1030. //
  1031. // Create the basic IPv6 header.
  1032. //
  1033. Head.FlowLabelL = 0;
  1034. Head.FlowLabelH = 0;
  1035. Head.PayloadLength = HTONS (PayloadLen);
  1036. Head.NextHeader = IP6_ICMP;
  1037. Head.HopLimit = IP6_HOP_LIMIT;
  1038. IP6_COPY_ADDRESS (&Head.SourceAddress, SourceAddress);
  1039. IP6_COPY_ADDRESS (&Head.DestinationAddress, DestinationAddress);
  1040. NetbufReserve (Packet, sizeof (EFI_IP6_HEADER));
  1041. //
  1042. // Fill in the ICMP header, Target address, and Target link-layer address.
  1043. // Set the Router flag, Solicited flag and Override flag.
  1044. //
  1045. IcmpHead = (IP6_ICMP_INFORMATION_HEAD *)NetbufAllocSpace (Packet, sizeof (IP6_ICMP_INFORMATION_HEAD), FALSE);
  1046. ASSERT (IcmpHead != NULL);
  1047. ZeroMem (IcmpHead, sizeof (IP6_ICMP_INFORMATION_HEAD));
  1048. IcmpHead->Head.Type = ICMP_V6_NEIGHBOR_ADVERTISE;
  1049. IcmpHead->Head.Code = 0;
  1050. if (IsRouter) {
  1051. IcmpHead->Fourth |= IP6_IS_ROUTER_FLAG;
  1052. }
  1053. if (Solicited) {
  1054. IcmpHead->Fourth |= IP6_SOLICITED_FLAG;
  1055. }
  1056. if (Override) {
  1057. IcmpHead->Fourth |= IP6_OVERRIDE_FLAG;
  1058. }
  1059. Target = (EFI_IPv6_ADDRESS *)NetbufAllocSpace (Packet, sizeof (EFI_IPv6_ADDRESS), FALSE);
  1060. ASSERT (Target != NULL);
  1061. IP6_COPY_ADDRESS (Target, TargetIp6Address);
  1062. LinkLayerOption = (IP6_ETHER_ADDR_OPTION *)NetbufAllocSpace (
  1063. Packet,
  1064. sizeof (IP6_ETHER_ADDR_OPTION),
  1065. FALSE
  1066. );
  1067. ASSERT (LinkLayerOption != NULL);
  1068. LinkLayerOption->Type = Ip6OptionEtherTarget;
  1069. LinkLayerOption->Length = 1;
  1070. CopyMem (LinkLayerOption->EtherAddr, TargetLinkAddress, 6);
  1071. //
  1072. // Transmit the packet
  1073. //
  1074. return Ip6Output (IpSb, NULL, NULL, Packet, &Head, NULL, 0, Ip6SysPacketSent, NULL);
  1075. }
  1076. /**
  1077. Generate the Neighbor Solicitation message and send it to the Destination Address.
  1078. @param[in] IpSb The IP service to send the packet
  1079. @param[in] SourceAddress The source address of the message.
  1080. @param[in] DestinationAddress The destination address of the message.
  1081. @param[in] TargetIp6Address The IP address of the target of the solicitation.
  1082. It must not be a multicast address.
  1083. @param[in] SourceLinkAddress The MAC address for the sender. If not NULL,
  1084. a source link-layer address option will be appended
  1085. to the message.
  1086. @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
  1087. @retval EFI_OUT_OF_RESOURCES Insufficient resources to complete the
  1088. operation.
  1089. @retval EFI_SUCCESS The Neighbor Advertise message was successfully sent.
  1090. **/
  1091. EFI_STATUS
  1092. Ip6SendNeighborSolicit (
  1093. IN IP6_SERVICE *IpSb,
  1094. IN EFI_IPv6_ADDRESS *SourceAddress,
  1095. IN EFI_IPv6_ADDRESS *DestinationAddress,
  1096. IN EFI_IPv6_ADDRESS *TargetIp6Address,
  1097. IN EFI_MAC_ADDRESS *SourceLinkAddress OPTIONAL
  1098. )
  1099. {
  1100. NET_BUF *Packet;
  1101. EFI_IP6_HEADER Head;
  1102. IP6_ICMP_INFORMATION_HEAD *IcmpHead;
  1103. IP6_ETHER_ADDR_OPTION *LinkLayerOption;
  1104. EFI_IPv6_ADDRESS *Target;
  1105. BOOLEAN IsDAD;
  1106. UINT16 PayloadLen;
  1107. IP6_NEIGHBOR_ENTRY *Neighbor;
  1108. //
  1109. // Check input parameters
  1110. //
  1111. NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
  1112. if ((DestinationAddress == NULL) || (TargetIp6Address == NULL)) {
  1113. return EFI_INVALID_PARAMETER;
  1114. }
  1115. IsDAD = FALSE;
  1116. if ((SourceAddress == NULL) || ((SourceAddress != NULL) && NetIp6IsUnspecifiedAddr (SourceAddress))) {
  1117. IsDAD = TRUE;
  1118. }
  1119. //
  1120. // The Neighbor Solicitation message should include a source link-layer address option
  1121. // if the solicitation is not sent by performing DAD - Duplicate Address Detection.
  1122. // Otherwise must not include it.
  1123. //
  1124. PayloadLen = (UINT16)(sizeof (IP6_ICMP_INFORMATION_HEAD) + sizeof (EFI_IPv6_ADDRESS));
  1125. if (!IsDAD) {
  1126. if (SourceLinkAddress == NULL) {
  1127. return EFI_INVALID_PARAMETER;
  1128. }
  1129. PayloadLen = (UINT16)(PayloadLen + sizeof (IP6_ETHER_ADDR_OPTION));
  1130. }
  1131. //
  1132. // Generate the packet to be sent
  1133. //
  1134. Packet = NetbufAlloc (sizeof (EFI_IP6_HEADER) + (UINT32)PayloadLen);
  1135. if (Packet == NULL) {
  1136. return EFI_OUT_OF_RESOURCES;
  1137. }
  1138. //
  1139. // Create the basic IPv6 header
  1140. //
  1141. Head.FlowLabelL = 0;
  1142. Head.FlowLabelH = 0;
  1143. Head.PayloadLength = HTONS (PayloadLen);
  1144. Head.NextHeader = IP6_ICMP;
  1145. Head.HopLimit = IP6_HOP_LIMIT;
  1146. if (SourceAddress != NULL) {
  1147. IP6_COPY_ADDRESS (&Head.SourceAddress, SourceAddress);
  1148. } else {
  1149. ZeroMem (&Head.SourceAddress, sizeof (EFI_IPv6_ADDRESS));
  1150. }
  1151. IP6_COPY_ADDRESS (&Head.DestinationAddress, DestinationAddress);
  1152. NetbufReserve (Packet, sizeof (EFI_IP6_HEADER));
  1153. //
  1154. // Fill in the ICMP header, Target address, and Source link-layer address.
  1155. //
  1156. IcmpHead = (IP6_ICMP_INFORMATION_HEAD *)NetbufAllocSpace (Packet, sizeof (IP6_ICMP_INFORMATION_HEAD), FALSE);
  1157. ASSERT (IcmpHead != NULL);
  1158. ZeroMem (IcmpHead, sizeof (IP6_ICMP_INFORMATION_HEAD));
  1159. IcmpHead->Head.Type = ICMP_V6_NEIGHBOR_SOLICIT;
  1160. IcmpHead->Head.Code = 0;
  1161. Target = (EFI_IPv6_ADDRESS *)NetbufAllocSpace (Packet, sizeof (EFI_IPv6_ADDRESS), FALSE);
  1162. ASSERT (Target != NULL);
  1163. IP6_COPY_ADDRESS (Target, TargetIp6Address);
  1164. LinkLayerOption = NULL;
  1165. if (!IsDAD) {
  1166. //
  1167. // Fill in the source link-layer address option
  1168. //
  1169. LinkLayerOption = (IP6_ETHER_ADDR_OPTION *)NetbufAllocSpace (
  1170. Packet,
  1171. sizeof (IP6_ETHER_ADDR_OPTION),
  1172. FALSE
  1173. );
  1174. ASSERT (LinkLayerOption != NULL);
  1175. LinkLayerOption->Type = Ip6OptionEtherSource;
  1176. LinkLayerOption->Length = 1;
  1177. CopyMem (LinkLayerOption->EtherAddr, SourceLinkAddress, 6);
  1178. }
  1179. //
  1180. // Create a Neighbor Cache entry in the INCOMPLETE state when performing
  1181. // address resolution.
  1182. //
  1183. if (!IsDAD && Ip6IsSNMulticastAddr (DestinationAddress)) {
  1184. Neighbor = Ip6FindNeighborEntry (IpSb, TargetIp6Address);
  1185. if (Neighbor == NULL) {
  1186. Neighbor = Ip6CreateNeighborEntry (IpSb, Ip6OnArpResolved, TargetIp6Address, NULL);
  1187. ASSERT (Neighbor != NULL);
  1188. }
  1189. }
  1190. //
  1191. // Transmit the packet
  1192. //
  1193. return Ip6Output (IpSb, IpSb->DefaultInterface, NULL, Packet, &Head, NULL, 0, Ip6SysPacketSent, NULL);
  1194. }
  1195. /**
  1196. Process the Neighbor Solicitation message. The message may be sent for Duplicate
  1197. Address Detection or Address Resolution.
  1198. @param[in] IpSb The IP service that received the packet.
  1199. @param[in] Head The IP head of the message.
  1200. @param[in] Packet The content of the message with IP head removed.
  1201. @retval EFI_SUCCESS The packet processed successfully.
  1202. @retval EFI_INVALID_PARAMETER The packet is invalid.
  1203. @retval EFI_ICMP_ERROR The packet indicates that DAD is failed.
  1204. @retval Others Failed to process the packet.
  1205. **/
  1206. EFI_STATUS
  1207. Ip6ProcessNeighborSolicit (
  1208. IN IP6_SERVICE *IpSb,
  1209. IN EFI_IP6_HEADER *Head,
  1210. IN NET_BUF *Packet
  1211. )
  1212. {
  1213. IP6_ICMP_INFORMATION_HEAD Icmp;
  1214. EFI_IPv6_ADDRESS Target;
  1215. IP6_ETHER_ADDR_OPTION LinkLayerOption;
  1216. BOOLEAN IsDAD;
  1217. BOOLEAN IsUnicast;
  1218. BOOLEAN IsMaintained;
  1219. IP6_DAD_ENTRY *DupAddrDetect;
  1220. IP6_INTERFACE *IpIf;
  1221. IP6_NEIGHBOR_ENTRY *Neighbor;
  1222. BOOLEAN Solicited;
  1223. BOOLEAN UpdateCache;
  1224. EFI_IPv6_ADDRESS Dest;
  1225. UINT16 OptionLen;
  1226. UINT8 *Option;
  1227. BOOLEAN Provided;
  1228. EFI_STATUS Status;
  1229. VOID *MacAddress;
  1230. NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *)&Icmp);
  1231. NetbufCopy (Packet, sizeof (Icmp), sizeof (Target), Target.Addr);
  1232. //
  1233. // Perform Message Validation:
  1234. // The IP Hop Limit field has a value of 255, i.e., the packet
  1235. // could not possibly have been forwarded by a router.
  1236. // ICMP Code is 0.
  1237. // Target Address is not a multicast address.
  1238. //
  1239. Status = EFI_INVALID_PARAMETER;
  1240. if ((Head->HopLimit != IP6_HOP_LIMIT) || (Icmp.Head.Code != 0) || !NetIp6IsValidUnicast (&Target)) {
  1241. goto Exit;
  1242. }
  1243. //
  1244. // ICMP length is 24 or more octets.
  1245. //
  1246. OptionLen = 0;
  1247. if (Head->PayloadLength < IP6_ND_LENGTH) {
  1248. goto Exit;
  1249. } else {
  1250. OptionLen = (UINT16)(Head->PayloadLength - IP6_ND_LENGTH);
  1251. if (OptionLen != 0) {
  1252. Option = NetbufGetByte (Packet, IP6_ND_LENGTH, NULL);
  1253. ASSERT (Option != NULL);
  1254. //
  1255. // All included options should have a length that is greater than zero.
  1256. //
  1257. if (!Ip6IsNDOptionValid (Option, OptionLen)) {
  1258. goto Exit;
  1259. }
  1260. }
  1261. }
  1262. IsDAD = NetIp6IsUnspecifiedAddr (&Head->SourceAddress);
  1263. IsUnicast = (BOOLEAN) !Ip6IsSNMulticastAddr (&Head->DestinationAddress);
  1264. IsMaintained = Ip6IsOneOfSetAddress (IpSb, &Target, &IpIf, NULL);
  1265. Provided = FALSE;
  1266. if (OptionLen >= sizeof (IP6_ETHER_ADDR_OPTION)) {
  1267. NetbufCopy (
  1268. Packet,
  1269. IP6_ND_LENGTH,
  1270. sizeof (IP6_ETHER_ADDR_OPTION),
  1271. (UINT8 *)&LinkLayerOption
  1272. );
  1273. //
  1274. // The solicitation for neighbor discovery should include a source link-layer
  1275. // address option. If the option is not recognized, silently ignore it.
  1276. //
  1277. if (LinkLayerOption.Type == Ip6OptionEtherSource) {
  1278. if (IsDAD) {
  1279. //
  1280. // If the IP source address is the unspecified address, the source
  1281. // link-layer address option must not be included in the message.
  1282. //
  1283. goto Exit;
  1284. }
  1285. Provided = TRUE;
  1286. }
  1287. }
  1288. //
  1289. // If the IP source address is the unspecified address, the IP
  1290. // destination address is a solicited-node multicast address.
  1291. //
  1292. if (IsDAD && IsUnicast) {
  1293. goto Exit;
  1294. }
  1295. //
  1296. // If the target address is tentative, and the source address is a unicast address,
  1297. // the solicitation's sender is performing address resolution on the target;
  1298. // the solicitation should be silently ignored.
  1299. //
  1300. if (!IsDAD && !IsMaintained) {
  1301. goto Exit;
  1302. }
  1303. //
  1304. // If received unicast neighbor solicitation but destination is not this node,
  1305. // drop the packet.
  1306. //
  1307. if (IsUnicast && !IsMaintained) {
  1308. goto Exit;
  1309. }
  1310. //
  1311. // In DAD, when target address is a tentative address,
  1312. // process the received neighbor solicitation message but not send out response.
  1313. //
  1314. if (IsDAD && !IsMaintained) {
  1315. DupAddrDetect = Ip6FindDADEntry (IpSb, &Target, &IpIf);
  1316. if (DupAddrDetect != NULL) {
  1317. //
  1318. // Check the MAC address of the incoming packet.
  1319. //
  1320. if (IpSb->RecvRequest.MnpToken.Packet.RxData == NULL) {
  1321. goto Exit;
  1322. }
  1323. MacAddress = IpSb->RecvRequest.MnpToken.Packet.RxData->SourceAddress;
  1324. if (MacAddress != NULL) {
  1325. if (CompareMem (
  1326. MacAddress,
  1327. &IpSb->SnpMode.CurrentAddress,
  1328. IpSb->SnpMode.HwAddressSize
  1329. ) != 0)
  1330. {
  1331. //
  1332. // The NS is from another node to performing DAD on the same address.
  1333. // Fail DAD for the tentative address.
  1334. //
  1335. Ip6OnDADFinished (FALSE, IpIf, DupAddrDetect);
  1336. Status = EFI_ICMP_ERROR;
  1337. } else {
  1338. //
  1339. // The below layer loopback the NS we sent. Record it and wait for more.
  1340. //
  1341. DupAddrDetect->Receive++;
  1342. Status = EFI_SUCCESS;
  1343. }
  1344. }
  1345. }
  1346. goto Exit;
  1347. }
  1348. //
  1349. // If the solicitation does not contain a link-layer address, DO NOT create or
  1350. // update the neighbor cache entries.
  1351. //
  1352. if (Provided) {
  1353. Neighbor = Ip6FindNeighborEntry (IpSb, &Head->SourceAddress);
  1354. UpdateCache = FALSE;
  1355. if (Neighbor == NULL) {
  1356. Neighbor = Ip6CreateNeighborEntry (IpSb, Ip6OnArpResolved, &Head->SourceAddress, NULL);
  1357. if (Neighbor == NULL) {
  1358. Status = EFI_OUT_OF_RESOURCES;
  1359. goto Exit;
  1360. }
  1361. UpdateCache = TRUE;
  1362. } else {
  1363. if (CompareMem (Neighbor->LinkAddress.Addr, LinkLayerOption.EtherAddr, 6) != 0) {
  1364. UpdateCache = TRUE;
  1365. }
  1366. }
  1367. if (UpdateCache) {
  1368. Neighbor->State = EfiNeighborStale;
  1369. Neighbor->Ticks = (UINT32)IP6_INFINIT_LIFETIME;
  1370. CopyMem (Neighbor->LinkAddress.Addr, LinkLayerOption.EtherAddr, 6);
  1371. //
  1372. // Send queued packets if exist.
  1373. //
  1374. Neighbor->CallBack ((VOID *)Neighbor);
  1375. }
  1376. }
  1377. //
  1378. // Sends a Neighbor Advertisement as response.
  1379. // Set the Router flag to zero since the node is a host.
  1380. // If the source address of the solicitation is unspecified, and target address
  1381. // is one of the maintained address, reply a unsolicited multicast advertisement.
  1382. //
  1383. if (IsDAD && IsMaintained) {
  1384. Solicited = FALSE;
  1385. Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &Dest);
  1386. } else {
  1387. Solicited = TRUE;
  1388. IP6_COPY_ADDRESS (&Dest, &Head->SourceAddress);
  1389. }
  1390. Status = Ip6SendNeighborAdvertise (
  1391. IpSb,
  1392. &Target,
  1393. &Dest,
  1394. &Target,
  1395. &IpSb->SnpMode.CurrentAddress,
  1396. FALSE,
  1397. TRUE,
  1398. Solicited
  1399. );
  1400. Exit:
  1401. NetbufFree (Packet);
  1402. return Status;
  1403. }
  1404. /**
  1405. Process the Neighbor Advertisement message.
  1406. @param[in] IpSb The IP service that received the packet.
  1407. @param[in] Head The IP head of the message.
  1408. @param[in] Packet The content of the message with IP head removed.
  1409. @retval EFI_SUCCESS The packet processed successfully.
  1410. @retval EFI_INVALID_PARAMETER The packet is invalid.
  1411. @retval EFI_ICMP_ERROR The packet indicates that DAD is failed.
  1412. @retval Others Failed to process the packet.
  1413. **/
  1414. EFI_STATUS
  1415. Ip6ProcessNeighborAdvertise (
  1416. IN IP6_SERVICE *IpSb,
  1417. IN EFI_IP6_HEADER *Head,
  1418. IN NET_BUF *Packet
  1419. )
  1420. {
  1421. IP6_ICMP_INFORMATION_HEAD Icmp;
  1422. EFI_IPv6_ADDRESS Target;
  1423. IP6_ETHER_ADDR_OPTION LinkLayerOption;
  1424. BOOLEAN Provided;
  1425. INTN Compare;
  1426. IP6_NEIGHBOR_ENTRY *Neighbor;
  1427. IP6_DEFAULT_ROUTER *DefaultRouter;
  1428. BOOLEAN Solicited;
  1429. BOOLEAN IsRouter;
  1430. BOOLEAN Override;
  1431. IP6_DAD_ENTRY *DupAddrDetect;
  1432. IP6_INTERFACE *IpIf;
  1433. UINT16 OptionLen;
  1434. UINT8 *Option;
  1435. EFI_STATUS Status;
  1436. NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *)&Icmp);
  1437. NetbufCopy (Packet, sizeof (Icmp), sizeof (Target), Target.Addr);
  1438. //
  1439. // Validate the incoming Neighbor Advertisement
  1440. //
  1441. Status = EFI_INVALID_PARAMETER;
  1442. //
  1443. // The IP Hop Limit field has a value of 255, i.e., the packet
  1444. // could not possibly have been forwarded by a router.
  1445. // ICMP Code is 0.
  1446. // Target Address is not a multicast address.
  1447. //
  1448. if ((Head->HopLimit != IP6_HOP_LIMIT) || (Icmp.Head.Code != 0) || !NetIp6IsValidUnicast (&Target)) {
  1449. goto Exit;
  1450. }
  1451. //
  1452. // ICMP length is 24 or more octets.
  1453. //
  1454. Provided = FALSE;
  1455. OptionLen = 0;
  1456. if (Head->PayloadLength < IP6_ND_LENGTH) {
  1457. goto Exit;
  1458. } else {
  1459. OptionLen = (UINT16)(Head->PayloadLength - IP6_ND_LENGTH);
  1460. if (OptionLen != 0) {
  1461. Option = NetbufGetByte (Packet, IP6_ND_LENGTH, NULL);
  1462. ASSERT (Option != NULL);
  1463. //
  1464. // All included options should have a length that is greater than zero.
  1465. //
  1466. if (!Ip6IsNDOptionValid (Option, OptionLen)) {
  1467. goto Exit;
  1468. }
  1469. }
  1470. }
  1471. //
  1472. // If the IP destination address is a multicast address, Solicited Flag is ZERO.
  1473. //
  1474. Solicited = FALSE;
  1475. if ((Icmp.Fourth & IP6_SOLICITED_FLAG) == IP6_SOLICITED_FLAG) {
  1476. Solicited = TRUE;
  1477. }
  1478. if (IP6_IS_MULTICAST (&Head->DestinationAddress) && Solicited) {
  1479. goto Exit;
  1480. }
  1481. //
  1482. // DAD - Check whether the Target is one of our tentative address.
  1483. //
  1484. DupAddrDetect = Ip6FindDADEntry (IpSb, &Target, &IpIf);
  1485. if (DupAddrDetect != NULL) {
  1486. //
  1487. // DAD fails, some other node is using this address.
  1488. //
  1489. NetbufFree (Packet);
  1490. Ip6OnDADFinished (FALSE, IpIf, DupAddrDetect);
  1491. return EFI_ICMP_ERROR;
  1492. }
  1493. //
  1494. // Search the Neighbor Cache for the target's entry. If no entry exists,
  1495. // the advertisement should be silently discarded.
  1496. //
  1497. Neighbor = Ip6FindNeighborEntry (IpSb, &Target);
  1498. if (Neighbor == NULL) {
  1499. goto Exit;
  1500. }
  1501. //
  1502. // Get IsRouter Flag and Override Flag
  1503. //
  1504. IsRouter = FALSE;
  1505. Override = FALSE;
  1506. if ((Icmp.Fourth & IP6_IS_ROUTER_FLAG) == IP6_IS_ROUTER_FLAG) {
  1507. IsRouter = TRUE;
  1508. }
  1509. if ((Icmp.Fourth & IP6_OVERRIDE_FLAG) == IP6_OVERRIDE_FLAG) {
  1510. Override = TRUE;
  1511. }
  1512. //
  1513. // Check whether link layer option is included.
  1514. //
  1515. if (OptionLen >= sizeof (IP6_ETHER_ADDR_OPTION)) {
  1516. NetbufCopy (
  1517. Packet,
  1518. IP6_ND_LENGTH,
  1519. sizeof (IP6_ETHER_ADDR_OPTION),
  1520. (UINT8 *)&LinkLayerOption
  1521. );
  1522. if (LinkLayerOption.Type == Ip6OptionEtherTarget) {
  1523. Provided = TRUE;
  1524. }
  1525. }
  1526. Compare = 0;
  1527. if (Provided) {
  1528. Compare = CompareMem (Neighbor->LinkAddress.Addr, LinkLayerOption.EtherAddr, 6);
  1529. }
  1530. if (!Neighbor->IsRouter && IsRouter) {
  1531. DefaultRouter = Ip6FindDefaultRouter (IpSb, &Target);
  1532. if (DefaultRouter != NULL) {
  1533. DefaultRouter->NeighborCache = Neighbor;
  1534. }
  1535. }
  1536. if (Neighbor->State == EfiNeighborInComplete) {
  1537. //
  1538. // If the target's Neighbor Cache entry is in INCOMPLETE state and no
  1539. // Target Link-Layer address option is included while link layer has
  1540. // address, the message should be silently discarded.
  1541. //
  1542. if (!Provided) {
  1543. goto Exit;
  1544. }
  1545. //
  1546. // Update the Neighbor Cache
  1547. //
  1548. CopyMem (Neighbor->LinkAddress.Addr, LinkLayerOption.EtherAddr, 6);
  1549. if (Solicited) {
  1550. Neighbor->State = EfiNeighborReachable;
  1551. Neighbor->Ticks = IP6_GET_TICKS (IpSb->ReachableTime);
  1552. } else {
  1553. Neighbor->State = EfiNeighborStale;
  1554. Neighbor->Ticks = (UINT32)IP6_INFINIT_LIFETIME;
  1555. //
  1556. // Send any packets queued for the neighbor awaiting address resolution.
  1557. //
  1558. Neighbor->CallBack ((VOID *)Neighbor);
  1559. }
  1560. Neighbor->IsRouter = IsRouter;
  1561. } else {
  1562. if (!Override && (Compare != 0)) {
  1563. //
  1564. // When the Override Flag is clear and supplied link-layer address differs from
  1565. // that in the cache, if the state of the entry is not REACHABLE, ignore the
  1566. // message. Otherwise set it to STALE but do not update the entry in any
  1567. // other way.
  1568. //
  1569. if (Neighbor->State == EfiNeighborReachable) {
  1570. Neighbor->State = EfiNeighborStale;
  1571. Neighbor->Ticks = (UINT32)IP6_INFINIT_LIFETIME;
  1572. }
  1573. } else {
  1574. if (Compare != 0) {
  1575. CopyMem (Neighbor->LinkAddress.Addr, LinkLayerOption.EtherAddr, 6);
  1576. }
  1577. //
  1578. // Update the entry's state
  1579. //
  1580. if (Solicited) {
  1581. Neighbor->State = EfiNeighborReachable;
  1582. Neighbor->Ticks = IP6_GET_TICKS (IpSb->ReachableTime);
  1583. } else {
  1584. if (Compare != 0) {
  1585. Neighbor->State = EfiNeighborStale;
  1586. Neighbor->Ticks = (UINT32)IP6_INFINIT_LIFETIME;
  1587. }
  1588. }
  1589. //
  1590. // When IsRouter is changed from TRUE to FALSE, remove the router from the
  1591. // Default Router List and remove the Destination Cache entries for all destinations
  1592. // using the neighbor as a router.
  1593. //
  1594. if (Neighbor->IsRouter && !IsRouter) {
  1595. DefaultRouter = Ip6FindDefaultRouter (IpSb, &Target);
  1596. if (DefaultRouter != NULL) {
  1597. Ip6DestroyDefaultRouter (IpSb, DefaultRouter);
  1598. }
  1599. }
  1600. Neighbor->IsRouter = IsRouter;
  1601. }
  1602. }
  1603. if (Neighbor->State == EfiNeighborReachable) {
  1604. Neighbor->CallBack ((VOID *)Neighbor);
  1605. }
  1606. Status = EFI_SUCCESS;
  1607. Exit:
  1608. NetbufFree (Packet);
  1609. return Status;
  1610. }
  1611. /**
  1612. Process the Router Advertisement message according to RFC4861.
  1613. @param[in] IpSb The IP service that received the packet.
  1614. @param[in] Head The IP head of the message.
  1615. @param[in] Packet The content of the message with the IP head removed.
  1616. @retval EFI_SUCCESS The packet processed successfully.
  1617. @retval EFI_INVALID_PARAMETER The packet is invalid.
  1618. @retval EFI_OUT_OF_RESOURCES Insufficient resources to complete the
  1619. operation.
  1620. @retval Others Failed to process the packet.
  1621. **/
  1622. EFI_STATUS
  1623. Ip6ProcessRouterAdvertise (
  1624. IN IP6_SERVICE *IpSb,
  1625. IN EFI_IP6_HEADER *Head,
  1626. IN NET_BUF *Packet
  1627. )
  1628. {
  1629. IP6_ICMP_INFORMATION_HEAD Icmp;
  1630. UINT32 ReachableTime;
  1631. UINT32 RetransTimer;
  1632. UINT16 RouterLifetime;
  1633. UINT32 Offset;
  1634. UINT8 Type;
  1635. UINT8 Length;
  1636. IP6_ETHER_ADDR_OPTION LinkLayerOption;
  1637. UINT32 Fourth;
  1638. UINT8 CurHopLimit;
  1639. BOOLEAN Mflag;
  1640. BOOLEAN Oflag;
  1641. IP6_DEFAULT_ROUTER *DefaultRouter;
  1642. IP6_NEIGHBOR_ENTRY *NeighborCache;
  1643. EFI_MAC_ADDRESS LinkLayerAddress;
  1644. IP6_MTU_OPTION MTUOption;
  1645. IP6_PREFIX_INFO_OPTION PrefixOption;
  1646. IP6_PREFIX_LIST_ENTRY *PrefixList;
  1647. BOOLEAN OnLink;
  1648. BOOLEAN Autonomous;
  1649. EFI_IPv6_ADDRESS StatelessAddress;
  1650. EFI_STATUS Status;
  1651. UINT16 OptionLen;
  1652. UINT8 *Option;
  1653. INTN Result;
  1654. Status = EFI_INVALID_PARAMETER;
  1655. if (IpSb->Ip6ConfigInstance.Policy != Ip6ConfigPolicyAutomatic) {
  1656. //
  1657. // Skip the process below as it's not required under the current policy.
  1658. //
  1659. goto Exit;
  1660. }
  1661. NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *)&Icmp);
  1662. //
  1663. // Validate the incoming Router Advertisement
  1664. //
  1665. //
  1666. // The IP source address must be a link-local address
  1667. //
  1668. if (!NetIp6IsLinkLocalAddr (&Head->SourceAddress)) {
  1669. goto Exit;
  1670. }
  1671. //
  1672. // The IP Hop Limit field has a value of 255, i.e. the packet
  1673. // could not possibly have been forwarded by a router.
  1674. // ICMP Code is 0.
  1675. // ICMP length (derived from the IP length) is 16 or more octets.
  1676. //
  1677. if ((Head->HopLimit != IP6_HOP_LIMIT) || (Icmp.Head.Code != 0) ||
  1678. (Head->PayloadLength < IP6_RA_LENGTH))
  1679. {
  1680. goto Exit;
  1681. }
  1682. //
  1683. // All included options have a length that is greater than zero.
  1684. //
  1685. OptionLen = (UINT16)(Head->PayloadLength - IP6_RA_LENGTH);
  1686. if (OptionLen != 0) {
  1687. Option = NetbufGetByte (Packet, IP6_RA_LENGTH, NULL);
  1688. ASSERT (Option != NULL);
  1689. if (!Ip6IsNDOptionValid (Option, OptionLen)) {
  1690. goto Exit;
  1691. }
  1692. }
  1693. //
  1694. // Process Fourth field.
  1695. // In Router Advertisement, Fourth is composed of CurHopLimit (8bit), M flag, O flag,
  1696. // and Router Lifetime (16 bit).
  1697. //
  1698. Fourth = NTOHL (Icmp.Fourth);
  1699. CopyMem (&RouterLifetime, &Fourth, sizeof (UINT16));
  1700. //
  1701. // If the source address already in the default router list, update it.
  1702. // Otherwise create a new entry.
  1703. // A Lifetime of zero indicates that the router is not a default router.
  1704. //
  1705. DefaultRouter = Ip6FindDefaultRouter (IpSb, &Head->SourceAddress);
  1706. if (DefaultRouter == NULL) {
  1707. if (RouterLifetime != 0) {
  1708. DefaultRouter = Ip6CreateDefaultRouter (IpSb, &Head->SourceAddress, RouterLifetime);
  1709. if (DefaultRouter == NULL) {
  1710. Status = EFI_OUT_OF_RESOURCES;
  1711. goto Exit;
  1712. }
  1713. }
  1714. } else {
  1715. if (RouterLifetime != 0) {
  1716. DefaultRouter->Lifetime = RouterLifetime;
  1717. //
  1718. // Check the corresponding neighbor cache entry here.
  1719. //
  1720. if (DefaultRouter->NeighborCache == NULL) {
  1721. DefaultRouter->NeighborCache = Ip6FindNeighborEntry (IpSb, &Head->SourceAddress);
  1722. }
  1723. } else {
  1724. //
  1725. // If the address is in the host's default router list and the router lifetime is zero,
  1726. // immediately time-out the entry.
  1727. //
  1728. Ip6DestroyDefaultRouter (IpSb, DefaultRouter);
  1729. }
  1730. }
  1731. CurHopLimit = *((UINT8 *)&Fourth + 3);
  1732. if (CurHopLimit != 0) {
  1733. IpSb->CurHopLimit = CurHopLimit;
  1734. }
  1735. Mflag = FALSE;
  1736. Oflag = FALSE;
  1737. if ((*((UINT8 *)&Fourth + 2) & IP6_M_ADDR_CONFIG_FLAG) == IP6_M_ADDR_CONFIG_FLAG) {
  1738. Mflag = TRUE;
  1739. } else {
  1740. if ((*((UINT8 *)&Fourth + 2) & IP6_O_CONFIG_FLAG) == IP6_O_CONFIG_FLAG) {
  1741. Oflag = TRUE;
  1742. }
  1743. }
  1744. if (Mflag || Oflag) {
  1745. //
  1746. // Use Ip6Config to get available addresses or other configuration from DHCP.
  1747. //
  1748. Ip6ConfigStartStatefulAutoConfig (&IpSb->Ip6ConfigInstance, Oflag);
  1749. }
  1750. //
  1751. // Process Reachable Time and Retrans Timer fields.
  1752. //
  1753. NetbufCopy (Packet, sizeof (Icmp), sizeof (UINT32), (UINT8 *)&ReachableTime);
  1754. NetbufCopy (Packet, sizeof (Icmp) + sizeof (UINT32), sizeof (UINT32), (UINT8 *)&RetransTimer);
  1755. ReachableTime = NTOHL (ReachableTime);
  1756. RetransTimer = NTOHL (RetransTimer);
  1757. if ((ReachableTime != 0) && (ReachableTime != IpSb->BaseReachableTime)) {
  1758. //
  1759. // If new value is not unspecified and differs from the previous one, record it
  1760. // in BaseReachableTime and recompute a ReachableTime.
  1761. //
  1762. IpSb->BaseReachableTime = ReachableTime;
  1763. Ip6UpdateReachableTime (IpSb);
  1764. }
  1765. if (RetransTimer != 0) {
  1766. IpSb->RetransTimer = RetransTimer;
  1767. }
  1768. //
  1769. // IsRouter flag must be set to TRUE if corresponding neighbor cache entry exists.
  1770. //
  1771. NeighborCache = Ip6FindNeighborEntry (IpSb, &Head->SourceAddress);
  1772. if (NeighborCache != NULL) {
  1773. NeighborCache->IsRouter = TRUE;
  1774. }
  1775. //
  1776. // If an valid router advertisement is received, stops router solicitation.
  1777. //
  1778. IpSb->RouterAdvertiseReceived = TRUE;
  1779. //
  1780. // The only defined options that may appear are the Source
  1781. // Link-Layer Address, Prefix information and MTU options.
  1782. // All included options have a length that is greater than zero and
  1783. // fit within the input packet.
  1784. //
  1785. Offset = 16;
  1786. while (Offset < (UINT32)Head->PayloadLength) {
  1787. NetbufCopy (Packet, Offset, sizeof (UINT8), &Type);
  1788. switch (Type) {
  1789. case Ip6OptionEtherSource:
  1790. //
  1791. // Update the neighbor cache
  1792. //
  1793. NetbufCopy (Packet, Offset, sizeof (IP6_ETHER_ADDR_OPTION), (UINT8 *)&LinkLayerOption);
  1794. //
  1795. // Option size validity ensured by Ip6IsNDOptionValid().
  1796. //
  1797. ASSERT (LinkLayerOption.Length != 0);
  1798. ASSERT (Offset + (UINT32)LinkLayerOption.Length * 8 <= (UINT32)Head->PayloadLength);
  1799. ZeroMem (&LinkLayerAddress, sizeof (EFI_MAC_ADDRESS));
  1800. CopyMem (&LinkLayerAddress, LinkLayerOption.EtherAddr, 6);
  1801. if (NeighborCache == NULL) {
  1802. NeighborCache = Ip6CreateNeighborEntry (
  1803. IpSb,
  1804. Ip6OnArpResolved,
  1805. &Head->SourceAddress,
  1806. &LinkLayerAddress
  1807. );
  1808. if (NeighborCache == NULL) {
  1809. Status = EFI_OUT_OF_RESOURCES;
  1810. goto Exit;
  1811. }
  1812. NeighborCache->IsRouter = TRUE;
  1813. NeighborCache->State = EfiNeighborStale;
  1814. NeighborCache->Ticks = (UINT32)IP6_INFINIT_LIFETIME;
  1815. } else {
  1816. Result = CompareMem (&LinkLayerAddress, &NeighborCache->LinkAddress, 6);
  1817. //
  1818. // If the link-local address is the same as that already in the cache,
  1819. // the cache entry's state remains unchanged. Otherwise update the
  1820. // reachability state to STALE.
  1821. //
  1822. if ((NeighborCache->State == EfiNeighborInComplete) || (Result != 0)) {
  1823. CopyMem (&NeighborCache->LinkAddress, &LinkLayerAddress, 6);
  1824. NeighborCache->Ticks = (UINT32)IP6_INFINIT_LIFETIME;
  1825. if (NeighborCache->State == EfiNeighborInComplete) {
  1826. //
  1827. // Send queued packets if exist.
  1828. //
  1829. NeighborCache->State = EfiNeighborStale;
  1830. NeighborCache->CallBack ((VOID *)NeighborCache);
  1831. } else {
  1832. NeighborCache->State = EfiNeighborStale;
  1833. }
  1834. }
  1835. }
  1836. Offset += (UINT32)LinkLayerOption.Length * 8;
  1837. break;
  1838. case Ip6OptionPrefixInfo:
  1839. NetbufCopy (Packet, Offset, sizeof (IP6_PREFIX_INFO_OPTION), (UINT8 *)&PrefixOption);
  1840. //
  1841. // Option size validity ensured by Ip6IsNDOptionValid().
  1842. //
  1843. ASSERT (PrefixOption.Length == 4);
  1844. ASSERT (Offset + (UINT32)PrefixOption.Length * 8 <= (UINT32)Head->PayloadLength);
  1845. PrefixOption.ValidLifetime = NTOHL (PrefixOption.ValidLifetime);
  1846. PrefixOption.PreferredLifetime = NTOHL (PrefixOption.PreferredLifetime);
  1847. //
  1848. // Get L and A flag, recorded in the lower 2 bits of Reserved1
  1849. //
  1850. OnLink = FALSE;
  1851. if ((PrefixOption.Reserved1 & IP6_ON_LINK_FLAG) == IP6_ON_LINK_FLAG) {
  1852. OnLink = TRUE;
  1853. }
  1854. Autonomous = FALSE;
  1855. if ((PrefixOption.Reserved1 & IP6_AUTO_CONFIG_FLAG) == IP6_AUTO_CONFIG_FLAG) {
  1856. Autonomous = TRUE;
  1857. }
  1858. //
  1859. // If the prefix is the link-local prefix, silently ignore the prefix option.
  1860. //
  1861. if ((PrefixOption.PrefixLength == IP6_LINK_LOCAL_PREFIX_LENGTH) &&
  1862. NetIp6IsLinkLocalAddr (&PrefixOption.Prefix)
  1863. )
  1864. {
  1865. Offset += sizeof (IP6_PREFIX_INFO_OPTION);
  1866. break;
  1867. }
  1868. //
  1869. // Do following if on-link flag is set according to RFC4861.
  1870. //
  1871. if (OnLink) {
  1872. PrefixList = Ip6FindPrefixListEntry (
  1873. IpSb,
  1874. TRUE,
  1875. PrefixOption.PrefixLength,
  1876. &PrefixOption.Prefix
  1877. );
  1878. //
  1879. // Create a new entry for the prefix, if the ValidLifetime is zero,
  1880. // silently ignore the prefix option.
  1881. //
  1882. if ((PrefixList == NULL) && (PrefixOption.ValidLifetime != 0)) {
  1883. PrefixList = Ip6CreatePrefixListEntry (
  1884. IpSb,
  1885. TRUE,
  1886. PrefixOption.ValidLifetime,
  1887. PrefixOption.PreferredLifetime,
  1888. PrefixOption.PrefixLength,
  1889. &PrefixOption.Prefix
  1890. );
  1891. if (PrefixList == NULL) {
  1892. Status = EFI_OUT_OF_RESOURCES;
  1893. goto Exit;
  1894. }
  1895. } else if (PrefixList != NULL) {
  1896. if (PrefixOption.ValidLifetime != 0) {
  1897. PrefixList->ValidLifetime = PrefixOption.ValidLifetime;
  1898. } else {
  1899. //
  1900. // If the prefix exists and incoming ValidLifetime is zero, immediately
  1901. // remove the prefix.
  1902. Ip6DestroyPrefixListEntry (IpSb, PrefixList, OnLink, TRUE);
  1903. }
  1904. }
  1905. }
  1906. //
  1907. // Do following if Autonomous flag is set according to RFC4862.
  1908. //
  1909. if (Autonomous && (PrefixOption.PreferredLifetime <= PrefixOption.ValidLifetime)) {
  1910. PrefixList = Ip6FindPrefixListEntry (
  1911. IpSb,
  1912. FALSE,
  1913. PrefixOption.PrefixLength,
  1914. &PrefixOption.Prefix
  1915. );
  1916. //
  1917. // Create a new entry for the prefix, and form an address by prefix + interface id
  1918. // If the sum of the prefix length and interface identifier length
  1919. // does not equal 128 bits, the Prefix Information option MUST be ignored.
  1920. //
  1921. if ((PrefixList == NULL) &&
  1922. (PrefixOption.ValidLifetime != 0) &&
  1923. (PrefixOption.PrefixLength + IpSb->InterfaceIdLen * 8 == 128)
  1924. )
  1925. {
  1926. //
  1927. // Form the address in network order.
  1928. //
  1929. CopyMem (&StatelessAddress, &PrefixOption.Prefix, sizeof (UINT64));
  1930. CopyMem (&StatelessAddress.Addr[8], IpSb->InterfaceId, sizeof (UINT64));
  1931. //
  1932. // If the address is not yet in the assigned address list, adds it into.
  1933. //
  1934. if (!Ip6IsOneOfSetAddress (IpSb, &StatelessAddress, NULL, NULL)) {
  1935. //
  1936. // And also not in the DAD process, check its uniqueness firstly.
  1937. //
  1938. if (Ip6FindDADEntry (IpSb, &StatelessAddress, NULL) == NULL) {
  1939. Status = Ip6SetAddress (
  1940. IpSb->DefaultInterface,
  1941. &StatelessAddress,
  1942. FALSE,
  1943. PrefixOption.PrefixLength,
  1944. PrefixOption.ValidLifetime,
  1945. PrefixOption.PreferredLifetime,
  1946. NULL,
  1947. NULL
  1948. );
  1949. if (EFI_ERROR (Status)) {
  1950. goto Exit;
  1951. }
  1952. }
  1953. }
  1954. //
  1955. // Adds the prefix option to stateless prefix option list.
  1956. //
  1957. PrefixList = Ip6CreatePrefixListEntry (
  1958. IpSb,
  1959. FALSE,
  1960. PrefixOption.ValidLifetime,
  1961. PrefixOption.PreferredLifetime,
  1962. PrefixOption.PrefixLength,
  1963. &PrefixOption.Prefix
  1964. );
  1965. if (PrefixList == NULL) {
  1966. Status = EFI_OUT_OF_RESOURCES;
  1967. goto Exit;
  1968. }
  1969. } else if (PrefixList != NULL) {
  1970. //
  1971. // Reset the preferred lifetime of the address if the advertised prefix exists.
  1972. // Perform specific action to valid lifetime together.
  1973. //
  1974. PrefixList->PreferredLifetime = PrefixOption.PreferredLifetime;
  1975. if ((PrefixOption.ValidLifetime > 7200) ||
  1976. (PrefixOption.ValidLifetime > PrefixList->ValidLifetime))
  1977. {
  1978. //
  1979. // If the received Valid Lifetime is greater than 2 hours or
  1980. // greater than RemainingLifetime, set the valid lifetime of the
  1981. // corresponding address to the advertised Valid Lifetime.
  1982. //
  1983. PrefixList->ValidLifetime = PrefixOption.ValidLifetime;
  1984. } else if (PrefixList->ValidLifetime <= 7200) {
  1985. //
  1986. // If RemainingLifetime is less than or equals to 2 hours, ignore the
  1987. // Prefix Information option with regards to the valid lifetime.
  1988. // TODO: If this option has been authenticated, set the valid lifetime.
  1989. //
  1990. } else {
  1991. //
  1992. // Otherwise, reset the valid lifetime of the corresponding
  1993. // address to 2 hours.
  1994. //
  1995. PrefixList->ValidLifetime = 7200;
  1996. }
  1997. }
  1998. }
  1999. Offset += sizeof (IP6_PREFIX_INFO_OPTION);
  2000. break;
  2001. case Ip6OptionMtu:
  2002. NetbufCopy (Packet, Offset, sizeof (IP6_MTU_OPTION), (UINT8 *)&MTUOption);
  2003. //
  2004. // Option size validity ensured by Ip6IsNDOptionValid().
  2005. //
  2006. ASSERT (MTUOption.Length == 1);
  2007. ASSERT (Offset + (UINT32)MTUOption.Length * 8 <= (UINT32)Head->PayloadLength);
  2008. //
  2009. // Use IPv6 minimum link MTU 1280 bytes as the maximum packet size in order
  2010. // to omit implementation of Path MTU Discovery. Thus ignore the MTU option
  2011. // in Router Advertisement.
  2012. //
  2013. Offset += sizeof (IP6_MTU_OPTION);
  2014. break;
  2015. default:
  2016. //
  2017. // Silently ignore unrecognized options
  2018. //
  2019. NetbufCopy (Packet, Offset + sizeof (UINT8), sizeof (UINT8), &Length);
  2020. ASSERT (Length != 0);
  2021. Offset += (UINT32)Length * 8;
  2022. break;
  2023. }
  2024. }
  2025. Status = EFI_SUCCESS;
  2026. Exit:
  2027. NetbufFree (Packet);
  2028. return Status;
  2029. }
  2030. /**
  2031. Process the ICMPv6 redirect message. Find the instance, then update
  2032. its route cache.
  2033. @param[in] IpSb The IP6 service binding instance that received
  2034. the packet.
  2035. @param[in] Head The IP head of the received ICMPv6 packet.
  2036. @param[in] Packet The content of the ICMPv6 redirect packet with
  2037. the IP head removed.
  2038. @retval EFI_INVALID_PARAMETER The parameter is invalid.
  2039. @retval EFI_OUT_OF_RESOURCES Insufficient resources to complete the
  2040. operation.
  2041. @retval EFI_SUCCESS Successfully updated the route caches.
  2042. **/
  2043. EFI_STATUS
  2044. Ip6ProcessRedirect (
  2045. IN IP6_SERVICE *IpSb,
  2046. IN EFI_IP6_HEADER *Head,
  2047. IN NET_BUF *Packet
  2048. )
  2049. {
  2050. IP6_ICMP_INFORMATION_HEAD *Icmp;
  2051. EFI_IPv6_ADDRESS *Target;
  2052. EFI_IPv6_ADDRESS *IcmpDest;
  2053. UINT8 *Option;
  2054. UINT16 OptionLen;
  2055. IP6_ROUTE_ENTRY *RouteEntry;
  2056. IP6_ROUTE_CACHE_ENTRY *RouteCache;
  2057. IP6_NEIGHBOR_ENTRY *NeighborCache;
  2058. INT32 Length;
  2059. UINT8 OptLen;
  2060. IP6_ETHER_ADDR_OPTION *LinkLayerOption;
  2061. EFI_MAC_ADDRESS Mac;
  2062. UINT32 Index;
  2063. BOOLEAN IsRouter;
  2064. EFI_STATUS Status;
  2065. INTN Result;
  2066. Status = EFI_INVALID_PARAMETER;
  2067. Icmp = (IP6_ICMP_INFORMATION_HEAD *)NetbufGetByte (Packet, 0, NULL);
  2068. if (Icmp == NULL) {
  2069. goto Exit;
  2070. }
  2071. //
  2072. // Validate the incoming Redirect message
  2073. //
  2074. //
  2075. // The IP Hop Limit field has a value of 255, i.e. the packet
  2076. // could not possibly have been forwarded by a router.
  2077. // ICMP Code is 0.
  2078. // ICMP length (derived from the IP length) is 40 or more octets.
  2079. //
  2080. if ((Head->HopLimit != IP6_HOP_LIMIT) || (Icmp->Head.Code != 0) ||
  2081. (Head->PayloadLength < IP6_REDITECT_LENGTH))
  2082. {
  2083. goto Exit;
  2084. }
  2085. //
  2086. // The IP source address must be a link-local address
  2087. //
  2088. if (!NetIp6IsLinkLocalAddr (&Head->SourceAddress)) {
  2089. goto Exit;
  2090. }
  2091. //
  2092. // The dest of this ICMP redirect message is not us.
  2093. //
  2094. if (!Ip6IsOneOfSetAddress (IpSb, &Head->DestinationAddress, NULL, NULL)) {
  2095. goto Exit;
  2096. }
  2097. //
  2098. // All included options have a length that is greater than zero.
  2099. //
  2100. OptionLen = (UINT16)(Head->PayloadLength - IP6_REDITECT_LENGTH);
  2101. if (OptionLen != 0) {
  2102. Option = NetbufGetByte (Packet, IP6_REDITECT_LENGTH, NULL);
  2103. ASSERT (Option != NULL);
  2104. if (!Ip6IsNDOptionValid (Option, OptionLen)) {
  2105. goto Exit;
  2106. }
  2107. }
  2108. Target = (EFI_IPv6_ADDRESS *)(Icmp + 1);
  2109. IcmpDest = Target + 1;
  2110. //
  2111. // The ICMP Destination Address field in the redirect message does not contain
  2112. // a multicast address.
  2113. //
  2114. if (IP6_IS_MULTICAST (IcmpDest)) {
  2115. goto Exit;
  2116. }
  2117. //
  2118. // The ICMP Target Address is either a link-local address (when redirected to
  2119. // a router) or the same as the ICMP Destination Address (when redirected to
  2120. // the on-link destination).
  2121. //
  2122. IsRouter = (BOOLEAN) !EFI_IP6_EQUAL (Target, IcmpDest);
  2123. if (!NetIp6IsLinkLocalAddr (Target) && IsRouter) {
  2124. goto Exit;
  2125. }
  2126. //
  2127. // Check the options. The only interested option here is the target-link layer
  2128. // address option.
  2129. //
  2130. Length = Packet->TotalSize - 40;
  2131. Option = (UINT8 *)(IcmpDest + 1);
  2132. LinkLayerOption = NULL;
  2133. while (Length > 0) {
  2134. switch (*Option) {
  2135. case Ip6OptionEtherTarget:
  2136. LinkLayerOption = (IP6_ETHER_ADDR_OPTION *)Option;
  2137. OptLen = LinkLayerOption->Length;
  2138. if (OptLen != 1) {
  2139. //
  2140. // For ethernet, the length must be 1.
  2141. //
  2142. goto Exit;
  2143. }
  2144. break;
  2145. default:
  2146. OptLen = *(Option + 1);
  2147. if (OptLen == 0) {
  2148. //
  2149. // A length of 0 is invalid.
  2150. //
  2151. goto Exit;
  2152. }
  2153. break;
  2154. }
  2155. Length -= 8 * OptLen;
  2156. Option += 8 * OptLen;
  2157. }
  2158. if (Length != 0) {
  2159. goto Exit;
  2160. }
  2161. //
  2162. // The IP source address of the Redirect is the same as the current
  2163. // first-hop router for the specified ICMP Destination Address.
  2164. //
  2165. RouteCache = Ip6FindRouteCache (IpSb->RouteTable, IcmpDest, &Head->DestinationAddress);
  2166. if (RouteCache != NULL) {
  2167. if (!EFI_IP6_EQUAL (&RouteCache->NextHop, &Head->SourceAddress)) {
  2168. //
  2169. // The source of this Redirect message must match the NextHop of the
  2170. // corresponding route cache entry.
  2171. //
  2172. goto Exit;
  2173. }
  2174. //
  2175. // Update the NextHop.
  2176. //
  2177. IP6_COPY_ADDRESS (&RouteCache->NextHop, Target);
  2178. if (!IsRouter) {
  2179. RouteEntry = (IP6_ROUTE_ENTRY *)RouteCache->Tag;
  2180. RouteEntry->Flag = RouteEntry->Flag | IP6_DIRECT_ROUTE;
  2181. }
  2182. } else {
  2183. //
  2184. // Get the Route Entry.
  2185. //
  2186. RouteEntry = Ip6FindRouteEntry (IpSb->RouteTable, IcmpDest, NULL);
  2187. if (RouteEntry == NULL) {
  2188. RouteEntry = Ip6CreateRouteEntry (IcmpDest, 0, NULL);
  2189. if (RouteEntry == NULL) {
  2190. Status = EFI_OUT_OF_RESOURCES;
  2191. goto Exit;
  2192. }
  2193. }
  2194. if (!IsRouter) {
  2195. RouteEntry->Flag = IP6_DIRECT_ROUTE;
  2196. }
  2197. //
  2198. // Create a route cache for this.
  2199. //
  2200. RouteCache = Ip6CreateRouteCacheEntry (
  2201. IcmpDest,
  2202. &Head->DestinationAddress,
  2203. Target,
  2204. (UINTN)RouteEntry
  2205. );
  2206. if (RouteCache == NULL) {
  2207. Status = EFI_OUT_OF_RESOURCES;
  2208. goto Exit;
  2209. }
  2210. //
  2211. // Insert the newly created route cache entry.
  2212. //
  2213. Index = IP6_ROUTE_CACHE_HASH (IcmpDest, &Head->DestinationAddress);
  2214. InsertHeadList (&IpSb->RouteTable->Cache.CacheBucket[Index], &RouteCache->Link);
  2215. }
  2216. //
  2217. // Try to locate the neighbor cache for the Target.
  2218. //
  2219. NeighborCache = Ip6FindNeighborEntry (IpSb, Target);
  2220. if (LinkLayerOption != NULL) {
  2221. if (NeighborCache == NULL) {
  2222. //
  2223. // Create a neighbor cache for the Target.
  2224. //
  2225. ZeroMem (&Mac, sizeof (EFI_MAC_ADDRESS));
  2226. CopyMem (&Mac, LinkLayerOption->EtherAddr, 6);
  2227. NeighborCache = Ip6CreateNeighborEntry (IpSb, Ip6OnArpResolved, Target, &Mac);
  2228. if (NeighborCache == NULL) {
  2229. //
  2230. // Just report a success here. The neighbor cache can be created in
  2231. // some other place.
  2232. //
  2233. Status = EFI_SUCCESS;
  2234. goto Exit;
  2235. }
  2236. NeighborCache->State = EfiNeighborStale;
  2237. NeighborCache->Ticks = (UINT32)IP6_INFINIT_LIFETIME;
  2238. } else {
  2239. Result = CompareMem (LinkLayerOption->EtherAddr, &NeighborCache->LinkAddress, 6);
  2240. //
  2241. // If the link-local address is the same as that already in the cache,
  2242. // the cache entry's state remains unchanged. Otherwise update the
  2243. // reachability state to STALE.
  2244. //
  2245. if ((NeighborCache->State == EfiNeighborInComplete) || (Result != 0)) {
  2246. CopyMem (&NeighborCache->LinkAddress, LinkLayerOption->EtherAddr, 6);
  2247. NeighborCache->Ticks = (UINT32)IP6_INFINIT_LIFETIME;
  2248. if (NeighborCache->State == EfiNeighborInComplete) {
  2249. //
  2250. // Send queued packets if exist.
  2251. //
  2252. NeighborCache->State = EfiNeighborStale;
  2253. NeighborCache->CallBack ((VOID *)NeighborCache);
  2254. } else {
  2255. NeighborCache->State = EfiNeighborStale;
  2256. }
  2257. }
  2258. }
  2259. }
  2260. if ((NeighborCache != NULL) && IsRouter) {
  2261. //
  2262. // The Target is a router, set IsRouter to TRUE.
  2263. //
  2264. NeighborCache->IsRouter = TRUE;
  2265. }
  2266. Status = EFI_SUCCESS;
  2267. Exit:
  2268. NetbufFree (Packet);
  2269. return Status;
  2270. }
  2271. /**
  2272. Add Neighbor cache entries. It is a work function for EfiIp6Neighbors().
  2273. @param[in] IpSb The IP6 service binding instance.
  2274. @param[in] TargetIp6Address Pointer to Target IPv6 address.
  2275. @param[in] TargetLinkAddress Pointer to link-layer address of the target. Ignored if NULL.
  2276. @param[in] Timeout Time in 100-ns units that this entry will remain in the neighbor
  2277. cache. It will be deleted after Timeout. A value of zero means that
  2278. the entry is permanent. A non-zero value means that the entry is
  2279. dynamic.
  2280. @param[in] Override If TRUE, the cached link-layer address of the matching entry will
  2281. be overridden and updated; if FALSE, and if a
  2282. corresponding cache entry already existed, EFI_ACCESS_DENIED
  2283. will be returned.
  2284. @retval EFI_SUCCESS The neighbor cache entry has been added.
  2285. @retval EFI_OUT_OF_RESOURCES Could not add the entry to the neighbor cache
  2286. due to insufficient resources.
  2287. @retval EFI_NOT_FOUND TargetLinkAddress is NULL.
  2288. @retval EFI_ACCESS_DENIED The to-be-added entry is already defined in the neighbor cache,
  2289. and that entry is tagged as un-overridden (when DeleteFlag
  2290. is FALSE).
  2291. **/
  2292. EFI_STATUS
  2293. Ip6AddNeighbor (
  2294. IN IP6_SERVICE *IpSb,
  2295. IN EFI_IPv6_ADDRESS *TargetIp6Address,
  2296. IN EFI_MAC_ADDRESS *TargetLinkAddress OPTIONAL,
  2297. IN UINT32 Timeout,
  2298. IN BOOLEAN Override
  2299. )
  2300. {
  2301. IP6_NEIGHBOR_ENTRY *Neighbor;
  2302. Neighbor = Ip6FindNeighborEntry (IpSb, TargetIp6Address);
  2303. if (Neighbor != NULL) {
  2304. if (!Override) {
  2305. return EFI_ACCESS_DENIED;
  2306. } else {
  2307. if (TargetLinkAddress != NULL) {
  2308. IP6_COPY_LINK_ADDRESS (&Neighbor->LinkAddress, TargetLinkAddress);
  2309. }
  2310. }
  2311. } else {
  2312. if (TargetLinkAddress == NULL) {
  2313. return EFI_NOT_FOUND;
  2314. }
  2315. Neighbor = Ip6CreateNeighborEntry (IpSb, Ip6OnArpResolved, TargetIp6Address, TargetLinkAddress);
  2316. if (Neighbor == NULL) {
  2317. return EFI_OUT_OF_RESOURCES;
  2318. }
  2319. }
  2320. Neighbor->State = EfiNeighborReachable;
  2321. if (Timeout != 0) {
  2322. Neighbor->Ticks = IP6_GET_TICKS (Timeout / TICKS_PER_MS);
  2323. Neighbor->Dynamic = TRUE;
  2324. } else {
  2325. Neighbor->Ticks = (UINT32)IP6_INFINIT_LIFETIME;
  2326. }
  2327. return EFI_SUCCESS;
  2328. }
  2329. /**
  2330. Delete or update Neighbor cache entries. It is a work function for EfiIp6Neighbors().
  2331. @param[in] IpSb The IP6 service binding instance.
  2332. @param[in] TargetIp6Address Pointer to Target IPv6 address.
  2333. @param[in] TargetLinkAddress Pointer to link-layer address of the target. Ignored if NULL.
  2334. @param[in] Timeout Time in 100-ns units that this entry will remain in the neighbor
  2335. cache. It will be deleted after Timeout. A value of zero means that
  2336. the entry is permanent. A non-zero value means that the entry is
  2337. dynamic.
  2338. @param[in] Override If TRUE, the cached link-layer address of the matching entry will
  2339. be overridden and updated; if FALSE, and if a
  2340. corresponding cache entry already existed, EFI_ACCESS_DENIED
  2341. will be returned.
  2342. @retval EFI_SUCCESS The neighbor cache entry has been updated or deleted.
  2343. @retval EFI_NOT_FOUND This entry is not in the neighbor cache.
  2344. **/
  2345. EFI_STATUS
  2346. Ip6DelNeighbor (
  2347. IN IP6_SERVICE *IpSb,
  2348. IN EFI_IPv6_ADDRESS *TargetIp6Address,
  2349. IN EFI_MAC_ADDRESS *TargetLinkAddress OPTIONAL,
  2350. IN UINT32 Timeout,
  2351. IN BOOLEAN Override
  2352. )
  2353. {
  2354. IP6_NEIGHBOR_ENTRY *Neighbor;
  2355. Neighbor = Ip6FindNeighborEntry (IpSb, TargetIp6Address);
  2356. if (Neighbor == NULL) {
  2357. return EFI_NOT_FOUND;
  2358. }
  2359. RemoveEntryList (&Neighbor->Link);
  2360. FreePool (Neighbor);
  2361. return EFI_SUCCESS;
  2362. }
  2363. /**
  2364. The heartbeat timer of ND module in IP6_TIMER_INTERVAL_IN_MS milliseconds.
  2365. This time routine handles DAD module and neighbor state transition.
  2366. It is also responsible for sending out router solicitations.
  2367. @param[in] Event The IP6 service instance's heartbeat timer.
  2368. @param[in] Context The IP6 service instance.
  2369. **/
  2370. VOID
  2371. EFIAPI
  2372. Ip6NdFasterTimerTicking (
  2373. IN EFI_EVENT Event,
  2374. IN VOID *Context
  2375. )
  2376. {
  2377. LIST_ENTRY *Entry;
  2378. LIST_ENTRY *Next;
  2379. LIST_ENTRY *Entry2;
  2380. IP6_INTERFACE *IpIf;
  2381. IP6_DELAY_JOIN_LIST *DelayNode;
  2382. EFI_IPv6_ADDRESS Source;
  2383. IP6_DAD_ENTRY *DupAddrDetect;
  2384. EFI_STATUS Status;
  2385. IP6_NEIGHBOR_ENTRY *NeighborCache;
  2386. EFI_IPv6_ADDRESS Destination;
  2387. IP6_SERVICE *IpSb;
  2388. BOOLEAN Flag;
  2389. IpSb = (IP6_SERVICE *)Context;
  2390. NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
  2391. ZeroMem (&Source, sizeof (EFI_IPv6_ADDRESS));
  2392. //
  2393. // A host SHOULD transmit up to MAX_RTR_SOLICITATIONS (3) Router
  2394. // Solicitation messages, each separated by at least
  2395. // RTR_SOLICITATION_INTERVAL (4) seconds.
  2396. //
  2397. if ((IpSb->Ip6ConfigInstance.Policy == Ip6ConfigPolicyAutomatic) &&
  2398. !IpSb->RouterAdvertiseReceived &&
  2399. (IpSb->SolicitTimer > 0)
  2400. )
  2401. {
  2402. if ((IpSb->Ticks == 0) || (--IpSb->Ticks == 0)) {
  2403. Status = Ip6SendRouterSolicit (IpSb, NULL, NULL, NULL, NULL);
  2404. if (!EFI_ERROR (Status)) {
  2405. IpSb->SolicitTimer--;
  2406. IpSb->Ticks = (UINT32)IP6_GET_TICKS (IP6_RTR_SOLICITATION_INTERVAL);
  2407. }
  2408. }
  2409. }
  2410. NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
  2411. IpIf = NET_LIST_USER_STRUCT (Entry, IP6_INTERFACE, Link);
  2412. //
  2413. // Process the delay list to join the solicited-node multicast address.
  2414. //
  2415. NET_LIST_FOR_EACH_SAFE (Entry2, Next, &IpIf->DelayJoinList) {
  2416. DelayNode = NET_LIST_USER_STRUCT (Entry2, IP6_DELAY_JOIN_LIST, Link);
  2417. if ((DelayNode->DelayTime == 0) || (--DelayNode->DelayTime == 0)) {
  2418. //
  2419. // The timer expires, init the duplicate address detection.
  2420. //
  2421. Ip6InitDADProcess (
  2422. DelayNode->Interface,
  2423. DelayNode->AddressInfo,
  2424. DelayNode->DadCallback,
  2425. DelayNode->Context
  2426. );
  2427. //
  2428. // Remove the delay node
  2429. //
  2430. RemoveEntryList (&DelayNode->Link);
  2431. FreePool (DelayNode);
  2432. }
  2433. }
  2434. //
  2435. // Process the duplicate address detection list.
  2436. //
  2437. NET_LIST_FOR_EACH_SAFE (Entry2, Next, &IpIf->DupAddrDetectList) {
  2438. DupAddrDetect = NET_LIST_USER_STRUCT (Entry2, IP6_DAD_ENTRY, Link);
  2439. if ((DupAddrDetect->RetransTick == 0) || (--DupAddrDetect->RetransTick == 0)) {
  2440. //
  2441. // The timer expires, check the remaining transmit counts.
  2442. //
  2443. if (DupAddrDetect->Transmit < DupAddrDetect->MaxTransmit) {
  2444. //
  2445. // Send the Neighbor Solicitation message with
  2446. // Source - unspecified address, destination - solicited-node multicast address
  2447. // Target - the address to be validated
  2448. //
  2449. Status = Ip6SendNeighborSolicit (
  2450. IpSb,
  2451. NULL,
  2452. &DupAddrDetect->Destination,
  2453. &DupAddrDetect->AddressInfo->Address,
  2454. NULL
  2455. );
  2456. if (EFI_ERROR (Status)) {
  2457. return;
  2458. }
  2459. DupAddrDetect->Transmit++;
  2460. DupAddrDetect->RetransTick = IP6_GET_TICKS (IpSb->RetransTimer);
  2461. } else {
  2462. //
  2463. // All required solicitation has been sent out, and the RetransTime after the last
  2464. // Neighbor Solicit is elapsed, finish the DAD process.
  2465. //
  2466. Flag = FALSE;
  2467. if ((DupAddrDetect->Receive == 0) ||
  2468. (DupAddrDetect->Transmit <= DupAddrDetect->Receive))
  2469. {
  2470. Flag = TRUE;
  2471. }
  2472. Ip6OnDADFinished (Flag, IpIf, DupAddrDetect);
  2473. }
  2474. }
  2475. }
  2476. }
  2477. //
  2478. // Polling the state of Neighbor cache
  2479. //
  2480. NET_LIST_FOR_EACH_SAFE (Entry, Next, &IpSb->NeighborTable) {
  2481. NeighborCache = NET_LIST_USER_STRUCT (Entry, IP6_NEIGHBOR_ENTRY, Link);
  2482. switch (NeighborCache->State) {
  2483. case EfiNeighborInComplete:
  2484. if (NeighborCache->Ticks > 0) {
  2485. --NeighborCache->Ticks;
  2486. }
  2487. //
  2488. // Retransmit Neighbor Solicitation messages approximately every
  2489. // RetransTimer milliseconds while awaiting a response.
  2490. //
  2491. if (NeighborCache->Ticks == 0) {
  2492. if (NeighborCache->Transmit > 1) {
  2493. //
  2494. // Send out multicast neighbor solicitation for address resolution.
  2495. // After last neighbor solicitation message has been sent out, wait
  2496. // for RetransTimer and then remove entry if no response is received.
  2497. //
  2498. Ip6CreateSNMulticastAddr (&NeighborCache->Neighbor, &Destination);
  2499. Status = Ip6SelectSourceAddress (IpSb, &NeighborCache->Neighbor, &Source);
  2500. if (EFI_ERROR (Status)) {
  2501. return;
  2502. }
  2503. Status = Ip6SendNeighborSolicit (
  2504. IpSb,
  2505. &Source,
  2506. &Destination,
  2507. &NeighborCache->Neighbor,
  2508. &IpSb->SnpMode.CurrentAddress
  2509. );
  2510. if (EFI_ERROR (Status)) {
  2511. return;
  2512. }
  2513. }
  2514. //
  2515. // Update the retransmit times.
  2516. //
  2517. if (NeighborCache->Transmit > 0) {
  2518. --NeighborCache->Transmit;
  2519. NeighborCache->Ticks = IP6_GET_TICKS (IpSb->RetransTimer);
  2520. }
  2521. }
  2522. if (NeighborCache->Transmit == 0) {
  2523. //
  2524. // Timeout, send ICMP destination unreachable packet and then remove entry
  2525. //
  2526. Status = Ip6FreeNeighborEntry (
  2527. IpSb,
  2528. NeighborCache,
  2529. TRUE,
  2530. TRUE,
  2531. EFI_ICMP_ERROR,
  2532. NULL,
  2533. NULL
  2534. );
  2535. if (EFI_ERROR (Status)) {
  2536. return;
  2537. }
  2538. }
  2539. break;
  2540. case EfiNeighborReachable:
  2541. //
  2542. // This entry is inserted by EfiIp6Neighbors() as static entry
  2543. // and will not timeout.
  2544. //
  2545. if (!NeighborCache->Dynamic && (NeighborCache->Ticks == IP6_INFINIT_LIFETIME)) {
  2546. break;
  2547. }
  2548. if ((NeighborCache->Ticks == 0) || (--NeighborCache->Ticks == 0)) {
  2549. if (NeighborCache->Dynamic) {
  2550. //
  2551. // This entry is inserted by EfiIp6Neighbors() as dynamic entry
  2552. // and will be deleted after timeout.
  2553. //
  2554. Status = Ip6FreeNeighborEntry (
  2555. IpSb,
  2556. NeighborCache,
  2557. FALSE,
  2558. TRUE,
  2559. EFI_TIMEOUT,
  2560. NULL,
  2561. NULL
  2562. );
  2563. if (EFI_ERROR (Status)) {
  2564. return;
  2565. }
  2566. } else {
  2567. NeighborCache->State = EfiNeighborStale;
  2568. NeighborCache->Ticks = (UINT32)IP6_INFINIT_LIFETIME;
  2569. }
  2570. }
  2571. break;
  2572. case EfiNeighborDelay:
  2573. if ((NeighborCache->Ticks == 0) || (--NeighborCache->Ticks == 0)) {
  2574. NeighborCache->State = EfiNeighborProbe;
  2575. NeighborCache->Ticks = IP6_GET_TICKS (IpSb->RetransTimer);
  2576. NeighborCache->Transmit = IP6_MAX_UNICAST_SOLICIT + 1;
  2577. //
  2578. // Send out unicast neighbor solicitation for Neighbor Unreachability Detection
  2579. //
  2580. Status = Ip6SelectSourceAddress (IpSb, &NeighborCache->Neighbor, &Source);
  2581. if (EFI_ERROR (Status)) {
  2582. return;
  2583. }
  2584. Status = Ip6SendNeighborSolicit (
  2585. IpSb,
  2586. &Source,
  2587. &NeighborCache->Neighbor,
  2588. &NeighborCache->Neighbor,
  2589. &IpSb->SnpMode.CurrentAddress
  2590. );
  2591. if (EFI_ERROR (Status)) {
  2592. return;
  2593. }
  2594. NeighborCache->Transmit--;
  2595. }
  2596. break;
  2597. case EfiNeighborProbe:
  2598. if (NeighborCache->Ticks > 0) {
  2599. --NeighborCache->Ticks;
  2600. }
  2601. //
  2602. // Retransmit Neighbor Solicitation messages approximately every
  2603. // RetransTimer milliseconds while awaiting a response.
  2604. //
  2605. if (NeighborCache->Ticks == 0) {
  2606. if (NeighborCache->Transmit > 1) {
  2607. //
  2608. // Send out unicast neighbor solicitation for Neighbor Unreachability
  2609. // Detection. After last neighbor solicitation message has been sent out,
  2610. // wait for RetransTimer and then remove entry if no response is received.
  2611. //
  2612. Status = Ip6SelectSourceAddress (IpSb, &NeighborCache->Neighbor, &Source);
  2613. if (EFI_ERROR (Status)) {
  2614. return;
  2615. }
  2616. Status = Ip6SendNeighborSolicit (
  2617. IpSb,
  2618. &Source,
  2619. &NeighborCache->Neighbor,
  2620. &NeighborCache->Neighbor,
  2621. &IpSb->SnpMode.CurrentAddress
  2622. );
  2623. if (EFI_ERROR (Status)) {
  2624. return;
  2625. }
  2626. }
  2627. //
  2628. // Update the retransmit times.
  2629. //
  2630. if (NeighborCache->Transmit > 0) {
  2631. --NeighborCache->Transmit;
  2632. NeighborCache->Ticks = IP6_GET_TICKS (IpSb->RetransTimer);
  2633. }
  2634. }
  2635. if (NeighborCache->Transmit == 0) {
  2636. //
  2637. // Delete the neighbor entry.
  2638. //
  2639. Status = Ip6FreeNeighborEntry (
  2640. IpSb,
  2641. NeighborCache,
  2642. FALSE,
  2643. TRUE,
  2644. EFI_TIMEOUT,
  2645. NULL,
  2646. NULL
  2647. );
  2648. if (EFI_ERROR (Status)) {
  2649. return;
  2650. }
  2651. }
  2652. break;
  2653. default:
  2654. break;
  2655. }
  2656. }
  2657. }
  2658. /**
  2659. The heartbeat timer of ND module in 1 second. This time routine handles following
  2660. things: 1) maintain default router list; 2) maintain prefix options;
  2661. 3) maintain route caches.
  2662. @param[in] IpSb The IP6 service binding instance.
  2663. **/
  2664. VOID
  2665. Ip6NdTimerTicking (
  2666. IN IP6_SERVICE *IpSb
  2667. )
  2668. {
  2669. LIST_ENTRY *Entry;
  2670. LIST_ENTRY *Next;
  2671. IP6_DEFAULT_ROUTER *DefaultRouter;
  2672. IP6_PREFIX_LIST_ENTRY *PrefixOption;
  2673. UINT8 Index;
  2674. IP6_ROUTE_CACHE_ENTRY *RouteCache;
  2675. //
  2676. // Decrease the lifetime of default router, if expires remove it from default router list.
  2677. //
  2678. NET_LIST_FOR_EACH_SAFE (Entry, Next, &IpSb->DefaultRouterList) {
  2679. DefaultRouter = NET_LIST_USER_STRUCT (Entry, IP6_DEFAULT_ROUTER, Link);
  2680. if (DefaultRouter->Lifetime != IP6_INF_ROUTER_LIFETIME) {
  2681. if ((DefaultRouter->Lifetime == 0) || (--DefaultRouter->Lifetime == 0)) {
  2682. Ip6DestroyDefaultRouter (IpSb, DefaultRouter);
  2683. }
  2684. }
  2685. }
  2686. //
  2687. // Decrease Valid lifetime and Preferred lifetime of Prefix options and corresponding addresses.
  2688. //
  2689. NET_LIST_FOR_EACH_SAFE (Entry, Next, &IpSb->AutonomousPrefix) {
  2690. PrefixOption = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
  2691. if (PrefixOption->ValidLifetime != (UINT32)IP6_INFINIT_LIFETIME) {
  2692. if ((PrefixOption->ValidLifetime > 0) && (--PrefixOption->ValidLifetime > 0)) {
  2693. if ((PrefixOption->PreferredLifetime != (UINT32)IP6_INFINIT_LIFETIME) &&
  2694. (PrefixOption->PreferredLifetime > 0)
  2695. )
  2696. {
  2697. --PrefixOption->PreferredLifetime;
  2698. }
  2699. } else {
  2700. Ip6DestroyPrefixListEntry (IpSb, PrefixOption, FALSE, TRUE);
  2701. }
  2702. }
  2703. }
  2704. NET_LIST_FOR_EACH_SAFE (Entry, Next, &IpSb->OnlinkPrefix) {
  2705. PrefixOption = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
  2706. if (PrefixOption->ValidLifetime != (UINT32)IP6_INFINIT_LIFETIME) {
  2707. if ((PrefixOption->ValidLifetime == 0) || (--PrefixOption->ValidLifetime == 0)) {
  2708. Ip6DestroyPrefixListEntry (IpSb, PrefixOption, TRUE, TRUE);
  2709. }
  2710. }
  2711. }
  2712. //
  2713. // Each bucket of route cache can contain at most IP6_ROUTE_CACHE_MAX entries.
  2714. // Remove the entries at the tail of the bucket. These entries
  2715. // are likely to be used least.
  2716. // Reclaim frequency is set to 1 second.
  2717. //
  2718. for (Index = 0; Index < IP6_ROUTE_CACHE_HASH_SIZE; Index++) {
  2719. while (IpSb->RouteTable->Cache.CacheNum[Index] > IP6_ROUTE_CACHE_MAX) {
  2720. Entry = NetListRemoveTail (&IpSb->RouteTable->Cache.CacheBucket[Index]);
  2721. if (Entry == NULL) {
  2722. break;
  2723. }
  2724. RouteCache = NET_LIST_USER_STRUCT (Entry, IP6_ROUTE_CACHE_ENTRY, Link);
  2725. Ip6FreeRouteCacheEntry (RouteCache);
  2726. ASSERT (IpSb->RouteTable->Cache.CacheNum[Index] > 0);
  2727. IpSb->RouteTable->Cache.CacheNum[Index]--;
  2728. }
  2729. }
  2730. }