Ip6ConfigImpl.c 80 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512
  1. /** @file
  2. The implementation of EFI IPv6 Configuration Protocol.
  3. Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
  4. Copyright (c) Microsoft Corporation.<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include "Ip6Impl.h"
  8. LIST_ENTRY mIp6ConfigInstanceList = { &mIp6ConfigInstanceList, &mIp6ConfigInstanceList };
  9. /**
  10. The event process routine when the DHCPv6 service binding protocol is installed
  11. in the system.
  12. @param[in] Event Not used.
  13. @param[in] Context Pointer to the IP6 config instance data.
  14. **/
  15. VOID
  16. EFIAPI
  17. Ip6ConfigOnDhcp6SbInstalled (
  18. IN EFI_EVENT Event,
  19. IN VOID *Context
  20. );
  21. /**
  22. Update the current policy to NewPolicy. During the transition
  23. period, the default router list, on-link prefix list, autonomous prefix list
  24. and address list in all interfaces will be released.
  25. @param[in] IpSb The IP6 service binding instance.
  26. @param[in] NewPolicy The new policy to be updated to.
  27. **/
  28. VOID
  29. Ip6ConfigOnPolicyChanged (
  30. IN IP6_SERVICE *IpSb,
  31. IN EFI_IP6_CONFIG_POLICY NewPolicy
  32. )
  33. {
  34. LIST_ENTRY *Entry;
  35. LIST_ENTRY *Entry2;
  36. LIST_ENTRY *Next;
  37. IP6_INTERFACE *IpIf;
  38. IP6_DAD_ENTRY *DadEntry;
  39. IP6_DELAY_JOIN_LIST *DelayNode;
  40. IP6_ADDRESS_INFO *AddrInfo;
  41. IP6_PROTOCOL *Instance;
  42. BOOLEAN Recovery;
  43. Recovery = FALSE;
  44. //
  45. // Currently there are only two policies: Manual and Automatic. Regardless of
  46. // what transition is going on, i.e., Manual -> Automatic and Automatic ->
  47. // Manual, we have to free default router list, on-link prefix list, autonomous
  48. // prefix list, address list in all the interfaces and destroy any IPv6 child
  49. // instance whose local IP is neither 0 nor the link-local address.
  50. //
  51. Ip6CleanDefaultRouterList (IpSb);
  52. Ip6CleanPrefixListTable (IpSb, &IpSb->OnlinkPrefix);
  53. Ip6CleanPrefixListTable (IpSb, &IpSb->AutonomousPrefix);
  54. //
  55. // It's tricky... If the LinkLocal address is O.K., add back the link-local
  56. // prefix to the on-link prefix table.
  57. //
  58. if (IpSb->LinkLocalOk) {
  59. Ip6CreatePrefixListEntry (
  60. IpSb,
  61. TRUE,
  62. (UINT32)IP6_INFINIT_LIFETIME,
  63. (UINT32)IP6_INFINIT_LIFETIME,
  64. IP6_LINK_LOCAL_PREFIX_LENGTH,
  65. &IpSb->LinkLocalAddr
  66. );
  67. }
  68. if (!IsListEmpty (&IpSb->DefaultInterface->AddressList) && (IpSb->DefaultInterface->AddressCount > 0)) {
  69. //
  70. // If any IPv6 children (Instance) in configured state and use global unicast address, it will be
  71. // destroyed in Ip6RemoveAddr() function later. Then, the upper layer driver's Stop() function will be
  72. // called, which may break the upper layer network stacks. So, the driver should take the responsibility
  73. // for the recovery by using ConnectController() after Ip6RemoveAddr().
  74. // Here, just check whether need to recover the upper layer network stacks later.
  75. //
  76. NET_LIST_FOR_EACH (Entry, &IpSb->DefaultInterface->AddressList) {
  77. AddrInfo = NET_LIST_USER_STRUCT_S (Entry, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);
  78. if (!IsListEmpty (&IpSb->Children)) {
  79. NET_LIST_FOR_EACH (Entry2, &IpSb->Children) {
  80. Instance = NET_LIST_USER_STRUCT_S (Entry2, IP6_PROTOCOL, Link, IP6_PROTOCOL_SIGNATURE);
  81. if ((Instance->State == IP6_STATE_CONFIGED) && EFI_IP6_EQUAL (&Instance->ConfigData.StationAddress, &AddrInfo->Address)) {
  82. Recovery = TRUE;
  83. break;
  84. }
  85. }
  86. }
  87. }
  88. //
  89. // All IPv6 children that use global unicast address as its source address
  90. // should be destroyed now. The survivers are those use the link-local address
  91. // or the unspecified address as the source address.
  92. // TODO: Conduct a check here.
  93. Ip6RemoveAddr (
  94. IpSb,
  95. &IpSb->DefaultInterface->AddressList,
  96. &IpSb->DefaultInterface->AddressCount,
  97. NULL,
  98. 0
  99. );
  100. if ((IpSb->Controller != NULL) && Recovery) {
  101. //
  102. // ConnectController() to recover the upper layer network stacks.
  103. //
  104. gBS->ConnectController (IpSb->Controller, NULL, NULL, TRUE);
  105. }
  106. }
  107. NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
  108. //
  109. // remove all pending delay node and DAD entries for the global addresses.
  110. //
  111. IpIf = NET_LIST_USER_STRUCT_S (Entry, IP6_INTERFACE, Link, IP6_INTERFACE_SIGNATURE);
  112. NET_LIST_FOR_EACH_SAFE (Entry2, Next, &IpIf->DelayJoinList) {
  113. DelayNode = NET_LIST_USER_STRUCT (Entry2, IP6_DELAY_JOIN_LIST, Link);
  114. if (!NetIp6IsLinkLocalAddr (&DelayNode->AddressInfo->Address)) {
  115. RemoveEntryList (&DelayNode->Link);
  116. FreePool (DelayNode);
  117. }
  118. }
  119. NET_LIST_FOR_EACH_SAFE (Entry2, Next, &IpIf->DupAddrDetectList) {
  120. DadEntry = NET_LIST_USER_STRUCT_S (Entry2, IP6_DAD_ENTRY, Link, IP6_DAD_ENTRY_SIGNATURE);
  121. if (!NetIp6IsLinkLocalAddr (&DadEntry->AddressInfo->Address)) {
  122. //
  123. // Fail this DAD entry if the address is not link-local.
  124. //
  125. Ip6OnDADFinished (FALSE, IpIf, DadEntry);
  126. }
  127. }
  128. }
  129. if (NewPolicy == Ip6ConfigPolicyAutomatic) {
  130. //
  131. // Set parameters to trigger router solicitation sending in timer handler.
  132. //
  133. IpSb->RouterAdvertiseReceived = FALSE;
  134. IpSb->SolicitTimer = IP6_MAX_RTR_SOLICITATIONS;
  135. //
  136. // delay 1 second
  137. //
  138. IpSb->Ticks = (UINT32)IP6_GET_TICKS (IP6_ONE_SECOND_IN_MS);
  139. }
  140. }
  141. /**
  142. The work function to trigger the DHCPv6 process to perform a stateful autoconfiguration.
  143. @param[in] Instance Pointer to the IP6 config instance data.
  144. @param[in] OtherInfoOnly If FALSE, get stateful address and other information
  145. via DHCPv6. Otherwise, only get the other information.
  146. @retval EFI_SUCCESS The operation finished successfully.
  147. @retval EFI_UNSUPPORTED The DHCP6 driver is not available.
  148. **/
  149. EFI_STATUS
  150. Ip6ConfigStartStatefulAutoConfig (
  151. IN IP6_CONFIG_INSTANCE *Instance,
  152. IN BOOLEAN OtherInfoOnly
  153. )
  154. {
  155. EFI_STATUS Status;
  156. IP6_SERVICE *IpSb;
  157. EFI_DHCP6_CONFIG_DATA Dhcp6CfgData;
  158. EFI_DHCP6_PROTOCOL *Dhcp6;
  159. EFI_DHCP6_PACKET_OPTION *OptList[1];
  160. UINT16 OptBuf[4];
  161. EFI_DHCP6_PACKET_OPTION *Oro;
  162. EFI_DHCP6_RETRANSMISSION InfoReqReXmit;
  163. //
  164. // A host must not invoke stateful address configuration if it is already
  165. // participating in the statuful protocol as a result of an earlier advertisement.
  166. //
  167. if (Instance->Dhcp6Handle != NULL) {
  168. return EFI_SUCCESS;
  169. }
  170. IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
  171. Instance->OtherInfoOnly = OtherInfoOnly;
  172. Status = NetLibCreateServiceChild (
  173. IpSb->Controller,
  174. IpSb->Image,
  175. &gEfiDhcp6ServiceBindingProtocolGuid,
  176. &Instance->Dhcp6Handle
  177. );
  178. if (Status == EFI_UNSUPPORTED) {
  179. //
  180. // No DHCPv6 Service Binding protocol, register a notify.
  181. //
  182. if (Instance->Dhcp6SbNotifyEvent == NULL) {
  183. Instance->Dhcp6SbNotifyEvent = EfiCreateProtocolNotifyEvent (
  184. &gEfiDhcp6ServiceBindingProtocolGuid,
  185. TPL_CALLBACK,
  186. Ip6ConfigOnDhcp6SbInstalled,
  187. (VOID *)Instance,
  188. &Instance->Registration
  189. );
  190. }
  191. }
  192. if (EFI_ERROR (Status)) {
  193. return Status;
  194. }
  195. if (Instance->Dhcp6SbNotifyEvent != NULL) {
  196. gBS->CloseEvent (Instance->Dhcp6SbNotifyEvent);
  197. }
  198. Status = gBS->OpenProtocol (
  199. Instance->Dhcp6Handle,
  200. &gEfiDhcp6ProtocolGuid,
  201. (VOID **)&Instance->Dhcp6,
  202. IpSb->Image,
  203. IpSb->Controller,
  204. EFI_OPEN_PROTOCOL_BY_DRIVER
  205. );
  206. ASSERT_EFI_ERROR (Status);
  207. Dhcp6 = Instance->Dhcp6;
  208. Dhcp6->Configure (Dhcp6, NULL);
  209. //
  210. // Set the exta options to send. Here we only want the option request option
  211. // with DNS SERVERS.
  212. //
  213. Oro = (EFI_DHCP6_PACKET_OPTION *)OptBuf;
  214. Oro->OpCode = HTONS (DHCP6_OPT_ORO);
  215. Oro->OpLen = HTONS (2);
  216. *((UINT16 *)&Oro->Data[0]) = HTONS (DHCP6_OPT_DNS_SERVERS);
  217. OptList[0] = Oro;
  218. Status = EFI_SUCCESS;
  219. if (!OtherInfoOnly) {
  220. //
  221. // Get stateful address and other information via DHCPv6.
  222. //
  223. Dhcp6CfgData.Dhcp6Callback = NULL;
  224. Dhcp6CfgData.CallbackContext = NULL;
  225. Dhcp6CfgData.OptionCount = 1;
  226. Dhcp6CfgData.OptionList = &OptList[0];
  227. Dhcp6CfgData.IaDescriptor.Type = EFI_DHCP6_IA_TYPE_NA;
  228. Dhcp6CfgData.IaDescriptor.IaId = Instance->IaId;
  229. Dhcp6CfgData.IaInfoEvent = Instance->Dhcp6Event;
  230. Dhcp6CfgData.ReconfigureAccept = FALSE;
  231. Dhcp6CfgData.RapidCommit = FALSE;
  232. Dhcp6CfgData.SolicitRetransmission = NULL;
  233. Status = Dhcp6->Configure (Dhcp6, &Dhcp6CfgData);
  234. if (!EFI_ERROR (Status)) {
  235. if (IpSb->LinkLocalOk) {
  236. Status = Dhcp6->Start (Dhcp6);
  237. } else {
  238. IpSb->Dhcp6NeedStart = TRUE;
  239. }
  240. }
  241. } else {
  242. //
  243. // Only get other information via DHCPv6, this doesn't require a config
  244. // action.
  245. //
  246. InfoReqReXmit.Irt = 4;
  247. InfoReqReXmit.Mrc = 64;
  248. InfoReqReXmit.Mrt = 60;
  249. InfoReqReXmit.Mrd = 0;
  250. if (IpSb->LinkLocalOk) {
  251. Status = Dhcp6->InfoRequest (
  252. Dhcp6,
  253. TRUE,
  254. Oro,
  255. 0,
  256. NULL,
  257. &InfoReqReXmit,
  258. Instance->Dhcp6Event,
  259. Ip6ConfigOnDhcp6Reply,
  260. Instance
  261. );
  262. } else {
  263. IpSb->Dhcp6NeedInfoRequest = TRUE;
  264. }
  265. }
  266. return Status;
  267. }
  268. /**
  269. Signal the registered event. It is the callback routine for NetMapIterate.
  270. @param[in] Map Points to the list of registered event.
  271. @param[in] Item The registered event.
  272. @param[in] Arg Not used.
  273. **/
  274. EFI_STATUS
  275. EFIAPI
  276. Ip6ConfigSignalEvent (
  277. IN NET_MAP *Map,
  278. IN NET_MAP_ITEM *Item,
  279. IN VOID *Arg
  280. )
  281. {
  282. gBS->SignalEvent ((EFI_EVENT)Item->Key);
  283. return EFI_SUCCESS;
  284. }
  285. /**
  286. Read the configuration data from variable storage according to the VarName and
  287. gEfiIp6ConfigProtocolGuid. It checks the integrity of variable data. If the
  288. data is corrupted, it clears the variable data to ZERO. Otherwise, it outputs the
  289. configuration data to IP6_CONFIG_INSTANCE.
  290. @param[in] VarName The pointer to the variable name
  291. @param[in, out] Instance The pointer to the IP6 config instance data.
  292. @retval EFI_NOT_FOUND The variable can not be found or already corrupted.
  293. @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
  294. @retval EFI_SUCCESS The configuration data was retrieved successfully.
  295. **/
  296. EFI_STATUS
  297. Ip6ConfigReadConfigData (
  298. IN CHAR16 *VarName,
  299. IN OUT IP6_CONFIG_INSTANCE *Instance
  300. )
  301. {
  302. EFI_STATUS Status;
  303. UINTN VarSize;
  304. IP6_CONFIG_VARIABLE *Variable;
  305. IP6_CONFIG_DATA_ITEM *DataItem;
  306. UINTN Index;
  307. IP6_CONFIG_DATA_RECORD DataRecord;
  308. CHAR8 *Data;
  309. //
  310. // Try to read the configuration variable.
  311. //
  312. VarSize = 0;
  313. Status = gRT->GetVariable (
  314. VarName,
  315. &gEfiIp6ConfigProtocolGuid,
  316. NULL,
  317. &VarSize,
  318. NULL
  319. );
  320. if (Status == EFI_BUFFER_TOO_SMALL) {
  321. //
  322. // Allocate buffer and read the config variable.
  323. //
  324. Variable = AllocatePool (VarSize);
  325. if (Variable == NULL) {
  326. return EFI_OUT_OF_RESOURCES;
  327. }
  328. Status = gRT->GetVariable (
  329. VarName,
  330. &gEfiIp6ConfigProtocolGuid,
  331. NULL,
  332. &VarSize,
  333. Variable
  334. );
  335. if (EFI_ERROR (Status) || ((UINT16)(~NetblockChecksum ((UINT8 *)Variable, (UINT32)VarSize)) != 0)) {
  336. //
  337. // GetVariable error or the variable is corrupted.
  338. //
  339. goto Error;
  340. }
  341. //
  342. // Get the IAID we use.
  343. //
  344. Instance->IaId = Variable->IaId;
  345. for (Index = 0; Index < Variable->DataRecordCount; Index++) {
  346. CopyMem (&DataRecord, &Variable->DataRecord[Index], sizeof (DataRecord));
  347. DataItem = &Instance->DataItem[DataRecord.DataType];
  348. if (DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED) &&
  349. (DataItem->DataSize != DataRecord.DataSize)
  350. )
  351. {
  352. //
  353. // Perhaps a corrupted data record...
  354. //
  355. continue;
  356. }
  357. if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED)) {
  358. //
  359. // This data item has variable length data.
  360. // Check that the length is contained within the variable before allocating.
  361. //
  362. if (DataRecord.DataSize > VarSize - DataRecord.Offset) {
  363. goto Error;
  364. }
  365. DataItem->Data.Ptr = AllocatePool (DataRecord.DataSize);
  366. if (DataItem->Data.Ptr == NULL) {
  367. //
  368. // no memory resource
  369. //
  370. continue;
  371. }
  372. }
  373. Data = (CHAR8 *)Variable + DataRecord.Offset;
  374. CopyMem (DataItem->Data.Ptr, Data, DataRecord.DataSize);
  375. DataItem->DataSize = DataRecord.DataSize;
  376. DataItem->Status = EFI_SUCCESS;
  377. }
  378. FreePool (Variable);
  379. return EFI_SUCCESS;
  380. }
  381. return Status;
  382. Error:
  383. //
  384. // Fall back to the default value.
  385. //
  386. if (Variable != NULL) {
  387. FreePool (Variable);
  388. }
  389. //
  390. // Remove the problematic variable and return EFI_NOT_FOUND, a new
  391. // variable will be set again.
  392. //
  393. gRT->SetVariable (
  394. VarName,
  395. &gEfiIp6ConfigProtocolGuid,
  396. IP6_CONFIG_VARIABLE_ATTRIBUTE,
  397. 0,
  398. NULL
  399. );
  400. return EFI_NOT_FOUND;
  401. }
  402. /**
  403. Write the configuration data from IP6_CONFIG_INSTANCE to variable storage.
  404. @param[in] VarName The pointer to the variable name.
  405. @param[in] Instance The pointer to the IP6 configuration instance data.
  406. @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
  407. @retval EFI_SUCCESS The configuration data is written successfully.
  408. **/
  409. EFI_STATUS
  410. Ip6ConfigWriteConfigData (
  411. IN CHAR16 *VarName,
  412. IN IP6_CONFIG_INSTANCE *Instance
  413. )
  414. {
  415. UINTN Index;
  416. UINTN VarSize;
  417. IP6_CONFIG_DATA_ITEM *DataItem;
  418. IP6_CONFIG_VARIABLE *Variable;
  419. IP6_CONFIG_DATA_RECORD *DataRecord;
  420. CHAR8 *Heap;
  421. EFI_STATUS Status;
  422. VarSize = sizeof (IP6_CONFIG_VARIABLE) - sizeof (IP6_CONFIG_DATA_RECORD);
  423. for (Index = 0; Index < Ip6ConfigDataTypeMaximum; Index++) {
  424. DataItem = &Instance->DataItem[Index];
  425. if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_VOLATILE) && !EFI_ERROR (DataItem->Status)) {
  426. VarSize += sizeof (IP6_CONFIG_DATA_RECORD) + DataItem->DataSize;
  427. }
  428. }
  429. Variable = AllocatePool (VarSize);
  430. if (Variable == NULL) {
  431. return EFI_OUT_OF_RESOURCES;
  432. }
  433. Variable->IaId = Instance->IaId;
  434. Heap = (CHAR8 *)Variable + VarSize;
  435. Variable->DataRecordCount = 0;
  436. for (Index = 0; Index < Ip6ConfigDataTypeMaximum; Index++) {
  437. DataItem = &Instance->DataItem[Index];
  438. if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_VOLATILE) && !EFI_ERROR (DataItem->Status)) {
  439. Heap -= DataItem->DataSize;
  440. CopyMem (Heap, DataItem->Data.Ptr, DataItem->DataSize);
  441. DataRecord = &Variable->DataRecord[Variable->DataRecordCount];
  442. DataRecord->DataType = (EFI_IP6_CONFIG_DATA_TYPE)Index;
  443. DataRecord->DataSize = (UINT32)DataItem->DataSize;
  444. DataRecord->Offset = (UINT16)(Heap - (CHAR8 *)Variable);
  445. Variable->DataRecordCount++;
  446. }
  447. }
  448. Variable->Checksum = 0;
  449. Variable->Checksum = (UINT16) ~NetblockChecksum ((UINT8 *)Variable, (UINT32)VarSize);
  450. Status = gRT->SetVariable (
  451. VarName,
  452. &gEfiIp6ConfigProtocolGuid,
  453. IP6_CONFIG_VARIABLE_ATTRIBUTE,
  454. VarSize,
  455. Variable
  456. );
  457. FreePool (Variable);
  458. return Status;
  459. }
  460. /**
  461. The work function for EfiIp6ConfigGetData() to get the interface information
  462. of the communication device this IP6Config instance manages.
  463. @param[in] Instance Pointer to the IP6 config instance data.
  464. @param[in, out] DataSize On input, in bytes, the size of Data. On output, in
  465. bytes, the size of buffer required to store the specified
  466. configuration data.
  467. @param[in] Data The data buffer in which the configuration data is returned.
  468. Ignored if DataSize is ZERO.
  469. @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified
  470. configuration data, and the required size is
  471. returned in DataSize.
  472. @retval EFI_SUCCESS The specified configuration data was obtained.
  473. **/
  474. EFI_STATUS
  475. Ip6ConfigGetIfInfo (
  476. IN IP6_CONFIG_INSTANCE *Instance,
  477. IN OUT UINTN *DataSize,
  478. IN VOID *Data OPTIONAL
  479. )
  480. {
  481. IP6_SERVICE *IpSb;
  482. UINTN Length;
  483. IP6_CONFIG_DATA_ITEM *Item;
  484. EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo;
  485. UINT32 AddressCount;
  486. UINT32 RouteCount;
  487. IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
  488. Length = sizeof (EFI_IP6_CONFIG_INTERFACE_INFO);
  489. //
  490. // Calculate the required length, add the buffer size for AddressInfo and
  491. // RouteTable
  492. //
  493. Ip6BuildEfiAddressList (IpSb, &AddressCount, NULL);
  494. Ip6BuildEfiRouteTable (IpSb->RouteTable, &RouteCount, NULL);
  495. Length += AddressCount * sizeof (EFI_IP6_ADDRESS_INFO) + RouteCount * sizeof (EFI_IP6_ROUTE_TABLE);
  496. if (*DataSize < Length) {
  497. *DataSize = Length;
  498. return EFI_BUFFER_TOO_SMALL;
  499. }
  500. //
  501. // Copy the fixed size part of the interface info.
  502. //
  503. Item = &Instance->DataItem[Ip6ConfigDataTypeInterfaceInfo];
  504. IfInfo = (EFI_IP6_CONFIG_INTERFACE_INFO *)Data;
  505. CopyMem (IfInfo, Item->Data.Ptr, sizeof (EFI_IP6_CONFIG_INTERFACE_INFO));
  506. //
  507. // AddressInfo
  508. //
  509. IfInfo->AddressInfo = (EFI_IP6_ADDRESS_INFO *)(IfInfo + 1);
  510. Ip6BuildEfiAddressList (IpSb, &IfInfo->AddressInfoCount, &IfInfo->AddressInfo);
  511. //
  512. // RouteTable
  513. //
  514. IfInfo->RouteTable = (EFI_IP6_ROUTE_TABLE *)(IfInfo->AddressInfo + IfInfo->AddressInfoCount);
  515. Ip6BuildEfiRouteTable (IpSb->RouteTable, &IfInfo->RouteCount, &IfInfo->RouteTable);
  516. if (IfInfo->AddressInfoCount == 0) {
  517. IfInfo->AddressInfo = NULL;
  518. }
  519. if (IfInfo->RouteCount == 0) {
  520. IfInfo->RouteTable = NULL;
  521. }
  522. return EFI_SUCCESS;
  523. }
  524. /**
  525. The work function for EfiIp6ConfigSetData() to set the alternative interface ID
  526. for the communication device managed by this IP6Config instance, if the link local
  527. IPv6 addresses generated from the interface ID based on the default source the
  528. EFI IPv6 Protocol uses is a duplicate address.
  529. @param[in] Instance Pointer to the IP6 configuration instance data.
  530. @param[in] DataSize Size of the buffer pointed to by Data in bytes.
  531. @param[in] Data The data buffer to set.
  532. @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type,
  533. 8 bytes.
  534. @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
  535. network stack was set.
  536. **/
  537. EFI_STATUS
  538. Ip6ConfigSetAltIfId (
  539. IN IP6_CONFIG_INSTANCE *Instance,
  540. IN UINTN DataSize,
  541. IN VOID *Data
  542. )
  543. {
  544. EFI_IP6_CONFIG_INTERFACE_ID *OldIfId;
  545. EFI_IP6_CONFIG_INTERFACE_ID *NewIfId;
  546. IP6_CONFIG_DATA_ITEM *DataItem;
  547. if (DataSize != sizeof (EFI_IP6_CONFIG_INTERFACE_ID)) {
  548. return EFI_BAD_BUFFER_SIZE;
  549. }
  550. DataItem = &Instance->DataItem[Ip6ConfigDataTypeAltInterfaceId];
  551. OldIfId = DataItem->Data.AltIfId;
  552. NewIfId = (EFI_IP6_CONFIG_INTERFACE_ID *)Data;
  553. CopyMem (OldIfId, NewIfId, DataSize);
  554. DataItem->Status = EFI_SUCCESS;
  555. return EFI_SUCCESS;
  556. }
  557. /**
  558. The work function for EfiIp6ConfigSetData() to set the general configuration
  559. policy for the EFI IPv6 network stack that is running on the communication device
  560. managed by this IP6Config instance. The policy will affect other configuration settings.
  561. @param[in] Instance Pointer to the IP6 config instance data.
  562. @param[in] DataSize Size of the buffer pointed to by Data in bytes.
  563. @param[in] Data The data buffer to set.
  564. @retval EFI_INVALID_PARAMETER The to be set policy is invalid.
  565. @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
  566. @retval EFI_ABORTED The new policy equals the current policy.
  567. @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
  568. network stack was set.
  569. **/
  570. EFI_STATUS
  571. Ip6ConfigSetPolicy (
  572. IN IP6_CONFIG_INSTANCE *Instance,
  573. IN UINTN DataSize,
  574. IN VOID *Data
  575. )
  576. {
  577. EFI_IP6_CONFIG_POLICY NewPolicy;
  578. IP6_CONFIG_DATA_ITEM *DataItem;
  579. IP6_SERVICE *IpSb;
  580. if (DataSize != sizeof (EFI_IP6_CONFIG_POLICY)) {
  581. return EFI_BAD_BUFFER_SIZE;
  582. }
  583. NewPolicy = *((EFI_IP6_CONFIG_POLICY *)Data);
  584. if (NewPolicy > Ip6ConfigPolicyAutomatic) {
  585. return EFI_INVALID_PARAMETER;
  586. }
  587. if (NewPolicy == Instance->Policy) {
  588. return EFI_ABORTED;
  589. } else {
  590. //
  591. // Clean the ManualAddress, Gateway and DnsServers, shrink the variable
  592. // data size, and fire up all the related events.
  593. //
  594. DataItem = &Instance->DataItem[Ip6ConfigDataTypeManualAddress];
  595. if (DataItem->Data.Ptr != NULL) {
  596. FreePool (DataItem->Data.Ptr);
  597. }
  598. DataItem->Data.Ptr = NULL;
  599. DataItem->DataSize = 0;
  600. DataItem->Status = EFI_NOT_FOUND;
  601. NetMapIterate (&DataItem->EventMap, Ip6ConfigSignalEvent, NULL);
  602. DataItem = &Instance->DataItem[Ip6ConfigDataTypeGateway];
  603. if (DataItem->Data.Ptr != NULL) {
  604. FreePool (DataItem->Data.Ptr);
  605. }
  606. DataItem->Data.Ptr = NULL;
  607. DataItem->DataSize = 0;
  608. DataItem->Status = EFI_NOT_FOUND;
  609. NetMapIterate (&DataItem->EventMap, Ip6ConfigSignalEvent, NULL);
  610. DataItem = &Instance->DataItem[Ip6ConfigDataTypeDnsServer];
  611. DataItem->Data.Ptr = NULL;
  612. DataItem->DataSize = 0;
  613. DataItem->Status = EFI_NOT_FOUND;
  614. NetMapIterate (&DataItem->EventMap, Ip6ConfigSignalEvent, NULL);
  615. if (NewPolicy == Ip6ConfigPolicyManual) {
  616. //
  617. // The policy is changed from automatic to manual. Stop the DHCPv6 process
  618. // and destroy the DHCPv6 child.
  619. //
  620. if (Instance->Dhcp6Handle != NULL) {
  621. Ip6ConfigDestroyDhcp6 (Instance);
  622. }
  623. }
  624. IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
  625. Ip6ConfigOnPolicyChanged (IpSb, NewPolicy);
  626. Instance->Policy = NewPolicy;
  627. return EFI_SUCCESS;
  628. }
  629. }
  630. /**
  631. The work function for EfiIp6ConfigSetData() to set the number of consecutive
  632. Neighbor Solicitation messages sent while performing Duplicate Address Detection
  633. on a tentative address. A value of ZERO indicates that Duplicate Address Detection
  634. will not be performed on a tentative address.
  635. @param[in] Instance The Instance Pointer to the IP6 config instance data.
  636. @param[in] DataSize Size of the buffer pointed to by Data in bytes.
  637. @param[in] Data The data buffer to set.
  638. @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
  639. @retval EFI_ABORTED The new transmit count equals the current configuration.
  640. @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
  641. network stack was set.
  642. **/
  643. EFI_STATUS
  644. Ip6ConfigSetDadXmits (
  645. IN IP6_CONFIG_INSTANCE *Instance,
  646. IN UINTN DataSize,
  647. IN VOID *Data
  648. )
  649. {
  650. EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS *OldDadXmits;
  651. if (DataSize != sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS)) {
  652. return EFI_BAD_BUFFER_SIZE;
  653. }
  654. OldDadXmits = Instance->DataItem[Ip6ConfigDataTypeDupAddrDetectTransmits].Data.DadXmits;
  655. if ((*(UINT32 *)Data) == OldDadXmits->DupAddrDetectTransmits) {
  656. return EFI_ABORTED;
  657. } else {
  658. OldDadXmits->DupAddrDetectTransmits = *((UINT32 *)Data);
  659. return EFI_SUCCESS;
  660. }
  661. }
  662. /**
  663. The callback function for Ip6SetAddr. The prototype is defined
  664. as IP6_DAD_CALLBACK. It is called after Duplicate Address Detection is performed
  665. for the manual address set by Ip6ConfigSetManualAddress.
  666. @param[in] IsDadPassed If TRUE, Duplicate Address Detection passed.
  667. @param[in] TargetAddress The tentative IPv6 address to be checked.
  668. @param[in] Context Pointer to the IP6 configuration instance data.
  669. **/
  670. VOID
  671. Ip6ManualAddrDadCallback (
  672. IN BOOLEAN IsDadPassed,
  673. IN EFI_IPv6_ADDRESS *TargetAddress,
  674. IN VOID *Context
  675. )
  676. {
  677. IP6_CONFIG_INSTANCE *Instance;
  678. UINTN Index;
  679. IP6_CONFIG_DATA_ITEM *Item;
  680. EFI_IP6_CONFIG_MANUAL_ADDRESS *ManualAddr;
  681. EFI_IP6_CONFIG_MANUAL_ADDRESS *PassedAddr;
  682. UINTN DadPassCount;
  683. UINTN DadFailCount;
  684. IP6_SERVICE *IpSb;
  685. Instance = (IP6_CONFIG_INSTANCE *)Context;
  686. NET_CHECK_SIGNATURE (Instance, IP6_CONFIG_INSTANCE_SIGNATURE);
  687. Item = &Instance->DataItem[Ip6ConfigDataTypeManualAddress];
  688. ManualAddr = NULL;
  689. if (Item->DataSize == 0) {
  690. return;
  691. }
  692. for (Index = 0; Index < Item->DataSize / sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS); Index++) {
  693. //
  694. // Find the original tag used to place into the NET_MAP.
  695. //
  696. ManualAddr = Item->Data.ManualAddress + Index;
  697. if (EFI_IP6_EQUAL (TargetAddress, &ManualAddr->Address)) {
  698. break;
  699. }
  700. }
  701. ASSERT (Index != Item->DataSize / sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS));
  702. if (IsDadPassed) {
  703. NetMapInsertTail (&Instance->DadPassedMap, ManualAddr, NULL);
  704. } else {
  705. NetMapInsertTail (&Instance->DadFailedMap, ManualAddr, NULL);
  706. }
  707. DadPassCount = NetMapGetCount (&Instance->DadPassedMap);
  708. DadFailCount = NetMapGetCount (&Instance->DadFailedMap);
  709. if ((DadPassCount + DadFailCount) == (Item->DataSize / sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS))) {
  710. //
  711. // All addresses have finished the configuration process.
  712. //
  713. if (DadFailCount != 0) {
  714. //
  715. // There is at least one duplicate address.
  716. //
  717. FreePool (Item->Data.Ptr);
  718. Item->DataSize = DadPassCount * sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS);
  719. if (Item->DataSize == 0) {
  720. //
  721. // All failed, bad luck.
  722. //
  723. Item->Data.Ptr = NULL;
  724. Item->Status = EFI_NOT_FOUND;
  725. } else {
  726. //
  727. // Part of addresses are detected to be duplicates, so update the
  728. // data with those passed.
  729. //
  730. PassedAddr = (EFI_IP6_CONFIG_MANUAL_ADDRESS *)AllocatePool (Item->DataSize);
  731. ASSERT (PassedAddr != NULL);
  732. Item->Data.Ptr = PassedAddr;
  733. Item->Status = EFI_SUCCESS;
  734. while (!NetMapIsEmpty (&Instance->DadPassedMap)) {
  735. ManualAddr = (EFI_IP6_CONFIG_MANUAL_ADDRESS *)NetMapRemoveHead (&Instance->DadPassedMap, NULL);
  736. CopyMem (PassedAddr, ManualAddr, sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS));
  737. PassedAddr++;
  738. }
  739. ASSERT ((UINTN)PassedAddr - (UINTN)Item->Data.Ptr == Item->DataSize);
  740. }
  741. } else {
  742. //
  743. // All addresses are valid.
  744. //
  745. Item->Status = EFI_SUCCESS;
  746. }
  747. //
  748. // Remove the tags we put in the NET_MAPs.
  749. //
  750. while (!NetMapIsEmpty (&Instance->DadFailedMap)) {
  751. NetMapRemoveHead (&Instance->DadFailedMap, NULL);
  752. }
  753. while (!NetMapIsEmpty (&Instance->DadPassedMap)) {
  754. NetMapRemoveHead (&Instance->DadPassedMap, NULL);
  755. }
  756. //
  757. // Signal the waiting events.
  758. //
  759. NetMapIterate (&Item->EventMap, Ip6ConfigSignalEvent, NULL);
  760. IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
  761. Ip6ConfigWriteConfigData (IpSb->MacString, Instance);
  762. }
  763. }
  764. /**
  765. The work function for EfiIp6ConfigSetData() to set the station addresses manually
  766. for the EFI IPv6 network stack. It is only configurable when the policy is
  767. Ip6ConfigPolicyManual.
  768. @param[in] Instance Pointer to the IP6 configuration instance data.
  769. @param[in] DataSize Size of the buffer pointed to by Data in bytes.
  770. @param[in] Data The data buffer to set.
  771. @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
  772. @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
  773. under the current policy.
  774. @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
  775. @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
  776. @retval EFI_NOT_READY An asynchronous process is invoked to set the specified
  777. configuration data, and the process is not finished.
  778. @retval EFI_ABORTED The manual addresses to be set equal current
  779. configuration.
  780. @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
  781. network stack was set.
  782. **/
  783. EFI_STATUS
  784. Ip6ConfigSetManualAddress (
  785. IN IP6_CONFIG_INSTANCE *Instance,
  786. IN UINTN DataSize,
  787. IN VOID *Data
  788. )
  789. {
  790. EFI_IP6_CONFIG_MANUAL_ADDRESS *NewAddress;
  791. EFI_IP6_CONFIG_MANUAL_ADDRESS *TmpAddress;
  792. IP6_CONFIG_DATA_ITEM *DataItem;
  793. UINTN NewAddressCount;
  794. UINTN Index1;
  795. UINTN Index2;
  796. IP6_SERVICE *IpSb;
  797. IP6_ADDRESS_INFO *CurrentAddrInfo;
  798. IP6_ADDRESS_INFO *Copy;
  799. LIST_ENTRY CurrentSourceList;
  800. UINT32 CurrentSourceCount;
  801. LIST_ENTRY *Entry;
  802. LIST_ENTRY *Entry2;
  803. IP6_INTERFACE *IpIf;
  804. IP6_PREFIX_LIST_ENTRY *PrefixEntry;
  805. EFI_STATUS Status;
  806. BOOLEAN IsUpdated;
  807. LIST_ENTRY *Next;
  808. IP6_DAD_ENTRY *DadEntry;
  809. IP6_DELAY_JOIN_LIST *DelayNode;
  810. NewAddress = NULL;
  811. TmpAddress = NULL;
  812. CurrentAddrInfo = NULL;
  813. Copy = NULL;
  814. Entry = NULL;
  815. Entry2 = NULL;
  816. IpIf = NULL;
  817. PrefixEntry = NULL;
  818. Next = NULL;
  819. DadEntry = NULL;
  820. DelayNode = NULL;
  821. Status = EFI_SUCCESS;
  822. ASSERT (Instance->DataItem[Ip6ConfigDataTypeManualAddress].Status != EFI_NOT_READY);
  823. if ((DataSize != 0) && ((DataSize % sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS)) != 0)) {
  824. return EFI_BAD_BUFFER_SIZE;
  825. }
  826. if (Instance->Policy != Ip6ConfigPolicyManual) {
  827. return EFI_WRITE_PROTECTED;
  828. }
  829. IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
  830. DataItem = &Instance->DataItem[Ip6ConfigDataTypeManualAddress];
  831. if ((Data != NULL) && (DataSize != 0)) {
  832. NewAddressCount = DataSize / sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS);
  833. NewAddress = (EFI_IP6_CONFIG_MANUAL_ADDRESS *)Data;
  834. for (Index1 = 0; Index1 < NewAddressCount; Index1++, NewAddress++) {
  835. if (NetIp6IsLinkLocalAddr (&NewAddress->Address) ||
  836. !NetIp6IsValidUnicast (&NewAddress->Address) ||
  837. (NewAddress->PrefixLength > 128)
  838. )
  839. {
  840. //
  841. // make sure the IPv6 address is unicast and not link-local address &&
  842. // the prefix length is valid.
  843. //
  844. return EFI_INVALID_PARAMETER;
  845. }
  846. TmpAddress = NewAddress + 1;
  847. for (Index2 = Index1 + 1; Index2 < NewAddressCount; Index2++, TmpAddress++) {
  848. //
  849. // Any two addresses in the array can't be equal.
  850. //
  851. if (EFI_IP6_EQUAL (&TmpAddress->Address, &NewAddress->Address)) {
  852. return EFI_INVALID_PARAMETER;
  853. }
  854. }
  855. }
  856. //
  857. // Build the current source address list.
  858. //
  859. InitializeListHead (&CurrentSourceList);
  860. CurrentSourceCount = 0;
  861. NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
  862. IpIf = NET_LIST_USER_STRUCT_S (Entry, IP6_INTERFACE, Link, IP6_INTERFACE_SIGNATURE);
  863. NET_LIST_FOR_EACH (Entry2, &IpIf->AddressList) {
  864. CurrentAddrInfo = NET_LIST_USER_STRUCT_S (Entry2, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);
  865. Copy = AllocateCopyPool (sizeof (IP6_ADDRESS_INFO), CurrentAddrInfo);
  866. if (Copy == NULL) {
  867. break;
  868. }
  869. InsertTailList (&CurrentSourceList, &Copy->Link);
  870. CurrentSourceCount++;
  871. }
  872. }
  873. //
  874. // Update the value... a long journey starts
  875. //
  876. NewAddress = AllocateCopyPool (DataSize, Data);
  877. if (NewAddress == NULL) {
  878. Ip6RemoveAddr (NULL, &CurrentSourceList, &CurrentSourceCount, NULL, 0);
  879. return EFI_OUT_OF_RESOURCES;
  880. }
  881. //
  882. // Store the new data, and init the DataItem status to EFI_NOT_READY because
  883. // we may have an asynchronous configuration process.
  884. //
  885. if (DataItem->Data.Ptr != NULL) {
  886. FreePool (DataItem->Data.Ptr);
  887. }
  888. DataItem->Data.Ptr = NewAddress;
  889. DataItem->DataSize = DataSize;
  890. DataItem->Status = EFI_NOT_READY;
  891. //
  892. // Trigger DAD, it's an asynchronous process.
  893. //
  894. IsUpdated = FALSE;
  895. for (Index1 = 0; Index1 < NewAddressCount; Index1++, NewAddress++) {
  896. if (Ip6IsOneOfSetAddress (IpSb, &NewAddress->Address, NULL, &CurrentAddrInfo)) {
  897. ASSERT (CurrentAddrInfo != NULL);
  898. //
  899. // Remove this already existing source address from the CurrentSourceList
  900. // built before.
  901. //
  902. Ip6RemoveAddr (
  903. NULL,
  904. &CurrentSourceList,
  905. &CurrentSourceCount,
  906. &CurrentAddrInfo->Address,
  907. 128
  908. );
  909. //
  910. // If the new address's prefix length is not specified, just use the previous configured
  911. // prefix length for this address.
  912. //
  913. if (NewAddress->PrefixLength == 0) {
  914. NewAddress->PrefixLength = CurrentAddrInfo->PrefixLength;
  915. }
  916. //
  917. // This manual address is already in use, see whether prefix length is changed.
  918. //
  919. if (NewAddress->PrefixLength != CurrentAddrInfo->PrefixLength) {
  920. //
  921. // Remove the on-link prefix table, the route entry will be removed
  922. // implicitly.
  923. //
  924. PrefixEntry = Ip6FindPrefixListEntry (
  925. IpSb,
  926. TRUE,
  927. CurrentAddrInfo->PrefixLength,
  928. &CurrentAddrInfo->Address
  929. );
  930. if (PrefixEntry != NULL) {
  931. Ip6DestroyPrefixListEntry (IpSb, PrefixEntry, TRUE, FALSE);
  932. }
  933. //
  934. // Save the prefix length.
  935. //
  936. CurrentAddrInfo->PrefixLength = NewAddress->PrefixLength;
  937. IsUpdated = TRUE;
  938. }
  939. //
  940. // create a new on-link prefix entry.
  941. //
  942. PrefixEntry = Ip6FindPrefixListEntry (
  943. IpSb,
  944. TRUE,
  945. NewAddress->PrefixLength,
  946. &NewAddress->Address
  947. );
  948. if (PrefixEntry == NULL) {
  949. Ip6CreatePrefixListEntry (
  950. IpSb,
  951. TRUE,
  952. (UINT32)IP6_INFINIT_LIFETIME,
  953. (UINT32)IP6_INFINIT_LIFETIME,
  954. NewAddress->PrefixLength,
  955. &NewAddress->Address
  956. );
  957. }
  958. CurrentAddrInfo->IsAnycast = NewAddress->IsAnycast;
  959. //
  960. // Artificially mark this address passed DAD be'coz it is already in use.
  961. //
  962. Ip6ManualAddrDadCallback (TRUE, &NewAddress->Address, Instance);
  963. } else {
  964. //
  965. // A new address.
  966. //
  967. IsUpdated = TRUE;
  968. //
  969. // Set the new address, this will trigger DAD and activate the address if
  970. // DAD succeeds.
  971. //
  972. Ip6SetAddress (
  973. IpSb->DefaultInterface,
  974. &NewAddress->Address,
  975. NewAddress->IsAnycast,
  976. NewAddress->PrefixLength,
  977. (UINT32)IP6_INFINIT_LIFETIME,
  978. (UINT32)IP6_INFINIT_LIFETIME,
  979. Ip6ManualAddrDadCallback,
  980. Instance
  981. );
  982. }
  983. }
  984. //
  985. // Check the CurrentSourceList, it now contains those addresses currently in
  986. // use and will be removed.
  987. //
  988. IpIf = IpSb->DefaultInterface;
  989. while (!IsListEmpty (&CurrentSourceList)) {
  990. IsUpdated = TRUE;
  991. CurrentAddrInfo = NET_LIST_HEAD (&CurrentSourceList, IP6_ADDRESS_INFO, Link);
  992. //
  993. // This local address is going to be removed, the IP instances that are
  994. // currently using it will be destroyed.
  995. //
  996. Ip6RemoveAddr (
  997. IpSb,
  998. &IpIf->AddressList,
  999. &IpIf->AddressCount,
  1000. &CurrentAddrInfo->Address,
  1001. 128
  1002. );
  1003. //
  1004. // Remove the on-link prefix table, the route entry will be removed
  1005. // implicitly.
  1006. //
  1007. PrefixEntry = Ip6FindPrefixListEntry (
  1008. IpSb,
  1009. TRUE,
  1010. CurrentAddrInfo->PrefixLength,
  1011. &CurrentAddrInfo->Address
  1012. );
  1013. if (PrefixEntry != NULL) {
  1014. Ip6DestroyPrefixListEntry (IpSb, PrefixEntry, TRUE, FALSE);
  1015. }
  1016. RemoveEntryList (&CurrentAddrInfo->Link);
  1017. FreePool (CurrentAddrInfo);
  1018. }
  1019. if (IsUpdated) {
  1020. if (DataItem->Status == EFI_NOT_READY) {
  1021. //
  1022. // If DAD is disabled on this interface, the configuration process is
  1023. // actually synchronous, and the data item's status will be changed to
  1024. // the final status before we reach here, just check it.
  1025. //
  1026. Status = EFI_NOT_READY;
  1027. } else {
  1028. Status = EFI_SUCCESS;
  1029. }
  1030. } else {
  1031. //
  1032. // No update is taken, reset the status to success and return EFI_ABORTED.
  1033. //
  1034. DataItem->Status = EFI_SUCCESS;
  1035. Status = EFI_ABORTED;
  1036. }
  1037. } else {
  1038. //
  1039. // DataSize is 0 and Data is NULL, clean up the manual address.
  1040. //
  1041. if (DataItem->Data.Ptr != NULL) {
  1042. FreePool (DataItem->Data.Ptr);
  1043. }
  1044. DataItem->Data.Ptr = NULL;
  1045. DataItem->DataSize = 0;
  1046. DataItem->Status = EFI_NOT_FOUND;
  1047. Ip6CleanDefaultRouterList (IpSb);
  1048. Ip6CleanPrefixListTable (IpSb, &IpSb->OnlinkPrefix);
  1049. Ip6CleanPrefixListTable (IpSb, &IpSb->AutonomousPrefix);
  1050. Ip6CleanAssembleTable (&IpSb->Assemble);
  1051. if (IpSb->LinkLocalOk) {
  1052. Ip6CreatePrefixListEntry (
  1053. IpSb,
  1054. TRUE,
  1055. (UINT32)IP6_INFINIT_LIFETIME,
  1056. (UINT32)IP6_INFINIT_LIFETIME,
  1057. IP6_LINK_LOCAL_PREFIX_LENGTH,
  1058. &IpSb->LinkLocalAddr
  1059. );
  1060. }
  1061. Ip6RemoveAddr (
  1062. IpSb,
  1063. &IpSb->DefaultInterface->AddressList,
  1064. &IpSb->DefaultInterface->AddressCount,
  1065. NULL,
  1066. 0
  1067. );
  1068. NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
  1069. //
  1070. // Remove all pending delay node and DAD entries for the global addresses.
  1071. //
  1072. IpIf = NET_LIST_USER_STRUCT_S (Entry, IP6_INTERFACE, Link, IP6_INTERFACE_SIGNATURE);
  1073. NET_LIST_FOR_EACH_SAFE (Entry2, Next, &IpIf->DelayJoinList) {
  1074. DelayNode = NET_LIST_USER_STRUCT (Entry2, IP6_DELAY_JOIN_LIST, Link);
  1075. if (!NetIp6IsLinkLocalAddr (&DelayNode->AddressInfo->Address)) {
  1076. RemoveEntryList (&DelayNode->Link);
  1077. FreePool (DelayNode);
  1078. }
  1079. }
  1080. NET_LIST_FOR_EACH_SAFE (Entry2, Next, &IpIf->DupAddrDetectList) {
  1081. DadEntry = NET_LIST_USER_STRUCT_S (Entry2, IP6_DAD_ENTRY, Link, IP6_DAD_ENTRY_SIGNATURE);
  1082. if (!NetIp6IsLinkLocalAddr (&DadEntry->AddressInfo->Address)) {
  1083. //
  1084. // Fail this DAD entry if the address is not link-local.
  1085. //
  1086. Ip6OnDADFinished (FALSE, IpIf, DadEntry);
  1087. }
  1088. }
  1089. }
  1090. }
  1091. return Status;
  1092. }
  1093. /**
  1094. The work function for EfiIp6ConfigSetData() to set the gateway addresses manually
  1095. for the EFI IPv6 network stack that is running on the communication device that
  1096. this EFI IPv6 Configuration Protocol manages. It is not configurable when the policy is
  1097. Ip6ConfigPolicyAutomatic. The gateway addresses must be unicast IPv6 addresses.
  1098. @param[in] Instance The pointer to the IP6 config instance data.
  1099. @param[in] DataSize The size of the buffer pointed to by Data in bytes.
  1100. @param[in] Data The data buffer to set. This points to an array of
  1101. EFI_IPv6_ADDRESS instances.
  1102. @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
  1103. @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
  1104. under the current policy.
  1105. @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
  1106. @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to complete the operation.
  1107. @retval EFI_ABORTED The manual gateway addresses to be set equal the
  1108. current configuration.
  1109. @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
  1110. network stack was set.
  1111. **/
  1112. EFI_STATUS
  1113. Ip6ConfigSetGateway (
  1114. IN IP6_CONFIG_INSTANCE *Instance,
  1115. IN UINTN DataSize,
  1116. IN VOID *Data
  1117. )
  1118. {
  1119. UINTN Index1;
  1120. UINTN Index2;
  1121. EFI_IPv6_ADDRESS *OldGateway;
  1122. EFI_IPv6_ADDRESS *NewGateway;
  1123. UINTN OldGatewayCount;
  1124. UINTN NewGatewayCount;
  1125. IP6_CONFIG_DATA_ITEM *Item;
  1126. BOOLEAN OneRemoved;
  1127. BOOLEAN OneAdded;
  1128. IP6_SERVICE *IpSb;
  1129. IP6_DEFAULT_ROUTER *DefaultRouter;
  1130. VOID *Tmp;
  1131. OldGateway = NULL;
  1132. NewGateway = NULL;
  1133. Item = NULL;
  1134. DefaultRouter = NULL;
  1135. Tmp = NULL;
  1136. OneRemoved = FALSE;
  1137. OneAdded = FALSE;
  1138. if ((DataSize != 0) && (DataSize % sizeof (EFI_IPv6_ADDRESS) != 0)) {
  1139. return EFI_BAD_BUFFER_SIZE;
  1140. }
  1141. if (Instance->Policy != Ip6ConfigPolicyManual) {
  1142. return EFI_WRITE_PROTECTED;
  1143. }
  1144. IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
  1145. Item = &Instance->DataItem[Ip6ConfigDataTypeGateway];
  1146. OldGateway = Item->Data.Gateway;
  1147. OldGatewayCount = Item->DataSize / sizeof (EFI_IPv6_ADDRESS);
  1148. for (Index1 = 0; Index1 < OldGatewayCount; Index1++) {
  1149. //
  1150. // Remove this default router.
  1151. //
  1152. DefaultRouter = Ip6FindDefaultRouter (IpSb, OldGateway + Index1);
  1153. if (DefaultRouter != NULL) {
  1154. Ip6DestroyDefaultRouter (IpSb, DefaultRouter);
  1155. OneRemoved = TRUE;
  1156. }
  1157. }
  1158. if ((Data != NULL) && (DataSize != 0)) {
  1159. NewGateway = (EFI_IPv6_ADDRESS *)Data;
  1160. NewGatewayCount = DataSize / sizeof (EFI_IPv6_ADDRESS);
  1161. for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {
  1162. if (!NetIp6IsValidUnicast (NewGateway + Index1)) {
  1163. return EFI_INVALID_PARAMETER;
  1164. }
  1165. for (Index2 = Index1 + 1; Index2 < NewGatewayCount; Index2++) {
  1166. if (EFI_IP6_EQUAL (NewGateway + Index1, NewGateway + Index2)) {
  1167. return EFI_INVALID_PARAMETER;
  1168. }
  1169. }
  1170. }
  1171. if (NewGatewayCount != OldGatewayCount) {
  1172. Tmp = AllocatePool (DataSize);
  1173. if (Tmp == NULL) {
  1174. return EFI_OUT_OF_RESOURCES;
  1175. }
  1176. } else {
  1177. Tmp = NULL;
  1178. }
  1179. for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {
  1180. DefaultRouter = Ip6FindDefaultRouter (IpSb, NewGateway + Index1);
  1181. if (DefaultRouter == NULL) {
  1182. Ip6CreateDefaultRouter (IpSb, NewGateway + Index1, IP6_INF_ROUTER_LIFETIME);
  1183. OneAdded = TRUE;
  1184. }
  1185. }
  1186. if (!OneRemoved && !OneAdded) {
  1187. Item->Status = EFI_SUCCESS;
  1188. return EFI_ABORTED;
  1189. } else {
  1190. if (Tmp != NULL) {
  1191. if (Item->Data.Ptr != NULL) {
  1192. FreePool (Item->Data.Ptr);
  1193. }
  1194. Item->Data.Ptr = Tmp;
  1195. }
  1196. CopyMem (Item->Data.Ptr, Data, DataSize);
  1197. Item->DataSize = DataSize;
  1198. Item->Status = EFI_SUCCESS;
  1199. return EFI_SUCCESS;
  1200. }
  1201. } else {
  1202. //
  1203. // DataSize is 0 and Data is NULL, clean up the Gateway address.
  1204. //
  1205. if (Item->Data.Ptr != NULL) {
  1206. FreePool (Item->Data.Ptr);
  1207. }
  1208. Item->Data.Ptr = NULL;
  1209. Item->DataSize = 0;
  1210. Item->Status = EFI_NOT_FOUND;
  1211. }
  1212. return EFI_SUCCESS;
  1213. }
  1214. /**
  1215. The work function for EfiIp6ConfigSetData() to set the DNS server list for the
  1216. EFI IPv6 network stack running on the communication device that this EFI IPv6
  1217. Configuration Protocol manages. It is not configurable when the policy is
  1218. Ip6ConfigPolicyAutomatic. The DNS server addresses must be unicast IPv6 addresses.
  1219. @param[in] Instance The pointer to the IP6 config instance data.
  1220. @param[in] DataSize The size of the buffer pointed to by Data in bytes.
  1221. @param[in] Data The data buffer to set, points to an array of
  1222. EFI_IPv6_ADDRESS instances.
  1223. @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
  1224. @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
  1225. under the current policy.
  1226. @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
  1227. @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
  1228. @retval EFI_ABORTED The DNS server addresses to be set equal the current
  1229. configuration.
  1230. @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
  1231. network stack was set.
  1232. **/
  1233. EFI_STATUS
  1234. Ip6ConfigSetDnsServer (
  1235. IN IP6_CONFIG_INSTANCE *Instance,
  1236. IN UINTN DataSize,
  1237. IN VOID *Data
  1238. )
  1239. {
  1240. UINTN OldIndex;
  1241. UINTN NewIndex;
  1242. EFI_IPv6_ADDRESS *OldDns;
  1243. EFI_IPv6_ADDRESS *NewDns;
  1244. UINTN OldDnsCount;
  1245. UINTN NewDnsCount;
  1246. IP6_CONFIG_DATA_ITEM *Item;
  1247. BOOLEAN OneAdded;
  1248. VOID *Tmp;
  1249. OldDns = NULL;
  1250. NewDns = NULL;
  1251. Item = NULL;
  1252. Tmp = NULL;
  1253. if ((DataSize != 0) && (DataSize % sizeof (EFI_IPv6_ADDRESS) != 0)) {
  1254. return EFI_BAD_BUFFER_SIZE;
  1255. }
  1256. if (Instance->Policy != Ip6ConfigPolicyManual) {
  1257. return EFI_WRITE_PROTECTED;
  1258. }
  1259. Item = &Instance->DataItem[Ip6ConfigDataTypeDnsServer];
  1260. if ((Data != NULL) && (DataSize != 0)) {
  1261. NewDns = (EFI_IPv6_ADDRESS *)Data;
  1262. OldDns = Item->Data.DnsServers;
  1263. NewDnsCount = DataSize / sizeof (EFI_IPv6_ADDRESS);
  1264. OldDnsCount = Item->DataSize / sizeof (EFI_IPv6_ADDRESS);
  1265. OneAdded = FALSE;
  1266. if (NewDnsCount != OldDnsCount) {
  1267. Tmp = AllocatePool (DataSize);
  1268. if (Tmp == NULL) {
  1269. return EFI_OUT_OF_RESOURCES;
  1270. }
  1271. } else {
  1272. Tmp = NULL;
  1273. }
  1274. for (NewIndex = 0; NewIndex < NewDnsCount; NewIndex++) {
  1275. if (!NetIp6IsValidUnicast (NewDns + NewIndex)) {
  1276. //
  1277. // The dns server address must be unicast.
  1278. //
  1279. if (Tmp != NULL) {
  1280. FreePool (Tmp);
  1281. }
  1282. return EFI_INVALID_PARAMETER;
  1283. }
  1284. if (OneAdded) {
  1285. //
  1286. // If any address in the new setting is not in the old settings, skip the
  1287. // comparision below.
  1288. //
  1289. continue;
  1290. }
  1291. for (OldIndex = 0; OldIndex < OldDnsCount; OldIndex++) {
  1292. if (EFI_IP6_EQUAL (NewDns + NewIndex, OldDns + OldIndex)) {
  1293. //
  1294. // If found break out.
  1295. //
  1296. break;
  1297. }
  1298. }
  1299. if (OldIndex == OldDnsCount) {
  1300. OneAdded = TRUE;
  1301. }
  1302. }
  1303. if (!OneAdded && (DataSize == Item->DataSize)) {
  1304. //
  1305. // No new item is added and the size is the same.
  1306. //
  1307. Item->Status = EFI_SUCCESS;
  1308. return EFI_ABORTED;
  1309. } else {
  1310. if (Tmp != NULL) {
  1311. if (Item->Data.Ptr != NULL) {
  1312. FreePool (Item->Data.Ptr);
  1313. }
  1314. Item->Data.Ptr = Tmp;
  1315. }
  1316. CopyMem (Item->Data.Ptr, Data, DataSize);
  1317. Item->DataSize = DataSize;
  1318. Item->Status = EFI_SUCCESS;
  1319. }
  1320. } else {
  1321. //
  1322. // DataSize is 0 and Data is NULL, clean up the DnsServer address.
  1323. //
  1324. if (Item->Data.Ptr != NULL) {
  1325. FreePool (Item->Data.Ptr);
  1326. }
  1327. Item->Data.Ptr = NULL;
  1328. Item->DataSize = 0;
  1329. Item->Status = EFI_NOT_FOUND;
  1330. }
  1331. return EFI_SUCCESS;
  1332. }
  1333. /**
  1334. Generate the operational state of the interface this IP6 config instance manages
  1335. and output in EFI_IP6_CONFIG_INTERFACE_INFO.
  1336. @param[in] IpSb The pointer to the IP6 service binding instance.
  1337. @param[out] IfInfo The pointer to the IP6 configuration interface information structure.
  1338. **/
  1339. VOID
  1340. Ip6ConfigInitIfInfo (
  1341. IN IP6_SERVICE *IpSb,
  1342. OUT EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo
  1343. )
  1344. {
  1345. UnicodeSPrint (
  1346. IfInfo->Name,
  1347. sizeof (IfInfo->Name),
  1348. L"eth%d",
  1349. IpSb->Ip6ConfigInstance.IfIndex
  1350. );
  1351. IfInfo->IfType = IpSb->SnpMode.IfType;
  1352. IfInfo->HwAddressSize = IpSb->SnpMode.HwAddressSize;
  1353. CopyMem (&IfInfo->HwAddress, &IpSb->SnpMode.CurrentAddress, IfInfo->HwAddressSize);
  1354. }
  1355. /**
  1356. Parse DHCPv6 reply packet to get the DNS server list.
  1357. It is the work function for Ip6ConfigOnDhcp6Reply and Ip6ConfigOnDhcp6Event.
  1358. @param[in] Dhcp6 The pointer to the EFI_DHCP6_PROTOCOL instance.
  1359. @param[in, out] Instance The pointer to the IP6 configuration instance data.
  1360. @param[in] Reply The pointer to the DHCPv6 reply packet.
  1361. @retval EFI_SUCCESS The DNS server address was retrieved from the reply packet.
  1362. @retval EFI_NOT_READY The reply packet does not contain the DNS server option, or
  1363. the DNS server address is not valid.
  1364. **/
  1365. EFI_STATUS
  1366. Ip6ConfigParseDhcpReply (
  1367. IN EFI_DHCP6_PROTOCOL *Dhcp6,
  1368. IN OUT IP6_CONFIG_INSTANCE *Instance,
  1369. IN EFI_DHCP6_PACKET *Reply
  1370. )
  1371. {
  1372. EFI_STATUS Status;
  1373. UINT32 OptCount;
  1374. EFI_DHCP6_PACKET_OPTION **OptList;
  1375. UINT16 OpCode;
  1376. UINT16 Length;
  1377. UINTN Index;
  1378. UINTN Index2;
  1379. EFI_IPv6_ADDRESS *DnsServer;
  1380. IP6_CONFIG_DATA_ITEM *Item;
  1381. //
  1382. // A DHCPv6 reply packet is received as the response to our InfoRequest
  1383. // packet.
  1384. //
  1385. OptCount = 0;
  1386. Status = Dhcp6->Parse (Dhcp6, Reply, &OptCount, NULL);
  1387. if (Status != EFI_BUFFER_TOO_SMALL) {
  1388. return EFI_NOT_READY;
  1389. }
  1390. OptList = AllocatePool (OptCount * sizeof (EFI_DHCP6_PACKET_OPTION *));
  1391. if (OptList == NULL) {
  1392. return EFI_NOT_READY;
  1393. }
  1394. Status = Dhcp6->Parse (Dhcp6, Reply, &OptCount, OptList);
  1395. if (EFI_ERROR (Status)) {
  1396. Status = EFI_NOT_READY;
  1397. goto ON_EXIT;
  1398. }
  1399. Status = EFI_SUCCESS;
  1400. for (Index = 0; Index < OptCount; Index++) {
  1401. //
  1402. // Go through all the options to check the ones we are interested in.
  1403. // The OpCode and Length are in network byte-order and may not be naturally
  1404. // aligned.
  1405. //
  1406. CopyMem (&OpCode, &OptList[Index]->OpCode, sizeof (OpCode));
  1407. OpCode = NTOHS (OpCode);
  1408. if (OpCode == DHCP6_OPT_DNS_SERVERS) {
  1409. CopyMem (&Length, &OptList[Index]->OpLen, sizeof (Length));
  1410. Length = NTOHS (Length);
  1411. if ((Length == 0) || ((Length % sizeof (EFI_IPv6_ADDRESS)) != 0)) {
  1412. //
  1413. // The length should be a multiple of 16 bytes.
  1414. //
  1415. Status = EFI_NOT_READY;
  1416. break;
  1417. }
  1418. //
  1419. // Validate the DnsServers: whether they are unicast addresses.
  1420. //
  1421. DnsServer = (EFI_IPv6_ADDRESS *)OptList[Index]->Data;
  1422. for (Index2 = 0; Index2 < Length / sizeof (EFI_IPv6_ADDRESS); Index2++) {
  1423. if (!NetIp6IsValidUnicast (DnsServer)) {
  1424. Status = EFI_NOT_READY;
  1425. goto ON_EXIT;
  1426. }
  1427. DnsServer++;
  1428. }
  1429. Item = &Instance->DataItem[Ip6ConfigDataTypeDnsServer];
  1430. if (Item->DataSize != Length) {
  1431. if (Item->Data.Ptr != NULL) {
  1432. FreePool (Item->Data.Ptr);
  1433. }
  1434. Item->Data.Ptr = AllocatePool (Length);
  1435. ASSERT (Item->Data.Ptr != NULL);
  1436. }
  1437. CopyMem (Item->Data.Ptr, OptList[Index]->Data, Length);
  1438. Item->DataSize = Length;
  1439. Item->Status = EFI_SUCCESS;
  1440. //
  1441. // Signal the waiting events.
  1442. //
  1443. NetMapIterate (&Item->EventMap, Ip6ConfigSignalEvent, NULL);
  1444. break;
  1445. }
  1446. }
  1447. ON_EXIT:
  1448. FreePool (OptList);
  1449. return Status;
  1450. }
  1451. /**
  1452. The callback function for Ip6SetAddr. The prototype is defined
  1453. as IP6_DAD_CALLBACK. It is called after Duplicate Address Detection is performed
  1454. on the tentative address by DHCPv6 in Ip6ConfigOnDhcp6Event().
  1455. @param[in] IsDadPassed If TRUE, Duplicate Address Detection passes.
  1456. @param[in] TargetAddress The tentative IPv6 address to be checked.
  1457. @param[in] Context Pointer to the IP6 configuration instance data.
  1458. **/
  1459. VOID
  1460. Ip6ConfigSetStatefulAddrCallback (
  1461. IN BOOLEAN IsDadPassed,
  1462. IN EFI_IPv6_ADDRESS *TargetAddress,
  1463. IN VOID *Context
  1464. )
  1465. {
  1466. IP6_CONFIG_INSTANCE *Instance;
  1467. Instance = (IP6_CONFIG_INSTANCE *)Context;
  1468. NET_CHECK_SIGNATURE (Instance, IP6_CONFIG_INSTANCE_SIGNATURE);
  1469. //
  1470. // We should record the addresses that fail the DAD, and DECLINE them.
  1471. //
  1472. if (IsDadPassed) {
  1473. //
  1474. // Decrease the count, no interests in those passed DAD.
  1475. //
  1476. if (Instance->FailedIaAddressCount > 0 ) {
  1477. Instance->FailedIaAddressCount--;
  1478. }
  1479. } else {
  1480. //
  1481. // Record it.
  1482. //
  1483. IP6_COPY_ADDRESS (Instance->DeclineAddress + Instance->DeclineAddressCount, TargetAddress);
  1484. Instance->DeclineAddressCount++;
  1485. }
  1486. if (Instance->FailedIaAddressCount == Instance->DeclineAddressCount) {
  1487. //
  1488. // The checking on all addresses are finished.
  1489. //
  1490. if (Instance->DeclineAddressCount != 0) {
  1491. //
  1492. // Decline those duplicates.
  1493. //
  1494. if (Instance->Dhcp6 != NULL) {
  1495. Instance->Dhcp6->Decline (
  1496. Instance->Dhcp6,
  1497. Instance->DeclineAddressCount,
  1498. Instance->DeclineAddress
  1499. );
  1500. }
  1501. }
  1502. if (Instance->DeclineAddress != NULL) {
  1503. FreePool (Instance->DeclineAddress);
  1504. }
  1505. Instance->DeclineAddress = NULL;
  1506. Instance->DeclineAddressCount = 0;
  1507. }
  1508. }
  1509. /**
  1510. The event handle routine when DHCPv6 process is finished or is updated.
  1511. @param[in] Event Not used.
  1512. @param[in] Context The pointer to the IP6 configuration instance data.
  1513. **/
  1514. VOID
  1515. EFIAPI
  1516. Ip6ConfigOnDhcp6Event (
  1517. IN EFI_EVENT Event,
  1518. IN VOID *Context
  1519. )
  1520. {
  1521. IP6_CONFIG_INSTANCE *Instance;
  1522. EFI_DHCP6_PROTOCOL *Dhcp6;
  1523. EFI_STATUS Status;
  1524. EFI_DHCP6_MODE_DATA Dhcp6ModeData;
  1525. EFI_DHCP6_IA *Ia;
  1526. EFI_DHCP6_IA_ADDRESS *IaAddr;
  1527. UINT32 Index;
  1528. IP6_SERVICE *IpSb;
  1529. IP6_ADDRESS_INFO *AddrInfo;
  1530. IP6_INTERFACE *IpIf;
  1531. Instance = (IP6_CONFIG_INSTANCE *)Context;
  1532. if ((Instance->Policy != Ip6ConfigPolicyAutomatic) || Instance->OtherInfoOnly) {
  1533. //
  1534. // IPv6 is not operating in the automatic policy now or
  1535. // the DHCPv6 information request message exchange is aborted.
  1536. //
  1537. return;
  1538. }
  1539. //
  1540. // The stateful address autoconfiguration is done or updated.
  1541. //
  1542. Dhcp6 = Instance->Dhcp6;
  1543. Status = Dhcp6->GetModeData (Dhcp6, &Dhcp6ModeData, NULL);
  1544. if (EFI_ERROR (Status)) {
  1545. return;
  1546. }
  1547. IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
  1548. IpIf = IpSb->DefaultInterface;
  1549. Ia = Dhcp6ModeData.Ia;
  1550. IaAddr = Ia->IaAddress;
  1551. if (Instance->DeclineAddress != NULL) {
  1552. FreePool (Instance->DeclineAddress);
  1553. }
  1554. Instance->DeclineAddress = (EFI_IPv6_ADDRESS *)AllocatePool (Ia->IaAddressCount * sizeof (EFI_IPv6_ADDRESS));
  1555. if (Instance->DeclineAddress == NULL) {
  1556. goto ON_EXIT;
  1557. }
  1558. Instance->FailedIaAddressCount = Ia->IaAddressCount;
  1559. Instance->DeclineAddressCount = 0;
  1560. for (Index = 0; Index < Ia->IaAddressCount; Index++, IaAddr++) {
  1561. if ((Ia->IaAddress[Index].ValidLifetime != 0) && (Ia->State == Dhcp6Bound)) {
  1562. //
  1563. // Set this address, either it's a new address or with updated lifetimes.
  1564. // An appropriate prefix length will be set.
  1565. //
  1566. Ip6SetAddress (
  1567. IpIf,
  1568. &IaAddr->IpAddress,
  1569. FALSE,
  1570. 0,
  1571. IaAddr->ValidLifetime,
  1572. IaAddr->PreferredLifetime,
  1573. Ip6ConfigSetStatefulAddrCallback,
  1574. Instance
  1575. );
  1576. } else {
  1577. //
  1578. // discard this address, artificially decrease the count as if this address
  1579. // passed DAD.
  1580. //
  1581. if (Ip6IsOneOfSetAddress (IpSb, &IaAddr->IpAddress, NULL, &AddrInfo)) {
  1582. ASSERT (AddrInfo != NULL);
  1583. Ip6RemoveAddr (
  1584. IpSb,
  1585. &IpIf->AddressList,
  1586. &IpIf->AddressCount,
  1587. &AddrInfo->Address,
  1588. AddrInfo->PrefixLength
  1589. );
  1590. }
  1591. if (Instance->FailedIaAddressCount > 0) {
  1592. Instance->FailedIaAddressCount--;
  1593. }
  1594. }
  1595. }
  1596. //
  1597. // Parse the Reply packet to get the options we need.
  1598. //
  1599. if (Dhcp6ModeData.Ia->ReplyPacket != NULL) {
  1600. Ip6ConfigParseDhcpReply (Dhcp6, Instance, Dhcp6ModeData.Ia->ReplyPacket);
  1601. }
  1602. ON_EXIT:
  1603. FreePool (Dhcp6ModeData.ClientId);
  1604. FreePool (Dhcp6ModeData.Ia);
  1605. }
  1606. /**
  1607. The event process routine when the DHCPv6 server is answered with a reply packet
  1608. for an information request.
  1609. @param[in] This Points to the EFI_DHCP6_PROTOCOL.
  1610. @param[in] Context The pointer to the IP6 configuration instance data.
  1611. @param[in] Packet The DHCPv6 reply packet.
  1612. @retval EFI_SUCCESS The DNS server address was retrieved from the reply packet.
  1613. @retval EFI_NOT_READY The reply packet does not contain the DNS server option, or
  1614. the DNS server address is not valid.
  1615. **/
  1616. EFI_STATUS
  1617. EFIAPI
  1618. Ip6ConfigOnDhcp6Reply (
  1619. IN EFI_DHCP6_PROTOCOL *This,
  1620. IN VOID *Context,
  1621. IN EFI_DHCP6_PACKET *Packet
  1622. )
  1623. {
  1624. return Ip6ConfigParseDhcpReply (This, (IP6_CONFIG_INSTANCE *)Context, Packet);
  1625. }
  1626. /**
  1627. The event process routine when the DHCPv6 service binding protocol is installed
  1628. in the system.
  1629. @param[in] Event Not used.
  1630. @param[in] Context The pointer to the IP6 config instance data.
  1631. **/
  1632. VOID
  1633. EFIAPI
  1634. Ip6ConfigOnDhcp6SbInstalled (
  1635. IN EFI_EVENT Event,
  1636. IN VOID *Context
  1637. )
  1638. {
  1639. IP6_CONFIG_INSTANCE *Instance;
  1640. Instance = (IP6_CONFIG_INSTANCE *)Context;
  1641. if ((Instance->Dhcp6Handle != NULL) || (Instance->Policy != Ip6ConfigPolicyAutomatic)) {
  1642. //
  1643. // The DHCP6 child is already created or the policy is no longer AUTOMATIC.
  1644. //
  1645. return;
  1646. }
  1647. Ip6ConfigStartStatefulAutoConfig (Instance, Instance->OtherInfoOnly);
  1648. }
  1649. /**
  1650. Set the configuration for the EFI IPv6 network stack running on the communication
  1651. device this EFI IPv6 Configuration Protocol instance manages.
  1652. This function is used to set the configuration data of type DataType for the EFI
  1653. IPv6 network stack that is running on the communication device that this EFI IPv6
  1654. Configuration Protocol instance manages.
  1655. DataSize is used to calculate the count of structure instances in the Data for
  1656. a DataType in which multiple structure instances are allowed.
  1657. This function is always non-blocking. When setting some type of configuration data,
  1658. an asynchronous process is invoked to check the correctness of the data, such as
  1659. performing Duplicate Address Detection on the manually set local IPv6 addresses.
  1660. EFI_NOT_READY is returned immediately to indicate that such an asynchronous process
  1661. is invoked, and the process is not finished yet. The caller wanting to get the result
  1662. of the asynchronous process is required to call RegisterDataNotify() to register an
  1663. event on the specified configuration data. Once the event is signaled, the caller
  1664. can call GetData() to obtain the configuration data and know the result.
  1665. For other types of configuration data that do not require an asynchronous configuration
  1666. process, the result of the operation is immediately returned.
  1667. @param[in] This The pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
  1668. @param[in] DataType The type of data to set.
  1669. @param[in] DataSize Size of the buffer pointed to by Data in bytes.
  1670. @param[in] Data The data buffer to set. The type of the data buffer is
  1671. associated with the DataType.
  1672. @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
  1673. network stack was set successfully.
  1674. @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
  1675. - This is NULL.
  1676. - One or more fields in Data and DataSizedo not match the
  1677. requirement of the data type indicated by DataType.
  1678. @retval EFI_WRITE_PROTECTED The specified configuration data is read-only or the specified
  1679. configuration data cannot be set under the current policy.
  1680. @retval EFI_ACCESS_DENIED Another set operation on the specified configuration
  1681. data is already in process.
  1682. @retval EFI_NOT_READY An asynchronous process was invoked to set the specified
  1683. configuration data, and the process is not finished yet.
  1684. @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type
  1685. indicated by DataType.
  1686. @retval EFI_UNSUPPORTED This DataType is not supported.
  1687. @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
  1688. @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred.
  1689. **/
  1690. EFI_STATUS
  1691. EFIAPI
  1692. EfiIp6ConfigSetData (
  1693. IN EFI_IP6_CONFIG_PROTOCOL *This,
  1694. IN EFI_IP6_CONFIG_DATA_TYPE DataType,
  1695. IN UINTN DataSize,
  1696. IN VOID *Data
  1697. )
  1698. {
  1699. EFI_TPL OldTpl;
  1700. EFI_STATUS Status;
  1701. IP6_CONFIG_INSTANCE *Instance;
  1702. IP6_SERVICE *IpSb;
  1703. if ((This == NULL) || ((Data == NULL) && (DataSize != 0)) || ((Data != NULL) && (DataSize == 0))) {
  1704. return EFI_INVALID_PARAMETER;
  1705. }
  1706. if (DataType >= Ip6ConfigDataTypeMaximum) {
  1707. return EFI_UNSUPPORTED;
  1708. }
  1709. Instance = IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This);
  1710. IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
  1711. NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
  1712. if (IpSb->LinkLocalDadFail) {
  1713. return EFI_DEVICE_ERROR;
  1714. }
  1715. OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
  1716. Status = Instance->DataItem[DataType].Status;
  1717. if (Status != EFI_NOT_READY) {
  1718. if (Instance->DataItem[DataType].SetData == NULL) {
  1719. //
  1720. // This type of data is readonly.
  1721. //
  1722. Status = EFI_WRITE_PROTECTED;
  1723. } else {
  1724. Status = Instance->DataItem[DataType].SetData (Instance, DataSize, Data);
  1725. if (!EFI_ERROR (Status)) {
  1726. //
  1727. // Fire up the events registered with this type of data.
  1728. //
  1729. NetMapIterate (&Instance->DataItem[DataType].EventMap, Ip6ConfigSignalEvent, NULL);
  1730. Ip6ConfigWriteConfigData (IpSb->MacString, Instance);
  1731. } else if (Status == EFI_ABORTED) {
  1732. //
  1733. // The SetData is aborted because the data to set is the same with
  1734. // the one maintained.
  1735. //
  1736. Status = EFI_SUCCESS;
  1737. NetMapIterate (&Instance->DataItem[DataType].EventMap, Ip6ConfigSignalEvent, NULL);
  1738. }
  1739. }
  1740. } else {
  1741. //
  1742. // Another asynchronous process is on the way.
  1743. //
  1744. Status = EFI_ACCESS_DENIED;
  1745. }
  1746. gBS->RestoreTPL (OldTpl);
  1747. return Status;
  1748. }
  1749. /**
  1750. Get the configuration data for the EFI IPv6 network stack running on the communication
  1751. device that this EFI IPv6 Configuration Protocol instance manages.
  1752. This function returns the configuration data of type DataType for the EFI IPv6 network
  1753. stack running on the communication device that this EFI IPv6 Configuration Protocol instance
  1754. manages.
  1755. The caller is responsible for allocating the buffer used to return the specified
  1756. configuration data. The required size will be returned to the caller if the size of
  1757. the buffer is too small.
  1758. EFI_NOT_READY is returned if the specified configuration data is not ready due to an
  1759. asynchronous configuration process already in progress. The caller can call RegisterDataNotify()
  1760. to register an event on the specified configuration data. Once the asynchronous configuration
  1761. process is finished, the event will be signaled, and a subsequent GetData() call will return
  1762. the specified configuration data.
  1763. @param[in] This Pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
  1764. @param[in] DataType The type of data to get.
  1765. @param[in, out] DataSize On input, in bytes, the size of Data. On output, in bytes, the
  1766. size of buffer required to store the specified configuration data.
  1767. @param[in] Data The data buffer in which the configuration data is returned. The
  1768. type of the data buffer is associated with the DataType.
  1769. This is an optional parameter that may be NULL.
  1770. @retval EFI_SUCCESS The specified configuration data was obtained successfully.
  1771. @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
  1772. - This is NULL.
  1773. - DataSize is NULL.
  1774. - Data is NULL if *DataSize is not zero.
  1775. @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified configuration data,
  1776. and the required size is returned in DataSize.
  1777. @retval EFI_NOT_READY The specified configuration data is not ready due to an
  1778. asynchronous configuration process already in progress.
  1779. @retval EFI_NOT_FOUND The specified configuration data is not found.
  1780. **/
  1781. EFI_STATUS
  1782. EFIAPI
  1783. EfiIp6ConfigGetData (
  1784. IN EFI_IP6_CONFIG_PROTOCOL *This,
  1785. IN EFI_IP6_CONFIG_DATA_TYPE DataType,
  1786. IN OUT UINTN *DataSize,
  1787. IN VOID *Data OPTIONAL
  1788. )
  1789. {
  1790. EFI_TPL OldTpl;
  1791. EFI_STATUS Status;
  1792. IP6_CONFIG_INSTANCE *Instance;
  1793. IP6_CONFIG_DATA_ITEM *DataItem;
  1794. if ((This == NULL) || (DataSize == NULL) || ((*DataSize != 0) && (Data == NULL))) {
  1795. return EFI_INVALID_PARAMETER;
  1796. }
  1797. if (DataType >= Ip6ConfigDataTypeMaximum) {
  1798. return EFI_NOT_FOUND;
  1799. }
  1800. OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
  1801. Instance = IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This);
  1802. DataItem = &Instance->DataItem[DataType];
  1803. Status = Instance->DataItem[DataType].Status;
  1804. if (!EFI_ERROR (Status)) {
  1805. if (DataItem->GetData != NULL) {
  1806. Status = DataItem->GetData (Instance, DataSize, Data);
  1807. } else if (*DataSize < Instance->DataItem[DataType].DataSize) {
  1808. //
  1809. // Update the buffer length.
  1810. //
  1811. *DataSize = Instance->DataItem[DataType].DataSize;
  1812. Status = EFI_BUFFER_TOO_SMALL;
  1813. } else {
  1814. *DataSize = Instance->DataItem[DataType].DataSize;
  1815. CopyMem (Data, Instance->DataItem[DataType].Data.Ptr, *DataSize);
  1816. }
  1817. }
  1818. gBS->RestoreTPL (OldTpl);
  1819. return Status;
  1820. }
  1821. /**
  1822. Register an event that is signaled whenever a configuration process on the specified
  1823. configuration data is done.
  1824. This function registers an event that is to be signaled whenever a configuration
  1825. process on the specified configuration data is performed. An event can be registered
  1826. for a different DataType simultaneously. The caller is responsible for determining
  1827. which type of configuration data causes the signaling of the event in such an event.
  1828. @param[in] This Pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
  1829. @param[in] DataType The type of data to unregister the event for.
  1830. @param[in] Event The event to register.
  1831. @retval EFI_SUCCESS The notification event for the specified configuration data is
  1832. registered.
  1833. @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
  1834. @retval EFI_UNSUPPORTED The configuration data type specified by DataType is not
  1835. supported.
  1836. @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
  1837. @retval EFI_ACCESS_DENIED The Event is already registered for the DataType.
  1838. **/
  1839. EFI_STATUS
  1840. EFIAPI
  1841. EfiIp6ConfigRegisterDataNotify (
  1842. IN EFI_IP6_CONFIG_PROTOCOL *This,
  1843. IN EFI_IP6_CONFIG_DATA_TYPE DataType,
  1844. IN EFI_EVENT Event
  1845. )
  1846. {
  1847. EFI_TPL OldTpl;
  1848. EFI_STATUS Status;
  1849. IP6_CONFIG_INSTANCE *Instance;
  1850. NET_MAP *EventMap;
  1851. NET_MAP_ITEM *Item;
  1852. if ((This == NULL) || (Event == NULL)) {
  1853. return EFI_INVALID_PARAMETER;
  1854. }
  1855. if (DataType >= Ip6ConfigDataTypeMaximum) {
  1856. return EFI_UNSUPPORTED;
  1857. }
  1858. OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
  1859. Instance = IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This);
  1860. EventMap = &Instance->DataItem[DataType].EventMap;
  1861. //
  1862. // Check whether this event is already registered for this DataType.
  1863. //
  1864. Item = NetMapFindKey (EventMap, Event);
  1865. if (Item == NULL) {
  1866. Status = NetMapInsertTail (EventMap, Event, NULL);
  1867. if (EFI_ERROR (Status)) {
  1868. Status = EFI_OUT_OF_RESOURCES;
  1869. }
  1870. } else {
  1871. Status = EFI_ACCESS_DENIED;
  1872. }
  1873. gBS->RestoreTPL (OldTpl);
  1874. return Status;
  1875. }
  1876. /**
  1877. Remove a previously registered event for the specified configuration data.
  1878. @param This The pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
  1879. @param DataType The type of data to remove from the previously
  1880. registered event.
  1881. @param Event The event to be unregistered.
  1882. @retval EFI_SUCCESS The event registered for the specified
  1883. configuration data was removed.
  1884. @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
  1885. @retval EFI_NOT_FOUND The Event has not been registered for the
  1886. specified DataType.
  1887. **/
  1888. EFI_STATUS
  1889. EFIAPI
  1890. EfiIp6ConfigUnregisterDataNotify (
  1891. IN EFI_IP6_CONFIG_PROTOCOL *This,
  1892. IN EFI_IP6_CONFIG_DATA_TYPE DataType,
  1893. IN EFI_EVENT Event
  1894. )
  1895. {
  1896. EFI_TPL OldTpl;
  1897. EFI_STATUS Status;
  1898. IP6_CONFIG_INSTANCE *Instance;
  1899. NET_MAP_ITEM *Item;
  1900. if ((This == NULL) || (Event == NULL)) {
  1901. return EFI_INVALID_PARAMETER;
  1902. }
  1903. if (DataType >= Ip6ConfigDataTypeMaximum) {
  1904. return EFI_NOT_FOUND;
  1905. }
  1906. OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
  1907. Instance = IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This);
  1908. Item = NetMapFindKey (&Instance->DataItem[DataType].EventMap, Event);
  1909. if (Item != NULL) {
  1910. NetMapRemoveItem (&Instance->DataItem[DataType].EventMap, Item, NULL);
  1911. Status = EFI_SUCCESS;
  1912. } else {
  1913. Status = EFI_NOT_FOUND;
  1914. }
  1915. gBS->RestoreTPL (OldTpl);
  1916. return Status;
  1917. }
  1918. /**
  1919. Initialize an IP6_CONFIG_INSTANCE.
  1920. @param[out] Instance The buffer of IP6_CONFIG_INSTANCE to be initialized.
  1921. @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
  1922. @retval EFI_SUCCESS The IP6_CONFIG_INSTANCE initialized successfully.
  1923. **/
  1924. EFI_STATUS
  1925. Ip6ConfigInitInstance (
  1926. OUT IP6_CONFIG_INSTANCE *Instance
  1927. )
  1928. {
  1929. IP6_SERVICE *IpSb;
  1930. IP6_CONFIG_INSTANCE *TmpInstance;
  1931. LIST_ENTRY *Entry;
  1932. EFI_STATUS Status;
  1933. UINTN Index;
  1934. UINT16 IfIndex;
  1935. IP6_CONFIG_DATA_ITEM *DataItem;
  1936. IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
  1937. Instance->Signature = IP6_CONFIG_INSTANCE_SIGNATURE;
  1938. //
  1939. // Determine the index of this interface.
  1940. //
  1941. IfIndex = 0;
  1942. NET_LIST_FOR_EACH (Entry, &mIp6ConfigInstanceList) {
  1943. TmpInstance = NET_LIST_USER_STRUCT_S (Entry, IP6_CONFIG_INSTANCE, Link, IP6_CONFIG_INSTANCE_SIGNATURE);
  1944. if (TmpInstance->IfIndex > IfIndex) {
  1945. //
  1946. // There is a sequence hole because some interface is down.
  1947. //
  1948. break;
  1949. }
  1950. IfIndex++;
  1951. }
  1952. Instance->IfIndex = IfIndex;
  1953. NetListInsertBefore (Entry, &Instance->Link);
  1954. for (Index = 0; Index < Ip6ConfigDataTypeMaximum; Index++) {
  1955. //
  1956. // Initialize the event map for each data item.
  1957. //
  1958. NetMapInit (&Instance->DataItem[Index].EventMap);
  1959. }
  1960. //
  1961. // Initialize the NET_MAPs used for DAD on manually configured source addresses.
  1962. //
  1963. NetMapInit (&Instance->DadFailedMap);
  1964. NetMapInit (&Instance->DadPassedMap);
  1965. //
  1966. // Initialize each data type: associate storage and set data size for the
  1967. // fixed size data types, hook the SetData function, set the data attribute.
  1968. //
  1969. DataItem = &Instance->DataItem[Ip6ConfigDataTypeInterfaceInfo];
  1970. DataItem->GetData = Ip6ConfigGetIfInfo;
  1971. DataItem->Data.Ptr = &Instance->InterfaceInfo;
  1972. DataItem->DataSize = sizeof (Instance->InterfaceInfo);
  1973. SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED | DATA_ATTRIB_VOLATILE);
  1974. Ip6ConfigInitIfInfo (IpSb, &Instance->InterfaceInfo);
  1975. DataItem = &Instance->DataItem[Ip6ConfigDataTypeAltInterfaceId];
  1976. DataItem->SetData = Ip6ConfigSetAltIfId;
  1977. DataItem->Data.Ptr = &Instance->AltIfId;
  1978. DataItem->DataSize = sizeof (Instance->AltIfId);
  1979. DataItem->Status = EFI_NOT_FOUND;
  1980. SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED);
  1981. DataItem = &Instance->DataItem[Ip6ConfigDataTypePolicy];
  1982. DataItem->SetData = Ip6ConfigSetPolicy;
  1983. DataItem->Data.Ptr = &Instance->Policy;
  1984. DataItem->DataSize = sizeof (Instance->Policy);
  1985. Instance->Policy = Ip6ConfigPolicyManual;
  1986. SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED);
  1987. DataItem = &Instance->DataItem[Ip6ConfigDataTypeDupAddrDetectTransmits];
  1988. DataItem->SetData = Ip6ConfigSetDadXmits;
  1989. DataItem->Data.Ptr = &Instance->DadXmits;
  1990. DataItem->DataSize = sizeof (Instance->DadXmits);
  1991. Instance->DadXmits.DupAddrDetectTransmits = IP6_CONFIG_DEFAULT_DAD_XMITS;
  1992. SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED);
  1993. DataItem = &Instance->DataItem[Ip6ConfigDataTypeManualAddress];
  1994. DataItem->SetData = Ip6ConfigSetManualAddress;
  1995. DataItem->Status = EFI_NOT_FOUND;
  1996. DataItem = &Instance->DataItem[Ip6ConfigDataTypeGateway];
  1997. DataItem->SetData = Ip6ConfigSetGateway;
  1998. DataItem->Status = EFI_NOT_FOUND;
  1999. DataItem = &Instance->DataItem[Ip6ConfigDataTypeDnsServer];
  2000. DataItem->SetData = Ip6ConfigSetDnsServer;
  2001. DataItem->Status = EFI_NOT_FOUND;
  2002. //
  2003. // Create the event used for DHCP.
  2004. //
  2005. Status = gBS->CreateEvent (
  2006. EVT_NOTIFY_SIGNAL,
  2007. TPL_CALLBACK,
  2008. Ip6ConfigOnDhcp6Event,
  2009. Instance,
  2010. &Instance->Dhcp6Event
  2011. );
  2012. ASSERT_EFI_ERROR (Status);
  2013. Instance->Configured = TRUE;
  2014. //
  2015. // Try to read the config data from NV variable.
  2016. //
  2017. Status = Ip6ConfigReadConfigData (IpSb->MacString, Instance);
  2018. if (Status == EFI_NOT_FOUND) {
  2019. //
  2020. // The NV variable is not set, so generate a random IAID, and write down the
  2021. // fresh new configuration as the NV variable now.
  2022. //
  2023. Instance->IaId = NET_RANDOM (NetRandomInitSeed ());
  2024. for (Index = 0; Index < IpSb->SnpMode.HwAddressSize; Index++) {
  2025. Instance->IaId |= (IpSb->SnpMode.CurrentAddress.Addr[Index] << ((Index << 3) & 31));
  2026. }
  2027. Ip6ConfigWriteConfigData (IpSb->MacString, Instance);
  2028. } else if (EFI_ERROR (Status)) {
  2029. return Status;
  2030. }
  2031. Instance->Ip6Config.SetData = EfiIp6ConfigSetData;
  2032. Instance->Ip6Config.GetData = EfiIp6ConfigGetData;
  2033. Instance->Ip6Config.RegisterDataNotify = EfiIp6ConfigRegisterDataNotify;
  2034. Instance->Ip6Config.UnregisterDataNotify = EfiIp6ConfigUnregisterDataNotify;
  2035. //
  2036. // Publish the IP6 configuration form
  2037. //
  2038. return Ip6ConfigFormInit (Instance);
  2039. }
  2040. /**
  2041. Release an IP6_CONFIG_INSTANCE.
  2042. @param[in, out] Instance The buffer of IP6_CONFIG_INSTANCE to be freed.
  2043. **/
  2044. VOID
  2045. Ip6ConfigCleanInstance (
  2046. IN OUT IP6_CONFIG_INSTANCE *Instance
  2047. )
  2048. {
  2049. UINTN Index;
  2050. IP6_CONFIG_DATA_ITEM *DataItem;
  2051. if (Instance->DeclineAddress != NULL) {
  2052. FreePool (Instance->DeclineAddress);
  2053. }
  2054. if (!Instance->Configured) {
  2055. return;
  2056. }
  2057. if (Instance->Dhcp6Handle != NULL) {
  2058. Ip6ConfigDestroyDhcp6 (Instance);
  2059. }
  2060. //
  2061. // Close the event.
  2062. //
  2063. if (Instance->Dhcp6Event != NULL) {
  2064. gBS->CloseEvent (Instance->Dhcp6Event);
  2065. }
  2066. NetMapClean (&Instance->DadPassedMap);
  2067. NetMapClean (&Instance->DadFailedMap);
  2068. for (Index = 0; Index < Ip6ConfigDataTypeMaximum; Index++) {
  2069. DataItem = &Instance->DataItem[Index];
  2070. if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED)) {
  2071. if (DataItem->Data.Ptr != NULL) {
  2072. FreePool (DataItem->Data.Ptr);
  2073. }
  2074. DataItem->Data.Ptr = NULL;
  2075. DataItem->DataSize = 0;
  2076. }
  2077. NetMapClean (&Instance->DataItem[Index].EventMap);
  2078. }
  2079. Ip6ConfigFormUnload (Instance);
  2080. RemoveEntryList (&Instance->Link);
  2081. }
  2082. /**
  2083. Destroy the Dhcp6 child in IP6_CONFIG_INSTANCE and release the resources.
  2084. @param[in, out] Instance The buffer of IP6_CONFIG_INSTANCE to be freed.
  2085. @retval EFI_SUCCESS The child was successfully destroyed.
  2086. @retval Others Failed to destroy the child.
  2087. **/
  2088. EFI_STATUS
  2089. Ip6ConfigDestroyDhcp6 (
  2090. IN OUT IP6_CONFIG_INSTANCE *Instance
  2091. )
  2092. {
  2093. IP6_SERVICE *IpSb;
  2094. EFI_STATUS Status;
  2095. EFI_DHCP6_PROTOCOL *Dhcp6;
  2096. Dhcp6 = Instance->Dhcp6;
  2097. ASSERT (Dhcp6 != NULL);
  2098. Dhcp6->Stop (Dhcp6);
  2099. Dhcp6->Configure (Dhcp6, NULL);
  2100. Instance->Dhcp6 = NULL;
  2101. IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
  2102. //
  2103. // Close DHCPv6 protocol and destroy the child.
  2104. //
  2105. Status = gBS->CloseProtocol (
  2106. Instance->Dhcp6Handle,
  2107. &gEfiDhcp6ProtocolGuid,
  2108. IpSb->Image,
  2109. IpSb->Controller
  2110. );
  2111. if (EFI_ERROR (Status)) {
  2112. return Status;
  2113. }
  2114. Status = NetLibDestroyServiceChild (
  2115. IpSb->Controller,
  2116. IpSb->Image,
  2117. &gEfiDhcp6ServiceBindingProtocolGuid,
  2118. Instance->Dhcp6Handle
  2119. );
  2120. Instance->Dhcp6Handle = NULL;
  2121. return Status;
  2122. }