--- /dev/null
+/** @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