]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Library/UefiShellNetwork2CommandsLib/Ifconfig6.c
ShellPkg: Merge Ping6 and Ifconfig6 tools to Shell command.
[mirror_edk2.git] / ShellPkg / Library / UefiShellNetwork2CommandsLib / Ifconfig6.c
diff --git a/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ifconfig6.c b/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ifconfig6.c
new file mode 100644 (file)
index 0000000..371b368
--- /dev/null
@@ -0,0 +1,1839 @@
+/** @file\r
+  The implementation for Shell command IfConfig6.\r
+\r
+  Copyright (c) 2016, 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
+\r
+**/\r
+#include "UefiShellNetwork2CommandsLib.h"\r
+\r
+enum {\r
+  IfConfig6OpList     = 1,\r
+  IfConfig6OpSet      = 2,\r
+  IfConfig6OpClear    = 3\r
+};\r
+\r
+typedef enum {\r
+  VarCheckReserved      = -1,\r
+  VarCheckOk            = 0,\r
+  VarCheckDuplicate,\r
+  VarCheckConflict,\r
+  VarCheckUnknown,\r
+  VarCheckLackValue,\r
+  VarCheckOutOfMem\r
+} VAR_CHECK_CODE;\r
+\r
+typedef enum {\r
+  FlagTypeSingle         = 0,\r
+  FlagTypeNeedVar,\r
+  FlagTypeNeedSet,\r
+  FlagTypeSkipUnknown\r
+} VAR_CHECK_FLAG_TYPE;\r
+\r
+#define MACADDRMAXSIZE    32\r
+#define PREFIXMAXLEN      16\r
+\r
+typedef struct _IFCONFIG6_INTERFACE_CB {\r
+  EFI_HANDLE                                  NicHandle;\r
+  LIST_ENTRY                                  Link;\r
+  EFI_IP6_CONFIG_PROTOCOL                     *IfCfg;\r
+  EFI_IP6_CONFIG_INTERFACE_INFO               *IfInfo;\r
+  EFI_IP6_CONFIG_INTERFACE_ID                 *IfId;\r
+  EFI_IP6_CONFIG_POLICY                       Policy;\r
+  EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS    Xmits;\r
+  UINT32                                      DnsCnt;\r
+  EFI_IPv6_ADDRESS                            DnsAddr[1];\r
+} IFCONFIG6_INTERFACE_CB;\r
+\r
+typedef struct _ARG_LIST ARG_LIST;\r
+\r
+struct _ARG_LIST {\r
+  ARG_LIST    *Next;\r
+  CHAR16      *Arg;\r
+};\r
+\r
+typedef struct _IFCONFIG6_PRIVATE_DATA {\r
+  EFI_HANDLE  ImageHandle;\r
+  LIST_ENTRY  IfList;\r
+\r
+  UINT32      OpCode;\r
+  CHAR16      *IfName;\r
+  ARG_LIST    *VarArg;\r
+} IFCONFIG6_PRIVATE_DATA;\r
+\r
+typedef struct _VAR_CHECK_ITEM{\r
+  CHAR16                 *FlagStr;\r
+  UINT32                 FlagID;\r
+  UINT32                 ConflictMask;\r
+  VAR_CHECK_FLAG_TYPE    FlagType;\r
+} VAR_CHECK_ITEM;\r
+\r
+\r
+SHELL_PARAM_ITEM    mIfConfig6CheckList[] = {\r
+  {\r
+    L"-b",\r
+    TypeFlag\r
+  },\r
+  {\r
+    L"-s",\r
+    TypeMaxValue\r
+  },\r
+  {\r
+    L"-l",\r
+    TypeValue\r
+  },\r
+  {\r
+    L"-r",\r
+    TypeValue\r
+  },\r
+  {\r
+    L"-?",\r
+    TypeFlag\r
+  },\r
+  {\r
+    NULL,\r
+    TypeMax\r
+  },\r
+};\r
+\r
+VAR_CHECK_ITEM  mIfConfig6SetCheckList[] = {\r
+  {\r
+   L"auto",\r
+    0x00000001,\r
+    0x00000001,\r
+    FlagTypeSingle\r
+  },\r
+  {\r
+    L"man",\r
+    0x00000002,\r
+    0x00000001,\r
+    FlagTypeSingle\r
+  },\r
+  {\r
+    L"host",\r
+    0x00000004,\r
+    0x00000002,\r
+    FlagTypeSingle\r
+  },\r
+  {\r
+    L"dad",\r
+    0x00000008,\r
+    0x00000004,\r
+    FlagTypeSingle\r
+  },\r
+  {\r
+    L"gw",\r
+    0x00000010,\r
+    0x00000008,\r
+    FlagTypeSingle\r
+  },\r
+  {\r
+    L"dns",\r
+    0x00000020,\r
+    0x00000010,\r
+    FlagTypeSingle\r
+  },\r
+  {\r
+    L"id",\r
+    0x00000040,\r
+    0x00000020,\r
+    FlagTypeSingle\r
+  },\r
+  {\r
+    NULL,\r
+    0x0,\r
+    0x0,\r
+    FlagTypeSkipUnknown\r
+  },\r
+};\r
+\r
+/**\r
+  Split a string with specified separator and save the substring to a list.\r
+\r
+  @param[in]    String       The pointer of the input string.\r
+  @param[in]    Separator    The specified separator.\r
+\r
+  @return The pointer of headnode of ARG_LIST.\r
+\r
+**/\r
+ARG_LIST *\r
+IfConfig6SplitStrToList (\r
+  IN CONST CHAR16    *String,\r
+  IN CHAR16          Separator\r
+  )\r
+{\r
+  CHAR16      *Str;\r
+  CHAR16      *ArgStr;\r
+  ARG_LIST    *ArgList;\r
+  ARG_LIST    *ArgNode;\r
+\r
+  if (String == NULL || *String == L'\0') {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Copy the CONST string to a local copy.\r
+  //\r
+  Str     = AllocateCopyPool (StrSize (String), String);\r
+  ASSERT (Str != NULL);\r
+  ArgStr  = Str;\r
+\r
+  //\r
+  // init a node for the list head.\r
+  //\r
+  ArgNode = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST));\r
+  ASSERT (ArgNode != NULL);\r
+  ArgList = ArgNode;\r
+\r
+  //\r
+  // Split the local copy and save in the list node.\r
+  //\r
+  while (*Str != L'\0') {\r
+    if (*Str == Separator) {\r
+      *Str          = L'\0';\r
+      ArgNode->Arg  = ArgStr;\r
+      ArgStr        = Str + 1;\r
+      ArgNode->Next = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST));\r
+      ASSERT (ArgNode->Next != NULL);\r
+      ArgNode = ArgNode->Next;\r
+    }\r
+\r
+    Str++;\r
+  }\r
+\r
+  ArgNode->Arg  = ArgStr;\r
+  ArgNode->Next = NULL;\r
+\r
+  return ArgList;\r
+}\r
+\r
+/**\r
+  Check the correctness of input Args with '-s' option.\r
+\r
+  @param[in]    CheckList    The pointer of VAR_CHECK_ITEM array.\r
+  @param[in]    Name         The pointer of input arg.\r
+  @param[in]    Init         The switch to execute the check.\r
+\r
+  @return The value of VAR_CHECK_CODE.\r
+\r
+**/\r
+VAR_CHECK_CODE\r
+IfConfig6RetriveCheckListByName(\r
+  IN VAR_CHECK_ITEM    *CheckList,\r
+  IN CHAR16            *Name,\r
+  IN BOOLEAN           Init\r
+)\r
+{\r
+  STATIC UINT32     CheckDuplicate;\r
+  STATIC UINT32     CheckConflict;\r
+  VAR_CHECK_CODE    RtCode;\r
+  UINT32            Index;\r
+  VAR_CHECK_ITEM    Arg;\r
+\r
+  if (Init) {\r
+    CheckDuplicate = 0;\r
+    CheckConflict  = 0;\r
+    return VarCheckOk;\r
+  }\r
+\r
+  RtCode  = VarCheckOk;\r
+  Index   = 0;\r
+  Arg     = CheckList[Index];\r
+\r
+  //\r
+  // Check the Duplicated/Conflicted/Unknown input Args.\r
+  //\r
+  while (Arg.FlagStr != NULL) {\r
+    if (StrCmp (Arg.FlagStr, Name) == 0) {\r
+\r
+      if (CheckDuplicate & Arg.FlagID) {\r
+        RtCode = VarCheckDuplicate;\r
+        break;\r
+      }\r
+\r
+      if (CheckConflict & Arg.ConflictMask) {\r
+        RtCode = VarCheckConflict;\r
+        break;\r
+      }\r
+\r
+      CheckDuplicate |= Arg.FlagID;\r
+      CheckConflict  |= Arg.ConflictMask;\r
+      break;\r
+    }\r
+\r
+    Arg = CheckList[++Index];\r
+  }\r
+\r
+  if (Arg.FlagStr == NULL) {\r
+    RtCode = VarCheckUnknown;\r
+  }\r
+\r
+  return RtCode;\r
+}\r
+\r
+/**\r
+  The notify function of create event when performing a manual config.\r
+\r
+  @param[in]    Event        The event this notify function registered to.\r
+  @param[in]    Context      Pointer to the context data registered to the event.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+IfConfig6ManualAddressNotify (\r
+  IN EFI_EVENT    Event,\r
+  IN VOID         *Context\r
+  )\r
+{\r
+  *((BOOLEAN *) Context) = TRUE;\r
+}\r
+\r
+/**\r
+  Print MAC address.\r
+\r
+  @param[in]    Node    The pointer of MAC address buffer.\r
+  @param[in]    Size    The size of MAC address buffer.\r
+\r
+**/\r
+VOID\r
+IfConfig6PrintMacAddr (\r
+  IN UINT8     *Node,\r
+  IN UINT32    Size\r
+  )\r
+{\r
+  UINTN    Index;\r
+\r
+  ASSERT (Size <= MACADDRMAXSIZE);\r
+\r
+  for (Index = 0; Index < Size; Index++) {\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_MAC_ADDR_BODY), gShellNetwork2HiiHandle, Node[Index]);\r
+    if (Index + 1 < Size) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), gShellNetwork2HiiHandle);\r
+    }\r
+  }\r
+\r
+  ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle);\r
+}\r
+\r
+/**\r
+  Print IPv6 address.\r
+\r
+  @param[in]    Ip           The pointer of Ip bufffer in EFI_IPv6_ADDRESS format.\r
+  @param[in]    PrefixLen    The pointer of PrefixLen that describes the size Prefix.\r
+\r
+**/\r
+VOID\r
+IfConfig6PrintIpAddr (\r
+  IN EFI_IPv6_ADDRESS    *Ip,\r
+  IN UINT8               *PrefixLen\r
+  )\r
+{\r
+  UINTN      Index;\r
+  BOOLEAN    Short;\r
+\r
+  Short = FALSE;\r
+\r
+  for (Index = 0; Index < PREFIXMAXLEN; Index = Index + 2) {\r
+\r
+    if (!Short && (Index + 1 < PREFIXMAXLEN) && (Index % 2 == 0) && (Ip->Addr[Index] == 0) && (Ip->Addr[Index + 1] == 0)) {\r
+      //\r
+      // Deal with the case of ::.\r
+      //\r
+      if (Index == 0) {\r
+        //\r
+        // :: is at the beginning of the address.\r
+        //\r
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), gShellNetwork2HiiHandle);\r
+      }\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), gShellNetwork2HiiHandle);\r
+\r
+      while ((Ip->Addr[Index] == 0) && (Ip->Addr[Index + 1] == 0) && (Index < PREFIXMAXLEN)) {\r
+        Index = Index + 2;\r
+        if (Index > PREFIXMAXLEN - 2) {\r
+          break;\r
+        }\r
+      }\r
+\r
+      Short = TRUE;\r
+\r
+      if (Index == PREFIXMAXLEN) {\r
+        //\r
+        // :: is at the end of the address.\r
+        //\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (Index < PREFIXMAXLEN - 1) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IP_ADDR_BODY), gShellNetwork2HiiHandle, Ip->Addr[Index]);\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IP_ADDR_BODY), gShellNetwork2HiiHandle, Ip->Addr[Index + 1]);\r
+    }\r
+\r
+    if (Index + 2 < PREFIXMAXLEN) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), gShellNetwork2HiiHandle);\r
+    }\r
+  }\r
+\r
+  if (PrefixLen != NULL) {\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_PREFIX_LEN), gShellNetwork2HiiHandle, *PrefixLen);\r
+  }\r
+}\r
+\r
+/**\r
+  Pick up host IPv6 address in string format from Args with "-s" option and convert it to EFI_IP6_CONFIG_MANUAL_ADDRESS format.\r
+\r
+  @param[in, out]    Arg        The pointer of the address of ARG_LIST which save Args with the "-s" option.\r
+  @param[out]        Buf        The pointer of the address of EFI_IP6_CONFIG_MANUAL_ADDRESS.\r
+  @param[out]        BufSize    The pointer of BufSize that describes the size of Buf in bytes.\r
+\r
+  @retval EFI_SUCCESS    The convertion is successful.\r
+  @retval Others         Does't find the host address, or it is an invalid IPv6 address in string format.\r
+\r
+**/\r
+EFI_STATUS\r
+IfConfig6ParseManualAddressList (\r
+  IN OUT ARG_LIST                         **Arg,\r
+     OUT EFI_IP6_CONFIG_MANUAL_ADDRESS    **Buf,\r
+     OUT UINTN                            *BufSize\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  EFI_IP6_CONFIG_MANUAL_ADDRESS    *AddrBuf;\r
+  ARG_LIST                         *VarArg;\r
+  EFI_IPv6_ADDRESS                 Address;\r
+  UINT8                            Prefix;\r
+  UINT8                            AddrCnt;\r
+\r
+  Prefix   = 0;\r
+  AddrCnt  = 0;\r
+  *BufSize = 0;\r
+  *Buf     = NULL;\r
+  VarArg   = *Arg;\r
+  Status   = EFI_SUCCESS;\r
+\r
+  //\r
+  // Go through the list to check the correctness of input host ip6 address.\r
+  //\r
+  while ((!EFI_ERROR (Status)) && (VarArg != NULL)) {\r
+\r
+    Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // host ip ip ... gw\r
+      //\r
+      break;\r
+    }\r
+\r
+    VarArg = VarArg->Next;\r
+    AddrCnt++;\r
+  }\r
+\r
+  if (AddrCnt == 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  AddrBuf = AllocateZeroPool (AddrCnt * sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS));\r
+  ASSERT (AddrBuf != NULL);\r
+\r
+  AddrCnt = 0;\r
+  VarArg  = *Arg;\r
+  Status  = EFI_SUCCESS;\r
+\r
+  //\r
+  // Go through the list to fill in the EFI_IP6_CONFIG_MANUAL_ADDRESS structure.\r
+  //\r
+  while ((!EFI_ERROR (Status)) && (VarArg != NULL)) {\r
+\r
+    Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    // If prefix length is not set, set it as Zero here. In the IfConfigSetInterfaceInfo()\r
+    // Zero prefix, length will be transfered to default prefix length.\r
+    //\r
+    if (Prefix == 0xFF) {\r
+      Prefix = 0;\r
+    }\r
+    AddrBuf[AddrCnt].IsAnycast    = FALSE;\r
+    AddrBuf[AddrCnt].PrefixLength = Prefix;\r
+    IP6_COPY_ADDRESS (&AddrBuf[AddrCnt].Address, &Address);\r
+    VarArg = VarArg->Next;\r
+    AddrCnt++;\r
+  }\r
+\r
+  *Arg = VarArg;\r
+\r
+  if (EFI_ERROR (Status) && (Status != EFI_INVALID_PARAMETER)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  *Buf     = AddrBuf;\r
+  *BufSize = AddrCnt * sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS);\r
+\r
+  return EFI_SUCCESS;\r
+\r
+ON_ERROR:\r
+\r
+  FreePool (AddrBuf);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Pick up gw/dns IPv6 address in string format from Args with "-s" option and convert it to EFI_IPv6_ADDRESS format.\r
+\r
+  @param[in, out]    Arg        The pointer of the address of ARG_LIST that save Args with the "-s" option.\r
+  @param[out]        Buf        The pointer of the address of EFI_IPv6_ADDRESS.\r
+  @param[out]        BufSize    The pointer of BufSize that describes the size of Buf in bytes.\r
+\r
+  @retval EFI_SUCCESS    The conversion is successful.\r
+  @retval Others         Doesn't find the host address, or it is an invalid IPv6 address in string format.\r
+\r
+**/\r
+EFI_STATUS\r
+IfConfig6ParseGwDnsAddressList (\r
+  IN OUT ARG_LIST            **Arg,\r
+     OUT EFI_IPv6_ADDRESS    **Buf,\r
+     OUT UINTN               *BufSize\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+  EFI_IPv6_ADDRESS    *AddrBuf;\r
+  ARG_LIST            *VarArg;\r
+  EFI_IPv6_ADDRESS    Address;\r
+  UINT8               Prefix;\r
+  UINT8               AddrCnt;\r
+\r
+  AddrCnt  = 0;\r
+  *BufSize = 0;\r
+  *Buf     = NULL;\r
+  VarArg   = *Arg;\r
+  Status   = EFI_SUCCESS;\r
+\r
+  //\r
+  // Go through the list to check the correctness of input gw/dns address.\r
+  //\r
+  while ((!EFI_ERROR (Status)) && (VarArg != NULL)) {\r
+\r
+    Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // gw ip ip ... host\r
+      //\r
+      break;\r
+    }\r
+\r
+    VarArg = VarArg->Next;\r
+    AddrCnt++;\r
+  }\r
+\r
+  if (AddrCnt == 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  AddrBuf = AllocateZeroPool (AddrCnt * sizeof (EFI_IPv6_ADDRESS));\r
+  ASSERT (AddrBuf != NULL);\r
+\r
+  AddrCnt = 0;\r
+  VarArg  = *Arg;\r
+  Status  = EFI_SUCCESS;\r
+\r
+  //\r
+  // Go through the list to fill in the EFI_IPv6_ADDRESS structure.\r
+  //\r
+  while ((!EFI_ERROR (Status)) && (VarArg != NULL)) {\r
+\r
+    Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+\r
+    IP6_COPY_ADDRESS (&AddrBuf[AddrCnt], &Address);\r
+\r
+    VarArg = VarArg->Next;\r
+    AddrCnt++;\r
+  }\r
+\r
+  *Arg = VarArg;\r
+\r
+  if (EFI_ERROR (Status) && (Status != EFI_INVALID_PARAMETER)) {\r
+   goto ON_ERROR;\r
+  }\r
+\r
+  *Buf     = AddrBuf;\r
+  *BufSize = AddrCnt * sizeof (EFI_IPv6_ADDRESS);\r
+\r
+  return EFI_SUCCESS;\r
+\r
+ON_ERROR:\r
+\r
+  FreePool (AddrBuf);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Parse InterfaceId in string format from Args with the "-s" option and convert it to EFI_IP6_CONFIG_INTERFACE_ID format.\r
+\r
+  @param[in, out]   Arg     The pointer of the address of ARG_LIST that saves Args with the "-s" option.\r
+  @param[out]       IfId    The pointer of EFI_IP6_CONFIG_INTERFACE_ID.\r
+\r
+  @retval EFI_SUCCESS              The get status processed successfullly.\r
+  @retval EFI_INVALID_PARAMETER    The get status process failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfConfig6ParseInterfaceId (\r
+  IN OUT ARG_LIST                       **Arg,\r
+     OUT EFI_IP6_CONFIG_INTERFACE_ID    **IfId\r
+  )\r
+{\r
+  UINT8     Index;\r
+  UINT8     NodeVal;\r
+  CHAR16    *IdStr;\r
+\r
+  if (*Arg == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Index = 0;\r
+  IdStr = (*Arg)->Arg;\r
+  ASSERT (IfId != NULL);\r
+  *IfId = AllocateZeroPool (sizeof (EFI_IP6_CONFIG_INTERFACE_ID));\r
+  ASSERT (*IfId != NULL);\r
+\r
+  while ((*IdStr != L'\0') && (Index < 8)) {\r
+\r
+    NodeVal = 0;\r
+    while ((*IdStr != L':') && (*IdStr != L'\0')) {\r
+\r
+      if ((*IdStr <= L'F') && (*IdStr >= L'A')) {\r
+        NodeVal = (UINT8)((NodeVal << 4) + *IdStr - L'A' + 10);\r
+      } else if ((*IdStr <= L'f') && (*IdStr >= L'a')) {\r
+        NodeVal = (UINT8)((NodeVal << 4) + *IdStr - L'a' + 10);\r
+      } else if ((*IdStr <= L'9') && (*IdStr >= L'0')) {\r
+        NodeVal = (UINT8)((NodeVal << 4) + *IdStr - L'0');\r
+      } else {\r
+        FreePool (*IfId);\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+      IdStr++;\r
+    }\r
+\r
+    (*IfId)->Id[Index++] = NodeVal;\r
+\r
+    if (*IdStr == L':') {\r
+      IdStr++;\r
+    }\r
+  }\r
+\r
+  *Arg = (*Arg)->Next;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Parse dad in string format from Args with the "-s" option and convert it to UINT32 format.\r
+\r
+  @param[in, out]   Arg      The pointer of the address of ARG_LIST that saves Args with the "-s" option.\r
+  @param[out]       Xmits    The pointer of Xmits.\r
+\r
+  @retval EFI_SUCCESS    The get status processed successfully.\r
+  @retval others         The get status process failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfConfig6ParseDadXmits (\r
+  IN OUT ARG_LIST    **Arg,\r
+     OUT UINT32      *Xmits\r
+  )\r
+{\r
+  CHAR16    *ValStr;\r
+\r
+  if (*Arg == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  ValStr = (*Arg)->Arg;\r
+  *Xmits = 0;\r
+\r
+  while (*ValStr != L'\0') {\r
+\r
+    if ((*ValStr <= L'9') && (*ValStr >= L'0')) {\r
+\r
+      *Xmits = (*Xmits * 10) + (*ValStr - L'0');\r
+\r
+    } else {\r
+\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    ValStr++;\r
+  }\r
+\r
+  *Arg = (*Arg)->Next;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  The get current status of all handles.\r
+\r
+  @param[in]   ImageHandle    The handle of  ImageHandle.\r
+  @param[in]   IfName         The pointer of  IfName(interface name).\r
+  @param[in]   IfList         The pointer of  IfList(interface list).\r
+\r
+  @retval EFI_SUCCESS    The get status processed successfully.\r
+  @retval others         The get status process failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfConfig6GetInterfaceInfo (\r
+  IN EFI_HANDLE    ImageHandle,\r
+  IN CHAR16        *IfName,\r
+  IN LIST_ENTRY    *IfList\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  UINTN                            HandleIndex;\r
+  UINTN                            HandleNum;\r
+  EFI_HANDLE                       *HandleBuffer;\r
+  EFI_IP6_CONFIG_PROTOCOL          *Ip6Cfg;\r
+  EFI_IP6_CONFIG_INTERFACE_INFO    *IfInfo;\r
+  IFCONFIG6_INTERFACE_CB           *IfCb;\r
+  UINTN                            DataSize;\r
+\r
+  HandleBuffer = NULL;\r
+  HandleNum    = 0;\r
+\r
+  IfInfo       = NULL;\r
+  IfCb         = NULL;\r
+\r
+  //\r
+  // Locate all the handles with ip6 service binding protocol.\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiIp6ServiceBindingProtocolGuid,\r
+                  NULL,\r
+                  &HandleNum,\r
+                  &HandleBuffer\r
+                 );\r
+  if (EFI_ERROR (Status) || (HandleNum == 0)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Enumerate all handles that installed with ip6 service binding protocol.\r
+  //\r
+  for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {\r
+    IfCb      = NULL;\r
+    IfInfo    = NULL;\r
+    DataSize  = 0;\r
+\r
+    //\r
+    // Ip6config protocol and ip6 service binding protocol are installed\r
+    // on the same handle.\r
+    //\r
+    ASSERT (HandleBuffer != NULL);\r
+    Status = gBS->HandleProtocol (\r
+                    HandleBuffer[HandleIndex],\r
+                    &gEfiIp6ConfigProtocolGuid,\r
+                    (VOID **) &Ip6Cfg\r
+                    );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_ERROR;\r
+    }\r
+    //\r
+    // Get the interface information size.\r
+    //\r
+    Status = Ip6Cfg->GetData (\r
+                       Ip6Cfg,\r
+                       Ip6ConfigDataTypeInterfaceInfo,\r
+                       &DataSize,\r
+                       NULL\r
+                       );\r
+\r
+    if (Status != EFI_BUFFER_TOO_SMALL) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);\r
+      goto ON_ERROR;\r
+    }\r
+\r
+    IfInfo = AllocateZeroPool (DataSize);\r
+\r
+    if (IfInfo == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto ON_ERROR;\r
+    }\r
+    //\r
+    // Get the interface info.\r
+    //\r
+    Status = Ip6Cfg->GetData (\r
+                       Ip6Cfg,\r
+                       Ip6ConfigDataTypeInterfaceInfo,\r
+                       &DataSize,\r
+                       IfInfo\r
+                       );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);\r
+      goto ON_ERROR;\r
+    }\r
+    //\r
+    // Check the interface name if required.\r
+    //\r
+    if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) != 0)) {\r
+      FreePool (IfInfo);\r
+      continue;\r
+    }\r
+\r
+    DataSize = 0;\r
+    //\r
+    // Get the size of dns server list.\r
+    //\r
+    Status = Ip6Cfg->GetData (\r
+                       Ip6Cfg,\r
+                       Ip6ConfigDataTypeDnsServer,\r
+                       &DataSize,\r
+                       NULL\r
+                       );\r
+\r
+    if ((Status != EFI_BUFFER_TOO_SMALL) && (Status != EFI_NOT_FOUND)) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);\r
+      goto ON_ERROR;\r
+    }\r
+\r
+    IfCb = AllocateZeroPool (sizeof (IFCONFIG6_INTERFACE_CB) + DataSize);\r
+\r
+    if (IfCb == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto ON_ERROR;\r
+    }\r
+\r
+    IfCb->NicHandle = HandleBuffer[HandleIndex];\r
+    IfCb->IfInfo    = IfInfo;\r
+    IfCb->IfCfg     = Ip6Cfg;\r
+    IfCb->DnsCnt    = (UINT32) (DataSize / sizeof (EFI_IPv6_ADDRESS));\r
+\r
+    //\r
+    // Get the dns server list if has.\r
+    //\r
+    if (DataSize > 0) {\r
+\r
+      Status = Ip6Cfg->GetData (\r
+                         Ip6Cfg,\r
+                         Ip6ConfigDataTypeDnsServer,\r
+                         &DataSize,\r
+                         IfCb->DnsAddr\r
+                         );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);\r
+        goto ON_ERROR;\r
+      }\r
+    }\r
+    //\r
+    // Get the interface id if has.\r
+    //\r
+    DataSize   = sizeof (EFI_IP6_CONFIG_INTERFACE_ID);\r
+    IfCb->IfId = AllocateZeroPool (DataSize);\r
+\r
+    if (IfCb->IfId == NULL) {\r
+      goto ON_ERROR;\r
+    }\r
+\r
+    Status = Ip6Cfg->GetData (\r
+                       Ip6Cfg,\r
+                       Ip6ConfigDataTypeAltInterfaceId,\r
+                       &DataSize,\r
+                       IfCb->IfId\r
+                       );\r
+\r
+    if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);\r
+      goto ON_ERROR;\r
+    }\r
+\r
+    if (Status == EFI_NOT_FOUND) {\r
+      FreePool (IfCb->IfId);\r
+      IfCb->IfId = NULL;\r
+    }\r
+    //\r
+    // Get the config policy.\r
+    //\r
+    DataSize = sizeof (EFI_IP6_CONFIG_POLICY);\r
+    Status   = Ip6Cfg->GetData (\r
+                         Ip6Cfg,\r
+                         Ip6ConfigDataTypePolicy,\r
+                         &DataSize,\r
+                         &IfCb->Policy\r
+                         );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);\r
+      goto ON_ERROR;\r
+    }\r
+    //\r
+    // Get the dad transmits.\r
+    //\r
+    DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);\r
+    Status   = Ip6Cfg->GetData (\r
+                         Ip6Cfg,\r
+                         Ip6ConfigDataTypeDupAddrDetectTransmits,\r
+                         &DataSize,\r
+                         &IfCb->Xmits\r
+                         );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);\r
+      goto ON_ERROR;\r
+    }\r
+\r
+    InsertTailList (IfList, &IfCb->Link);\r
+\r
+    if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) == 0)) {\r
+      //\r
+      // Only need the appointed interface, keep the allocated buffer.\r
+      //\r
+      IfCb   = NULL;\r
+      IfInfo = NULL;\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (HandleBuffer != NULL) {\r
+    FreePool (HandleBuffer);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+ON_ERROR:\r
+\r
+  if (IfInfo != NULL) {\r
+    FreePool (IfInfo);\r
+  }\r
+\r
+  if (IfCb != NULL) {\r
+    if (IfCb->IfId != NULL) {\r
+      FreePool (IfCb->IfId);\r
+    }\r
+\r
+    FreePool (IfCb);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  The list process of the IfConfig6 application.\r
+\r
+  @param[in]   IfList    The pointer of IfList(interface list).\r
+\r
+  @retval SHELL_SUCCESS  The IfConfig6 list processed successfully.\r
+  @retval others         The IfConfig6 list process failed.\r
+\r
+**/\r
+SHELL_STATUS\r
+IfConfig6ShowInterfaceInfo (\r
+  IN LIST_ENTRY    *IfList\r
+  )\r
+{\r
+  LIST_ENTRY                *Entry;\r
+  IFCONFIG6_INTERFACE_CB    *IfCb;\r
+  UINTN                     Index;\r
+\r
+  Entry  = IfList->ForwardLink;\r
+\r
+  if (IsListEmpty (IfList)) {\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_INTERFACE), gShellNetwork2HiiHandle);\r
+  }\r
+\r
+  //\r
+  // Go through the interface list.\r
+  //\r
+  while (Entry != IfList) {\r
+\r
+    IfCb = BASE_CR (Entry, IFCONFIG6_INTERFACE_CB, Link);\r
+\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_BREAK), gShellNetwork2HiiHandle);\r
+\r
+    //\r
+    // Print interface name.\r
+    //\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IF_NAME), gShellNetwork2HiiHandle, IfCb->IfInfo->Name);\r
+\r
+    //\r
+    // Print interface config policy.\r
+    //\r
+    if (IfCb->Policy == Ip6ConfigPolicyAutomatic) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_POLICY_AUTO), gShellNetwork2HiiHandle);\r
+    } else {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_POLICY_MAN), gShellNetwork2HiiHandle);\r
+    }\r
+\r
+    //\r
+    // Print dad transmit.\r
+    //\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_DAD_TRANSMITS), gShellNetwork2HiiHandle, IfCb->Xmits);\r
+\r
+    //\r
+    // Print interface id if has.\r
+    //\r
+    if (IfCb->IfId != NULL) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_INTERFACE_ID_HEAD), gShellNetwork2HiiHandle);\r
+\r
+      IfConfig6PrintMacAddr (\r
+        IfCb->IfId->Id,\r
+        8\r
+        );\r
+    }\r
+    //\r
+    // Print mac address of the interface.\r
+    //\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_MAC_ADDR_HEAD), gShellNetwork2HiiHandle);\r
+\r
+    IfConfig6PrintMacAddr (\r
+      IfCb->IfInfo->HwAddress.Addr,\r
+      IfCb->IfInfo->HwAddressSize\r
+      );\r
+\r
+    //\r
+    // Print ip addresses list of the interface.\r
+    //\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IP_ADDR_HEAD), gShellNetwork2HiiHandle);\r
+\r
+    for (Index = 0; Index < IfCb->IfInfo->AddressInfoCount; Index++) {\r
+      IfConfig6PrintIpAddr (\r
+        &IfCb->IfInfo->AddressInfo[Index].Address,\r
+        &IfCb->IfInfo->AddressInfo[Index].PrefixLength\r
+        );\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle);\r
+    }\r
+\r
+    //\r
+    // Print dns server addresses list of the interface if has.\r
+    //\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_DNS_ADDR_HEAD), gShellNetwork2HiiHandle);\r
+\r
+    for (Index = 0; Index < IfCb->DnsCnt; Index++) {\r
+      IfConfig6PrintIpAddr (\r
+        &IfCb->DnsAddr[Index],\r
+        NULL\r
+        );\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle);\r
+    }\r
+\r
+    //\r
+    // Print route table of the interface if has.\r
+    //\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_ROUTE_HEAD), gShellNetwork2HiiHandle);\r
+\r
+    for (Index = 0; Index < IfCb->IfInfo->RouteCount; Index++) {\r
+      IfConfig6PrintIpAddr (\r
+        &IfCb->IfInfo->RouteTable[Index].Destination,\r
+        &IfCb->IfInfo->RouteTable[Index].PrefixLength\r
+        );\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_JOINT), gShellNetwork2HiiHandle);\r
+\r
+      IfConfig6PrintIpAddr (\r
+        &IfCb->IfInfo->RouteTable[Index].Gateway,\r
+        NULL\r
+        );\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle);\r
+    }\r
+\r
+    Entry = Entry->ForwardLink;\r
+  }\r
+\r
+  ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_BREAK), gShellNetwork2HiiHandle);\r
+\r
+  return SHELL_SUCCESS;\r
+}\r
+\r
+/**\r
+  The clean process of the IfConfig6 application.\r
+\r
+  @param[in]   IfList    The pointer of IfList(interface list).\r
+\r
+  @retval SHELL_SUCCESS  The IfConfig6 clean processed successfully.\r
+  @retval others         The IfConfig6 clean process failed.\r
+\r
+**/\r
+SHELL_STATUS\r
+IfConfig6ClearInterfaceInfo (\r
+  IN LIST_ENTRY    *IfList\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  SHELL_STATUS              ShellStatus;\r
+  LIST_ENTRY                *Entry;\r
+  IFCONFIG6_INTERFACE_CB    *IfCb;\r
+  EFI_IP6_CONFIG_POLICY     Policy;\r
+\r
+  Policy = Ip6ConfigPolicyAutomatic;\r
+  Entry  = IfList->ForwardLink;\r
+  Status = EFI_SUCCESS;\r
+  ShellStatus = SHELL_SUCCESS;\r
+\r
+  if (IsListEmpty (IfList)) {\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_INTERFACE), gShellNetwork2HiiHandle);\r
+  }\r
+\r
+  //\r
+  // Go through the interface list.\r
+  //\r
+  while (Entry != IfList) {\r
+\r
+    IfCb = BASE_CR (Entry, IFCONFIG6_INTERFACE_CB, Link);\r
+\r
+    Status = IfCb->IfCfg->SetData (\r
+                            IfCb->IfCfg,\r
+                            Ip6ConfigDataTypePolicy,\r
+                            sizeof (EFI_IP6_CONFIG_POLICY),\r
+                            &Policy\r
+                            );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      ShellStatus = SHELL_ACCESS_DENIED;\r
+      break;\r
+    }\r
+\r
+    Entry  = Entry->ForwardLink;\r
+  }\r
+\r
+  return ShellStatus;\r
+}\r
+\r
+/**\r
+  The set process of the IfConfig6 application.\r
+\r
+  @param[in]   IfList    The pointer of IfList(interface list).\r
+  @param[in]   VarArg    The pointer of ARG_LIST(Args with "-s" option).\r
+\r
+  @retval SHELL_SUCCESS  The IfConfig6 set processed successfully.\r
+  @retval others         The IfConfig6 set process failed.\r
+\r
+**/\r
+SHELL_STATUS\r
+IfConfig6SetInterfaceInfo (\r
+  IN LIST_ENTRY    *IfList,\r
+  IN ARG_LIST      *VarArg\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  SHELL_STATUS                     ShellStatus;\r
+  IFCONFIG6_INTERFACE_CB           *IfCb;\r
+  EFI_IP6_CONFIG_MANUAL_ADDRESS    *CfgManAddr;\r
+  EFI_IPv6_ADDRESS                 *CfgAddr;\r
+  UINTN                            AddrSize;\r
+  EFI_IP6_CONFIG_INTERFACE_ID      *InterfaceId;\r
+  UINT32                           DadXmits;\r
+  UINT32                           CurDadXmits;\r
+  UINTN                            CurDadXmitsLen;\r
+  EFI_IP6_CONFIG_POLICY            Policy;\r
+\r
+  VAR_CHECK_CODE                   CheckCode;\r
+  EFI_EVENT                        TimeOutEvt;\r
+  EFI_EVENT                        MappedEvt;\r
+  BOOLEAN                          IsAddressOk;\r
+\r
+  UINTN                            DataSize;\r
+  UINT32                           Index;\r
+  UINT32                           Index2;\r
+  BOOLEAN                          IsAddressSet;\r
+  EFI_IP6_CONFIG_INTERFACE_INFO    *IfInfo;\r
+\r
+  CfgManAddr  = NULL;\r
+  CfgAddr     = NULL;\r
+  TimeOutEvt  = NULL;\r
+  MappedEvt   = NULL;\r
+  IfInfo      = NULL;\r
+  InterfaceId = NULL;\r
+  CurDadXmits = 0;\r
+\r
+  if (IsListEmpty (IfList)) {\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_INTERFACE), gShellNetwork2HiiHandle);\r
+    return SHELL_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Make sure to set only one interface each time.\r
+  //\r
+  IfCb   = BASE_CR (IfList->ForwardLink, IFCONFIG6_INTERFACE_CB, Link);\r
+  Status = EFI_SUCCESS;\r
+  ShellStatus = SHELL_SUCCESS;\r
+\r
+  //\r
+  // Initialize check list mechanism.\r
+  //\r
+  CheckCode = IfConfig6RetriveCheckListByName(\r
+                NULL,\r
+                NULL,\r
+                TRUE\r
+                );\r
+\r
+  //\r
+  // Create events & timers for asynchronous settings.\r
+  //\r
+  Status = gBS->CreateEvent (\r
+                  EVT_TIMER,\r
+                  TPL_CALLBACK,\r
+                  NULL,\r
+                  NULL,\r
+                  &TimeOutEvt\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    ShellStatus = SHELL_ACCESS_DENIED;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  IfConfig6ManualAddressNotify,\r
+                  &IsAddressOk,\r
+                  &MappedEvt\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    ShellStatus = SHELL_ACCESS_DENIED;\r
+    goto ON_EXIT;\r
+  }\r
+  //\r
+  // Parse the setting variables.\r
+  //\r
+  while (VarArg != NULL) {\r
+     //\r
+     // Check invalid parameters (duplication & unknown & conflict).\r
+     //\r
+    CheckCode = IfConfig6RetriveCheckListByName(\r
+                  mIfConfig6SetCheckList,\r
+                  VarArg->Arg,\r
+                  FALSE\r
+                  );\r
+\r
+    if (VarCheckOk != CheckCode) {\r
+      switch (CheckCode) {\r
+        case VarCheckDuplicate:\r
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_DUPLICATE_COMMAND), gShellNetwork2HiiHandle, VarArg->Arg);\r
+          break;\r
+\r
+        case VarCheckConflict:\r
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_CONFLICT_COMMAND), gShellNetwork2HiiHandle, VarArg->Arg);\r
+          break;\r
+\r
+        case VarCheckUnknown:\r
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_UNKNOWN_COMMAND), gShellNetwork2HiiHandle, VarArg->Arg);\r
+          break;\r
+\r
+        default:\r
+          break;\r
+      }\r
+\r
+      VarArg = VarArg->Next;\r
+      continue;\r
+    }\r
+    //\r
+    // Process valid variables.\r
+    //\r
+    if (StrCmp(VarArg->Arg, L"auto") == 0) {\r
+      //\r
+      // Set automaic config policy\r
+      //\r
+      Policy = Ip6ConfigPolicyAutomatic;\r
+      Status = IfCb->IfCfg->SetData (\r
+                              IfCb->IfCfg,\r
+                              Ip6ConfigDataTypePolicy,\r
+                              sizeof (EFI_IP6_CONFIG_POLICY),\r
+                              &Policy\r
+                              );\r
+\r
+      if (EFI_ERROR(Status)) {\r
+        ShellStatus = SHELL_ACCESS_DENIED;\r
+        goto ON_EXIT;\r
+      }\r
+\r
+      VarArg= VarArg->Next;\r
+\r
+    } else if (StrCmp (VarArg->Arg, L"man") == 0) {\r
+      //\r
+      // Set manual config policy.\r
+      //\r
+      Policy = Ip6ConfigPolicyManual;\r
+      Status = IfCb->IfCfg->SetData (\r
+                              IfCb->IfCfg,\r
+                              Ip6ConfigDataTypePolicy,\r
+                              sizeof (EFI_IP6_CONFIG_POLICY),\r
+                              &Policy\r
+                              );\r
+\r
+      if (EFI_ERROR(Status)) {\r
+        ShellStatus = SHELL_ACCESS_DENIED;\r
+        goto ON_EXIT;\r
+      }\r
+\r
+      VarArg= VarArg->Next;\r
+\r
+    } else if (StrCmp (VarArg->Arg, L"host") == 0) {\r
+      //\r
+      // Parse till the next tag or the end of command line.\r
+      //\r
+      VarArg = VarArg->Next;\r
+      Status = IfConfig6ParseManualAddressList (\r
+                 &VarArg,\r
+                 &CfgManAddr,\r
+                 &AddrSize\r
+                 );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        if (Status == EFI_INVALID_PARAMETER) {\r
+          ShellStatus = SHELL_INVALID_PARAMETER;\r
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_ARGUMENTS), gShellNetwork2HiiHandle, L"host");\r
+          continue;\r
+        } else {\r
+          ShellStatus = SHELL_ACCESS_DENIED;\r
+          goto ON_EXIT;\r
+        }\r
+      }\r
+      //\r
+      // Set static host ip6 address list.\r
+      //   This is a asynchronous process.\r
+      //\r
+      IsAddressOk = FALSE;\r
+\r
+      Status = IfCb->IfCfg->RegisterDataNotify (\r
+                              IfCb->IfCfg,\r
+                              Ip6ConfigDataTypeManualAddress,\r
+                              MappedEvt\r
+                              );\r
+      if (EFI_ERROR (Status)) {\r
+        ShellStatus = SHELL_ACCESS_DENIED;\r
+        goto ON_EXIT;\r
+      }\r
+\r
+      Status = IfCb->IfCfg->SetData (\r
+                              IfCb->IfCfg,\r
+                              Ip6ConfigDataTypeManualAddress,\r
+                              AddrSize,\r
+                              CfgManAddr\r
+                              );\r
+\r
+      if (Status == EFI_NOT_READY) {\r
+        //\r
+        // Get current dad transmits count.\r
+        //\r
+        CurDadXmitsLen = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);\r
+        IfCb->IfCfg->GetData (\r
+                       IfCb->IfCfg,\r
+                       Ip6ConfigDataTypeDupAddrDetectTransmits,\r
+                       &CurDadXmitsLen,\r
+                       &CurDadXmits\r
+                       );\r
+\r
+        gBS->SetTimer (TimeOutEvt, TimerRelative, 50000000 + 10000000 * CurDadXmits);\r
+\r
+        while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) {\r
+          if (IsAddressOk) {\r
+            Status = EFI_SUCCESS;\r
+            break;\r
+          }\r
+        }\r
+      }\r
+\r
+      IfCb->IfCfg->UnregisterDataNotify (\r
+                     IfCb->IfCfg,\r
+                     Ip6ConfigDataTypeManualAddress,\r
+                     MappedEvt\r
+                     );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_MAN_HOST), gShellNetwork2HiiHandle, Status);\r
+        ShellStatus = SHELL_ACCESS_DENIED;\r
+        goto ON_EXIT;\r
+      }\r
+\r
+      //\r
+      // Check whether the address is set successfully.\r
+      //\r
+      DataSize = 0;\r
+\r
+      Status = IfCb->IfCfg->GetData (\r
+                              IfCb->IfCfg,\r
+                              Ip6ConfigDataTypeInterfaceInfo,\r
+                              &DataSize,\r
+                              NULL\r
+                              );\r
+\r
+      if (Status != EFI_BUFFER_TOO_SMALL) {\r
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);\r
+        ShellStatus = SHELL_ACCESS_DENIED;\r
+        goto ON_EXIT;\r
+      }\r
+\r
+      IfInfo = AllocateZeroPool (DataSize);\r
+\r
+      if (IfInfo == NULL) {\r
+        ShellStatus = SHELL_OUT_OF_RESOURCES;\r
+        goto ON_EXIT;\r
+      }\r
+\r
+      Status = IfCb->IfCfg->GetData (\r
+                              IfCb->IfCfg,\r
+                              Ip6ConfigDataTypeInterfaceInfo,\r
+                              &DataSize,\r
+                              IfInfo\r
+                              );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);\r
+        ShellStatus = SHELL_ACCESS_DENIED;\r
+        goto ON_EXIT;\r
+      }\r
+\r
+      for ( Index = 0; Index < (UINTN) (AddrSize / sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS)); Index++) {\r
+        IsAddressSet = FALSE;\r
+        //\r
+        // By default, the prefix length 0 is regarded as 64.\r
+        //\r
+        if (CfgManAddr[Index].PrefixLength == 0) {\r
+          CfgManAddr[Index].PrefixLength = 64;\r
+        }\r
+\r
+        for (Index2 = 0; Index2 < IfInfo->AddressInfoCount; Index2++) {\r
+          if (EFI_IP6_EQUAL (&IfInfo->AddressInfo[Index2].Address, &CfgManAddr[Index].Address) &&\r
+              (IfInfo->AddressInfo[Index2].PrefixLength == CfgManAddr[Index].PrefixLength)) {\r
+            IsAddressSet = TRUE;\r
+            break;\r
+          }\r
+        }\r
+\r
+        if (!IsAddressSet) {\r
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_ADDRESS_FAILED), gShellNetwork2HiiHandle);\r
+          IfConfig6PrintIpAddr (\r
+            &CfgManAddr[Index].Address,\r
+            &CfgManAddr[Index].PrefixLength\r
+            );\r
+        }\r
+      }\r
+\r
+    } else if (StrCmp (VarArg->Arg, L"gw") == 0) {\r
+      //\r
+      // Parse till the next tag or the end of command line.\r
+      //\r
+      VarArg = VarArg->Next;\r
+      Status = IfConfig6ParseGwDnsAddressList (\r
+                 &VarArg,\r
+                 &CfgAddr,\r
+                 &AddrSize\r
+                 );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        if (Status == EFI_INVALID_PARAMETER) {\r
+          ShellStatus = SHELL_INVALID_PARAMETER;\r
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_ARGUMENTS), gShellNetwork2HiiHandle, L"gw");\r
+          continue;\r
+        } else {\r
+          ShellStatus = SHELL_ACCESS_DENIED;\r
+          goto ON_EXIT;\r
+        }\r
+      }\r
+      //\r
+      // Set static gateway ip6 address list.\r
+      //\r
+      Status = IfCb->IfCfg->SetData (\r
+                              IfCb->IfCfg,\r
+                              Ip6ConfigDataTypeGateway,\r
+                              AddrSize,\r
+                              CfgAddr\r
+                              );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        ShellStatus = SHELL_ACCESS_DENIED;\r
+        goto ON_EXIT;\r
+      }\r
+\r
+    } else if (StrCmp (VarArg->Arg, L"dns") == 0) {\r
+      //\r
+      // Parse till the next tag or the end of command line.\r
+      //\r
+      VarArg = VarArg->Next;\r
+      Status = IfConfig6ParseGwDnsAddressList (\r
+                 &VarArg,\r
+                 &CfgAddr,\r
+                 &AddrSize\r
+                 );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        if (Status == EFI_INVALID_PARAMETER) {\r
+          ShellStatus = SHELL_INVALID_PARAMETER;\r
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_ARGUMENTS), gShellNetwork2HiiHandle, L"dns");\r
+          continue;\r
+        } else {\r
+          ShellStatus = SHELL_ACCESS_DENIED;\r
+          goto ON_EXIT;\r
+        }\r
+      }\r
+      //\r
+      // Set static DNS server ip6 address list.\r
+      //\r
+      Status = IfCb->IfCfg->SetData (\r
+                              IfCb->IfCfg,\r
+                              Ip6ConfigDataTypeDnsServer,\r
+                              AddrSize,\r
+                              CfgAddr\r
+                              );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        ShellStatus = SHELL_ACCESS_DENIED;\r
+        goto ON_EXIT;\r
+      }\r
+\r
+    } else if (StrCmp (VarArg->Arg, L"id") == 0) {\r
+      //\r
+      // Parse till the next tag or the end of command line.\r
+      //\r
+      VarArg = VarArg->Next;\r
+      Status = IfConfig6ParseInterfaceId (&VarArg, &InterfaceId);\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        ShellStatus = SHELL_INVALID_PARAMETER;\r
+        goto ON_EXIT;\r
+      }\r
+      //\r
+      // Set alternative interface id.\r
+      //\r
+      Status = IfCb->IfCfg->SetData (\r
+                              IfCb->IfCfg,\r
+                              Ip6ConfigDataTypeAltInterfaceId,\r
+                              sizeof (EFI_IP6_CONFIG_INTERFACE_ID),\r
+                              InterfaceId\r
+                              );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        ShellStatus = SHELL_ACCESS_DENIED;\r
+        goto ON_EXIT;\r
+      }\r
+\r
+    } else if (StrCmp (VarArg->Arg, L"dad") == 0) {\r
+      //\r
+      // Parse till the next tag or the end of command line.\r
+      //\r
+      VarArg = VarArg->Next;\r
+      Status = IfConfig6ParseDadXmits (&VarArg, &DadXmits);\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        ShellStatus = SHELL_ACCESS_DENIED;\r
+        goto ON_EXIT;\r
+      }\r
+      //\r
+      // Set dad transmits count.\r
+      //\r
+      Status = IfCb->IfCfg->SetData (\r
+                              IfCb->IfCfg,\r
+                              Ip6ConfigDataTypeDupAddrDetectTransmits,\r
+                              sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS),\r
+                              &DadXmits\r
+                              );\r
+\r
+      if (EFI_ERROR(Status)) {\r
+        ShellStatus = SHELL_ACCESS_DENIED;\r
+        goto ON_EXIT;\r
+      }\r
+    }\r
+  }\r
+\r
+ON_EXIT:\r
+\r
+  if (CfgManAddr != NULL) {\r
+    FreePool (CfgManAddr);\r
+  }\r
+\r
+  if (CfgAddr != NULL) {\r
+    FreePool (CfgAddr);\r
+  }\r
+\r
+  if (MappedEvt != NULL) {\r
+    gBS->CloseEvent (MappedEvt);\r
+  }\r
+\r
+  if (TimeOutEvt != NULL) {\r
+    gBS->CloseEvent (TimeOutEvt);\r
+  }\r
+\r
+  if (IfInfo != NULL) {\r
+    FreePool (IfInfo);\r
+  }\r
+\r
+  return ShellStatus;\r
+\r
+}\r
+\r
+/**\r
+  The IfConfig6 main process.\r
+\r
+  @param[in]   Private    The pointer of IFCONFIG6_PRIVATE_DATA.\r
+\r
+  @retval SHELL_SUCCESS   IfConfig6 processed successfully.\r
+  @retval others          The IfConfig6 process failed.\r
+\r
+**/\r
+SHELL_STATUS\r
+IfConfig6 (\r
+  IN IFCONFIG6_PRIVATE_DATA    *Private\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  SHELL_STATUS  ShellStatus;\r
+\r
+  ShellStatus = SHELL_SUCCESS;\r
+\r
+  //\r
+  // Get configure information of all interfaces.\r
+  //\r
+  Status = IfConfig6GetInterfaceInfo (\r
+             Private->ImageHandle,\r
+             Private->IfName,\r
+             &Private->IfList\r
+             );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ShellStatus = SHELL_NOT_FOUND;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  switch (Private->OpCode) {\r
+  case IfConfig6OpList:\r
+    ShellStatus = IfConfig6ShowInterfaceInfo (&Private->IfList);\r
+    break;\r
+\r
+  case IfConfig6OpClear:\r
+    ShellStatus = IfConfig6ClearInterfaceInfo (&Private->IfList);\r
+    break;\r
+\r
+  case IfConfig6OpSet:\r
+    ShellStatus = IfConfig6SetInterfaceInfo (&Private->IfList, Private->VarArg);\r
+    break;\r
+\r
+  default:\r
+    ShellStatus = SHELL_UNSUPPORTED;\r
+  }\r
+\r
+ON_EXIT:\r
+\r
+  return ShellStatus;\r
+}\r
+\r
+/**\r
+  The IfConfig6 cleanup process, free the allocated memory.\r
+\r
+  @param[in]   Private    The pointer of  IFCONFIG6_PRIVATE_DATA.\r
+\r
+**/\r
+VOID\r
+IfConfig6Cleanup (\r
+  IN IFCONFIG6_PRIVATE_DATA    *Private\r
+  )\r
+{\r
+  LIST_ENTRY                *Entry;\r
+  LIST_ENTRY                *NextEntry;\r
+  IFCONFIG6_INTERFACE_CB    *IfCb;\r
+  ARG_LIST                  *ArgNode;\r
+  ARG_LIST                  *ArgHead;\r
+\r
+  ASSERT (Private != NULL);\r
+\r
+  //\r
+  // Clean the list which save the set config Args.\r
+  //\r
+  if (Private->VarArg != NULL) {\r
+    ArgHead = Private->VarArg;\r
+\r
+    while (ArgHead->Next != NULL) {\r
+      ArgNode = ArgHead->Next;\r
+      FreePool (ArgHead);\r
+      ArgHead = ArgNode;\r
+    }\r
+\r
+    FreePool (ArgHead);\r
+  }\r
+\r
+  if (Private->IfName != NULL)\r
+    FreePool (Private->IfName);\r
+\r
+\r
+  //\r
+  // Clean the IFCONFIG6_INTERFACE_CB list.\r
+  //\r
+  Entry     = Private->IfList.ForwardLink;\r
+  NextEntry = Entry->ForwardLink;\r
+\r
+  while (Entry != &Private->IfList) {\r
+\r
+    IfCb = BASE_CR (Entry, IFCONFIG6_INTERFACE_CB, Link);\r
+\r
+    RemoveEntryList (&IfCb->Link);\r
+\r
+    if (IfCb->IfId != NULL) {\r
+\r
+      FreePool (IfCb->IfId);\r
+    }\r
+\r
+    if (IfCb->IfInfo != NULL) {\r
+\r
+      FreePool (IfCb->IfInfo);\r
+    }\r
+\r
+    FreePool (IfCb);\r
+\r
+    Entry     = NextEntry;\r
+    NextEntry = Entry->ForwardLink;\r
+  }\r
+\r
+  FreePool (Private);\r
+}\r
+\r
+/**\r
+  Function for 'ifconfig6' command.\r
+\r
+  @param[in] ImageHandle  Handle to the Image (NULL if Internal).\r
+  @param[in] SystemTable  Pointer to the System Table (NULL if Internal).\r
+\r
+  @retval SHELL_SUCCESS   ifconfig6 command processed successfully.\r
+  @retval others          The ifconfig6 command process failed.\r
+\r
+**/\r
+SHELL_STATUS\r
+EFIAPI\r
+ShellCommandRunIfconfig6 (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  SHELL_STATUS              ShellStatus;\r
+  IFCONFIG6_PRIVATE_DATA    *Private;\r
+  LIST_ENTRY                *ParamPackage;\r
+  CONST CHAR16              *ValueStr;\r
+  ARG_LIST                  *ArgList;\r
+  CHAR16                    *ProblemParam;\r
+  CHAR16                    *Str;\r
+\r
+  Private = NULL;\r
+  Status = EFI_INVALID_PARAMETER;\r
+  ShellStatus = SHELL_SUCCESS;\r
+\r
+  Status = ShellCommandLineParseEx (mIfConfig6CheckList, &ParamPackage, &ProblemParam, TRUE, FALSE);\r
+  if (EFI_ERROR (Status)) {\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_COMMAND), gShellNetwork2HiiHandle, L"ifconfig6", ProblemParam);\r
+    ShellStatus = SHELL_INVALID_PARAMETER;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // To handle no option.\r
+  //\r
+  if (!ShellCommandLineGetFlag (ParamPackage, L"-r") && !ShellCommandLineGetFlag (ParamPackage, L"-s") &&\r
+      !ShellCommandLineGetFlag (ParamPackage, L"-?") && !ShellCommandLineGetFlag (ParamPackage, L"-l")) {\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_LACK_OPTION), gShellNetwork2HiiHandle);\r
+    ShellStatus = SHELL_INVALID_PARAMETER;\r
+    goto ON_EXIT;\r
+  }\r
+  //\r
+  // To handle conflict options.\r
+  //\r
+  if (((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-s"))) ||\r
+      ((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-l"))) ||\r
+      ((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-?"))) ||\r
+      ((ShellCommandLineGetFlag (ParamPackage, L"-s")) && (ShellCommandLineGetFlag (ParamPackage, L"-l"))) ||\r
+      ((ShellCommandLineGetFlag (ParamPackage, L"-s")) && (ShellCommandLineGetFlag (ParamPackage, L"-?"))) ||\r
+      ((ShellCommandLineGetFlag (ParamPackage, L"-l")) && (ShellCommandLineGetFlag (ParamPackage, L"-?")))) {\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_CONFLICT_OPTIONS), gShellNetwork2HiiHandle);\r
+    ShellStatus = SHELL_INVALID_PARAMETER;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Private = AllocateZeroPool (sizeof (IFCONFIG6_PRIVATE_DATA));\r
+\r
+  if (Private == NULL) {\r
+    ShellStatus = SHELL_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  InitializeListHead (&Private->IfList);\r
+\r
+  //\r
+  // To get interface name for the list option.\r
+  //\r
+  if (ShellCommandLineGetFlag (ParamPackage, L"-l")) {\r
+    Private->OpCode = IfConfig6OpList;\r
+    ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l");\r
+    if (ValueStr != NULL) {\r
+      Str             = AllocateCopyPool (StrSize (ValueStr), ValueStr);\r
+      ASSERT (Str != NULL);\r
+      Private->IfName = Str;\r
+    }\r
+  }\r
+  //\r
+  // To get interface name for the clear option.\r
+  //\r
+  if (ShellCommandLineGetFlag (ParamPackage, L"-r")) {\r
+    Private->OpCode = IfConfig6OpClear;\r
+    ValueStr = ShellCommandLineGetValue (ParamPackage, L"-r");\r
+    if (ValueStr != NULL) {\r
+      Str             = AllocateCopyPool (StrSize (ValueStr), ValueStr);\r
+      ASSERT (Str != NULL);\r
+      Private->IfName = Str;\r
+    }\r
+  }\r
+  //\r
+  // To get interface name and corresponding Args for the set option.\r
+  //\r
+  if (ShellCommandLineGetFlag (ParamPackage, L"-s")) {\r
+\r
+    ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s");\r
+    if (ValueStr == NULL) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_INTERFACE), gShellNetwork2HiiHandle);\r
+      ShellStatus = SHELL_INVALID_PARAMETER;\r
+      goto ON_EXIT;\r
+    }\r
+    //\r
+    // To split the configuration into multi-section.\r
+    //\r
+    ArgList         = IfConfig6SplitStrToList (ValueStr, L' ');\r
+    ASSERT (ArgList != NULL);\r
+\r
+    Private->OpCode = IfConfig6OpSet;\r
+    Private->IfName = ArgList->Arg;\r
+\r
+    Private->VarArg = ArgList->Next;\r
+\r
+    if (Private->IfName == NULL || Private->VarArg == NULL) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_COMMAND), gShellNetwork2HiiHandle);\r
+      ShellStatus = SHELL_INVALID_PARAMETER;\r
+      goto ON_EXIT;\r
+    }\r
+  }\r
+  //\r
+  // Main process of ifconfig6.\r
+  //\r
+  ShellStatus = IfConfig6 (Private);\r
+\r
+ON_EXIT:\r
+\r
+  ShellCommandLineFreeVarList (ParamPackage);\r
+  if (Private != NULL) {\r
+    IfConfig6Cleanup (Private);\r
+  }\r
+  return ShellStatus;\r
+\r
+}\r
+\r