Dhcp6Utility.c 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305
  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 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. {
  360. Found = TRUE;
  361. break;
  362. }
  363. }
  364. if (!Found) {
  365. return EFI_NOT_FOUND;
  366. }
  367. }
  368. return EFI_SUCCESS;
  369. }
  370. /**
  371. Deprive the addresses from current Ia, and generate another eliminated Ia.
  372. @param[in] Ia The pointer to the Ia.
  373. @param[in] AddressCount The number of addresses.
  374. @param[in] Addresses The pointer to the addresses buffer.
  375. @retval NULL If it failed to generate the deprived Ia.
  376. @retval others The pointer to the deprived Ia.
  377. **/
  378. EFI_DHCP6_IA *
  379. Dhcp6DepriveAddress (
  380. IN EFI_DHCP6_IA *Ia,
  381. IN UINT32 AddressCount,
  382. IN EFI_IPv6_ADDRESS *Addresses
  383. )
  384. {
  385. EFI_DHCP6_IA *IaCopy;
  386. UINTN IaCopySize;
  387. UINTN Index1;
  388. UINTN Index2;
  389. BOOLEAN Found;
  390. if (AddressCount == 0) {
  391. //
  392. // It means release all Ia addresses if address count is zero.
  393. //
  394. AddressCount = Ia->IaAddressCount;
  395. }
  396. ASSERT (AddressCount != 0);
  397. IaCopySize = sizeof (EFI_DHCP6_IA) + (AddressCount - 1) * sizeof (EFI_DHCP6_IA_ADDRESS);
  398. IaCopy = AllocateZeroPool (IaCopySize);
  399. if (IaCopy == NULL) {
  400. return NULL;
  401. }
  402. if (AddressCount == Ia->IaAddressCount) {
  403. //
  404. // If release all Ia addresses, just copy the configured Ia and then set
  405. // its address count as zero.
  406. // We may decline/release part of addresses at the beginning. So it's a
  407. // forwarding step to update address infor for decline/release, while the
  408. // other infor such as Ia state will be updated when receiving reply.
  409. //
  410. CopyMem (IaCopy, Ia, IaCopySize);
  411. Ia->IaAddressCount = 0;
  412. return IaCopy;
  413. }
  414. CopyMem (IaCopy, Ia, sizeof (EFI_DHCP6_IA));
  415. //
  416. // Move the addresses from the Ia of instance to the deprived Ia.
  417. //
  418. for (Index1 = 0; Index1 < AddressCount; Index1++) {
  419. Found = FALSE;
  420. for (Index2 = 0; Index2 < Ia->IaAddressCount; Index2++) {
  421. if (CompareMem (
  422. &Addresses[Index1],
  423. &Ia->IaAddress[Index2],
  424. sizeof (EFI_IPv6_ADDRESS)
  425. ) == 0)
  426. {
  427. //
  428. // Copy the deprived address to the copy of Ia
  429. //
  430. CopyMem (
  431. &IaCopy->IaAddress[Index1],
  432. &Ia->IaAddress[Index2],
  433. sizeof (EFI_DHCP6_IA_ADDRESS)
  434. );
  435. //
  436. // Delete the deprived address from the instance Ia
  437. //
  438. if (Index2 + 1 < Ia->IaAddressCount) {
  439. CopyMem (
  440. &Ia->IaAddress[Index2],
  441. &Ia->IaAddress[Index2 + 1],
  442. (Ia->IaAddressCount - Index2 - 1) * sizeof (EFI_DHCP6_IA_ADDRESS)
  443. );
  444. }
  445. Found = TRUE;
  446. break;
  447. }
  448. }
  449. ASSERT (Found == TRUE);
  450. }
  451. Ia->IaAddressCount -= AddressCount;
  452. IaCopy->IaAddressCount = AddressCount;
  453. return IaCopy;
  454. }
  455. /**
  456. The dummy ext buffer free callback routine.
  457. @param[in] Arg The pointer to the parameter.
  458. **/
  459. VOID
  460. EFIAPI
  461. Dhcp6DummyExtFree (
  462. IN VOID *Arg
  463. )
  464. {
  465. }
  466. /**
  467. The callback routine once message transmitted.
  468. @param[in] Wrap The pointer to the received net buffer.
  469. @param[in] EndPoint The pointer to the udp end point.
  470. @param[in] IoStatus The return status from udp io.
  471. @param[in] Context The opaque parameter to the function.
  472. **/
  473. VOID
  474. EFIAPI
  475. Dhcp6OnTransmitted (
  476. IN NET_BUF *Wrap,
  477. IN UDP_END_POINT *EndPoint,
  478. IN EFI_STATUS IoStatus,
  479. IN VOID *Context
  480. )
  481. {
  482. NetbufFree (Wrap);
  483. }
  484. /**
  485. Append the option to Buf, and move Buf to the end.
  486. @param[in, out] Buf The pointer to the buffer.
  487. @param[in] OptType The option type.
  488. @param[in] OptLen The length of option contents.
  489. @param[in] Data The pointer to the option content.
  490. @return Buf The position to append the next option.
  491. **/
  492. UINT8 *
  493. Dhcp6AppendOption (
  494. IN OUT UINT8 *Buf,
  495. IN UINT16 OptType,
  496. IN UINT16 OptLen,
  497. IN UINT8 *Data
  498. )
  499. {
  500. //
  501. // The format of Dhcp6 option:
  502. //
  503. // 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
  504. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  505. // | option-code | option-len (option data) |
  506. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  507. // | option-data |
  508. // | (option-len octets) |
  509. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  510. //
  511. ASSERT (OptLen != 0);
  512. WriteUnaligned16 ((UINT16 *)Buf, OptType);
  513. Buf += 2;
  514. WriteUnaligned16 ((UINT16 *)Buf, OptLen);
  515. Buf += 2;
  516. CopyMem (Buf, Data, NTOHS (OptLen));
  517. Buf += NTOHS (OptLen);
  518. return Buf;
  519. }
  520. /**
  521. Append the appointed IA Address option to Buf, and move Buf to the end.
  522. @param[in, out] Buf The pointer to the position to append.
  523. @param[in] IaAddr The pointer to the IA Address.
  524. @param[in] MessageType Message type of DHCP6 package.
  525. @return Buf The position to append the next option.
  526. **/
  527. UINT8 *
  528. Dhcp6AppendIaAddrOption (
  529. IN OUT UINT8 *Buf,
  530. IN EFI_DHCP6_IA_ADDRESS *IaAddr,
  531. IN UINT32 MessageType
  532. )
  533. {
  534. // The format of the IA Address option is:
  535. //
  536. // 0 1 2 3
  537. // 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
  538. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  539. // | OPTION_IAADDR | option-len |
  540. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  541. // | |
  542. // | IPv6 address |
  543. // | |
  544. // | |
  545. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  546. // | preferred-lifetime |
  547. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  548. // | valid-lifetime |
  549. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  550. // . .
  551. // . IAaddr-options .
  552. // . .
  553. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  554. //
  555. // Fill the value of Ia Address option type
  556. //
  557. WriteUnaligned16 ((UINT16 *)Buf, HTONS (Dhcp6OptIaAddr));
  558. Buf += 2;
  559. WriteUnaligned16 ((UINT16 *)Buf, HTONS (sizeof (EFI_DHCP6_IA_ADDRESS)));
  560. Buf += 2;
  561. CopyMem (Buf, &IaAddr->IpAddress, sizeof (EFI_IPv6_ADDRESS));
  562. Buf += sizeof (EFI_IPv6_ADDRESS);
  563. //
  564. // Fill the value of preferred-lifetime and valid-lifetime.
  565. // According to RFC3315 Chapter 18.1.2, the preferred-lifetime and valid-lifetime fields
  566. // should set to 0 when initiate a Confirm message.
  567. //
  568. if (MessageType != Dhcp6MsgConfirm) {
  569. WriteUnaligned32 ((UINT32 *)Buf, HTONL (IaAddr->PreferredLifetime));
  570. }
  571. Buf += 4;
  572. if (MessageType != Dhcp6MsgConfirm) {
  573. WriteUnaligned32 ((UINT32 *)Buf, HTONL (IaAddr->ValidLifetime));
  574. }
  575. Buf += 4;
  576. return Buf;
  577. }
  578. /**
  579. Append the appointed Ia option to Buf, and move Buf to the end.
  580. @param[in, out] Buf The pointer to the position to append.
  581. @param[in] Ia The pointer to the Ia.
  582. @param[in] T1 The time of T1.
  583. @param[in] T2 The time of T2.
  584. @param[in] MessageType Message type of DHCP6 package.
  585. @return Buf The position to append the next Ia option.
  586. **/
  587. UINT8 *
  588. Dhcp6AppendIaOption (
  589. IN OUT UINT8 *Buf,
  590. IN EFI_DHCP6_IA *Ia,
  591. IN UINT32 T1,
  592. IN UINT32 T2,
  593. IN UINT32 MessageType
  594. )
  595. {
  596. UINT8 *AddrOpt;
  597. UINT16 *Len;
  598. UINTN Index;
  599. //
  600. // The format of IA_NA and IA_TA option:
  601. //
  602. // 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
  603. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  604. // | OPTION_IA_NA | option-len |
  605. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  606. // | IAID (4 octets) |
  607. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  608. // | T1 (only for IA_NA) |
  609. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  610. // | T2 (only for IA_NA) |
  611. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  612. // | |
  613. // . IA_NA-options/IA_TA-options .
  614. // . .
  615. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  616. //
  617. //
  618. // Fill the value of Ia option type
  619. //
  620. WriteUnaligned16 ((UINT16 *)Buf, HTONS (Ia->Descriptor.Type));
  621. Buf += 2;
  622. //
  623. // Fill the len of Ia option later, keep the pointer first
  624. //
  625. Len = (UINT16 *)Buf;
  626. Buf += 2;
  627. //
  628. // Fill the value of iaid
  629. //
  630. WriteUnaligned32 ((UINT32 *)Buf, HTONL (Ia->Descriptor.IaId));
  631. Buf += 4;
  632. //
  633. // Fill the value of t1 and t2 if iana, keep it 0xffffffff if no specified.
  634. //
  635. if (Ia->Descriptor.Type == Dhcp6OptIana) {
  636. WriteUnaligned32 ((UINT32 *)Buf, HTONL ((T1 != 0) ? T1 : 0xffffffff));
  637. Buf += 4;
  638. WriteUnaligned32 ((UINT32 *)Buf, HTONL ((T2 != 0) ? T2 : 0xffffffff));
  639. Buf += 4;
  640. }
  641. //
  642. // Fill all the addresses belong to the Ia
  643. //
  644. for (Index = 0; Index < Ia->IaAddressCount; Index++) {
  645. AddrOpt = (UINT8 *)Ia->IaAddress + Index * sizeof (EFI_DHCP6_IA_ADDRESS);
  646. Buf = Dhcp6AppendIaAddrOption (Buf, (EFI_DHCP6_IA_ADDRESS *)AddrOpt, MessageType);
  647. }
  648. //
  649. // Fill the value of Ia option length
  650. //
  651. *Len = HTONS ((UINT16)(Buf - (UINT8 *)Len - 2));
  652. return Buf;
  653. }
  654. /**
  655. Append the appointed Elapsed time option to Buf, and move Buf to the end.
  656. @param[in, out] Buf The pointer to the position to append.
  657. @param[in] Instance The pointer to the Dhcp6 instance.
  658. @param[out] Elapsed The pointer to the elapsed time value in
  659. the generated packet.
  660. @return Buf The position to append the next Ia option.
  661. **/
  662. UINT8 *
  663. Dhcp6AppendETOption (
  664. IN OUT UINT8 *Buf,
  665. IN DHCP6_INSTANCE *Instance,
  666. OUT UINT16 **Elapsed
  667. )
  668. {
  669. //
  670. // The format of elapsed time option:
  671. //
  672. // 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
  673. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  674. // | OPTION_ELAPSED_TIME | option-len |
  675. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  676. // | elapsed-time |
  677. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  678. //
  679. //
  680. // Fill the value of elapsed-time option type.
  681. //
  682. WriteUnaligned16 ((UINT16 *)Buf, HTONS (Dhcp6OptElapsedTime));
  683. Buf += 2;
  684. //
  685. // Fill the len of elapsed-time option, which is fixed.
  686. //
  687. WriteUnaligned16 ((UINT16 *)Buf, HTONS (2));
  688. Buf += 2;
  689. //
  690. // Fill in elapsed time value with 0 value for now. The actual value is
  691. // filled in later just before the packet is transmitted.
  692. //
  693. WriteUnaligned16 ((UINT16 *)Buf, HTONS (0));
  694. *Elapsed = (UINT16 *)Buf;
  695. Buf += 2;
  696. return Buf;
  697. }
  698. /**
  699. Set the elapsed time based on the given instance and the pointer to the
  700. elapsed time option.
  701. @param[in] Elapsed The pointer to the position to append.
  702. @param[in] Instance The pointer to the Dhcp6 instance.
  703. **/
  704. VOID
  705. SetElapsedTime (
  706. IN UINT16 *Elapsed,
  707. IN DHCP6_INSTANCE *Instance
  708. )
  709. {
  710. EFI_TIME Time;
  711. UINT64 CurrentStamp;
  712. UINT64 ElapsedTimeValue;
  713. //
  714. // Generate a time stamp of the centiseconds from 2000/1/1, assume 30day/month.
  715. //
  716. gRT->GetTime (&Time, NULL);
  717. CurrentStamp = MultU64x32 (
  718. ((((UINT32)(Time.Year - 2000) * 360 + (Time.Month - 1) * 30 + (Time.Day - 1)) * 24 + Time.Hour) * 60 + Time.Minute) * 60 + Time.Second,
  719. 100
  720. ) +
  721. DivU64x32 (
  722. Time.Nanosecond,
  723. 10000000
  724. );
  725. //
  726. // Sentinel value of 0 means that this is the first DHCP packet that we are
  727. // sending and that we need to initialize the value. First DHCP message
  728. // gets 0 elapsed-time. Otherwise, calculate based on StartTime.
  729. //
  730. if (Instance->StartTime == 0) {
  731. ElapsedTimeValue = 0;
  732. Instance->StartTime = CurrentStamp;
  733. } else {
  734. ElapsedTimeValue = CurrentStamp - Instance->StartTime;
  735. //
  736. // If elapsed time cannot fit in two bytes, set it to 0xffff.
  737. //
  738. if (ElapsedTimeValue > 0xffff) {
  739. ElapsedTimeValue = 0xffff;
  740. }
  741. }
  742. WriteUnaligned16 (Elapsed, HTONS ((UINT16)ElapsedTimeValue));
  743. }
  744. /**
  745. Seek the address of the first byte of the option header.
  746. @param[in] Buf The pointer to the buffer.
  747. @param[in] SeekLen The length to seek.
  748. @param[in] OptType The option type.
  749. @retval NULL If it failed to seek the option.
  750. @retval others The position to the option.
  751. **/
  752. UINT8 *
  753. Dhcp6SeekOption (
  754. IN UINT8 *Buf,
  755. IN UINT32 SeekLen,
  756. IN UINT16 OptType
  757. )
  758. {
  759. UINT8 *Cursor;
  760. UINT8 *Option;
  761. UINT16 DataLen;
  762. UINT16 OpCode;
  763. Option = NULL;
  764. Cursor = Buf;
  765. //
  766. // The format of Dhcp6 option refers to Dhcp6AppendOption().
  767. //
  768. while (Cursor < Buf + SeekLen) {
  769. OpCode = ReadUnaligned16 ((UINT16 *)Cursor);
  770. if (OpCode == HTONS (OptType)) {
  771. Option = Cursor;
  772. break;
  773. }
  774. DataLen = NTOHS (ReadUnaligned16 ((UINT16 *)(Cursor + 2)));
  775. Cursor += (DataLen + 4);
  776. }
  777. return Option;
  778. }
  779. /**
  780. Seek the address of the first byte of the Ia option header.
  781. @param[in] Buf The pointer to the buffer.
  782. @param[in] SeekLen The length to seek.
  783. @param[in] IaDesc The pointer to the Ia descriptor.
  784. @retval NULL If it failed to seek the Ia option.
  785. @retval others The position to the Ia option.
  786. **/
  787. UINT8 *
  788. Dhcp6SeekIaOption (
  789. IN UINT8 *Buf,
  790. IN UINT32 SeekLen,
  791. IN EFI_DHCP6_IA_DESCRIPTOR *IaDesc
  792. )
  793. {
  794. UINT8 *Cursor;
  795. UINT8 *Option;
  796. UINT16 DataLen;
  797. UINT16 OpCode;
  798. UINT32 IaId;
  799. //
  800. // The format of IA_NA and IA_TA option refers to Dhcp6AppendIaOption().
  801. //
  802. Option = NULL;
  803. Cursor = Buf;
  804. while (Cursor < Buf + SeekLen) {
  805. OpCode = ReadUnaligned16 ((UINT16 *)Cursor);
  806. IaId = ReadUnaligned32 ((UINT32 *)(Cursor + 4));
  807. if ((OpCode == HTONS (IaDesc->Type)) && (IaId == HTONL (IaDesc->IaId))) {
  808. Option = Cursor;
  809. break;
  810. }
  811. DataLen = NTOHS (ReadUnaligned16 ((UINT16 *)(Cursor + 2)));
  812. Cursor += (DataLen + 4);
  813. }
  814. return Option;
  815. }
  816. /**
  817. Check whether the incoming IPv6 address in IaAddr is one of the maintained
  818. addresses in the IA control block.
  819. @param[in] IaAddr The pointer to the IA Address to be checked.
  820. @param[in] CurrentIa The pointer to the IA in IA control block.
  821. @retval TRUE Yes, this Address is already in IA control block.
  822. @retval FALSE No, this Address is NOT in IA control block.
  823. **/
  824. BOOLEAN
  825. Dhcp6AddrIsInCurrentIa (
  826. IN EFI_DHCP6_IA_ADDRESS *IaAddr,
  827. IN EFI_DHCP6_IA *CurrentIa
  828. )
  829. {
  830. UINT32 Index;
  831. ASSERT (IaAddr != NULL && CurrentIa != NULL);
  832. for (Index = 0; Index < CurrentIa->IaAddressCount; Index++) {
  833. if (EFI_IP6_EQUAL (&IaAddr->IpAddress, &CurrentIa->IaAddress[Index].IpAddress)) {
  834. return TRUE;
  835. }
  836. }
  837. return FALSE;
  838. }
  839. /**
  840. Parse the address option and update the address information.
  841. @param[in] CurrentIa The pointer to the Ia Address in control block.
  842. @param[in] IaInnerOpt The pointer to the buffer.
  843. @param[in] IaInnerLen The length to parse.
  844. @param[out] AddrNum The number of addresses.
  845. @param[in, out] AddrBuf The pointer to the address buffer.
  846. **/
  847. VOID
  848. Dhcp6ParseAddrOption (
  849. IN EFI_DHCP6_IA *CurrentIa,
  850. IN UINT8 *IaInnerOpt,
  851. IN UINT16 IaInnerLen,
  852. OUT UINT32 *AddrNum,
  853. IN OUT EFI_DHCP6_IA_ADDRESS *AddrBuf
  854. )
  855. {
  856. UINT8 *Cursor;
  857. UINT16 DataLen;
  858. UINT16 OpCode;
  859. UINT32 ValidLt;
  860. UINT32 PreferredLt;
  861. EFI_DHCP6_IA_ADDRESS *IaAddr;
  862. //
  863. // The format of the IA Address option:
  864. //
  865. // 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
  866. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  867. // | OPTION_IAADDR | option-len |
  868. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  869. // | |
  870. // | IPv6 address |
  871. // | |
  872. // | |
  873. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  874. // | preferred-lifetime |
  875. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  876. // | valid-lifetime |
  877. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  878. // . .
  879. // . IAaddr-options .
  880. // . .
  881. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  882. //
  883. //
  884. // Two usage model:
  885. //
  886. // 1. Pass addrbuf == null, to get the addrnum over the Ia inner options.
  887. // 2. Pass addrbuf != null, to resolve the addresses over the Ia inner
  888. // options to the addrbuf.
  889. //
  890. Cursor = IaInnerOpt;
  891. *AddrNum = 0;
  892. while (Cursor < IaInnerOpt + IaInnerLen) {
  893. //
  894. // Refer to RFC3315 Chapter 18.1.8, we need to update lifetimes for any addresses in the IA option
  895. // that the client already has recorded in the IA, and discard the Ia address option with 0 valid time.
  896. //
  897. OpCode = ReadUnaligned16 ((UINT16 *)Cursor);
  898. PreferredLt = NTOHL (ReadUnaligned32 ((UINT32 *)(Cursor + 20)));
  899. ValidLt = NTOHL (ReadUnaligned32 ((UINT32 *)(Cursor + 24)));
  900. IaAddr = (EFI_DHCP6_IA_ADDRESS *)(Cursor + 4);
  901. if ((OpCode == HTONS (Dhcp6OptIaAddr)) && (ValidLt >= PreferredLt) &&
  902. (Dhcp6AddrIsInCurrentIa (IaAddr, CurrentIa) || (ValidLt != 0)))
  903. {
  904. if (AddrBuf != NULL) {
  905. CopyMem (AddrBuf, IaAddr, sizeof (EFI_DHCP6_IA_ADDRESS));
  906. AddrBuf->PreferredLifetime = PreferredLt;
  907. AddrBuf->ValidLifetime = ValidLt;
  908. AddrBuf = (EFI_DHCP6_IA_ADDRESS *)((UINT8 *)AddrBuf + sizeof (EFI_DHCP6_IA_ADDRESS));
  909. }
  910. (*AddrNum)++;
  911. }
  912. DataLen = NTOHS (ReadUnaligned16 ((UINT16 *)(Cursor + 2)));
  913. Cursor += (DataLen + 4);
  914. }
  915. }
  916. /**
  917. Create a control block for the Ia according to the corresponding options.
  918. @param[in] Instance The pointer to DHCP6 Instance.
  919. @param[in] IaInnerOpt The pointer to the inner options in the Ia option.
  920. @param[in] IaInnerLen The length of all the inner options in the Ia option.
  921. @param[in] T1 T1 time in the Ia option.
  922. @param[in] T2 T2 time in the Ia option.
  923. @retval EFI_NOT_FOUND No valid IA option is found.
  924. @retval EFI_SUCCESS Create an IA control block successfully.
  925. @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
  926. @retval EFI_DEVICE_ERROR An unexpected error.
  927. **/
  928. EFI_STATUS
  929. Dhcp6GenerateIaCb (
  930. IN DHCP6_INSTANCE *Instance,
  931. IN UINT8 *IaInnerOpt,
  932. IN UINT16 IaInnerLen,
  933. IN UINT32 T1,
  934. IN UINT32 T2
  935. )
  936. {
  937. UINT32 AddrNum;
  938. UINT32 IaSize;
  939. EFI_DHCP6_IA *Ia;
  940. if (Instance->IaCb.Ia == NULL) {
  941. return EFI_DEVICE_ERROR;
  942. }
  943. //
  944. // Calculate the number of addresses for this Ia, excluding the addresses with
  945. // the value 0 of valid lifetime.
  946. //
  947. Dhcp6ParseAddrOption (Instance->IaCb.Ia, IaInnerOpt, IaInnerLen, &AddrNum, NULL);
  948. if (AddrNum == 0) {
  949. return EFI_NOT_FOUND;
  950. }
  951. //
  952. // Allocate for new IA.
  953. //
  954. IaSize = sizeof (EFI_DHCP6_IA) + (AddrNum - 1) * sizeof (EFI_DHCP6_IA_ADDRESS);
  955. Ia = AllocateZeroPool (IaSize);
  956. if (Ia == NULL) {
  957. return EFI_OUT_OF_RESOURCES;
  958. }
  959. //
  960. // Fill up this new IA fields.
  961. //
  962. Ia->State = Instance->IaCb.Ia->State;
  963. Ia->IaAddressCount = AddrNum;
  964. CopyMem (&Ia->Descriptor, &Instance->Config->IaDescriptor, sizeof (EFI_DHCP6_IA_DESCRIPTOR));
  965. Dhcp6ParseAddrOption (Instance->IaCb.Ia, IaInnerOpt, IaInnerLen, &AddrNum, Ia->IaAddress);
  966. //
  967. // Free original IA resource.
  968. //
  969. if (Instance->IaCb.Ia->ReplyPacket != NULL) {
  970. FreePool (Instance->IaCb.Ia->ReplyPacket);
  971. }
  972. FreePool (Instance->IaCb.Ia);
  973. ZeroMem (&Instance->IaCb, sizeof (DHCP6_IA_CB));
  974. //
  975. // Update IaCb to use new IA.
  976. //
  977. Instance->IaCb.Ia = Ia;
  978. //
  979. // Fill in IaCb fields. Such as T1, T2, AllExpireTime and LeaseTime.
  980. //
  981. Instance->IaCb.T1 = T1;
  982. Instance->IaCb.T2 = T2;
  983. Dhcp6CalculateLeaseTime (&Instance->IaCb);
  984. return EFI_SUCCESS;
  985. }
  986. /**
  987. Cache the current IA configuration information.
  988. @param[in] Instance The pointer to DHCP6 Instance.
  989. @retval EFI_SUCCESS Cache the current IA successfully.
  990. @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
  991. **/
  992. EFI_STATUS
  993. Dhcp6CacheIa (
  994. IN DHCP6_INSTANCE *Instance
  995. )
  996. {
  997. UINTN IaSize;
  998. EFI_DHCP6_IA *Ia;
  999. Ia = Instance->IaCb.Ia;
  1000. if ((Instance->CacheIa == NULL) && (Ia != NULL)) {
  1001. //
  1002. // Cache the current IA.
  1003. //
  1004. IaSize = sizeof (EFI_DHCP6_IA) + (Ia->IaAddressCount - 1) * sizeof (EFI_DHCP6_IA_ADDRESS);
  1005. Instance->CacheIa = AllocateZeroPool (IaSize);
  1006. if (Instance->CacheIa == NULL) {
  1007. return EFI_OUT_OF_RESOURCES;
  1008. }
  1009. CopyMem (Instance->CacheIa, Ia, IaSize);
  1010. }
  1011. return EFI_SUCCESS;
  1012. }
  1013. /**
  1014. Append CacheIa to the current IA. Meanwhile, clear CacheIa.ValidLifetime to 0.
  1015. @param[in] Instance The pointer to DHCP6 instance.
  1016. **/
  1017. VOID
  1018. Dhcp6AppendCacheIa (
  1019. IN DHCP6_INSTANCE *Instance
  1020. )
  1021. {
  1022. UINT8 *Ptr;
  1023. UINTN Index;
  1024. UINTN IaSize;
  1025. UINTN NewIaSize;
  1026. EFI_DHCP6_IA *Ia;
  1027. EFI_DHCP6_IA *NewIa;
  1028. EFI_DHCP6_IA *CacheIa;
  1029. Ia = Instance->IaCb.Ia;
  1030. CacheIa = Instance->CacheIa;
  1031. if ((CacheIa != NULL) && (CacheIa->IaAddressCount != 0)) {
  1032. //
  1033. // There are old addresses existing. Merge with current addresses.
  1034. //
  1035. NewIaSize = sizeof (EFI_DHCP6_IA) + (Ia->IaAddressCount + CacheIa->IaAddressCount - 1) * sizeof (EFI_DHCP6_IA_ADDRESS);
  1036. NewIa = AllocateZeroPool (NewIaSize);
  1037. if (NewIa == NULL) {
  1038. return;
  1039. }
  1040. IaSize = sizeof (EFI_DHCP6_IA) + (Ia->IaAddressCount - 1) * sizeof (EFI_DHCP6_IA_ADDRESS);
  1041. CopyMem (NewIa, Ia, IaSize);
  1042. //
  1043. // Clear old address.ValidLifetime
  1044. //
  1045. for (Index = 0; Index < CacheIa->IaAddressCount; Index++) {
  1046. CacheIa->IaAddress[Index].ValidLifetime = 0;
  1047. }
  1048. NewIa->IaAddressCount += CacheIa->IaAddressCount;
  1049. Ptr = (UINT8 *)&NewIa->IaAddress[Ia->IaAddressCount];
  1050. CopyMem (Ptr, CacheIa->IaAddress, CacheIa->IaAddressCount * sizeof (EFI_DHCP6_IA_ADDRESS));
  1051. //
  1052. // Migrate to the NewIa and free previous.
  1053. //
  1054. FreePool (Instance->CacheIa);
  1055. FreePool (Instance->IaCb.Ia);
  1056. Instance->CacheIa = NULL;
  1057. Instance->IaCb.Ia = NewIa;
  1058. }
  1059. }
  1060. /**
  1061. Calculate the Dhcp6 get mapping timeout by adding additional delay to the IP6 DAD transmits count.
  1062. @param[in] Ip6Cfg The pointer to Ip6 config protocol.
  1063. @param[out] TimeOut The time out value in 100ns units.
  1064. @retval EFI_INVALID_PARAMETER Input parameters are invalid.
  1065. @retval EFI_SUCCESS Calculate the time out value successfully.
  1066. **/
  1067. EFI_STATUS
  1068. Dhcp6GetMappingTimeOut (
  1069. IN EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg,
  1070. OUT UINTN *TimeOut
  1071. )
  1072. {
  1073. EFI_STATUS Status;
  1074. UINTN DataSize;
  1075. EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits;
  1076. if ((Ip6Cfg == NULL) || (TimeOut == NULL)) {
  1077. return EFI_INVALID_PARAMETER;
  1078. }
  1079. DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);
  1080. Status = Ip6Cfg->GetData (
  1081. Ip6Cfg,
  1082. Ip6ConfigDataTypeDupAddrDetectTransmits,
  1083. &DataSize,
  1084. &DadXmits
  1085. );
  1086. if (EFI_ERROR (Status)) {
  1087. return Status;
  1088. }
  1089. *TimeOut = TICKS_PER_SECOND * DadXmits.DupAddrDetectTransmits + DHCP6_DAD_ADDITIONAL_DELAY;
  1090. return EFI_SUCCESS;
  1091. }