]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c
NetworkPkg: Apply uncrustify changes
[mirror_edk2.git] / NetworkPkg / Dhcp6Dxe / Dhcp6Utility.c
index ac0e577f5e333eaae1661d606c58520cc4dc4e1b..e6368b5b1c6c65f8f2387ef4a202d96286ae4a47 100644 (file)
@@ -1,21 +1,15 @@
 /** @file\r
   Dhcp6 support functions implementation.\r
 \r
-  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
+  Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
 \r
-  This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php.\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "Dhcp6Impl.h"\r
 \r
-\r
 /**\r
   Generate client Duid in the format of Duid-llt.\r
 \r
 **/\r
 EFI_DHCP6_DUID *\r
 Dhcp6GenerateClientId (\r
-  IN EFI_SIMPLE_NETWORK_MODE   *Mode\r
+  IN EFI_SIMPLE_NETWORK_MODE  *Mode\r
   )\r
 {\r
-  EFI_STATUS                Status;\r
-  EFI_DHCP6_DUID            *Duid;\r
-  EFI_TIME                  Time;\r
-  UINT32                    Stamp;\r
-  EFI_GUID                  Uuid;\r
-\r
+  EFI_STATUS      Status;\r
+  EFI_DHCP6_DUID  *Duid;\r
+  EFI_TIME        Time;\r
+  UINT32          Stamp;\r
+  EFI_GUID        Uuid;\r
 \r
   //\r
   // Attempt to get client Id from variable to keep it constant.\r
   // See details in section-9 of rfc-3315.\r
   //\r
-  Duid = GetVariable (L"ClientId", &gEfiDhcp6ServiceBindingProtocolGuid);\r
+  GetVariable2 (L"ClientId", &gEfiDhcp6ServiceBindingProtocolGuid, (VOID **)&Duid, NULL);\r
   if (Duid != NULL) {\r
     return Duid;\r
   }\r
@@ -63,11 +56,11 @@ Dhcp6GenerateClientId (
   //\r
   // If System UUID is found from SMBIOS Table, use DUID-UUID type.\r
   //\r
-  if (!EFI_ERROR (NetLibGetSystemGuid (&Uuid))) {\r
+  if ((PcdGet8 (PcdDhcp6UidType) == Dhcp6DuidTypeUuid) && !EFI_ERROR (NetLibGetSystemGuid (&Uuid)) && !CompareGuid (&Uuid, &gZeroGuid)) {\r
     //\r
     //\r
     //  The format of DUID-UUID:\r
-    //   \r
+    //\r
     //    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\r
     //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
     //   |          DUID-Type (4)        |    UUID (128 bits)            |\r
@@ -89,17 +82,15 @@ Dhcp6GenerateClientId (
     //\r
     // sizeof (Duid-type + UUID-size) = 18 bytes\r
     //\r
-    Duid->Length = (UINT16) (18);\r
-  \r
+    Duid->Length = (UINT16)(18);\r
+\r
     //\r
     // Set the Duid-type and copy UUID.\r
     //\r
-    WriteUnaligned16 ((UINT16 *) (Duid->Duid), HTONS (Dhcp6DuidTypeUuid));\r
-  \r
-    CopyMem (Duid->Duid + 2, &Uuid, sizeof(EFI_GUID));\r
+    WriteUnaligned16 ((UINT16 *)(Duid->Duid), HTONS (Dhcp6DuidTypeUuid));\r
 \r
+    CopyMem (Duid->Duid + 2, &Uuid, sizeof (EFI_GUID));\r
   } else {\r
-      \r
     //\r
     //\r
     //  The format of DUID-LLT:\r
@@ -121,11 +112,11 @@ Dhcp6GenerateClientId (
     //\r
     gRT->GetTime (&Time, NULL);\r
     Stamp = (UINT32)\r
-      (\r
-        (((((Time.Year - 2000) * 360 + (Time.Month - 1)) * 30 + (Time.Day - 1)) * 24 + Time.Hour) * 60 + Time.Minute) *\r
-        60 +\r
-        Time.Second\r
-      );\r
+            (\r
+             ((((UINT32)(Time.Year - 2000) * 360 + (Time.Month - 1) * 30 + (Time.Day - 1)) * 24 + Time.Hour) * 60 + Time.Minute) *\r
+             60 +\r
+             Time.Second\r
+            );\r
 \r
     //\r
     // sizeof (option-len + Duid-type + hardware-type + time) = 10 bytes\r
@@ -134,19 +125,19 @@ Dhcp6GenerateClientId (
     if (Duid == NULL) {\r
       return NULL;\r
     }\r
-  \r
+\r
     //\r
     // sizeof (Duid-type + hardware-type + time) = 8 bytes\r
     //\r
-    Duid->Length = (UINT16) (Mode->HwAddressSize + 8);\r
-  \r
+    Duid->Length = (UINT16)(Mode->HwAddressSize + 8);\r
+\r
     //\r
     // Set the Duid-type, hardware-type, time and copy the hardware address.\r
     //\r
-    WriteUnaligned16 ((UINT16 *) (Duid->Duid), HTONS (Dhcp6DuidTypeLlt));\r
-    WriteUnaligned16 ((UINT16 *) (Duid->Duid + 2), HTONS (NET_IFTYPE_ETHERNET));\r
-    WriteUnaligned32 ((UINT32 *) (Duid->Duid + 4), HTONL (Stamp));\r
-  \r
+    WriteUnaligned16 ((UINT16 *)((UINT8 *)Duid + OFFSET_OF (EFI_DHCP6_DUID, Duid)), HTONS (Dhcp6DuidTypeLlt));\r
+    WriteUnaligned16 ((UINT16 *)((UINT8 *)Duid + OFFSET_OF (EFI_DHCP6_DUID, Duid) + 2), HTONS (NET_IFTYPE_ETHERNET));\r
+    WriteUnaligned32 ((UINT32 *)((UINT8 *)Duid + OFFSET_OF (EFI_DHCP6_DUID, Duid) + 4), HTONL (Stamp));\r
+\r
     CopyMem (Duid->Duid + 8, &Mode->CurrentAddress, Mode->HwAddressSize);\r
   }\r
 \r
@@ -155,14 +146,16 @@ Dhcp6GenerateClientId (
                   &gEfiDhcp6ServiceBindingProtocolGuid,\r
                   (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS),\r
                   Duid->Length + 2,\r
-                  (VOID *) Duid\r
+                  (VOID *)Duid\r
                   );\r
-  ASSERT_EFI_ERROR (Status);\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (Duid);\r
+    return NULL;\r
+  }\r
 \r
   return Duid;\r
 }\r
 \r
-\r
 /**\r
   Copy the Dhcp6 configure data.\r
 \r
@@ -175,13 +168,13 @@ Dhcp6GenerateClientId (
 **/\r
 EFI_STATUS\r
 Dhcp6CopyConfigData (\r
-  IN EFI_DHCP6_CONFIG_DATA      *DstCfg,\r
-  IN EFI_DHCP6_CONFIG_DATA      *SorCfg\r
+  IN EFI_DHCP6_CONFIG_DATA  *DstCfg,\r
+  IN EFI_DHCP6_CONFIG_DATA  *SorCfg\r
   )\r
 {\r
-  UINTN                     Index;\r
-  UINTN                     OptionListSize;\r
-  UINTN                     OptionSize;\r
+  UINTN  Index;\r
+  UINTN  OptionListSize;\r
+  UINTN  OptionSize;\r
 \r
   CopyMem (DstCfg, SorCfg, sizeof (EFI_DHCP6_CONFIG_DATA));\r
 \r
@@ -189,7 +182,6 @@ Dhcp6CopyConfigData (
   // Allocate another buffer for solicitretransmission, and copy it.\r
   //\r
   if (SorCfg->SolicitRetransmission != NULL) {\r
-\r
     DstCfg->SolicitRetransmission = AllocateZeroPool (sizeof (EFI_DHCP6_RETRANSMISSION));\r
 \r
     if (DstCfg->SolicitRetransmission == NULL) {\r
@@ -206,8 +198,7 @@ Dhcp6CopyConfigData (
       );\r
   }\r
 \r
-  if (SorCfg->OptionList != NULL && SorCfg->OptionCount != 0) {\r
-\r
+  if ((SorCfg->OptionList != NULL) && (SorCfg->OptionCount != 0)) {\r
     OptionListSize     = SorCfg->OptionCount * sizeof (EFI_DHCP6_PACKET_OPTION *);\r
     DstCfg->OptionList = AllocateZeroPool (OptionListSize);\r
 \r
@@ -219,7 +210,6 @@ Dhcp6CopyConfigData (
     }\r
 \r
     for (Index = 0; Index < SorCfg->OptionCount; Index++) {\r
-\r
       OptionSize                = NTOHS (SorCfg->OptionList[Index]->OpLen) + 4;\r
       DstCfg->OptionList[Index] = AllocateZeroPool (OptionSize);\r
 \r
@@ -241,7 +231,6 @@ Dhcp6CopyConfigData (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Clean up the configure data.\r
 \r
@@ -250,10 +239,10 @@ Dhcp6CopyConfigData (
 **/\r
 VOID\r
 Dhcp6CleanupConfigData (\r
-  IN OUT EFI_DHCP6_CONFIG_DATA       *CfgData\r
+  IN OUT EFI_DHCP6_CONFIG_DATA  *CfgData\r
   )\r
 {\r
-  UINTN                          Index;\r
+  UINTN  Index;\r
 \r
   ASSERT (CfgData != NULL);\r
   //\r
@@ -266,6 +255,7 @@ Dhcp6CleanupConfigData (
         FreePool (CfgData->OptionList[Index]);\r
       }\r
     }\r
+\r
     FreePool (CfgData->OptionList);\r
   }\r
 \r
@@ -276,7 +266,6 @@ Dhcp6CleanupConfigData (
   ZeroMem (CfgData, sizeof (EFI_DHCP6_CONFIG_DATA));\r
 }\r
 \r
-\r
 /**\r
   Clean up the mode data.\r
 \r
@@ -285,7 +274,7 @@ Dhcp6CleanupConfigData (
 **/\r
 VOID\r
 Dhcp6CleanupModeData (\r
-  IN OUT EFI_DHCP6_MODE_DATA        *ModeData\r
+  IN OUT EFI_DHCP6_MODE_DATA  *ModeData\r
   )\r
 {\r
   ASSERT (ModeData != NULL);\r
@@ -298,38 +287,37 @@ Dhcp6CleanupModeData (
   }\r
 \r
   if (ModeData->Ia != NULL) {\r
-\r
     if (ModeData->Ia->ReplyPacket != NULL) {\r
       FreePool (ModeData->Ia->ReplyPacket);\r
     }\r
+\r
     FreePool (ModeData->Ia);\r
   }\r
 \r
   ZeroMem (ModeData, sizeof (EFI_DHCP6_MODE_DATA));\r
 }\r
 \r
-\r
 /**\r
   Calculate the expire time by the algorithm defined in rfc.\r
 \r
   @param[in]  Base          The base value of the time.\r
   @param[in]  IsFirstRt     If TRUE, it is the first time to calculate expire time.\r
-  @param[in]  NeedSigned    If TRUE, the the signed factor is needed.\r
+  @param[in]  NeedSigned    If TRUE, the signed factor is needed.\r
 \r
   @return     Expire        The calculated result for the new expire time.\r
 \r
 **/\r
 UINT32\r
 Dhcp6CalculateExpireTime (\r
-  IN UINT32                 Base,\r
-  IN BOOLEAN                IsFirstRt,\r
-  IN BOOLEAN                NeedSigned\r
+  IN UINT32   Base,\r
+  IN BOOLEAN  IsFirstRt,\r
+  IN BOOLEAN  NeedSigned\r
   )\r
 {\r
-  EFI_TIME                  Time;\r
-  BOOLEAN                   Signed;\r
-  UINT32                    Seed;\r
-  UINT32                    Expire;\r
+  EFI_TIME  Time;\r
+  BOOLEAN   Signed;\r
+  UINT32    Seed;\r
+  UINT32    Expire;\r
 \r
   //\r
   // Take the 10bits of microsecond in system time as a uniform distribution.\r
@@ -337,8 +325,8 @@ Dhcp6CalculateExpireTime (
   //\r
   gRT->GetTime (&Time, NULL);\r
   Seed   = ((Time.Nanosecond >> 10) & DHCP6_10_BIT_MASK);\r
-  Signed = (BOOLEAN) ((((Time.Nanosecond >> 9) & 0x01) != 0) ? TRUE : FALSE);\r
-  Signed = (BOOLEAN) (NeedSigned ? Signed : FALSE);\r
+  Signed = (BOOLEAN)((((Time.Nanosecond >> 9) & 0x01) != 0) ? TRUE : FALSE);\r
+  Signed = (BOOLEAN)(NeedSigned ? Signed : FALSE);\r
 \r
   //\r
   // Calculate expire by the following algo:\r
@@ -350,20 +338,13 @@ Dhcp6CalculateExpireTime (
   // The (Seed / 0x3ff / 10) is used to a random range (0, 0.1).\r
   //\r
   if (IsFirstRt && Signed) {\r
-\r
-    Expire = Base - (UINT32) (Base * Seed / DHCP6_10_BIT_MASK / 10);\r
-\r
+    Expire = Base - (UINT32)(Base * Seed / DHCP6_10_BIT_MASK / 10);\r
   } else if (IsFirstRt && !Signed) {\r
-\r
-    Expire = Base + (UINT32) (Base * Seed / DHCP6_10_BIT_MASK / 10);\r
-\r
+    Expire = Base + (UINT32)(Base * Seed / DHCP6_10_BIT_MASK / 10);\r
   } else if (!IsFirstRt && Signed) {\r
-\r
-    Expire = 2 * Base - (UINT32) (Base * Seed / DHCP6_10_BIT_MASK / 10);\r
-\r
+    Expire = 2 * Base - (UINT32)(Base * Seed / DHCP6_10_BIT_MASK / 10);\r
   } else {\r
-\r
-    Expire = 2 * Base + (UINT32) (Base * Seed / DHCP6_10_BIT_MASK / 10);\r
+    Expire = 2 * Base + (UINT32)(Base * Seed / DHCP6_10_BIT_MASK / 10);\r
   }\r
 \r
   Expire = (Expire != 0) ? Expire : 1;\r
@@ -371,7 +352,6 @@ Dhcp6CalculateExpireTime (
   return Expire;\r
 }\r
 \r
-\r
 /**\r
   Calculate the lease time by the algorithm defined in rfc.\r
 \r
@@ -380,27 +360,25 @@ Dhcp6CalculateExpireTime (
 **/\r
 VOID\r
 Dhcp6CalculateLeaseTime (\r
-  IN DHCP6_IA_CB              *IaCb\r
+  IN DHCP6_IA_CB  *IaCb\r
   )\r
 {\r
-  EFI_DHCP6_IA_ADDRESS        *IaAddr;\r
-  UINT32                      MinLt;\r
-  UINT32                      MaxLt;\r
-  UINTN                       Index;\r
+  UINT32  MinLt;\r
+  UINT32  MaxLt;\r
+  UINTN   Index;\r
 \r
   ASSERT (IaCb->Ia->IaAddressCount > 0);\r
 \r
-  MinLt    = (UINT32) (-1);\r
-  MaxLt    = 0;\r
+  MinLt = (UINT32)(-1);\r
+  MaxLt = 0;\r
 \r
   //\r
   // Calculate minlt as min of all valid life time, and maxlt as max of all\r
   // valid life time.\r
   //\r
   for (Index = 0; Index < IaCb->Ia->IaAddressCount; Index++) {\r
-    IaAddr = IaCb->Ia->IaAddress + Index * sizeof (EFI_DHCP6_IA_ADDRESS);\r
-    MinLt  = MIN (MinLt, IaAddr->ValidLifetime);\r
-    MaxLt  = MAX (MinLt, IaAddr->ValidLifetime);\r
+    MinLt = MIN (MinLt, IaCb->Ia->IaAddress[Index].ValidLifetime);\r
+    MaxLt = MAX (MinLt, IaCb->Ia->IaAddress[Index].ValidLifetime);\r
   }\r
 \r
   //\r
@@ -413,7 +391,6 @@ Dhcp6CalculateLeaseTime (
   IaCb->LeaseTime     = 0;\r
 }\r
 \r
-\r
 /**\r
   Check whether the addresses are all included by the configured Ia.\r
 \r
@@ -427,31 +404,29 @@ Dhcp6CalculateLeaseTime (
 **/\r
 EFI_STATUS\r
 Dhcp6CheckAddress (\r
-  IN EFI_DHCP6_IA             *Ia,\r
-  IN UINT32                   AddressCount,\r
-  IN EFI_IPv6_ADDRESS         *Addresses\r
+  IN EFI_DHCP6_IA      *Ia,\r
+  IN UINT32            AddressCount,\r
+  IN EFI_IPv6_ADDRESS  *Addresses\r
   )\r
 {\r
-  UINTN                       Index1;\r
-  UINTN                       Index2;\r
-  BOOLEAN                     Found;\r
+  UINTN    Index1;\r
+  UINTN    Index2;\r
+  BOOLEAN  Found;\r
 \r
   //\r
   // Check whether the addresses are all included by the configured IA. And it\r
   // will return success if address count is zero, which means all addresses.\r
   //\r
   for (Index1 = 0; Index1 < AddressCount; Index1++) {\r
-\r
     Found = FALSE;\r
 \r
     for (Index2 = 0; Index2 < Ia->IaAddressCount; Index2++) {\r
-\r
       if (CompareMem (\r
             &Addresses[Index1],\r
             &Ia->IaAddress[Index2],\r
             sizeof (EFI_IPv6_ADDRESS)\r
-            ) == 0) {\r
-\r
+            ) == 0)\r
+      {\r
         Found = TRUE;\r
         break;\r
       }\r
@@ -465,7 +440,6 @@ Dhcp6CheckAddress (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Deprive the addresses from current Ia, and generate another eliminated Ia.\r
 \r
@@ -479,16 +453,16 @@ Dhcp6CheckAddress (
 **/\r
 EFI_DHCP6_IA *\r
 Dhcp6DepriveAddress (\r
-  IN EFI_DHCP6_IA             *Ia,\r
-  IN UINT32                   AddressCount,\r
-  IN EFI_IPv6_ADDRESS         *Addresses\r
+  IN EFI_DHCP6_IA      *Ia,\r
+  IN UINT32            AddressCount,\r
+  IN EFI_IPv6_ADDRESS  *Addresses\r
   )\r
 {\r
-  EFI_DHCP6_IA                *IaCopy;\r
-  UINTN                       IaCopySize;\r
-  UINTN                       Index1;\r
-  UINTN                       Index2;\r
-  BOOLEAN                     Found;\r
+  EFI_DHCP6_IA  *IaCopy;\r
+  UINTN         IaCopySize;\r
+  UINTN         Index1;\r
+  UINTN         Index2;\r
+  BOOLEAN       Found;\r
 \r
   if (AddressCount == 0) {\r
     //\r
@@ -510,7 +484,7 @@ Dhcp6DepriveAddress (
     //\r
     // If release all Ia addresses, just copy the configured Ia and then set\r
     // its address count as zero.\r
-    // We may decline/release part of addresses at the begining. So it's a\r
+    // We may decline/release part of addresses at the beginning. So it's a\r
     // forwarding step to update address infor for decline/release, while the\r
     // other infor such as Ia state will be updated when receiving reply.\r
     //\r
@@ -525,16 +499,15 @@ Dhcp6DepriveAddress (
   // Move the addresses from the Ia of instance to the deprived Ia.\r
   //\r
   for (Index1 = 0; Index1 < AddressCount; Index1++) {\r
-\r
     Found = FALSE;\r
 \r
     for (Index2 = 0; Index2 < Ia->IaAddressCount; Index2++) {\r
-\r
       if (CompareMem (\r
             &Addresses[Index1],\r
             &Ia->IaAddress[Index2],\r
             sizeof (EFI_IPv6_ADDRESS)\r
-            ) == 0) {\r
+            ) == 0)\r
+      {\r
         //\r
         // Copy the deprived address to the copy of Ia\r
         //\r
@@ -553,10 +526,12 @@ Dhcp6DepriveAddress (
             (Ia->IaAddressCount - Index2 - 1) * sizeof (EFI_DHCP6_IA_ADDRESS)\r
             );\r
         }\r
+\r
         Found = TRUE;\r
         break;\r
       }\r
     }\r
+\r
     ASSERT (Found == TRUE);\r
   }\r
 \r
@@ -566,7 +541,6 @@ Dhcp6DepriveAddress (
   return IaCopy;\r
 }\r
 \r
-\r
 /**\r
   The dummy ext buffer free callback routine.\r
 \r
@@ -576,12 +550,11 @@ Dhcp6DepriveAddress (
 VOID\r
 EFIAPI\r
 Dhcp6DummyExtFree (\r
-  IN VOID                      *Arg\r
+  IN VOID  *Arg\r
   )\r
 {\r
 }\r
 \r
-\r
 /**\r
   The callback routine once message transmitted.\r
 \r
@@ -594,16 +567,15 @@ Dhcp6DummyExtFree (
 VOID\r
 EFIAPI\r
 Dhcp6OnTransmitted (\r
-  IN NET_BUF                   *Wrap,\r
-  IN UDP_END_POINT             *EndPoint,\r
-  IN EFI_STATUS                IoStatus,\r
-  IN VOID                      *Context\r
+  IN NET_BUF        *Wrap,\r
+  IN UDP_END_POINT  *EndPoint,\r
+  IN EFI_STATUS     IoStatus,\r
+  IN VOID           *Context\r
   )\r
 {\r
   NetbufFree (Wrap);\r
 }\r
 \r
-\r
 /**\r
   Append the option to Buf, and move Buf to the end.\r
 \r
@@ -617,10 +589,10 @@ Dhcp6OnTransmitted (
 **/\r
 UINT8 *\r
 Dhcp6AppendOption (\r
-  IN OUT UINT8               *Buf,\r
-  IN     UINT16              OptType,\r
-  IN     UINT16              OptLen,\r
-  IN     UINT8               *Data\r
+  IN OUT UINT8   *Buf,\r
+  IN     UINT16  OptType,\r
+  IN     UINT16  OptLen,\r
+  IN     UINT8   *Data\r
   )\r
 {\r
   //\r
@@ -637,16 +609,85 @@ Dhcp6AppendOption (
 \r
   ASSERT (OptLen != 0);\r
 \r
-  WriteUnaligned16 ((UINT16 *) Buf, OptType);\r
-  Buf            += 2;\r
-  WriteUnaligned16 ((UINT16 *) Buf, OptLen);\r
-  Buf            += 2;\r
+  WriteUnaligned16 ((UINT16 *)Buf, OptType);\r
+  Buf += 2;\r
+  WriteUnaligned16 ((UINT16 *)Buf, OptLen);\r
+  Buf += 2;\r
   CopyMem (Buf, Data, NTOHS (OptLen));\r
-  Buf            += NTOHS (OptLen);\r
+  Buf += NTOHS (OptLen);\r
 \r
   return Buf;\r
 }\r
 \r
+/**\r
+  Append the appointed IA Address option to Buf, and move Buf to the end.\r
+\r
+  @param[in, out] Buf           The pointer to the position to append.\r
+  @param[in]      IaAddr        The pointer to the IA Address.\r
+  @param[in]      MessageType   Message type of DHCP6 package.\r
+\r
+  @return         Buf           The position to append the next option.\r
+\r
+**/\r
+UINT8 *\r
+Dhcp6AppendIaAddrOption (\r
+  IN OUT UINT8                 *Buf,\r
+  IN     EFI_DHCP6_IA_ADDRESS  *IaAddr,\r
+  IN     UINT32                MessageType\r
+  )\r
+{\r
+  //  The format of the IA Address option is:\r
+  //\r
+  //       0                   1                   2                   3\r
+  //       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\r
+  //      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+  //      |          OPTION_IAADDR        |          option-len           |\r
+  //      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+  //      |                                                               |\r
+  //      |                         IPv6 address                          |\r
+  //      |                                                               |\r
+  //      |                                                               |\r
+  //      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+  //      |                      preferred-lifetime                       |\r
+  //      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+  //      |                        valid-lifetime                         |\r
+  //      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+  //      .                                                               .\r
+  //      .                        IAaddr-options                         .\r
+  //      .                                                               .\r
+  //      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+\r
+  //\r
+  // Fill the value of Ia Address option type\r
+  //\r
+  WriteUnaligned16 ((UINT16 *)Buf, HTONS (Dhcp6OptIaAddr));\r
+  Buf += 2;\r
+\r
+  WriteUnaligned16 ((UINT16 *)Buf, HTONS (sizeof (EFI_DHCP6_IA_ADDRESS)));\r
+  Buf += 2;\r
+\r
+  CopyMem (Buf, &IaAddr->IpAddress, sizeof (EFI_IPv6_ADDRESS));\r
+  Buf += sizeof (EFI_IPv6_ADDRESS);\r
+\r
+  //\r
+  // Fill the value of preferred-lifetime and valid-lifetime.\r
+  // According to RFC3315 Chapter 18.1.2, the preferred-lifetime and valid-lifetime fields\r
+  // should set to 0 when initiate a Confirm message.\r
+  //\r
+  if (MessageType != Dhcp6MsgConfirm) {\r
+    WriteUnaligned32 ((UINT32 *)Buf, HTONL (IaAddr->PreferredLifetime));\r
+  }\r
+\r
+  Buf += 4;\r
+\r
+  if (MessageType != Dhcp6MsgConfirm) {\r
+    WriteUnaligned32 ((UINT32 *)Buf, HTONL (IaAddr->ValidLifetime));\r
+  }\r
+\r
+  Buf += 4;\r
+\r
+  return Buf;\r
+}\r
 \r
 /**\r
   Append the appointed Ia option to Buf, and move Buf to the end.\r
@@ -655,22 +696,23 @@ Dhcp6AppendOption (
   @param[in]      Ia            The pointer to the Ia.\r
   @param[in]      T1            The time of T1.\r
   @param[in]      T2            The time of T2.\r
+  @param[in]      MessageType   Message type of DHCP6 package.\r
 \r
   @return         Buf           The position to append the next Ia option.\r
 \r
 **/\r
 UINT8 *\r
 Dhcp6AppendIaOption (\r
-  IN OUT UINT8                  *Buf,\r
-  IN     EFI_DHCP6_IA           *Ia,\r
-  IN     UINT32                 T1,\r
-  IN     UINT32                 T2\r
+  IN OUT UINT8         *Buf,\r
+  IN     EFI_DHCP6_IA  *Ia,\r
+  IN     UINT32        T1,\r
+  IN     UINT32        T2,\r
+  IN     UINT32        MessageType\r
   )\r
 {\r
-  UINT8                     *AddrOpt;\r
-  UINT16                    *Len;\r
-  UINTN                     Index;\r
-  UINT16                    Length;\r
+  UINT8   *AddrOpt;\r
+  UINT16  *Len;\r
+  UINTN   Index;\r
 \r
   //\r
   //  The format of IA_NA and IA_TA option:\r
@@ -694,50 +736,43 @@ Dhcp6AppendIaOption (
   //\r
   // Fill the value of Ia option type\r
   //\r
-  WriteUnaligned16 ((UINT16 *) Buf, HTONS (Ia->Descriptor.Type));\r
-  Buf                     += 2;\r
+  WriteUnaligned16 ((UINT16 *)Buf, HTONS (Ia->Descriptor.Type));\r
+  Buf += 2;\r
 \r
   //\r
   // Fill the len of Ia option later, keep the pointer first\r
   //\r
-  Len                      = (UINT16 *) Buf;\r
-  Buf                     += 2;\r
+  Len  = (UINT16 *)Buf;\r
+  Buf += 2;\r
 \r
   //\r
   // Fill the value of iaid\r
   //\r
-  WriteUnaligned32 ((UINT32 *) Buf, HTONL (Ia->Descriptor.IaId));\r
-  Buf                     += 4;\r
+  WriteUnaligned32 ((UINT32 *)Buf, HTONL (Ia->Descriptor.IaId));\r
+  Buf += 4;\r
 \r
   //\r
   // Fill the value of t1 and t2 if iana, keep it 0xffffffff if no specified.\r
   //\r
   if (Ia->Descriptor.Type == Dhcp6OptIana) {\r
-    WriteUnaligned32 ((UINT32 *) Buf, ((T1 != 0) ? T1 : 0xffffffff));\r
-    Buf                   += 4;\r
-    WriteUnaligned32 ((UINT32 *) Buf, ((T2 != 0) ? T2 : 0xffffffff));\r
-    Buf                   += 4;\r
+    WriteUnaligned32 ((UINT32 *)Buf, HTONL ((T1 != 0) ? T1 : 0xffffffff));\r
+    Buf += 4;\r
+    WriteUnaligned32 ((UINT32 *)Buf, HTONL ((T2 != 0) ? T2 : 0xffffffff));\r
+    Buf += 4;\r
   }\r
 \r
   //\r
   // Fill all the addresses belong to the Ia\r
   //\r
   for (Index = 0; Index < Ia->IaAddressCount; Index++) {\r
-\r
-     AddrOpt = (UINT8 *) Ia->IaAddress + Index * sizeof (EFI_DHCP6_IA_ADDRESS);\r
-     Length  = HTONS ((UINT16) sizeof (EFI_DHCP6_IA_ADDRESS));\r
-     Buf     = Dhcp6AppendOption (\r
-                 Buf,\r
-                 HTONS (Dhcp6OptIaAddr),\r
-                 Length,\r
-                 AddrOpt\r
-                 );\r
+    AddrOpt = (UINT8 *)Ia->IaAddress + Index * sizeof (EFI_DHCP6_IA_ADDRESS);\r
+    Buf     = Dhcp6AppendIaAddrOption (Buf, (EFI_DHCP6_IA_ADDRESS *)AddrOpt, MessageType);\r
   }\r
 \r
   //\r
   // Fill the value of Ia option length\r
   //\r
-  *Len = HTONS ((UINT16) (Buf - (UINT8 *) Len - 2));\r
+  *Len = HTONS ((UINT16)(Buf - (UINT8 *)Len - 2));\r
 \r
   return Buf;\r
 }\r
@@ -755,9 +790,9 @@ Dhcp6AppendIaOption (
 **/\r
 UINT8 *\r
 Dhcp6AppendETOption (\r
-  IN OUT UINT8                  *Buf,\r
-  IN     DHCP6_INSTANCE         *Instance,\r
-  OUT    UINT16                 **Elapsed\r
+  IN OUT UINT8           *Buf,\r
+  IN     DHCP6_INSTANCE  *Instance,\r
+  OUT    UINT16          **Elapsed\r
   )\r
 {\r
   //\r
@@ -774,22 +809,22 @@ Dhcp6AppendETOption (
   //\r
   // Fill the value of elapsed-time option type.\r
   //\r
-  WriteUnaligned16 ((UINT16 *) Buf, HTONS (Dhcp6OptElapsedTime));\r
-  Buf                     += 2;\r
+  WriteUnaligned16 ((UINT16 *)Buf, HTONS (Dhcp6OptElapsedTime));\r
+  Buf += 2;\r
 \r
   //\r
   // Fill the len of elapsed-time option, which is fixed.\r
   //\r
-  WriteUnaligned16 ((UINT16 *) Buf, HTONS(2));\r
-  Buf                     += 2;\r
+  WriteUnaligned16 ((UINT16 *)Buf, HTONS (2));\r
+  Buf += 2;\r
 \r
   //\r
   // Fill in elapsed time value with 0 value for now.  The actual value is\r
   // filled in later just before the packet is transmitted.\r
   //\r
-  WriteUnaligned16 ((UINT16 *) Buf, HTONS(0));\r
-  *Elapsed                  = (UINT16 *) Buf;\r
-  Buf                     += 2;\r
+  WriteUnaligned16 ((UINT16 *)Buf, HTONS (0));\r
+  *Elapsed = (UINT16 *)Buf;\r
+  Buf     += 2;\r
 \r
   return Buf;\r
 }\r
@@ -804,34 +839,34 @@ Dhcp6AppendETOption (
 **/\r
 VOID\r
 SetElapsedTime (\r
-  IN     UINT16                 *Elapsed,\r
-  IN     DHCP6_INSTANCE         *Instance\r
+  IN     UINT16          *Elapsed,\r
+  IN     DHCP6_INSTANCE  *Instance\r
   )\r
 {\r
-  EFI_TIME          Time;\r
-  UINT64            CurrentStamp;\r
-  UINT64            ElapsedTimeValue;\r
+  EFI_TIME  Time;\r
+  UINT64    CurrentStamp;\r
+  UINT64    ElapsedTimeValue;\r
 \r
   //\r
   // Generate a time stamp of the centiseconds from 2000/1/1, assume 30day/month.\r
   //\r
   gRT->GetTime (&Time, NULL);\r
-  CurrentStamp = (UINT64)\r
-    (\r
-      ((((((Time.Year - 2000) * 360 +\r
-       (Time.Month - 1)) * 30 +\r
-       (Time.Day - 1)) * 24 + Time.Hour) * 60 +\r
-       Time.Minute) * 60 + Time.Second) * 100\r
-       + DivU64x32(Time.Nanosecond, 10000000)\r
-    );\r
+  CurrentStamp = MultU64x32 (\r
+                   ((((UINT32)(Time.Year - 2000) * 360 + (Time.Month - 1) * 30 + (Time.Day - 1)) * 24 + Time.Hour) * 60 + Time.Minute) * 60 + Time.Second,\r
+                   100\r
+                   ) +\r
+                 DivU64x32 (\r
+                   Time.Nanosecond,\r
+                   10000000\r
+                   );\r
 \r
   //\r
   // Sentinel value of 0 means that this is the first DHCP packet that we are\r
-  // sending and that we need to initialize the value.  First DHCP Solicit\r
+  // sending and that we need to initialize the value.  First DHCP message\r
   // gets 0 elapsed-time.  Otherwise, calculate based on StartTime.\r
   //\r
   if (Instance->StartTime == 0) {\r
-    ElapsedTimeValue = 0;\r
+    ElapsedTimeValue    = 0;\r
     Instance->StartTime = CurrentStamp;\r
   } else {\r
     ElapsedTimeValue = CurrentStamp - Instance->StartTime;\r
@@ -843,9 +878,9 @@ SetElapsedTime (
       ElapsedTimeValue = 0xffff;\r
     }\r
   }\r
-  WriteUnaligned16 (Elapsed, HTONS((UINT16) ElapsedTimeValue));\r
-}\r
 \r
+  WriteUnaligned16 (Elapsed, HTONS ((UINT16)ElapsedTimeValue));\r
+}\r
 \r
 /**\r
   Seek the address of the first byte of the option header.\r
@@ -860,15 +895,15 @@ SetElapsedTime (
 **/\r
 UINT8 *\r
 Dhcp6SeekOption (\r
-  IN UINT8           *Buf,\r
-  IN UINT32          SeekLen,\r
-  IN UINT16          OptType\r
+  IN UINT8   *Buf,\r
+  IN UINT32  SeekLen,\r
+  IN UINT16  OptType\r
   )\r
 {\r
-  UINT8              *Cursor;\r
-  UINT8              *Option;\r
-  UINT16             DataLen;\r
-  UINT16             OpCode;\r
+  UINT8   *Cursor;\r
+  UINT8   *Option;\r
+  UINT16  DataLen;\r
+  UINT16  OpCode;\r
 \r
   Option = NULL;\r
   Cursor = Buf;\r
@@ -877,19 +912,19 @@ Dhcp6SeekOption (
   // The format of Dhcp6 option refers to Dhcp6AppendOption().\r
   //\r
   while (Cursor < Buf + SeekLen) {\r
-    OpCode = ReadUnaligned16 ((UINT16 *) Cursor);\r
+    OpCode = ReadUnaligned16 ((UINT16 *)Cursor);\r
     if (OpCode == HTONS (OptType)) {\r
       Option = Cursor;\r
       break;\r
     }\r
-    DataLen = NTOHS (ReadUnaligned16 ((UINT16 *) (Cursor + 2)));\r
+\r
+    DataLen = NTOHS (ReadUnaligned16 ((UINT16 *)(Cursor + 2)));\r
     Cursor += (DataLen + 4);\r
   }\r
 \r
   return Option;\r
 }\r
 \r
-\r
 /**\r
   Seek the address of the first byte of the Ia option header.\r
 \r
@@ -908,11 +943,11 @@ Dhcp6SeekIaOption (
   IN EFI_DHCP6_IA_DESCRIPTOR  *IaDesc\r
   )\r
 {\r
-  UINT8              *Cursor;\r
-  UINT8              *Option;\r
-  UINT16             DataLen;\r
-  UINT16             OpCode;\r
-  UINT32             IaId;\r
+  UINT8   *Cursor;\r
+  UINT8   *Option;\r
+  UINT16  DataLen;\r
+  UINT16  OpCode;\r
+  UINT32  IaId;\r
 \r
   //\r
   // The format of IA_NA and IA_TA option refers to Dhcp6AppendIaOption().\r
@@ -921,23 +956,54 @@ Dhcp6SeekIaOption (
   Cursor = Buf;\r
 \r
   while (Cursor < Buf + SeekLen) {\r
-    OpCode = ReadUnaligned16 ((UINT16 *) Cursor);\r
-    IaId   = ReadUnaligned32 ((UINT32 *) (Cursor + 4));\r
-    if (OpCode == HTONS (IaDesc->Type) && IaId == HTONL (IaDesc->IaId)) {\r
+    OpCode = ReadUnaligned16 ((UINT16 *)Cursor);\r
+    IaId   = ReadUnaligned32 ((UINT32 *)(Cursor + 4));\r
+    if ((OpCode == HTONS (IaDesc->Type)) && (IaId == HTONL (IaDesc->IaId))) {\r
       Option = Cursor;\r
       break;\r
     }\r
-    DataLen = NTOHS (ReadUnaligned16 ((UINT16 *) (Cursor + 2)));\r
+\r
+    DataLen = NTOHS (ReadUnaligned16 ((UINT16 *)(Cursor + 2)));\r
     Cursor += (DataLen + 4);\r
   }\r
 \r
   return Option;\r
 }\r
 \r
+/**\r
+  Check whether the incoming IPv6 address in IaAddr is one of the maintained\r
+  addresses in the IA control block.\r
+\r
+  @param[in]  IaAddr            The pointer to the IA Address to be checked.\r
+  @param[in]  CurrentIa         The pointer to the IA in IA control block.\r
+\r
+  @retval     TRUE              Yes, this Address is already in IA control block.\r
+  @retval     FALSE             No, this Address is NOT in IA control block.\r
+\r
+**/\r
+BOOLEAN\r
+Dhcp6AddrIsInCurrentIa (\r
+  IN    EFI_DHCP6_IA_ADDRESS  *IaAddr,\r
+  IN    EFI_DHCP6_IA          *CurrentIa\r
+  )\r
+{\r
+  UINT32  Index;\r
+\r
+  ASSERT (IaAddr != NULL && CurrentIa != NULL);\r
+\r
+  for (Index = 0; Index < CurrentIa->IaAddressCount; Index++) {\r
+    if (EFI_IP6_EQUAL (&IaAddr->IpAddress, &CurrentIa->IaAddress[Index].IpAddress)) {\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
 \r
 /**\r
-  Parse the address option and update the address infomation.\r
+  Parse the address option and update the address information.\r
 \r
+  @param[in]      CurrentIa     The pointer to the Ia Address in control block.\r
   @param[in]      IaInnerOpt    The pointer to the buffer.\r
   @param[in]      IaInnerLen    The length to parse.\r
   @param[out]     AddrNum       The number of addresses.\r
@@ -946,16 +1012,19 @@ Dhcp6SeekIaOption (
 **/\r
 VOID\r
 Dhcp6ParseAddrOption (\r
-  IN     UINT8                   *IaInnerOpt,\r
-  IN     UINT16                  IaInnerLen,\r
-     OUT UINT32                  *AddrNum,\r
-  IN OUT EFI_DHCP6_IA_ADDRESS    *AddrBuf\r
+  IN     EFI_DHCP6_IA          *CurrentIa,\r
+  IN     UINT8                 *IaInnerOpt,\r
+  IN     UINT16                IaInnerLen,\r
+  OUT UINT32                   *AddrNum,\r
+  IN OUT EFI_DHCP6_IA_ADDRESS  *AddrBuf\r
   )\r
 {\r
-  UINT8                       *Cursor;\r
-  UINT16                      DataLen;\r
-  UINT16                      OpCode;\r
-  UINT32                      ValidLt;\r
+  UINT8                 *Cursor;\r
+  UINT16                DataLen;\r
+  UINT16                OpCode;\r
+  UINT32                ValidLt;\r
+  UINT32                PreferredLt;\r
+  EFI_DHCP6_IA_ADDRESS  *IaAddr;\r
 \r
   //\r
   //  The format of the IA Address option:\r
@@ -992,29 +1061,33 @@ Dhcp6ParseAddrOption (
 \r
   while (Cursor < IaInnerOpt + IaInnerLen) {\r
     //\r
-    // Count the Ia address option with non-0 valid time.\r
+    // Refer to RFC3315 Chapter 18.1.8, we need to update lifetimes for any addresses in the IA option\r
+    // that the client already has recorded in the IA, and discard the Ia address option with 0 valid time.\r
     //\r
-    OpCode  = ReadUnaligned16 ((UINT16 *) Cursor);\r
-    ValidLt = ReadUnaligned32 ((UINT32 *) (Cursor + 24));\r
-    if (OpCode == HTONS (Dhcp6OptIaAddr) && ValidLt != 0) {\r
-\r
+    OpCode      = ReadUnaligned16 ((UINT16 *)Cursor);\r
+    PreferredLt = NTOHL (ReadUnaligned32 ((UINT32 *)(Cursor + 20)));\r
+    ValidLt     = NTOHL (ReadUnaligned32 ((UINT32 *)(Cursor + 24)));\r
+    IaAddr      = (EFI_DHCP6_IA_ADDRESS *)(Cursor + 4);\r
+    if ((OpCode == HTONS (Dhcp6OptIaAddr)) && (ValidLt >= PreferredLt) &&\r
+        (Dhcp6AddrIsInCurrentIa (IaAddr, CurrentIa) || (ValidLt != 0)))\r
+    {\r
       if (AddrBuf != NULL) {\r
-        CopyMem (AddrBuf, Cursor + 4, sizeof (EFI_DHCP6_IA_ADDRESS));\r
-        AddrBuf->PreferredLifetime = NTOHL (AddrBuf->PreferredLifetime);\r
-        AddrBuf->ValidLifetime     = NTOHL (AddrBuf->ValidLifetime);\r
-        AddrBuf = (EFI_DHCP6_IA_ADDRESS *) ((UINT8 *) AddrBuf + sizeof (EFI_DHCP6_IA_ADDRESS));\r
+        CopyMem (AddrBuf, IaAddr, sizeof (EFI_DHCP6_IA_ADDRESS));\r
+        AddrBuf->PreferredLifetime = PreferredLt;\r
+        AddrBuf->ValidLifetime     = ValidLt;\r
+        AddrBuf                    = (EFI_DHCP6_IA_ADDRESS *)((UINT8 *)AddrBuf + sizeof (EFI_DHCP6_IA_ADDRESS));\r
       }\r
 \r
       (*AddrNum)++;\r
     }\r
-    DataLen = NTOHS (ReadUnaligned16 ((UINT16 *) (Cursor + 2)));\r
+\r
+    DataLen = NTOHS (ReadUnaligned16 ((UINT16 *)(Cursor + 2)));\r
     Cursor += (DataLen + 4);\r
   }\r
 }\r
 \r
-\r
 /**\r
-  Create a control blcok for the Ia according to the corresponding options.\r
+  Create a control block for the Ia according to the corresponding options.\r
 \r
   @param[in]  Instance              The pointer to DHCP6 Instance.\r
   @param[in]  IaInnerOpt            The pointer to the inner options in the Ia option.\r
@@ -1025,30 +1098,31 @@ Dhcp6ParseAddrOption (
   @retval     EFI_NOT_FOUND         No valid IA option is found.\r
   @retval     EFI_SUCCESS           Create an IA control block successfully.\r
   @retval     EFI_OUT_OF_RESOURCES  Required system resources could not be allocated.\r
+  @retval     EFI_DEVICE_ERROR      An unexpected error.\r
 \r
 **/\r
 EFI_STATUS\r
 Dhcp6GenerateIaCb (\r
-  IN  DHCP6_INSTANCE           *Instance,\r
-  IN  UINT8                    *IaInnerOpt,\r
-  IN  UINT16                   IaInnerLen,\r
-  IN  UINT32                   T1,\r
-  IN  UINT32                   T2\r
+  IN  DHCP6_INSTANCE  *Instance,\r
+  IN  UINT8           *IaInnerOpt,\r
+  IN  UINT16          IaInnerLen,\r
+  IN  UINT32          T1,\r
+  IN  UINT32          T2\r
   )\r
 {\r
-  UINT32                       AddrNum;\r
-  UINT32                       IaSize;\r
-  EFI_DHCP6_IA                 *Ia;\r
+  UINT32        AddrNum;\r
+  UINT32        IaSize;\r
+  EFI_DHCP6_IA  *Ia;\r
 \r
   if (Instance->IaCb.Ia == NULL) {\r
-    return EFI_NOT_FOUND;\r
+    return EFI_DEVICE_ERROR;\r
   }\r
 \r
   //\r
   // Calculate the number of addresses for this Ia, excluding the addresses with\r
   // the value 0 of valid lifetime.\r
   //\r
-  Dhcp6ParseAddrOption (IaInnerOpt, IaInnerLen, &AddrNum, NULL);\r
+  Dhcp6ParseAddrOption (Instance->IaCb.Ia, IaInnerOpt, IaInnerLen, &AddrNum, NULL);\r
 \r
   if (AddrNum == 0) {\r
     return EFI_NOT_FOUND;\r
@@ -1058,7 +1132,7 @@ Dhcp6GenerateIaCb (
   // Allocate for new IA.\r
   //\r
   IaSize = sizeof (EFI_DHCP6_IA) + (AddrNum - 1) * sizeof (EFI_DHCP6_IA_ADDRESS);\r
-  Ia = AllocateZeroPool (IaSize);\r
+  Ia     = AllocateZeroPool (IaSize);\r
 \r
   if (Ia == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
@@ -1070,7 +1144,7 @@ Dhcp6GenerateIaCb (
   Ia->State          = Instance->IaCb.Ia->State;\r
   Ia->IaAddressCount = AddrNum;\r
   CopyMem (&Ia->Descriptor, &Instance->Config->IaDescriptor, sizeof (EFI_DHCP6_IA_DESCRIPTOR));\r
-  Dhcp6ParseAddrOption (IaInnerOpt, IaInnerLen, &AddrNum, Ia->IaAddress);\r
+  Dhcp6ParseAddrOption (Instance->IaCb.Ia, IaInnerOpt, IaInnerLen, &AddrNum, Ia->IaAddress);\r
 \r
   //\r
   // Free original IA resource.\r
@@ -1078,19 +1152,19 @@ Dhcp6GenerateIaCb (
   if (Instance->IaCb.Ia->ReplyPacket != NULL) {\r
     FreePool (Instance->IaCb.Ia->ReplyPacket);\r
   }\r
-  FreePool (Instance->IaCb.Ia);\r
 \r
+  FreePool (Instance->IaCb.Ia);\r
 \r
   ZeroMem (&Instance->IaCb, sizeof (DHCP6_IA_CB));\r
 \r
   //\r
   // Update IaCb to use new IA.\r
   //\r
-  Instance->IaCb.Ia   = Ia;\r
+  Instance->IaCb.Ia = Ia;\r
 \r
   //\r
 \r
- // Fill in IaCb fields. Such as T1, T2, AllExpireTime and LeaseTime.\r
 // Fill in IaCb fields. Such as T1, T2, AllExpireTime and LeaseTime.\r
   //\r
   Instance->IaCb.T1 = T1;\r
   Instance->IaCb.T2 = T2;\r
@@ -1099,7 +1173,6 @@ Dhcp6GenerateIaCb (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Cache the current IA configuration information.\r
 \r
@@ -1111,11 +1184,11 @@ Dhcp6GenerateIaCb (
 **/\r
 EFI_STATUS\r
 Dhcp6CacheIa (\r
-  IN DHCP6_INSTANCE           *Instance\r
+  IN DHCP6_INSTANCE  *Instance\r
   )\r
 {\r
-  UINTN                        IaSize;\r
-  EFI_DHCP6_IA                 *Ia;\r
+  UINTN         IaSize;\r
+  EFI_DHCP6_IA  *Ia;\r
 \r
   Ia = Instance->IaCb.Ia;\r
 \r
@@ -1129,29 +1202,31 @@ Dhcp6CacheIa (
     if (Instance->CacheIa == NULL) {\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
+\r
     CopyMem (Instance->CacheIa, Ia, IaSize);\r
   }\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
-  Append CacheIa to the currrent IA. Meanwhile, clear CacheIa.ValidLifetime to 0.\r
+  Append CacheIa to the current IA. Meanwhile, clear CacheIa.ValidLifetime to 0.\r
 \r
   @param[in]  Instance            The pointer to DHCP6 instance.\r
 \r
 **/\r
 VOID\r
 Dhcp6AppendCacheIa (\r
-  IN DHCP6_INSTANCE           *Instance\r
+  IN DHCP6_INSTANCE  *Instance\r
   )\r
 {\r
-  UINT8                        *Ptr;\r
-  UINTN                        Index;\r
-  UINTN                        IaSize;\r
-  UINTN                        NewIaSize;\r
-  EFI_DHCP6_IA                 *Ia;\r
-  EFI_DHCP6_IA                 *NewIa;\r
-  EFI_DHCP6_IA                 *CacheIa;\r
+  UINT8         *Ptr;\r
+  UINTN         Index;\r
+  UINTN         IaSize;\r
+  UINTN         NewIaSize;\r
+  EFI_DHCP6_IA  *Ia;\r
+  EFI_DHCP6_IA  *NewIa;\r
+  EFI_DHCP6_IA  *CacheIa;\r
 \r
   Ia      = Instance->IaCb.Ia;\r
   CacheIa = Instance->CacheIa;\r
@@ -1173,11 +1248,11 @@ Dhcp6AppendCacheIa (
     // Clear old address.ValidLifetime\r
     //\r
     for (Index = 0; Index < CacheIa->IaAddressCount; Index++) {\r
-      CacheIa->IaAddress[Index].ValidLifetime  = 0;\r
+      CacheIa->IaAddress[Index].ValidLifetime = 0;\r
     }\r
 \r
     NewIa->IaAddressCount += CacheIa->IaAddressCount;\r
-    Ptr   = (UINT8*)&NewIa->IaAddress[Ia->IaAddressCount];\r
+    Ptr                    = (UINT8 *)&NewIa->IaAddress[Ia->IaAddressCount];\r
     CopyMem (Ptr, CacheIa->IaAddress, CacheIa->IaAddressCount * sizeof (EFI_DHCP6_IA_ADDRESS));\r
 \r
     //\r
@@ -1185,7 +1260,46 @@ Dhcp6AppendCacheIa (
     //\r
     FreePool (Instance->CacheIa);\r
     FreePool (Instance->IaCb.Ia);\r
-    Instance->CacheIa  = NULL;\r
-    Instance->IaCb.Ia  = NewIa;\r
+    Instance->CacheIa = NULL;\r
+    Instance->IaCb.Ia = NewIa;\r
+  }\r
+}\r
+\r
+/**\r
+  Calculate the Dhcp6 get mapping timeout by adding additional delay to the IP6 DAD transmits count.\r
+\r
+  @param[in]   Ip6Cfg              The pointer to Ip6 config protocol.\r
+  @param[out]  TimeOut             The time out value in 100ns units.\r
+\r
+  @retval   EFI_INVALID_PARAMETER  Input parameters are invalid.\r
+  @retval   EFI_SUCCESS            Calculate the time out value successfully.\r
+**/\r
+EFI_STATUS\r
+Dhcp6GetMappingTimeOut (\r
+  IN  EFI_IP6_CONFIG_PROTOCOL  *Ip6Cfg,\r
+  OUT UINTN                    *TimeOut\r
+  )\r
+{\r
+  EFI_STATUS                                Status;\r
+  UINTN                                     DataSize;\r
+  EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS  DadXmits;\r
+\r
+  if ((Ip6Cfg == NULL) || (TimeOut == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);\r
+  Status   = Ip6Cfg->GetData (\r
+                       Ip6Cfg,\r
+                       Ip6ConfigDataTypeDupAddrDetectTransmits,\r
+                       &DataSize,\r
+                       &DadXmits\r
+                       );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
   }\r
+\r
+  *TimeOut = TICKS_PER_SECOND * DadXmits.DupAddrDetectTransmits + DHCP6_DAD_ADDITIONAL_DELAY;\r
+\r
+  return EFI_SUCCESS;\r
 }\r