/** @file | |
The implementation for Shell command IfConfig6. | |
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> | |
(C) Copyright 2017 Hewlett Packard Enterprise Development LP<BR> | |
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; | |
} | |