]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c
Remove ASSERT when failed to Get/Set “AttemptOrder” and “ClientId” variable.
[mirror_edk2.git] / NetworkPkg / Dhcp6Dxe / Dhcp6Utility.c
index f4e7649e6cba2b4734db308cb52fd6e1de080835..7591bf56bab2bda372d1c1bfa97c75deabcc14c6 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Dhcp6 support functions implementation.\r
 \r
 /** @file\r
   Dhcp6 support functions implementation.\r
 \r
-  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2014, 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
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -34,27 +34,18 @@ Dhcp6GenerateClientId (
   EFI_DHCP6_DUID            *Duid;\r
   EFI_TIME                  Time;\r
   UINT32                    Stamp;\r
   EFI_DHCP6_DUID            *Duid;\r
   EFI_TIME                  Time;\r
   UINT32                    Stamp;\r
+  EFI_GUID                  Uuid;\r
+\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
 \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
 \r
   if (Duid != NULL) {\r
     return Duid;\r
   }\r
 \r
-  //\r
-  // Generate a time stamp of the seconds from 2000/1/1, assume 30day/month.\r
-  //\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
   //\r
   //  The format of client identifier option:\r
   //\r
   //\r
   //  The format of client identifier option:\r
   //\r
@@ -68,42 +59,96 @@ Dhcp6GenerateClientId (
   //    .                                                               .\r
   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
   //\r
   //    .                                                               .\r
   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
   //\r
-  //\r
-  //  The format of DUID-LLT:\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 (1)        |    hardware type (16 bits)    |\r
-  //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
-  //    |                        time (32 bits)                         |\r
-  //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
-  //    .                                                               .\r
-  //    .             link-layer address (variable length)              .\r
-  //    .                                                               .\r
-  //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
-  //\r
 \r
   //\r
 \r
   //\r
-  // sizeof (option-len + Duid-type + hardware-type + time) = 10 bytes\r
+  // If System UUID is found from SMBIOS Table, use DUID-UUID type.\r
   //\r
   //\r
-  Duid = AllocateZeroPool (10 + Mode->HwAddressSize);\r
-  if (Duid == NULL) {\r
-    return NULL;\r
-  }\r
+  if (!EFI_ERROR (NetLibGetSystemGuid (&Uuid))) {\r
+    //\r
+    //\r
+    //  The format of DUID-UUID:\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
+    //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |\r
+    //   |                                                               |\r
+    //   |                                                               |\r
+    //   |                                -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+    //   |                                |\r
+    //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-\r
 \r
 \r
-  //\r
-  // sizeof (Duid-type + hardware-type + time) = 8 bytes\r
-  //\r
-  Duid->Length = (UINT16) (Mode->HwAddressSize + 8);\r
+    //\r
+    // sizeof (option-len + Duid-type + UUID-size) = 20 bytes\r
+    //\r
+    Duid = AllocateZeroPool (2 + 2 + sizeof (EFI_GUID));\r
+    if (Duid == NULL) {\r
+      return NULL;\r
+    }\r
 \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
+    // sizeof (Duid-type + UUID-size) = 18 bytes\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
+\r
+  } else {\r
+      \r
+    //\r
+    //\r
+    //  The format of DUID-LLT:\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 (1)        |    hardware type (16 bits)    |\r
+    //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+    //    |                        time (32 bits)                         |\r
+    //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+    //    .                                                               .\r
+    //    .             link-layer address (variable length)              .\r
+    //    .                                                               .\r
+    //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+    //\r
 \r
 \r
-  CopyMem (Duid->Duid + 8, &Mode->CurrentAddress, Mode->HwAddressSize);\r
+    //\r
+    // Generate a time stamp of the seconds from 2000/1/1, assume 30day/month.\r
+    //\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
+    //\r
+    // sizeof (option-len + Duid-type + hardware-type + time) = 10 bytes\r
+    //\r
+    Duid = AllocateZeroPool (10 + Mode->HwAddressSize);\r
+    if (Duid == NULL) {\r
+      return NULL;\r
+    }\r
+  \r
+    //\r
+    // sizeof (Duid-type + hardware-type + time) = 8 bytes\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
+    CopyMem (Duid->Duid + 8, &Mode->CurrentAddress, Mode->HwAddressSize);\r
+  }\r
 \r
   Status = gRT->SetVariable (\r
                   L"ClientId",\r
 \r
   Status = gRT->SetVariable (\r
                   L"ClientId",\r
@@ -112,7 +157,10 @@ Dhcp6GenerateClientId (
                   Duid->Length + 2,\r
                   (VOID *) Duid\r
                   );\r
                   Duid->Length + 2,\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
   return Duid;\r
 }\r
@@ -602,6 +650,75 @@ Dhcp6AppendOption (
   return Buf;\r
 }\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
+\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
+  Buf                     += 4;\r
+\r
+  if (MessageType != Dhcp6MsgConfirm) {\r
+    WriteUnaligned32 ((UINT32 *) Buf, HTONL (IaAddr->ValidLifetime));\r
+  }\r
+  Buf                     += 4;\r
+\r
+  return Buf;\r
+}\r
+\r
 \r
 /**\r
   Append the appointed Ia option to Buf, and move Buf to the end.\r
 \r
 /**\r
   Append the appointed Ia option to Buf, and move Buf to the end.\r
@@ -610,6 +727,7 @@ 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]      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
   @return         Buf           The position to append the next Ia option.\r
 \r
@@ -619,13 +737,13 @@ Dhcp6AppendIaOption (
   IN OUT UINT8                  *Buf,\r
   IN     EFI_DHCP6_IA           *Ia,\r
   IN     UINT32                 T1,\r
   IN OUT UINT8                  *Buf,\r
   IN     EFI_DHCP6_IA           *Ia,\r
   IN     UINT32                 T1,\r
-  IN     UINT32                 T2\r
+  IN     UINT32                 T2,\r
+  IN     UINT32                 MessageType\r
   )\r
 {\r
   UINT8                     *AddrOpt;\r
   UINT16                    *Len;\r
   UINTN                     Index;\r
   )\r
 {\r
   UINT8                     *AddrOpt;\r
   UINT16                    *Len;\r
   UINTN                     Index;\r
-  UINT16                    Length;\r
 \r
   //\r
   //  The format of IA_NA and IA_TA option:\r
 \r
   //\r
   //  The format of IA_NA and IA_TA option:\r
@@ -668,9 +786,9 @@ Dhcp6AppendIaOption (
   // Fill the value of t1 and t2 if iana, keep it 0xffffffff if no specified.\r
   //\r
   if (Ia->Descriptor.Type == Dhcp6OptIana) {\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
+    WriteUnaligned32 ((UINT32 *) Buf, HTONL ((T1 != 0) ? T1 : 0xffffffff));\r
     Buf                   += 4;\r
     Buf                   += 4;\r
-    WriteUnaligned32 ((UINT32 *) Buf, ((T2 != 0) ? T2 : 0xffffffff));\r
+    WriteUnaligned32 ((UINT32 *) Buf, HTONL ((T2 != 0) ? T2 : 0xffffffff));\r
     Buf                   += 4;\r
   }\r
 \r
     Buf                   += 4;\r
   }\r
 \r
@@ -678,15 +796,8 @@ Dhcp6AppendIaOption (
   // Fill all the addresses belong to the Ia\r
   //\r
   for (Index = 0; Index < Ia->IaAddressCount; Index++) {\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
   }\r
 \r
   //\r
@@ -782,7 +893,7 @@ SetElapsedTime (
 \r
   //\r
   // Sentinel value of 0 means that this is the first DHCP packet that we are\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
   // gets 0 elapsed-time.  Otherwise, calculate based on StartTime.\r
   //\r
   if (Instance->StartTime == 0) {\r
@@ -889,10 +1000,39 @@ Dhcp6SeekIaOption (
   return Option;\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 blcok.\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
+  return FALSE;\r
+}\r
 \r
 /**\r
   Parse the address option and update the address infomation.\r
 \r
 \r
 /**\r
   Parse the address option and update the address infomation.\r
 \r
+  @param[in]      CurrentIa     The pointer to the Ia Address in control blcok.\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
   @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
@@ -901,6 +1041,7 @@ Dhcp6SeekIaOption (
 **/\r
 VOID\r
 Dhcp6ParseAddrOption (\r
 **/\r
 VOID\r
 Dhcp6ParseAddrOption (\r
+  IN     EFI_DHCP6_IA            *CurrentIa,\r
   IN     UINT8                   *IaInnerOpt,\r
   IN     UINT16                  IaInnerLen,\r
      OUT UINT32                  *AddrNum,\r
   IN     UINT8                   *IaInnerOpt,\r
   IN     UINT16                  IaInnerLen,\r
      OUT UINT32                  *AddrNum,\r
@@ -911,6 +1052,8 @@ Dhcp6ParseAddrOption (
   UINT16                      DataLen;\r
   UINT16                      OpCode;\r
   UINT32                      ValidLt;\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
 \r
   //\r
   //  The format of the IA Address option:\r
@@ -947,19 +1090,21 @@ Dhcp6ParseAddrOption (
 \r
   while (Cursor < IaInnerOpt + IaInnerLen) {\r
     //\r
 \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
     //\r
     OpCode  = ReadUnaligned16 ((UINT16 *) Cursor);\r
-    ValidLt = ReadUnaligned32 ((UINT32 *) (Cursor + 24));\r
-    if (OpCode == HTONS (Dhcp6OptIaAddr) && ValidLt != 0) {\r
-\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
       if (AddrBuf != NULL) {\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
+        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
         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
       (*AddrNum)++;\r
     }\r
     DataLen = NTOHS (ReadUnaligned16 ((UINT16 *) (Cursor + 2)));\r
@@ -980,6 +1125,7 @@ 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_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
 \r
 **/\r
 EFI_STATUS\r
@@ -996,14 +1142,14 @@ Dhcp6GenerateIaCb (
   EFI_DHCP6_IA                 *Ia;\r
 \r
   if (Instance->IaCb.Ia == NULL) {\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
   }\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
 \r
   if (AddrNum == 0) {\r
     return EFI_NOT_FOUND;\r
@@ -1025,7 +1171,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
   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
 \r
   //\r
   // Free original IA resource.\r
@@ -1144,3 +1290,42 @@ Dhcp6AppendCacheIa (
     Instance->IaCb.Ia  = NewIa;\r
   }\r
 }\r
     Instance->IaCb.Ia  = NewIa;\r
   }\r
 }\r
+\r
+/**\r
+  Calculate the Dhcp6 get mapping timeout by adding additinal 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