Dhcp6Utility.c 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324
  1. /** @file
  2. Dhcp6 support functions implementation.
  3. (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
  4. Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include "Dhcp6Impl.h"
  8. /**
  9. Generate client Duid in the format of Duid-llt.
  10. @param[in] Mode The pointer to the mode of SNP.
  11. @retval NULL If it failed to generate a client Id.
  12. @retval others The pointer to the new client id.
  13. **/
  14. EFI_DHCP6_DUID *
  15. Dhcp6GenerateClientId (
  16. IN EFI_SIMPLE_NETWORK_MODE *Mode
  17. )
  18. {
  19. EFI_STATUS Status;
  20. EFI_DHCP6_DUID *Duid;
  21. EFI_TIME Time;
  22. UINT32 Stamp;
  23. EFI_GUID Uuid;
  24. //
  25. // Attempt to get client Id from variable to keep it constant.
  26. // See details in section-9 of rfc-3315.
  27. //
  28. GetVariable2 (L"ClientId", &gEfiDhcp6ServiceBindingProtocolGuid, (VOID**)&Duid, NULL);
  29. if (Duid != NULL) {
  30. return Duid;
  31. }
  32. //
  33. // The format of client identifier option:
  34. //
  35. // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  36. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  37. // | OPTION_CLIENTID | option-len |
  38. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  39. // . .
  40. // . DUID .
  41. // . (variable length) .
  42. // . .
  43. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  44. //
  45. //
  46. // If System UUID is found from SMBIOS Table, use DUID-UUID type.
  47. //
  48. if ((PcdGet8 (PcdDhcp6UidType) == Dhcp6DuidTypeUuid) && !EFI_ERROR (NetLibGetSystemGuid (&Uuid)) && !CompareGuid (&Uuid, &gZeroGuid)) {
  49. //
  50. //
  51. // The format of DUID-UUID:
  52. //
  53. // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  54. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  55. // | DUID-Type (4) | UUID (128 bits) |
  56. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
  57. // | |
  58. // | |
  59. // | -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  60. // | |
  61. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
  62. //
  63. // sizeof (option-len + Duid-type + UUID-size) = 20 bytes
  64. //
  65. Duid = AllocateZeroPool (2 + 2 + sizeof (EFI_GUID));
  66. if (Duid == NULL) {
  67. return NULL;
  68. }
  69. //
  70. // sizeof (Duid-type + UUID-size) = 18 bytes
  71. //
  72. Duid->Length = (UINT16) (18);
  73. //
  74. // Set the Duid-type and copy UUID.
  75. //
  76. WriteUnaligned16 ((UINT16 *) (Duid->Duid), HTONS (Dhcp6DuidTypeUuid));
  77. CopyMem (Duid->Duid + 2, &Uuid, sizeof(EFI_GUID));
  78. } else {
  79. //
  80. //
  81. // The format of DUID-LLT:
  82. //
  83. // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  84. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  85. // | Duid type (1) | hardware type (16 bits) |
  86. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  87. // | time (32 bits) |
  88. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  89. // . .
  90. // . link-layer address (variable length) .
  91. // . .
  92. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  93. //
  94. //
  95. // Generate a time stamp of the seconds from 2000/1/1, assume 30day/month.
  96. //
  97. gRT->GetTime (&Time, NULL);
  98. Stamp = (UINT32)
  99. (
  100. ((((UINT32)(Time.Year - 2000) * 360 + (Time.Month - 1) * 30 + (Time.Day - 1)) * 24 + Time.Hour) * 60 + Time.Minute) *
  101. 60 +
  102. Time.Second
  103. );
  104. //
  105. // sizeof (option-len + Duid-type + hardware-type + time) = 10 bytes
  106. //
  107. Duid = AllocateZeroPool (10 + Mode->HwAddressSize);
  108. if (Duid == NULL) {
  109. return NULL;
  110. }
  111. //
  112. // sizeof (Duid-type + hardware-type + time) = 8 bytes
  113. //
  114. Duid->Length = (UINT16) (Mode->HwAddressSize + 8);
  115. //
  116. // Set the Duid-type, hardware-type, time and copy the hardware address.
  117. //
  118. WriteUnaligned16 ((UINT16 *) ((UINT8 *) Duid + OFFSET_OF (EFI_DHCP6_DUID, Duid)), HTONS (Dhcp6DuidTypeLlt));
  119. WriteUnaligned16 ((UINT16 *) ((UINT8 *) Duid + OFFSET_OF (EFI_DHCP6_DUID, Duid) + 2), HTONS (NET_IFTYPE_ETHERNET));
  120. WriteUnaligned32 ((UINT32 *) ((UINT8 *) Duid + OFFSET_OF (EFI_DHCP6_DUID, Duid) + 4), HTONL (Stamp));
  121. CopyMem (Duid->Duid + 8, &Mode->CurrentAddress, Mode->HwAddressSize);
  122. }
  123. Status = gRT->SetVariable (
  124. L"ClientId",
  125. &gEfiDhcp6ServiceBindingProtocolGuid,
  126. (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS),
  127. Duid->Length + 2,
  128. (VOID *) Duid
  129. );
  130. if (EFI_ERROR (Status)) {
  131. FreePool (Duid);
  132. return NULL;
  133. }
  134. return Duid;
  135. }
  136. /**
  137. Copy the Dhcp6 configure data.
  138. @param[in] DstCfg The pointer to the destination configure data.
  139. @param[in] SorCfg The pointer to the source configure data.
  140. @retval EFI_SUCCESS Copy the content from SorCfg from DstCfg successfully.
  141. @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
  142. **/
  143. EFI_STATUS
  144. Dhcp6CopyConfigData (
  145. IN EFI_DHCP6_CONFIG_DATA *DstCfg,
  146. IN EFI_DHCP6_CONFIG_DATA *SorCfg
  147. )
  148. {
  149. UINTN Index;
  150. UINTN OptionListSize;
  151. UINTN OptionSize;
  152. CopyMem (DstCfg, SorCfg, sizeof (EFI_DHCP6_CONFIG_DATA));
  153. //
  154. // Allocate another buffer for solicitretransmission, and copy it.
  155. //
  156. if (SorCfg->SolicitRetransmission != NULL) {
  157. DstCfg->SolicitRetransmission = AllocateZeroPool (sizeof (EFI_DHCP6_RETRANSMISSION));
  158. if (DstCfg->SolicitRetransmission == NULL) {
  159. //
  160. // Error will be handled out of this function.
  161. //
  162. return EFI_OUT_OF_RESOURCES;
  163. }
  164. CopyMem (
  165. DstCfg->SolicitRetransmission,
  166. SorCfg->SolicitRetransmission,
  167. sizeof (EFI_DHCP6_RETRANSMISSION)
  168. );
  169. }
  170. if (SorCfg->OptionList != NULL && SorCfg->OptionCount != 0) {
  171. OptionListSize = SorCfg->OptionCount * sizeof (EFI_DHCP6_PACKET_OPTION *);
  172. DstCfg->OptionList = AllocateZeroPool (OptionListSize);
  173. if (DstCfg->OptionList == NULL) {
  174. //
  175. // Error will be handled out of this function.
  176. //
  177. return EFI_OUT_OF_RESOURCES;
  178. }
  179. for (Index = 0; Index < SorCfg->OptionCount; Index++) {
  180. OptionSize = NTOHS (SorCfg->OptionList[Index]->OpLen) + 4;
  181. DstCfg->OptionList[Index] = AllocateZeroPool (OptionSize);
  182. if (DstCfg->OptionList[Index] == NULL) {
  183. //
  184. // Error will be handled out of this function.
  185. //
  186. return EFI_OUT_OF_RESOURCES;
  187. }
  188. CopyMem (
  189. DstCfg->OptionList[Index],
  190. SorCfg->OptionList[Index],
  191. OptionSize
  192. );
  193. }
  194. }
  195. return EFI_SUCCESS;
  196. }
  197. /**
  198. Clean up the configure data.
  199. @param[in, out] CfgData The pointer to the configure data.
  200. **/
  201. VOID
  202. Dhcp6CleanupConfigData (
  203. IN OUT EFI_DHCP6_CONFIG_DATA *CfgData
  204. )
  205. {
  206. UINTN Index;
  207. ASSERT (CfgData != NULL);
  208. //
  209. // Clean up all fields in config data including the reference buffers, but do
  210. // not free the config data buffer itself.
  211. //
  212. if (CfgData->OptionList != NULL) {
  213. for (Index = 0; Index < CfgData->OptionCount; Index++) {
  214. if (CfgData->OptionList[Index] != NULL) {
  215. FreePool (CfgData->OptionList[Index]);
  216. }
  217. }
  218. FreePool (CfgData->OptionList);
  219. }
  220. if (CfgData->SolicitRetransmission != NULL) {
  221. FreePool (CfgData->SolicitRetransmission);
  222. }
  223. ZeroMem (CfgData, sizeof (EFI_DHCP6_CONFIG_DATA));
  224. }
  225. /**
  226. Clean up the mode data.
  227. @param[in, out] ModeData The pointer to the mode data.
  228. **/
  229. VOID
  230. Dhcp6CleanupModeData (
  231. IN OUT EFI_DHCP6_MODE_DATA *ModeData
  232. )
  233. {
  234. ASSERT (ModeData != NULL);
  235. //
  236. // Clean up all fields in mode data including the reference buffers, but do
  237. // not free the mode data buffer itself.
  238. //
  239. if (ModeData->ClientId != NULL) {
  240. FreePool (ModeData->ClientId);
  241. }
  242. if (ModeData->Ia != NULL) {
  243. if (ModeData->Ia->ReplyPacket != NULL) {
  244. FreePool (ModeData->Ia->ReplyPacket);
  245. }
  246. FreePool (ModeData->Ia);
  247. }
  248. ZeroMem (ModeData, sizeof (EFI_DHCP6_MODE_DATA));
  249. }
  250. /**
  251. Calculate the expire time by the algorithm defined in rfc.
  252. @param[in] Base The base value of the time.
  253. @param[in] IsFirstRt If TRUE, it is the first time to calculate expire time.
  254. @param[in] NeedSigned If TRUE, the the signed factor is needed.
  255. @return Expire The calculated result for the new expire time.
  256. **/
  257. UINT32
  258. Dhcp6CalculateExpireTime (
  259. IN UINT32 Base,
  260. IN BOOLEAN IsFirstRt,
  261. IN BOOLEAN NeedSigned
  262. )
  263. {
  264. EFI_TIME Time;
  265. BOOLEAN Signed;
  266. UINT32 Seed;
  267. UINT32 Expire;
  268. //
  269. // Take the 10bits of microsecond in system time as a uniform distribution.
  270. // Take the 10th bit as a flag to determine it's signed or not.
  271. //
  272. gRT->GetTime (&Time, NULL);
  273. Seed = ((Time.Nanosecond >> 10) & DHCP6_10_BIT_MASK);
  274. Signed = (BOOLEAN) ((((Time.Nanosecond >> 9) & 0x01) != 0) ? TRUE : FALSE);
  275. Signed = (BOOLEAN) (NeedSigned ? Signed : FALSE);
  276. //
  277. // Calculate expire by the following algo:
  278. // 1. base + base * (-0.1 ~ 0) for the first solicit
  279. // 2. base + base * (-0.1 ~ 0.1) for the first other messages
  280. // 3. 2 * base + base * (-0.1 ~ 0.1) for the subsequent all messages
  281. // 4. base + base * (-0.1 ~ 0) for the more than mrt timeout
  282. //
  283. // The (Seed / 0x3ff / 10) is used to a random range (0, 0.1).
  284. //
  285. if (IsFirstRt && Signed) {
  286. Expire = Base - (UINT32) (Base * Seed / DHCP6_10_BIT_MASK / 10);
  287. } else if (IsFirstRt && !Signed) {
  288. Expire = Base + (UINT32) (Base * Seed / DHCP6_10_BIT_MASK / 10);
  289. } else if (!IsFirstRt && Signed) {
  290. Expire = 2 * Base - (UINT32) (Base * Seed / DHCP6_10_BIT_MASK / 10);
  291. } else {
  292. Expire = 2 * Base + (UINT32) (Base * Seed / DHCP6_10_BIT_MASK / 10);
  293. }
  294. Expire = (Expire != 0) ? Expire : 1;
  295. return Expire;
  296. }
  297. /**
  298. Calculate the lease time by the algorithm defined in rfc.
  299. @param[in] IaCb The pointer to the Ia control block.
  300. **/
  301. VOID
  302. Dhcp6CalculateLeaseTime (
  303. IN DHCP6_IA_CB *IaCb
  304. )
  305. {
  306. UINT32 MinLt;
  307. UINT32 MaxLt;
  308. UINTN Index;
  309. ASSERT (IaCb->Ia->IaAddressCount > 0);
  310. MinLt = (UINT32) (-1);
  311. MaxLt = 0;
  312. //
  313. // Calculate minlt as min of all valid life time, and maxlt as max of all
  314. // valid life time.
  315. //
  316. for (Index = 0; Index < IaCb->Ia->IaAddressCount; Index++) {
  317. MinLt = MIN (MinLt, IaCb->Ia->IaAddress[Index].ValidLifetime);
  318. MaxLt = MAX (MinLt, IaCb->Ia->IaAddress[Index].ValidLifetime);
  319. }
  320. //
  321. // Take 50% minlt as t1, and 80% maxlt as t2 if Dhcp6 server doesn't offer
  322. // such information.
  323. //
  324. IaCb->T1 = (IaCb->T1 != 0) ? IaCb->T1 : (UINT32)(MinLt * 5 / 10);
  325. IaCb->T2 = (IaCb->T2 != 0) ? IaCb->T2 : (UINT32)(MinLt * 8 / 10);
  326. IaCb->AllExpireTime = MaxLt;
  327. IaCb->LeaseTime = 0;
  328. }
  329. /**
  330. Check whether the addresses are all included by the configured Ia.
  331. @param[in] Ia The pointer to the Ia.
  332. @param[in] AddressCount The number of addresses.
  333. @param[in] Addresses The pointer to the addresses buffer.
  334. @retval EFI_SUCCESS The addresses are all included by the configured IA.
  335. @retval EFI_NOT_FOUND The addresses are not included by the configured IA.
  336. **/
  337. EFI_STATUS
  338. Dhcp6CheckAddress (
  339. IN EFI_DHCP6_IA *Ia,
  340. IN UINT32 AddressCount,
  341. IN EFI_IPv6_ADDRESS *Addresses
  342. )
  343. {
  344. UINTN Index1;
  345. UINTN Index2;
  346. BOOLEAN Found;
  347. //
  348. // Check whether the addresses are all included by the configured IA. And it
  349. // will return success if address count is zero, which means all addresses.
  350. //
  351. for (Index1 = 0; Index1 < AddressCount; Index1++) {
  352. Found = FALSE;
  353. for (Index2 = 0; Index2 < Ia->IaAddressCount; Index2++) {
  354. if (CompareMem (
  355. &Addresses[Index1],
  356. &Ia->IaAddress[Index2],
  357. sizeof (EFI_IPv6_ADDRESS)
  358. ) == 0) {
  359. Found = TRUE;
  360. break;
  361. }
  362. }
  363. if (!Found) {
  364. return EFI_NOT_FOUND;
  365. }
  366. }
  367. return EFI_SUCCESS;
  368. }
  369. /**
  370. Deprive the addresses from current Ia, and generate another eliminated Ia.
  371. @param[in] Ia The pointer to the Ia.
  372. @param[in] AddressCount The number of addresses.
  373. @param[in] Addresses The pointer to the addresses buffer.
  374. @retval NULL If it failed to generate the deprived Ia.
  375. @retval others The pointer to the deprived Ia.
  376. **/
  377. EFI_DHCP6_IA *
  378. Dhcp6DepriveAddress (
  379. IN EFI_DHCP6_IA *Ia,
  380. IN UINT32 AddressCount,
  381. IN EFI_IPv6_ADDRESS *Addresses
  382. )
  383. {
  384. EFI_DHCP6_IA *IaCopy;
  385. UINTN IaCopySize;
  386. UINTN Index1;
  387. UINTN Index2;
  388. BOOLEAN Found;
  389. if (AddressCount == 0) {
  390. //
  391. // It means release all Ia addresses if address count is zero.
  392. //
  393. AddressCount = Ia->IaAddressCount;
  394. }
  395. ASSERT (AddressCount != 0);
  396. IaCopySize = sizeof (EFI_DHCP6_IA) + (AddressCount - 1) * sizeof (EFI_DHCP6_IA_ADDRESS);
  397. IaCopy = AllocateZeroPool (IaCopySize);
  398. if (IaCopy == NULL) {
  399. return NULL;
  400. }
  401. if (AddressCount == Ia->IaAddressCount) {
  402. //
  403. // If release all Ia addresses, just copy the configured Ia and then set
  404. // its address count as zero.
  405. // We may decline/release part of addresses at the begining. So it's a
  406. // forwarding step to update address infor for decline/release, while the
  407. // other infor such as Ia state will be updated when receiving reply.
  408. //
  409. CopyMem (IaCopy, Ia, IaCopySize);
  410. Ia->IaAddressCount = 0;
  411. return IaCopy;
  412. }
  413. CopyMem (IaCopy, Ia, sizeof (EFI_DHCP6_IA));
  414. //
  415. // Move the addresses from the Ia of instance to the deprived Ia.
  416. //
  417. for (Index1 = 0; Index1 < AddressCount; Index1++) {
  418. Found = FALSE;
  419. for (Index2 = 0; Index2 < Ia->IaAddressCount; Index2++) {
  420. if (CompareMem (
  421. &Addresses[Index1],
  422. &Ia->IaAddress[Index2],
  423. sizeof (EFI_IPv6_ADDRESS)
  424. ) == 0) {
  425. //
  426. // Copy the deprived address to the copy of Ia
  427. //
  428. CopyMem (
  429. &IaCopy->IaAddress[Index1],
  430. &Ia->IaAddress[Index2],
  431. sizeof (EFI_DHCP6_IA_ADDRESS)
  432. );
  433. //
  434. // Delete the deprived address from the instance Ia
  435. //
  436. if (Index2 + 1 < Ia->IaAddressCount) {
  437. CopyMem (
  438. &Ia->IaAddress[Index2],
  439. &Ia->IaAddress[Index2 + 1],
  440. (Ia->IaAddressCount - Index2 - 1) * sizeof (EFI_DHCP6_IA_ADDRESS)
  441. );
  442. }
  443. Found = TRUE;
  444. break;
  445. }
  446. }
  447. ASSERT (Found == TRUE);
  448. }
  449. Ia->IaAddressCount -= AddressCount;
  450. IaCopy->IaAddressCount = AddressCount;
  451. return IaCopy;
  452. }
  453. /**
  454. The dummy ext buffer free callback routine.
  455. @param[in] Arg The pointer to the parameter.
  456. **/
  457. VOID
  458. EFIAPI
  459. Dhcp6DummyExtFree (
  460. IN VOID *Arg
  461. )
  462. {
  463. }
  464. /**
  465. The callback routine once message transmitted.
  466. @param[in] Wrap The pointer to the received net buffer.
  467. @param[in] EndPoint The pointer to the udp end point.
  468. @param[in] IoStatus The return status from udp io.
  469. @param[in] Context The opaque parameter to the function.
  470. **/
  471. VOID
  472. EFIAPI
  473. Dhcp6OnTransmitted (
  474. IN NET_BUF *Wrap,
  475. IN UDP_END_POINT *EndPoint,
  476. IN EFI_STATUS IoStatus,
  477. IN VOID *Context
  478. )
  479. {
  480. NetbufFree (Wrap);
  481. }
  482. /**
  483. Append the option to Buf, and move Buf to the end.
  484. @param[in, out] Buf The pointer to the buffer.
  485. @param[in] OptType The option type.
  486. @param[in] OptLen The length of option contents.
  487. @param[in] Data The pointer to the option content.
  488. @return Buf The position to append the next option.
  489. **/
  490. UINT8 *
  491. Dhcp6AppendOption (
  492. IN OUT UINT8 *Buf,
  493. IN UINT16 OptType,
  494. IN UINT16 OptLen,
  495. IN UINT8 *Data
  496. )
  497. {
  498. //
  499. // The format of Dhcp6 option:
  500. //
  501. // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  502. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  503. // | option-code | option-len (option data) |
  504. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  505. // | option-data |
  506. // | (option-len octets) |
  507. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  508. //
  509. ASSERT (OptLen != 0);
  510. WriteUnaligned16 ((UINT16 *) Buf, OptType);
  511. Buf += 2;
  512. WriteUnaligned16 ((UINT16 *) Buf, OptLen);
  513. Buf += 2;
  514. CopyMem (Buf, Data, NTOHS (OptLen));
  515. Buf += NTOHS (OptLen);
  516. return Buf;
  517. }
  518. /**
  519. Append the appointed IA Address option to Buf, and move Buf to the end.
  520. @param[in, out] Buf The pointer to the position to append.
  521. @param[in] IaAddr The pointer to the IA Address.
  522. @param[in] MessageType Message type of DHCP6 package.
  523. @return Buf The position to append the next option.
  524. **/
  525. UINT8 *
  526. Dhcp6AppendIaAddrOption (
  527. IN OUT UINT8 *Buf,
  528. IN EFI_DHCP6_IA_ADDRESS *IaAddr,
  529. IN UINT32 MessageType
  530. )
  531. {
  532. // The format of the IA Address option is:
  533. //
  534. // 0 1 2 3
  535. // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  536. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  537. // | OPTION_IAADDR | option-len |
  538. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  539. // | |
  540. // | IPv6 address |
  541. // | |
  542. // | |
  543. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  544. // | preferred-lifetime |
  545. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  546. // | valid-lifetime |
  547. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  548. // . .
  549. // . IAaddr-options .
  550. // . .
  551. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  552. //
  553. // Fill the value of Ia Address option type
  554. //
  555. WriteUnaligned16 ((UINT16 *) Buf, HTONS (Dhcp6OptIaAddr));
  556. Buf += 2;
  557. WriteUnaligned16 ((UINT16 *) Buf, HTONS (sizeof (EFI_DHCP6_IA_ADDRESS)));
  558. Buf += 2;
  559. CopyMem (Buf, &IaAddr->IpAddress, sizeof(EFI_IPv6_ADDRESS));
  560. Buf += sizeof(EFI_IPv6_ADDRESS);
  561. //
  562. // Fill the value of preferred-lifetime and valid-lifetime.
  563. // According to RFC3315 Chapter 18.1.2, the preferred-lifetime and valid-lifetime fields
  564. // should set to 0 when initiate a Confirm message.
  565. //
  566. if (MessageType != Dhcp6MsgConfirm) {
  567. WriteUnaligned32 ((UINT32 *) Buf, HTONL (IaAddr->PreferredLifetime));
  568. }
  569. Buf += 4;
  570. if (MessageType != Dhcp6MsgConfirm) {
  571. WriteUnaligned32 ((UINT32 *) Buf, HTONL (IaAddr->ValidLifetime));
  572. }
  573. Buf += 4;
  574. return Buf;
  575. }
  576. /**
  577. Append the appointed Ia option to Buf, and move Buf to the end.
  578. @param[in, out] Buf The pointer to the position to append.
  579. @param[in] Ia The pointer to the Ia.
  580. @param[in] T1 The time of T1.
  581. @param[in] T2 The time of T2.
  582. @param[in] MessageType Message type of DHCP6 package.
  583. @return Buf The position to append the next Ia option.
  584. **/
  585. UINT8 *
  586. Dhcp6AppendIaOption (
  587. IN OUT UINT8 *Buf,
  588. IN EFI_DHCP6_IA *Ia,
  589. IN UINT32 T1,
  590. IN UINT32 T2,
  591. IN UINT32 MessageType
  592. )
  593. {
  594. UINT8 *AddrOpt;
  595. UINT16 *Len;
  596. UINTN Index;
  597. //
  598. // The format of IA_NA and IA_TA option:
  599. //
  600. // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  601. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  602. // | OPTION_IA_NA | option-len |
  603. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  604. // | IAID (4 octets) |
  605. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  606. // | T1 (only for IA_NA) |
  607. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  608. // | T2 (only for IA_NA) |
  609. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  610. // | |
  611. // . IA_NA-options/IA_TA-options .
  612. // . .
  613. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  614. //
  615. //
  616. // Fill the value of Ia option type
  617. //
  618. WriteUnaligned16 ((UINT16 *) Buf, HTONS (Ia->Descriptor.Type));
  619. Buf += 2;
  620. //
  621. // Fill the len of Ia option later, keep the pointer first
  622. //
  623. Len = (UINT16 *) Buf;
  624. Buf += 2;
  625. //
  626. // Fill the value of iaid
  627. //
  628. WriteUnaligned32 ((UINT32 *) Buf, HTONL (Ia->Descriptor.IaId));
  629. Buf += 4;
  630. //
  631. // Fill the value of t1 and t2 if iana, keep it 0xffffffff if no specified.
  632. //
  633. if (Ia->Descriptor.Type == Dhcp6OptIana) {
  634. WriteUnaligned32 ((UINT32 *) Buf, HTONL ((T1 != 0) ? T1 : 0xffffffff));
  635. Buf += 4;
  636. WriteUnaligned32 ((UINT32 *) Buf, HTONL ((T2 != 0) ? T2 : 0xffffffff));
  637. Buf += 4;
  638. }
  639. //
  640. // Fill all the addresses belong to the Ia
  641. //
  642. for (Index = 0; Index < Ia->IaAddressCount; Index++) {
  643. AddrOpt = (UINT8 *) Ia->IaAddress + Index * sizeof (EFI_DHCP6_IA_ADDRESS);
  644. Buf = Dhcp6AppendIaAddrOption (Buf, (EFI_DHCP6_IA_ADDRESS *) AddrOpt, MessageType);
  645. }
  646. //
  647. // Fill the value of Ia option length
  648. //
  649. *Len = HTONS ((UINT16) (Buf - (UINT8 *) Len - 2));
  650. return Buf;
  651. }
  652. /**
  653. Append the appointed Elapsed time option to Buf, and move Buf to the end.
  654. @param[in, out] Buf The pointer to the position to append.
  655. @param[in] Instance The pointer to the Dhcp6 instance.
  656. @param[out] Elapsed The pointer to the elapsed time value in
  657. the generated packet.
  658. @return Buf The position to append the next Ia option.
  659. **/
  660. UINT8 *
  661. Dhcp6AppendETOption (
  662. IN OUT UINT8 *Buf,
  663. IN DHCP6_INSTANCE *Instance,
  664. OUT UINT16 **Elapsed
  665. )
  666. {
  667. //
  668. // The format of elapsed time option:
  669. //
  670. // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  671. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  672. // | OPTION_ELAPSED_TIME | option-len |
  673. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  674. // | elapsed-time |
  675. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  676. //
  677. //
  678. // Fill the value of elapsed-time option type.
  679. //
  680. WriteUnaligned16 ((UINT16 *) Buf, HTONS (Dhcp6OptElapsedTime));
  681. Buf += 2;
  682. //
  683. // Fill the len of elapsed-time option, which is fixed.
  684. //
  685. WriteUnaligned16 ((UINT16 *) Buf, HTONS(2));
  686. Buf += 2;
  687. //
  688. // Fill in elapsed time value with 0 value for now. The actual value is
  689. // filled in later just before the packet is transmitted.
  690. //
  691. WriteUnaligned16 ((UINT16 *) Buf, HTONS(0));
  692. *Elapsed = (UINT16 *) Buf;
  693. Buf += 2;
  694. return Buf;
  695. }
  696. /**
  697. Set the elapsed time based on the given instance and the pointer to the
  698. elapsed time option.
  699. @param[in] Elapsed The pointer to the position to append.
  700. @param[in] Instance The pointer to the Dhcp6 instance.
  701. **/
  702. VOID
  703. SetElapsedTime (
  704. IN UINT16 *Elapsed,
  705. IN DHCP6_INSTANCE *Instance
  706. )
  707. {
  708. EFI_TIME Time;
  709. UINT64 CurrentStamp;
  710. UINT64 ElapsedTimeValue;
  711. //
  712. // Generate a time stamp of the centiseconds from 2000/1/1, assume 30day/month.
  713. //
  714. gRT->GetTime (&Time, NULL);
  715. CurrentStamp = MultU64x32 (
  716. ((((UINT32)(Time.Year - 2000) * 360 + (Time.Month - 1) * 30 + (Time.Day - 1)) * 24 + Time.Hour) * 60 + Time.Minute) * 60 + Time.Second,
  717. 100
  718. ) +
  719. DivU64x32(
  720. Time.Nanosecond,
  721. 10000000
  722. );
  723. //
  724. // Sentinel value of 0 means that this is the first DHCP packet that we are
  725. // sending and that we need to initialize the value. First DHCP message
  726. // gets 0 elapsed-time. Otherwise, calculate based on StartTime.
  727. //
  728. if (Instance->StartTime == 0) {
  729. ElapsedTimeValue = 0;
  730. Instance->StartTime = CurrentStamp;
  731. } else {
  732. ElapsedTimeValue = CurrentStamp - Instance->StartTime;
  733. //
  734. // If elapsed time cannot fit in two bytes, set it to 0xffff.
  735. //
  736. if (ElapsedTimeValue > 0xffff) {
  737. ElapsedTimeValue = 0xffff;
  738. }
  739. }
  740. WriteUnaligned16 (Elapsed, HTONS((UINT16) ElapsedTimeValue));
  741. }
  742. /**
  743. Seek the address of the first byte of the option header.
  744. @param[in] Buf The pointer to the buffer.
  745. @param[in] SeekLen The length to seek.
  746. @param[in] OptType The option type.
  747. @retval NULL If it failed to seek the option.
  748. @retval others The position to the option.
  749. **/
  750. UINT8 *
  751. Dhcp6SeekOption (
  752. IN UINT8 *Buf,
  753. IN UINT32 SeekLen,
  754. IN UINT16 OptType
  755. )
  756. {
  757. UINT8 *Cursor;
  758. UINT8 *Option;
  759. UINT16 DataLen;
  760. UINT16 OpCode;
  761. Option = NULL;
  762. Cursor = Buf;
  763. //
  764. // The format of Dhcp6 option refers to Dhcp6AppendOption().
  765. //
  766. while (Cursor < Buf + SeekLen) {
  767. OpCode = ReadUnaligned16 ((UINT16 *) Cursor);
  768. if (OpCode == HTONS (OptType)) {
  769. Option = Cursor;
  770. break;
  771. }
  772. DataLen = NTOHS (ReadUnaligned16 ((UINT16 *) (Cursor + 2)));
  773. Cursor += (DataLen + 4);
  774. }
  775. return Option;
  776. }
  777. /**
  778. Seek the address of the first byte of the Ia option header.
  779. @param[in] Buf The pointer to the buffer.
  780. @param[in] SeekLen The length to seek.
  781. @param[in] IaDesc The pointer to the Ia descriptor.
  782. @retval NULL If it failed to seek the Ia option.
  783. @retval others The position to the Ia option.
  784. **/
  785. UINT8 *
  786. Dhcp6SeekIaOption (
  787. IN UINT8 *Buf,
  788. IN UINT32 SeekLen,
  789. IN EFI_DHCP6_IA_DESCRIPTOR *IaDesc
  790. )
  791. {
  792. UINT8 *Cursor;
  793. UINT8 *Option;
  794. UINT16 DataLen;
  795. UINT16 OpCode;
  796. UINT32 IaId;
  797. //
  798. // The format of IA_NA and IA_TA option refers to Dhcp6AppendIaOption().
  799. //
  800. Option = NULL;
  801. Cursor = Buf;
  802. while (Cursor < Buf + SeekLen) {
  803. OpCode = ReadUnaligned16 ((UINT16 *) Cursor);
  804. IaId = ReadUnaligned32 ((UINT32 *) (Cursor + 4));
  805. if (OpCode == HTONS (IaDesc->Type) && IaId == HTONL (IaDesc->IaId)) {
  806. Option = Cursor;
  807. break;
  808. }
  809. DataLen = NTOHS (ReadUnaligned16 ((UINT16 *) (Cursor + 2)));
  810. Cursor += (DataLen + 4);
  811. }
  812. return Option;
  813. }
  814. /**
  815. Check whether the incoming IPv6 address in IaAddr is one of the maintained
  816. addresses in the IA control blcok.
  817. @param[in] IaAddr The pointer to the IA Address to be checked.
  818. @param[in] CurrentIa The pointer to the IA in IA control block.
  819. @retval TRUE Yes, this Address is already in IA control block.
  820. @retval FALSE No, this Address is NOT in IA control block.
  821. **/
  822. BOOLEAN
  823. Dhcp6AddrIsInCurrentIa (
  824. IN EFI_DHCP6_IA_ADDRESS *IaAddr,
  825. IN EFI_DHCP6_IA *CurrentIa
  826. )
  827. {
  828. UINT32 Index;
  829. ASSERT (IaAddr != NULL && CurrentIa != NULL);
  830. for (Index = 0; Index < CurrentIa->IaAddressCount; Index++) {
  831. if (EFI_IP6_EQUAL(&IaAddr->IpAddress, &CurrentIa->IaAddress[Index].IpAddress)) {
  832. return TRUE;
  833. }
  834. }
  835. return FALSE;
  836. }
  837. /**
  838. Parse the address option and update the address infomation.
  839. @param[in] CurrentIa The pointer to the Ia Address in control blcok.
  840. @param[in] IaInnerOpt The pointer to the buffer.
  841. @param[in] IaInnerLen The length to parse.
  842. @param[out] AddrNum The number of addresses.
  843. @param[in, out] AddrBuf The pointer to the address buffer.
  844. **/
  845. VOID
  846. Dhcp6ParseAddrOption (
  847. IN EFI_DHCP6_IA *CurrentIa,
  848. IN UINT8 *IaInnerOpt,
  849. IN UINT16 IaInnerLen,
  850. OUT UINT32 *AddrNum,
  851. IN OUT EFI_DHCP6_IA_ADDRESS *AddrBuf
  852. )
  853. {
  854. UINT8 *Cursor;
  855. UINT16 DataLen;
  856. UINT16 OpCode;
  857. UINT32 ValidLt;
  858. UINT32 PreferredLt;
  859. EFI_DHCP6_IA_ADDRESS *IaAddr;
  860. //
  861. // The format of the IA Address option:
  862. //
  863. // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  864. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  865. // | OPTION_IAADDR | option-len |
  866. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  867. // | |
  868. // | IPv6 address |
  869. // | |
  870. // | |
  871. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  872. // | preferred-lifetime |
  873. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  874. // | valid-lifetime |
  875. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  876. // . .
  877. // . IAaddr-options .
  878. // . .
  879. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  880. //
  881. //
  882. // Two usage model:
  883. //
  884. // 1. Pass addrbuf == null, to get the addrnum over the Ia inner options.
  885. // 2. Pass addrbuf != null, to resolve the addresses over the Ia inner
  886. // options to the addrbuf.
  887. //
  888. Cursor = IaInnerOpt;
  889. *AddrNum = 0;
  890. while (Cursor < IaInnerOpt + IaInnerLen) {
  891. //
  892. // Refer to RFC3315 Chapter 18.1.8, we need to update lifetimes for any addresses in the IA option
  893. // that the client already has recorded in the IA, and discard the Ia address option with 0 valid time.
  894. //
  895. OpCode = ReadUnaligned16 ((UINT16 *) Cursor);
  896. PreferredLt = NTOHL (ReadUnaligned32 ((UINT32 *) (Cursor + 20)));
  897. ValidLt = NTOHL (ReadUnaligned32 ((UINT32 *) (Cursor + 24)));
  898. IaAddr = (EFI_DHCP6_IA_ADDRESS *) (Cursor + 4);
  899. if (OpCode == HTONS (Dhcp6OptIaAddr) && ValidLt >= PreferredLt &&
  900. (Dhcp6AddrIsInCurrentIa(IaAddr, CurrentIa) || ValidLt !=0)) {
  901. if (AddrBuf != NULL) {
  902. CopyMem (AddrBuf, IaAddr, sizeof (EFI_DHCP6_IA_ADDRESS));
  903. AddrBuf->PreferredLifetime = PreferredLt;
  904. AddrBuf->ValidLifetime = ValidLt;
  905. AddrBuf = (EFI_DHCP6_IA_ADDRESS *) ((UINT8 *) AddrBuf + sizeof (EFI_DHCP6_IA_ADDRESS));
  906. }
  907. (*AddrNum)++;
  908. }
  909. DataLen = NTOHS (ReadUnaligned16 ((UINT16 *) (Cursor + 2)));
  910. Cursor += (DataLen + 4);
  911. }
  912. }
  913. /**
  914. Create a control blcok for the Ia according to the corresponding options.
  915. @param[in] Instance The pointer to DHCP6 Instance.
  916. @param[in] IaInnerOpt The pointer to the inner options in the Ia option.
  917. @param[in] IaInnerLen The length of all the inner options in the Ia option.
  918. @param[in] T1 T1 time in the Ia option.
  919. @param[in] T2 T2 time in the Ia option.
  920. @retval EFI_NOT_FOUND No valid IA option is found.
  921. @retval EFI_SUCCESS Create an IA control block successfully.
  922. @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
  923. @retval EFI_DEVICE_ERROR An unexpected error.
  924. **/
  925. EFI_STATUS
  926. Dhcp6GenerateIaCb (
  927. IN DHCP6_INSTANCE *Instance,
  928. IN UINT8 *IaInnerOpt,
  929. IN UINT16 IaInnerLen,
  930. IN UINT32 T1,
  931. IN UINT32 T2
  932. )
  933. {
  934. UINT32 AddrNum;
  935. UINT32 IaSize;
  936. EFI_DHCP6_IA *Ia;
  937. if (Instance->IaCb.Ia == NULL) {
  938. return EFI_DEVICE_ERROR;
  939. }
  940. //
  941. // Calculate the number of addresses for this Ia, excluding the addresses with
  942. // the value 0 of valid lifetime.
  943. //
  944. Dhcp6ParseAddrOption (Instance->IaCb.Ia, IaInnerOpt, IaInnerLen, &AddrNum, NULL);
  945. if (AddrNum == 0) {
  946. return EFI_NOT_FOUND;
  947. }
  948. //
  949. // Allocate for new IA.
  950. //
  951. IaSize = sizeof (EFI_DHCP6_IA) + (AddrNum - 1) * sizeof (EFI_DHCP6_IA_ADDRESS);
  952. Ia = AllocateZeroPool (IaSize);
  953. if (Ia == NULL) {
  954. return EFI_OUT_OF_RESOURCES;
  955. }
  956. //
  957. // Fill up this new IA fields.
  958. //
  959. Ia->State = Instance->IaCb.Ia->State;
  960. Ia->IaAddressCount = AddrNum;
  961. CopyMem (&Ia->Descriptor, &Instance->Config->IaDescriptor, sizeof (EFI_DHCP6_IA_DESCRIPTOR));
  962. Dhcp6ParseAddrOption (Instance->IaCb.Ia, IaInnerOpt, IaInnerLen, &AddrNum, Ia->IaAddress);
  963. //
  964. // Free original IA resource.
  965. //
  966. if (Instance->IaCb.Ia->ReplyPacket != NULL) {
  967. FreePool (Instance->IaCb.Ia->ReplyPacket);
  968. }
  969. FreePool (Instance->IaCb.Ia);
  970. ZeroMem (&Instance->IaCb, sizeof (DHCP6_IA_CB));
  971. //
  972. // Update IaCb to use new IA.
  973. //
  974. Instance->IaCb.Ia = Ia;
  975. //
  976. // Fill in IaCb fields. Such as T1, T2, AllExpireTime and LeaseTime.
  977. //
  978. Instance->IaCb.T1 = T1;
  979. Instance->IaCb.T2 = T2;
  980. Dhcp6CalculateLeaseTime (&Instance->IaCb);
  981. return EFI_SUCCESS;
  982. }
  983. /**
  984. Cache the current IA configuration information.
  985. @param[in] Instance The pointer to DHCP6 Instance.
  986. @retval EFI_SUCCESS Cache the current IA successfully.
  987. @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
  988. **/
  989. EFI_STATUS
  990. Dhcp6CacheIa (
  991. IN DHCP6_INSTANCE *Instance
  992. )
  993. {
  994. UINTN IaSize;
  995. EFI_DHCP6_IA *Ia;
  996. Ia = Instance->IaCb.Ia;
  997. if ((Instance->CacheIa == NULL) && (Ia != NULL)) {
  998. //
  999. // Cache the current IA.
  1000. //
  1001. IaSize = sizeof (EFI_DHCP6_IA) + (Ia->IaAddressCount - 1) * sizeof (EFI_DHCP6_IA_ADDRESS);
  1002. Instance->CacheIa = AllocateZeroPool (IaSize);
  1003. if (Instance->CacheIa == NULL) {
  1004. return EFI_OUT_OF_RESOURCES;
  1005. }
  1006. CopyMem (Instance->CacheIa, Ia, IaSize);
  1007. }
  1008. return EFI_SUCCESS;
  1009. }
  1010. /**
  1011. Append CacheIa to the currrent IA. Meanwhile, clear CacheIa.ValidLifetime to 0.
  1012. @param[in] Instance The pointer to DHCP6 instance.
  1013. **/
  1014. VOID
  1015. Dhcp6AppendCacheIa (
  1016. IN DHCP6_INSTANCE *Instance
  1017. )
  1018. {
  1019. UINT8 *Ptr;
  1020. UINTN Index;
  1021. UINTN IaSize;
  1022. UINTN NewIaSize;
  1023. EFI_DHCP6_IA *Ia;
  1024. EFI_DHCP6_IA *NewIa;
  1025. EFI_DHCP6_IA *CacheIa;
  1026. Ia = Instance->IaCb.Ia;
  1027. CacheIa = Instance->CacheIa;
  1028. if ((CacheIa != NULL) && (CacheIa->IaAddressCount != 0)) {
  1029. //
  1030. // There are old addresses existing. Merge with current addresses.
  1031. //
  1032. NewIaSize = sizeof (EFI_DHCP6_IA) + (Ia->IaAddressCount + CacheIa->IaAddressCount - 1) * sizeof (EFI_DHCP6_IA_ADDRESS);
  1033. NewIa = AllocateZeroPool (NewIaSize);
  1034. if (NewIa == NULL) {
  1035. return;
  1036. }
  1037. IaSize = sizeof (EFI_DHCP6_IA) + (Ia->IaAddressCount - 1) * sizeof (EFI_DHCP6_IA_ADDRESS);
  1038. CopyMem (NewIa, Ia, IaSize);
  1039. //
  1040. // Clear old address.ValidLifetime
  1041. //
  1042. for (Index = 0; Index < CacheIa->IaAddressCount; Index++) {
  1043. CacheIa->IaAddress[Index].ValidLifetime = 0;
  1044. }
  1045. NewIa->IaAddressCount += CacheIa->IaAddressCount;
  1046. Ptr = (UINT8*)&NewIa->IaAddress[Ia->IaAddressCount];
  1047. CopyMem (Ptr, CacheIa->IaAddress, CacheIa->IaAddressCount * sizeof (EFI_DHCP6_IA_ADDRESS));
  1048. //
  1049. // Migrate to the NewIa and free previous.
  1050. //
  1051. FreePool (Instance->CacheIa);
  1052. FreePool (Instance->IaCb.Ia);
  1053. Instance->CacheIa = NULL;
  1054. Instance->IaCb.Ia = NewIa;
  1055. }
  1056. }
  1057. /**
  1058. Calculate the Dhcp6 get mapping timeout by adding additinal delay to the IP6 DAD transmits count.
  1059. @param[in] Ip6Cfg The pointer to Ip6 config protocol.
  1060. @param[out] TimeOut The time out value in 100ns units.
  1061. @retval EFI_INVALID_PARAMETER Input parameters are invalid.
  1062. @retval EFI_SUCCESS Calculate the time out value successfully.
  1063. **/
  1064. EFI_STATUS
  1065. Dhcp6GetMappingTimeOut (
  1066. IN EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg,
  1067. OUT UINTN *TimeOut
  1068. )
  1069. {
  1070. EFI_STATUS Status;
  1071. UINTN DataSize;
  1072. EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits;
  1073. if (Ip6Cfg == NULL || TimeOut == NULL) {
  1074. return EFI_INVALID_PARAMETER;
  1075. }
  1076. DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);
  1077. Status = Ip6Cfg->GetData (
  1078. Ip6Cfg,
  1079. Ip6ConfigDataTypeDupAddrDetectTransmits,
  1080. &DataSize,
  1081. &DadXmits
  1082. );
  1083. if (EFI_ERROR (Status)) {
  1084. return Status;
  1085. }
  1086. *TimeOut = TICKS_PER_SECOND * DadXmits.DupAddrDetectTransmits + DHCP6_DAD_ADDITIONAL_DELAY;
  1087. return EFI_SUCCESS;
  1088. }