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