mirror of https://github.com/acidanthera/audk.git
1840 lines
49 KiB
C
1840 lines
49 KiB
C
/** @file
|
|
The implementation for Shell command IfConfig6.
|
|
|
|
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
|
|
|
|
This program and the accompanying materials
|
|
are licensed and made available under the terms and conditions of the BSD License
|
|
which accompanies this distribution. The full text of the license may be found at
|
|
http://opensource.org/licenses/bsd-license.php.
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
**/
|
|
#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
|
|
},
|
|
};
|
|
|
|
/**
|
|
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);
|
|
ASSERT (Str != NULL);
|
|
ArgStr = Str;
|
|
|
|
//
|
|
// init a node for the list head.
|
|
//
|
|
ArgNode = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST));
|
|
ASSERT (ArgNode != 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));
|
|
ASSERT (ArgNode->Next != 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);
|
|
|
|
return SHELL_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
The clean process of the IfConfig6 application.
|
|
|
|
@param[in] IfList The pointer of IfList(interface list).
|
|
|
|
@retval SHELL_SUCCESS The IfConfig6 clean processed successfully.
|
|
@retval others The IfConfig6 clean process failed.
|
|
|
|
**/
|
|
SHELL_STATUS
|
|
IfConfig6ClearInterfaceInfo (
|
|
IN LIST_ENTRY *IfList
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
SHELL_STATUS ShellStatus;
|
|
LIST_ENTRY *Entry;
|
|
IFCONFIG6_INTERFACE_CB *IfCb;
|
|
EFI_IP6_CONFIG_POLICY Policy;
|
|
|
|
Policy = Ip6ConfigPolicyAutomatic;
|
|
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.
|
|
//
|
|
while (Entry != IfList) {
|
|
|
|
IfCb = BASE_CR (Entry, IFCONFIG6_INTERFACE_CB, Link);
|
|
|
|
Status = IfCb->IfCfg->SetData (
|
|
IfCb->IfCfg,
|
|
Ip6ConfigDataTypePolicy,
|
|
sizeof (EFI_IP6_CONFIG_POLICY),
|
|
&Policy
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
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;
|
|
|
|
} 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
|
|
);
|
|
}
|
|
}
|
|
|
|
} 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;
|
|
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);
|
|
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;
|
|
ARG_LIST *ArgNode;
|
|
ARG_LIST *ArgHead;
|
|
|
|
ASSERT (Private != NULL);
|
|
|
|
//
|
|
// Clean the list which save the set config Args.
|
|
//
|
|
if (Private->VarArg != NULL) {
|
|
ArgHead = Private->VarArg;
|
|
|
|
while (ArgHead->Next != NULL) {
|
|
ArgNode = ArgHead->Next;
|
|
FreePool (ArgHead);
|
|
ArgHead = ArgNode;
|
|
}
|
|
|
|
FreePool (ArgHead);
|
|
}
|
|
|
|
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);
|
|
ASSERT (Str != NULL);
|
|
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);
|
|
ASSERT (Str != NULL);
|
|
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' ');
|
|
ASSERT (ArgList != NULL);
|
|
|
|
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;
|
|
|
|
}
|
|
|