Follow the Shell Spec, when the interface name is Specified, we need to refresh the Ipv6 configuration. Cc: Hegde Nagaraj P <nagaraj-p.hegde@hpe.com> Cc: Ye Ting <ting.ye@intel.com> Cc: Fu Siyuan <siyuan.fu@intel.com> Cc: Wu Jiaxin <jiaxin.wu@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Zhang Lubo <lubo.zhang@intel.com> Reviewed-by: Hegde Nagaraj P <nagaraj-p.hegde@hpe.com> Reviewed-by: Sriram Subramanian <sriram-s@hpe.com> Reviewed-by: Jaben Carsey <jaben.carsey@intel.com> Reviewed-By: Wu Jiaxin <jiaxin.wu@intel.com>
		
			
				
	
	
		
			1862 lines
		
	
	
		
			50 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1862 lines
		
	
	
		
			50 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);
 | 
						|
  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;
 | 
						|
 | 
						|
    } 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, 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;
 | 
						|
  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;
 | 
						|
 | 
						|
}
 | 
						|
 |