From a3bcde70e6dc69000f85cc5deee98101d2ae200a Mon Sep 17 00:00:00 2001 From: hhtian Date: Mon, 1 Nov 2010 06:13:54 +0000 Subject: Add NetworkPkg (P.UDK2010.UP3.Network.P1) git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10986 6f19259b-4bc3-4df7-8a09-765794883524 --- NetworkPkg/Application/IfConfig6/IfConfig6.c | 1781 +++++++++++++++++ NetworkPkg/Application/IfConfig6/IfConfig6.h | 84 + NetworkPkg/Application/IfConfig6/IfConfig6.inf | 52 + .../Application/IfConfig6/IfConfig6Strings.uni | Bin 0 -> 15424 bytes NetworkPkg/Application/IpsecConfig/Delete.c | 110 ++ NetworkPkg/Application/IpsecConfig/Delete.h | 42 + NetworkPkg/Application/IpsecConfig/Dump.c | 530 +++++ NetworkPkg/Application/IpsecConfig/Dump.h | 34 + NetworkPkg/Application/IpsecConfig/ForEach.c | 115 ++ NetworkPkg/Application/IpsecConfig/ForEach.h | 54 + NetworkPkg/Application/IpsecConfig/Helper.c | 419 ++++ NetworkPkg/Application/IpsecConfig/Helper.h | 143 ++ NetworkPkg/Application/IpsecConfig/Indexer.c | 248 +++ NetworkPkg/Application/IpsecConfig/Indexer.h | 58 + NetworkPkg/Application/IpsecConfig/IpSecConfig.c | 809 ++++++++ NetworkPkg/Application/IpsecConfig/IpSecConfig.h | 123 ++ NetworkPkg/Application/IpsecConfig/IpSecConfig.inf | 61 + .../Application/IpsecConfig/IpSecConfigStrings.uni | Bin 0 -> 22142 bytes NetworkPkg/Application/IpsecConfig/Match.c | 163 ++ NetworkPkg/Application/IpsecConfig/Match.h | 41 + .../Application/IpsecConfig/PolicyEntryOperation.c | 2016 ++++++++++++++++++++ .../Application/IpsecConfig/PolicyEntryOperation.h | 158 ++ NetworkPkg/Application/Ping6/Ia32/Tsc.c | 28 + NetworkPkg/Application/Ping6/Ipf/Itc.c | 28 + NetworkPkg/Application/Ping6/Ping6.c | 1179 ++++++++++++ NetworkPkg/Application/Ping6/Ping6.h | 92 + NetworkPkg/Application/Ping6/Ping6.inf | 64 + NetworkPkg/Application/Ping6/Ping6Strings.uni | Bin 0 -> 7222 bytes NetworkPkg/Application/Ping6/X64/Tsc.c | 28 + NetworkPkg/Application/VConfig/VConfig.c | 668 +++++++ NetworkPkg/Application/VConfig/VConfig.inf | 47 + NetworkPkg/Application/VConfig/VConfigStrings.uni | Bin 0 -> 8624 bytes 32 files changed, 9175 insertions(+) create mode 100644 NetworkPkg/Application/IfConfig6/IfConfig6.c create mode 100644 NetworkPkg/Application/IfConfig6/IfConfig6.h create mode 100644 NetworkPkg/Application/IfConfig6/IfConfig6.inf create mode 100644 NetworkPkg/Application/IfConfig6/IfConfig6Strings.uni create mode 100644 NetworkPkg/Application/IpsecConfig/Delete.c create mode 100644 NetworkPkg/Application/IpsecConfig/Delete.h create mode 100644 NetworkPkg/Application/IpsecConfig/Dump.c create mode 100644 NetworkPkg/Application/IpsecConfig/Dump.h create mode 100644 NetworkPkg/Application/IpsecConfig/ForEach.c create mode 100644 NetworkPkg/Application/IpsecConfig/ForEach.h create mode 100644 NetworkPkg/Application/IpsecConfig/Helper.c create mode 100644 NetworkPkg/Application/IpsecConfig/Helper.h create mode 100644 NetworkPkg/Application/IpsecConfig/Indexer.c create mode 100644 NetworkPkg/Application/IpsecConfig/Indexer.h create mode 100644 NetworkPkg/Application/IpsecConfig/IpSecConfig.c create mode 100644 NetworkPkg/Application/IpsecConfig/IpSecConfig.h create mode 100644 NetworkPkg/Application/IpsecConfig/IpSecConfig.inf create mode 100644 NetworkPkg/Application/IpsecConfig/IpSecConfigStrings.uni create mode 100644 NetworkPkg/Application/IpsecConfig/Match.c create mode 100644 NetworkPkg/Application/IpsecConfig/Match.h create mode 100644 NetworkPkg/Application/IpsecConfig/PolicyEntryOperation.c create mode 100644 NetworkPkg/Application/IpsecConfig/PolicyEntryOperation.h create mode 100644 NetworkPkg/Application/Ping6/Ia32/Tsc.c create mode 100644 NetworkPkg/Application/Ping6/Ipf/Itc.c create mode 100644 NetworkPkg/Application/Ping6/Ping6.c create mode 100644 NetworkPkg/Application/Ping6/Ping6.h create mode 100644 NetworkPkg/Application/Ping6/Ping6.inf create mode 100644 NetworkPkg/Application/Ping6/Ping6Strings.uni create mode 100644 NetworkPkg/Application/Ping6/X64/Tsc.c create mode 100644 NetworkPkg/Application/VConfig/VConfig.c create mode 100644 NetworkPkg/Application/VConfig/VConfig.inf create mode 100644 NetworkPkg/Application/VConfig/VConfigStrings.uni (limited to 'NetworkPkg/Application') diff --git a/NetworkPkg/Application/IfConfig6/IfConfig6.c b/NetworkPkg/Application/IfConfig6/IfConfig6.c new file mode 100644 index 0000000000..b2eada639a --- /dev/null +++ b/NetworkPkg/Application/IfConfig6/IfConfig6.c @@ -0,0 +1,1781 @@ +/** @file + The implementation for Shell application IfConfig6. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "IfConfig6.h" + +EFI_HII_HANDLE mHiiHandle; + +EFI_GUID mEfiIfConfig6Guid = EFI_IFCONFIG6_GUID; +SHELL_PARAM_ITEM mIfConfig6CheckList[] = { + { + L"-b", + TypeFlag + }, + { + L"-s", + TypeMaxValue + }, + { + L"-l", + TypeValue + }, + { + L"-r", + TypeValue + }, + { + L"-?", + TypeFlag + }, + { + NULL, + TypeMax + }, +}; + +VAR_CHECK_ITEM mSetCheckList[] = { + { + 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 * +SplitStrToList ( + IN CONST CHAR16 *String, + IN CHAR16 Separator + ) +{ + CHAR16 *Str; + CHAR16 *ArgStr; + ARG_LIST *ArgList; + ARG_LIST *ArgNode; + + if (*String == L'\0') { + return NULL; + } + + // + // Copy the CONST string to a local copy. + // + Str = (CHAR16 *) AllocateZeroPool (StrSize (String)); + ASSERT (Str != NULL); + Str = StrCpy (Str, String); + 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] CheckList The pointer of Event. + @param[in] Context The pointer of Context. + +**/ +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), mHiiHandle, Node[Index]); + if (Index + 1 < Size) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), mHiiHandle); + } + } + + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), mHiiHandle); +} + +/** + 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), mHiiHandle); + } + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), mHiiHandle); + + 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), mHiiHandle, Ip->Addr[Index]); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IP_ADDR_BODY), mHiiHandle, Ip->Addr[Index + 1]); + } + + if (Index + 2 < PREFIXMAXLEN) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), mHiiHandle); + } + } + + if (PrefixLen != NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_PREFIX_LEN), mHiiHandle, *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] Address 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; + + 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] Address 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 EFI_ABORTED; + } + + // + // 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), mHiiHandle, 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), mHiiHandle, 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), mHiiHandle, 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), mHiiHandle, 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), mHiiHandle, 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), mHiiHandle, 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), mHiiHandle, 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 EFI_SUCCESS The IfConfig6 list processed successfully. + @retval others The IfConfig6 list process failed. + +**/ +EFI_STATUS +IfConfig6ShowInterfaceInfo ( + IN LIST_ENTRY *IfList + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Entry; + IFCONFIG6_INTERFACE_CB *IfCb; + UINTN Index; + + Entry = IfList->ForwardLink; + Status = EFI_SUCCESS; + + if (IsListEmpty (IfList)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_INTERFACE), mHiiHandle); + } + + // + // 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), mHiiHandle); + + // + // Print interface name. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IF_NAME), mHiiHandle, IfCb->IfInfo->Name); + + // + // Print interface config policy. + // + if (IfCb->Policy == Ip6ConfigPolicyAutomatic) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_POLICY_AUTO), mHiiHandle); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_POLICY_MAN), mHiiHandle); + } + + // + // Print dad transmit. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_DAD_TRANSMITS), mHiiHandle, IfCb->Xmits); + + // + // Print interface id if has. + // + if (IfCb->IfId != NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_INTERFACE_ID_HEAD), mHiiHandle); + + IfConfig6PrintMacAddr ( + IfCb->IfId->Id, + 8 + ); + } + // + // Print mac address of the interface. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_MAC_ADDR_HEAD), mHiiHandle); + + 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), mHiiHandle); + + 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), mHiiHandle); + } + + // + // Print dns server addresses list of the interface if has. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_DNS_ADDR_HEAD), mHiiHandle); + + for (Index = 0; Index < IfCb->DnsCnt; Index++) { + IfConfig6PrintIpAddr ( + &IfCb->DnsAddr[Index], + NULL + ); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), mHiiHandle); + } + + // + // Print route table of the interface if has. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_ROUTE_HEAD), mHiiHandle); + + 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), mHiiHandle); + + IfConfig6PrintIpAddr ( + &IfCb->IfInfo->RouteTable[Index].Gateway, + NULL + ); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), mHiiHandle); + } + + Entry = Entry->ForwardLink; + } + + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_BREAK), mHiiHandle); + + return Status; +} + +/** + The clean process of the IfConfig6 application. + + @param[in] IfList The pointer of IfList(interface list). + + @retval EFI_SUCCESS The IfConfig6 clean processed successfully. + @retval others The IfConfig6 clean process failed. + +**/ +EFI_STATUS +IfConfig6ClearInterfaceInfo ( + IN LIST_ENTRY *IfList + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Entry; + IFCONFIG6_INTERFACE_CB *IfCb; + EFI_IP6_CONFIG_POLICY Policy; + + Policy = Ip6ConfigPolicyAutomatic; + Entry = IfList->ForwardLink; + Status = EFI_SUCCESS; + + if (IsListEmpty (IfList)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_INTERFACE), mHiiHandle); + } + + // + // Go through the interface list. + // + while (Entry != IfList) { + + IfCb = BASE_CR (Entry, IFCONFIG6_INTERFACE_CB, Link); + + Status = IfCb->IfCfg->SetData ( + IfCb->IfCfg, + Ip6ConfigDataTypePolicy, + sizeof (EFI_IP6_CONFIG_POLICY), + &Policy + ); + + if (EFI_ERROR (Status)) { + break; + } + + Entry = Entry->ForwardLink; + } + + return Status; +} + +/** + 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 EFI_SUCCESS The IfConfig6 set processed successfully. + @retval others The IfConfig6 set process failed. + +**/ +EFI_STATUS +IfConfig6SetInterfaceInfo ( + IN LIST_ENTRY *IfList, + IN ARG_LIST *VarArg + ) +{ + EFI_STATUS Status; + 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), mHiiHandle); + return EFI_INVALID_PARAMETER; + } + // + // Make sure to set only one interface each time. + // + IfCb = BASE_CR (IfList->ForwardLink, IFCONFIG6_INTERFACE_CB, Link); + Status = EFI_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)) { + goto ON_EXIT; + } + + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + IfConfig6ManualAddressNotify, + &IsAddressOk, + &MappedEvt + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + // + // Parse the setting variables. + // + while (VarArg != NULL) { + // + // Check invalid parameters (duplication & unknown & conflict). + // + CheckCode = IfConfig6RetriveCheckListByName( + mSetCheckList, + VarArg->Arg, + FALSE + ); + + if (VarCheckOk != CheckCode) { + switch (CheckCode) { + case VarCheckDuplicate: + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_DUPLICATE_COMMAND), mHiiHandle, VarArg->Arg); + break; + + case VarCheckConflict: + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_CONFLICT_COMMAND), mHiiHandle, VarArg->Arg); + break; + + case VarCheckUnknown: + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_UNKNOWN_COMMAND), mHiiHandle, 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)) { + 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)) { + 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) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_ARGUMENTS), mHiiHandle, L"host"); + continue; + } else { + 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)) { + 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), mHiiHandle, Status); + 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), mHiiHandle, Status); + goto ON_EXIT; + } + + IfInfo = AllocateZeroPool (DataSize); + + if (IfInfo == NULL) { + Status = EFI_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), mHiiHandle, Status); + 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), mHiiHandle); + 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) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_ARGUMENTS), mHiiHandle, L"gw"); + continue; + } else { + goto ON_EXIT; + } + } + // + // Set static gateway ip6 address list. + // + Status = IfCb->IfCfg->SetData ( + IfCb->IfCfg, + Ip6ConfigDataTypeGateway, + AddrSize, + CfgAddr + ); + + if (EFI_ERROR (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) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_ARGUMENTS), mHiiHandle, L"dns"); + continue; + } else { + goto ON_EXIT; + } + } + // + // Set static dhs server ip6 address list. + // + Status = IfCb->IfCfg->SetData ( + IfCb->IfCfg, + Ip6ConfigDataTypeDnsServer, + AddrSize, + CfgAddr + ); + + if (EFI_ERROR (Status)) { + 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)) { + 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)) { + 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)) { + 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)) { + 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 Status; + +} + +/** + The IfConfig6 main process. + + @param[in] Private The pointer of IFCONFIG6_PRIVATE_DATA. + + @retval EFI_SUCCESS IfConfig6 processed successfully. + @retval others The IfConfig6 process failed. + +**/ +EFI_STATUS +IfConfig6 ( + IN IFCONFIG6_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + + // + // Get configure information of all interfaces. + // + Status = IfConfig6GetInterfaceInfo ( + Private->ImageHandle, + Private->IfName, + &Private->IfList + ); + + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + switch (Private->OpCode) { + case IfConfig6OpList: + Status = IfConfig6ShowInterfaceInfo (&Private->IfList); + break; + + case IfConfig6OpClear: + Status = IfConfig6ClearInterfaceInfo (&Private->IfList); + break; + + case IfConfig6OpSet: + Status = IfConfig6SetInterfaceInfo (&Private->IfList, Private->VarArg); + break; + + default: + Status = EFI_ABORTED; + } + +ON_EXIT: + + return Status; +} + +/** + 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); +} + +/** + This is the declaration of an EFI image entry point. This entry point is + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including + both device drivers and bus drivers. + + The entry point for the IfConfig6 application which parses the command line input and calls the IfConfig6 process. + + @param[in] ImageHandle The image handle of this application. + @param[in] SystemTable The pointer to the EFI System Table. + + @retval EFI_SUCCESS The operation completed successfully. + @retval Others Some errors occur. + +**/ +EFI_STATUS +EFIAPI +IfConfig6Initialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + IFCONFIG6_PRIVATE_DATA *Private; + LIST_ENTRY *ParamPackage; + CONST CHAR16 *ValueStr; + ARG_LIST *ArgList; + CHAR16 *ProblemParam; + CHAR16 *Str; + + Private = NULL; + + // + // Register our string package with HII and return the handle to it. + // + mHiiHandle = HiiAddPackages (&gEfiCallerIdGuid, ImageHandle, IfConfig6Strings, NULL); + ASSERT (mHiiHandle != NULL); + + Status = ShellCommandLineParseEx (mIfConfig6CheckList, &ParamPackage, &ProblemParam, TRUE, FALSE); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_COMMAND), mHiiHandle, ProblemParam); + 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), mHiiHandle); + 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), mHiiHandle); + goto ON_EXIT; + } + // + // To show the help information of ifconfig6 command. + // + if (ShellCommandLineGetFlag (ParamPackage, L"-?")) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_HELP), mHiiHandle); + goto ON_EXIT; + } + + Status = EFI_INVALID_PARAMETER; + + Private = AllocateZeroPool (sizeof (IFCONFIG6_PRIVATE_DATA)); + + if (Private == NULL) { + Status = EFI_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 = (CHAR16 *) AllocateZeroPool (StrSize (ValueStr)); + ASSERT (Str != NULL); + + Str = StrCpy (Str, ValueStr); + 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 = (CHAR16 *) AllocateZeroPool (StrSize (ValueStr)); + ASSERT (Str != NULL); + + Str = StrCpy (Str, ValueStr); + 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), mHiiHandle); + goto ON_EXIT; + } + // + // To split the configuration into multi-section. + // + ArgList = SplitStrToList (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), mHiiHandle); + goto ON_EXIT; + } + } + // + // Main process of ifconfig6. + // + Status = IfConfig6 (Private); + +ON_EXIT: + + ShellCommandLineFreeVarList (ParamPackage); + HiiRemovePackages (mHiiHandle); + if (Private != NULL) + IfConfig6Cleanup (Private); + + return Status; +} + diff --git a/NetworkPkg/Application/IfConfig6/IfConfig6.h b/NetworkPkg/Application/IfConfig6/IfConfig6.h new file mode 100644 index 0000000000..eea7df55d1 --- /dev/null +++ b/NetworkPkg/Application/IfConfig6/IfConfig6.h @@ -0,0 +1,84 @@ +/** @file + The interface function declaration of shell application IfConfig6. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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. + +**/ + +#ifndef _IFCONFIG6_H_ +#define _IFCONFIG6_H_ + +#define EFI_IFCONFIG6_GUID \ + { \ + 0xbab7296b, 0x222c, 0x4408, {0x9e, 0x6c, 0xc2, 0x5c, 0x18, 0x7e, 0xff, 0x33} \ + } + +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; +#endif diff --git a/NetworkPkg/Application/IfConfig6/IfConfig6.inf b/NetworkPkg/Application/IfConfig6/IfConfig6.inf new file mode 100644 index 0000000000..dd3ab64493 --- /dev/null +++ b/NetworkPkg/Application/IfConfig6/IfConfig6.inf @@ -0,0 +1,52 @@ +## @file +# Component description file for Shell application IfConfig6. +# +# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+# +# 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. +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = IfConfig6 + FILE_GUID = 6F71926E-60CE-428d-AA58-A3D9FB879429 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = IfConfig6Initialize + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF +# +[Sources] + IfConfig6Strings.uni + IfConfig6.c + IfConfig6.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ShellPkg/ShellPkg.dec + +[LibraryClasses] + BaseLib + UefiBootServicesTableLib + UefiApplicationEntryPoint + BaseMemoryLib + ShellLib + MemoryAllocationLib + DebugLib + HiiLib + NetLib + +[Protocols] + gEfiIp6ServiceBindingProtocolGuid ## CONSUMS + gEfiIp6ConfigProtocolGuid ## CONSUMS diff --git a/NetworkPkg/Application/IfConfig6/IfConfig6Strings.uni b/NetworkPkg/Application/IfConfig6/IfConfig6Strings.uni new file mode 100644 index 0000000000..a5e7fd04cf Binary files /dev/null and b/NetworkPkg/Application/IfConfig6/IfConfig6Strings.uni differ diff --git a/NetworkPkg/Application/IpsecConfig/Delete.c b/NetworkPkg/Application/IpsecConfig/Delete.c new file mode 100644 index 0000000000..caeb1c8350 --- /dev/null +++ b/NetworkPkg/Application/IpsecConfig/Delete.c @@ -0,0 +1,110 @@ +/** @file + The implementation of delete policy entry function in IpSecConfig application. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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 "IpSecConfig.h" +#include "Indexer.h" +#include "Delete.h" +#include "Match.h" +#include "ForEach.h" + +/** + Private function to delete entry information in database. + + @param[in] Selector The pointer to EFI_IPSEC_CONFIG_SELECTOR structure. + @param[in] Data The pointer to Data. + @param[in] Context The pointer to DELETE_POLICY_ENTRY_CONTEXT. + + @retval EFI_ABORTED Abort the iteration. + @retval EFI_SUCCESS Continue the iteration. +**/ +EFI_STATUS +DeletePolicyEntry ( + IN EFI_IPSEC_CONFIG_SELECTOR *Selector, + IN VOID *Data, + IN DELETE_POLICY_ENTRY_CONTEXT *Context + ) +{ + if (mMatchPolicyEntry[Context->DataType] (Selector, Data, &Context->Indexer)) { + Context->Status = mIpSecConfig->SetData ( + mIpSecConfig, + Context->DataType, + Selector, + NULL, + NULL + ); + // + // Abort the iteration after the insertion. + // + return EFI_ABORTED; + } + + return EFI_SUCCESS; +} + +/** + Flush or delete entry information in the database according to datatype. + + @param[in] DataType The value of EFI_IPSEC_CONFIG_DATA_TYPE. + @param[in] ParamPackage The pointer to the ParamPackage list. + + @retval EFI_SUCCESS Delete entry information successfully. + @retval EFI_NOT_FOUND Can't find the specified entry. + @retval Others Some mistaken case. +**/ +EFI_STATUS +FlushOrDeletePolicyEntry ( + IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, + IN LIST_ENTRY *ParamPackage + ) +{ + EFI_STATUS Status; + DELETE_POLICY_ENTRY_CONTEXT Context; + CONST CHAR16 *ValueStr; + + // + // If user wants to remove all. + // + if (ShellCommandLineGetFlag (ParamPackage, L"-f")) { + Status = mIpSecConfig->SetData ( + mIpSecConfig, + DataType, + NULL, + NULL, + NULL + ); + } else { + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-d"); + if (ValueStr == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INDEX_NOT_SPECIFIED), mHiiHandle, mAppName, ValueStr); + return EFI_NOT_FOUND; + } + + Status = mConstructPolicyEntryIndexer[DataType] (&Context.Indexer, ParamPackage); + if (!EFI_ERROR (Status)) { + Context.DataType = DataType; + Context.Status = EFI_NOT_FOUND; + ForeachPolicyEntry (DataType, (VISIT_POLICY_ENTRY) DeletePolicyEntry, &Context); + Status = Context.Status; + + if (Status == EFI_NOT_FOUND) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INDEX_NOT_FOUND), mHiiHandle, mAppName, ValueStr); + } else if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_DELETE_FAILED), mHiiHandle, mAppName); + } + } + } + + return Status; +} diff --git a/NetworkPkg/Application/IpsecConfig/Delete.h b/NetworkPkg/Application/IpsecConfig/Delete.h new file mode 100644 index 0000000000..49f3b0d5fa --- /dev/null +++ b/NetworkPkg/Application/IpsecConfig/Delete.h @@ -0,0 +1,42 @@ +/** @file + The internal structure and function declaration of delete policy entry function + in IpSecConfig application. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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. + +**/ + +#ifndef __DELETE_H_ +#define __DELETE_H_ + +typedef struct { + EFI_IPSEC_CONFIG_DATA_TYPE DataType; + POLICY_ENTRY_INDEXER Indexer; + EFI_STATUS Status; //Indicate whether deletion succeeds. +} DELETE_POLICY_ENTRY_CONTEXT; + +/** + Flush or delete entry information in the database according to datatype. + + @param[in] DataType The value of EFI_IPSEC_CONFIG_DATA_TYPE. + @param[in] ParamPackage The pointer to the ParamPackage list. + + @retval EFI_SUCCESS Delete entry information successfully. + @retval EFI_NOT_FOUND Can't find the specified entry. + @retval Others Some mistaken case. +**/ +EFI_STATUS +FlushOrDeletePolicyEntry ( + IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, + IN LIST_ENTRY *ParamPackage + ); + +#endif diff --git a/NetworkPkg/Application/IpsecConfig/Dump.c b/NetworkPkg/Application/IpsecConfig/Dump.c new file mode 100644 index 0000000000..004ab1089c --- /dev/null +++ b/NetworkPkg/Application/IpsecConfig/Dump.c @@ -0,0 +1,530 @@ +/** @file + The implementation of dump policy entry function in IpSecConfig application. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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 "IpSecConfig.h" +#include "Dump.h" +#include "ForEach.h" +#include "Helper.h" + +/** + Private function called to get the version infomation from an EFI_IP_ADDRESS_INFO structure. + + @param[in] AddressInfo The pointer to the EFI_IP_ADDRESS_INFO structure. + + @return the value of version. +**/ +UINTN +GetVerFromAddrInfo ( + IN EFI_IP_ADDRESS_INFO *AddressInfo +) +{ + if((AddressInfo->PrefixLength <= 32) && (AddressInfo->Address.Addr[1] == 0) && + (AddressInfo->Address.Addr[2] == 0) && (AddressInfo->Address.Addr[3] == 0)) { + return IP_VERSION_4; + } else { + return IP_VERSION_6; + } +} + +/** + Private function called to get the version information from a EFI_IP_ADDRESS structure. + + @param[in] Address The pointer to the EFI_IP_ADDRESS structure. + + @return The value of the version. +**/ +UINTN +GetVerFromIpAddr ( + IN EFI_IP_ADDRESS *Address +) +{ + if ((Address->Addr[1] == 0) && (Address->Addr[2] == 0) && (Address->Addr[3] == 0)) { + return IP_VERSION_4; + } else { + return IP_VERSION_6; + } +} + +/** + Private function called to print an ASCII string in unicode char format. + + @param[in] Str The pointer to the ASCII string. + @param[in] Length The value of the ASCII string length. +**/ +VOID +DumpAsciiString ( + IN CHAR8 *Str, + IN UINTN Length + ) +{ + UINTN Index; + for (Index = 0; Index < Length; Index++) { + Print (L"%c", (CHAR16) Str[Index]); + } +} + +/** + Private function called to print EFI_IP_ADDRESS_INFO content. + + @param[in] AddressInfo The pointer to the EFI_IP_ADDRESS_INFO structure. +**/ +VOID +DumpAddressInfo ( + IN EFI_IP_ADDRESS_INFO *AddressInfo + ) +{ + if (IP_VERSION_4 == GetVerFromAddrInfo (AddressInfo)) { + Print ( + L"%d.%d.%d.%d", + (UINTN) AddressInfo->Address.v4.Addr[0], + (UINTN) AddressInfo->Address.v4.Addr[1], + (UINTN) AddressInfo->Address.v4.Addr[2], + (UINTN) AddressInfo->Address.v4.Addr[3] + ); + if (AddressInfo->PrefixLength != 32) { + Print (L"/%d", (UINTN) AddressInfo->PrefixLength); + } + } + + if (IP_VERSION_6 == GetVerFromAddrInfo (AddressInfo)) { + Print ( + L"%x:%x:%x:%x:%x:%x:%x:%x", + (((UINT16) AddressInfo->Address.v6.Addr[0]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[1]), + (((UINT16) AddressInfo->Address.v6.Addr[2]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[3]), + (((UINT16) AddressInfo->Address.v6.Addr[4]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[5]), + (((UINT16) AddressInfo->Address.v6.Addr[6]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[7]), + (((UINT16) AddressInfo->Address.v6.Addr[8]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[9]), + (((UINT16) AddressInfo->Address.v6.Addr[10]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[11]), + (((UINT16) AddressInfo->Address.v6.Addr[12]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[13]), + (((UINT16) AddressInfo->Address.v6.Addr[14]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[15]) + ); + if (AddressInfo->PrefixLength != 128) { + Print (L"/%d", AddressInfo->PrefixLength); + } + } +} + +/** + Private function called to print EFI_IP_ADDRESS content. + + @param[in] IpAddress The pointer to the EFI_IP_ADDRESS structure. +**/ +VOID +DumpIpAddress ( + IN EFI_IP_ADDRESS *IpAddress + ) +{ + if (IP_VERSION_4 == GetVerFromIpAddr (IpAddress)) { + Print ( + L"%d.%d.%d.%d", + (UINTN) IpAddress->v4.Addr[0], + (UINTN) IpAddress->v4.Addr[1], + (UINTN) IpAddress->v4.Addr[2], + (UINTN) IpAddress->v4.Addr[3] + ); + } + + if (IP_VERSION_6 == GetVerFromIpAddr (IpAddress)) { + Print ( + L"%x:%x:%x:%x:%x:%x:%x:%x", + (((UINT16) IpAddress->v6.Addr[0]) << 8) | ((UINT16) IpAddress->v6.Addr[1]), + (((UINT16) IpAddress->v6.Addr[2]) << 8) | ((UINT16) IpAddress->v6.Addr[3]), + (((UINT16) IpAddress->v6.Addr[4]) << 8) | ((UINT16) IpAddress->v6.Addr[5]), + (((UINT16) IpAddress->v6.Addr[6]) << 8) | ((UINT16) IpAddress->v6.Addr[7]), + (((UINT16) IpAddress->v6.Addr[8]) << 8) | ((UINT16) IpAddress->v6.Addr[9]), + (((UINT16) IpAddress->v6.Addr[10]) << 8) | ((UINT16) IpAddress->v6.Addr[11]), + (((UINT16) IpAddress->v6.Addr[12]) << 8) | ((UINT16) IpAddress->v6.Addr[13]), + (((UINT16) IpAddress->v6.Addr[14]) << 8) | ((UINT16) IpAddress->v6.Addr[15]) + ); + } + +} + +/** + Private function called to print EFI_IPSEC_SPD_SELECTOR content. + + @param[in] Selector The pointer to the EFI_IPSEC_SPD_SELECTOR structure. +**/ +VOID +DumpSpdSelector ( + IN EFI_IPSEC_SPD_SELECTOR *Selector + ) +{ + UINT32 Index; + CHAR16 *Str; + + for (Index = 0; Index < Selector->LocalAddressCount; Index++) { + if (Index > 0) { + Print (L","); + } + + DumpAddressInfo (&Selector->LocalAddress[Index]); + } + + if (Index == 0) { + Print (L"localhost"); + } + + Print (L" -> "); + + for (Index = 0; Index < Selector->RemoteAddressCount; Index++) { + if (Index > 0) { + Print (L","); + } + + DumpAddressInfo (&Selector->RemoteAddress[Index]); + } + + Str = MapIntegerToString (Selector->NextLayerProtocol, mMapIpProtocol); + if (Str != NULL) { + Print (L" %s", Str); + } else { + Print (L" proto:%d", (UINTN) Selector->NextLayerProtocol); + } + + if ((Selector->NextLayerProtocol == EFI_IP4_PROTO_TCP) || (Selector->NextLayerProtocol == EFI_IP4_PROTO_UDP)) { + Print (L" port:"); + if (Selector->LocalPort != EFI_IPSEC_ANY_PORT) { + Print (L"%d", Selector->LocalPort); + if (Selector->LocalPortRange != 0) { + Print (L"~%d", (UINTN) Selector->LocalPort + Selector->LocalPortRange); + } + } else { + Print (L"any"); + } + + Print (L" -> "); + if (Selector->RemotePort != EFI_IPSEC_ANY_PORT) { + Print (L"%d", Selector->RemotePort); + if (Selector->RemotePortRange != 0) { + Print (L"~%d", (UINTN) Selector->RemotePort + Selector->RemotePortRange); + } + } else { + Print (L"any"); + } + } else if (Selector->NextLayerProtocol == EFI_IP4_PROTO_ICMP) { + Print (L" class/code:"); + if (Selector->LocalPort != 0) { + Print (L"%d", (UINTN) (UINT8) Selector->LocalPort); + } else { + Print (L"any"); + } + + Print (L"/"); + if (Selector->RemotePort != 0) { + Print (L"%d", (UINTN) (UINT8) Selector->RemotePort); + } else { + Print (L"any"); + } + } +} + +/** + Print EFI_IPSEC_SPD_SELECTOR and EFI_IPSEC_SPD_DATA content. + + @param[in] Selector The pointer to the EFI_IPSEC_SPD_SELECTOR structure. + @param[in] Data The pointer to the EFI_IPSEC_SPD_DATA structure. + @param[in] EntryIndex The pointer to the Index in SPD Database. + + @retval EFI_SUCCESS Dump SPD information successfully. +**/ +EFI_STATUS +DumpSpdEntry ( + IN EFI_IPSEC_SPD_SELECTOR *Selector, + IN EFI_IPSEC_SPD_DATA *Data, + IN UINTN *EntryIndex + ) +{ + BOOLEAN HasPre; + CHAR16 DataName[128]; + CHAR16 *String1; + CHAR16 *String2; + CHAR16 *String3; + UINT8 Index; + + Print (L"%d.", (*EntryIndex)++); + + // + // xxx.xxx.xxx.xxx/yy -> xxx.xxx.xxx.xx/yy proto:23 port:100~300 -> 300~400 + // Protect PF:0x34323423 Name:First Entry + // ext-sequence sequence-overflow fragcheck life:[B0,S1024,H3600] + // ESP algo1 algo2 Tunnel [xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx set] + // + + DumpSpdSelector (Selector); + Print (L"\n "); + + Print (L"%s ", MapIntegerToString (Data->Action, mMapIpSecAction)); + Print (L"PF:%08x ", Data->PackageFlag); + + Index = 0; + while (Data->Name[Index] != 0) { + DataName[Index] = (CHAR16) Data->Name[Index]; + Index++; + ASSERT (Index < 128); + } + DataName[Index] = L'\0'; + + Print (L"Name:%s", DataName); + + if (Data->Action == EfiIPsecActionProtect) { + Print (L"\n "); + if (Data->ProcessingPolicy->ExtSeqNum) { + Print (L"ext-sequence "); + } + + if (Data->ProcessingPolicy->SeqOverflow) { + Print (L"sequence-overflow "); + } + + if (Data->ProcessingPolicy->FragCheck) { + Print (L"fragment-check "); + } + + HasPre = FALSE; + if (Data->ProcessingPolicy->SaLifetime.ByteCount != 0) { + Print (HasPre ? L"," : L"life:["); + Print (L"%lxB", Data->ProcessingPolicy->SaLifetime.ByteCount); + HasPre = TRUE; + } + + if (Data->ProcessingPolicy->SaLifetime.SoftLifetime != 0) { + Print (HasPre ? L"," : L"life:["); + Print (L"%lxs", Data->ProcessingPolicy->SaLifetime.SoftLifetime); + HasPre = TRUE; + } + + if (Data->ProcessingPolicy->SaLifetime.HardLifetime != 0) { + Print (HasPre ? L"," : L"life:["); + Print (L"%lxS", Data->ProcessingPolicy->SaLifetime.HardLifetime); + HasPre = TRUE; + } + + if (HasPre) { + Print (L"]"); + } + + if (HasPre || Data->ProcessingPolicy->ExtSeqNum || + Data->ProcessingPolicy->SeqOverflow || Data->ProcessingPolicy->FragCheck) { + Print (L"\n "); + } + + String1 = MapIntegerToString (Data->ProcessingPolicy->Proto, mMapIpSecProtocol); + String2 = MapIntegerToString (Data->ProcessingPolicy->AuthAlgoId, mMapAuthAlgo); + String3 = MapIntegerToString (Data->ProcessingPolicy->EncAlgoId, mMapEncAlgo); + Print ( + L"%s Auth:%s Encrypt:%s ", + String1, + String2, + String3 + ); + + Print (L"%s ", MapIntegerToString (Data->ProcessingPolicy->Mode, mMapIpSecMode)); + if (Data->ProcessingPolicy->Mode == EfiIPsecTunnel) { + Print (L"["); + DumpIpAddress (&Data->ProcessingPolicy->TunnelOption->LocalTunnelAddress); + Print (L" -> "); + DumpIpAddress (&Data->ProcessingPolicy->TunnelOption->RemoteTunnelAddress); + Print (L" %s]", MapIntegerToString (Data->ProcessingPolicy->TunnelOption->DF, mMapDfOption)); + } + } + + Print (L"\n"); + + return EFI_SUCCESS; +} + +/** + Print EFI_IPSEC_SA_ID and EFI_IPSEC_SA_DATA content. + + @param[in] SaId The pointer to the EFI_IPSEC_SA_ID structure. + @param[in] Data The pointer to the EFI_IPSEC_SA_DATA structure. + @param[in] EntryIndex The pointer to the Index in the SAD Database. + + @retval EFI_SUCCESS Dump SAD information successfully. +**/ +EFI_STATUS +DumpSadEntry ( + IN EFI_IPSEC_SA_ID *SaId, + IN EFI_IPSEC_SA_DATA *Data, + IN UINTN *EntryIndex + ) +{ + BOOLEAN HasPre; + CHAR16 *String1; + CHAR16 *String2; + + // + // SPI:1234 ESP Destination:xxx.xxx.xxx.xxx + // Mode:Transport SeqNum:134 AntiReplayWin:64 life:[0B,1023s,3400S] PathMTU:34 + // Auth:xxxx/password Encrypt:yyyy/password + // xxx.xxx.xxx.xxx/yy -> xxx.xxx.xxx.xx/yy proto:23 port:100~300 -> 300~400 + // + + Print (L"%d.", (*EntryIndex)++); + Print (L"0x%x %s ", (UINTN) SaId->Spi, MapIntegerToString (SaId->Proto, mMapIpSecProtocol)); + Print (L"Destination:"); + DumpIpAddress (&SaId->DestAddress); + Print (L"\n"); + + Print ( + L" Mode:%s SeqNum:%lx AntiReplayWin:%d ", + MapIntegerToString (Data->Mode, mMapIpSecMode), + Data->SNCount, + (UINTN) Data->AntiReplayWindows + ); + + HasPre = FALSE; + if (Data->SaLifetime.ByteCount != 0) { + Print (HasPre ? L"," : L"life:["); + Print (L"%lxB", Data->SaLifetime.ByteCount); + HasPre = TRUE; + } + + if (Data->SaLifetime.SoftLifetime != 0) { + Print (HasPre ? L"," : L"life:["); + Print (L"%lxs", Data->SaLifetime.SoftLifetime); + HasPre = TRUE; + } + + if (Data->SaLifetime.HardLifetime != 0) { + Print (HasPre ? L"," : L"life:["); + Print (L"%lxS", Data->SaLifetime.HardLifetime); + HasPre = TRUE; + } + + if (HasPre) { + Print (L"] "); + } + + Print (L"PathMTU:%d\n", (UINTN) Data->PathMTU); + + if (SaId->Proto == EfiIPsecAH) { + Print ( + L" Auth:%s/%s\n", + MapIntegerToString (Data->AlgoInfo.AhAlgoInfo.AuthAlgoId, mMapAuthAlgo), + Data->AlgoInfo.AhAlgoInfo.AuthKey + ); + } else { + String1 = MapIntegerToString (Data->AlgoInfo.EspAlgoInfo.AuthAlgoId, mMapAuthAlgo); + String2 = MapIntegerToString (Data->AlgoInfo.EspAlgoInfo.EncAlgoId, mMapEncAlgo); + Print ( + L" Auth:%s/%s Encrypt:%s/%s\n", + String1, + Data->AlgoInfo.EspAlgoInfo.AuthKey, + String2, + Data->AlgoInfo.EspAlgoInfo.EncKey + ); + } + + if (Data->SpdSelector != NULL) { + Print (L" "); + DumpSpdSelector (Data->SpdSelector); + Print (L"\n"); + } + + return EFI_SUCCESS; +} + +/** + Print EFI_IPSEC_PAD_ID and EFI_IPSEC_PAD_DATA content. + + @param[in] PadId The pointer to the EFI_IPSEC_PAD_ID structure. + @param[in] Data The pointer to the EFI_IPSEC_PAD_DATA structure. + @param[in] EntryIndex The pointer to the Index in the PAD Database. + + @retval EFI_SUCCESS Dump PAD information successfully. +**/ +EFI_STATUS +DumpPadEntry ( + IN EFI_IPSEC_PAD_ID *PadId, + IN EFI_IPSEC_PAD_DATA *Data, + IN UINTN *EntryIndex + ) +{ + CHAR16 *String1; + CHAR16 *String2; + + // + // ADDR:10.23.17.34/15 + // IDEv1 PreSharedSecret IKE-ID + // password + // + + Print (L"%d.", (*EntryIndex)++); + + if (PadId->PeerIdValid) { + Print (L"ID:%s", PadId->Id.PeerId); + } else { + Print (L"ADDR:"); + DumpAddressInfo (&PadId->Id.IpAddress); + } + + Print (L"\n"); + + String1 = MapIntegerToString (Data->AuthProtocol, mMapAuthProto); + String2 = MapIntegerToString (Data->AuthMethod, mMapAuthMethod); + Print ( + L" %s %s", + String1, + String2 + ); + + if (Data->IkeIdFlag) { + Print (L"IKE-ID"); + } + + Print (L"\n"); + + if (Data->AuthData != NULL) { + DumpAsciiString (Data->AuthData, Data->AuthDataSize); + Print (L"\n"); + } + + if (Data->RevocationData != NULL) { + Print (L" %s\n", Data->RevocationData); + } + + return EFI_SUCCESS; + +} + +VISIT_POLICY_ENTRY mDumpPolicyEntry[] = { + (VISIT_POLICY_ENTRY) DumpSpdEntry, + (VISIT_POLICY_ENTRY) DumpSadEntry, + (VISIT_POLICY_ENTRY) DumpPadEntry +}; + +/** + Print all entry information in the database according to datatype. + + @param[in] DataType The value of EFI_IPSEC_CONFIG_DATA_TYPE. + @param[in] ParamPackage The pointer to the ParamPackage list. + + @retval EFI_SUCCESS Dump all information successfully. + @retval Others Some mistaken case. +**/ +EFI_STATUS +ListPolicyEntry ( + IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, + IN LIST_ENTRY *ParamPackage + ) +{ + UINTN EntryIndex; + + EntryIndex = 0; + return ForeachPolicyEntry (DataType, mDumpPolicyEntry[DataType], &EntryIndex); +} + diff --git a/NetworkPkg/Application/IpsecConfig/Dump.h b/NetworkPkg/Application/IpsecConfig/Dump.h new file mode 100644 index 0000000000..3c475dd304 --- /dev/null +++ b/NetworkPkg/Application/IpsecConfig/Dump.h @@ -0,0 +1,34 @@ +/** @file + The function declaration of dump policy entry function in IpSecConfig application. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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. + +**/ + +#ifndef _DUMP_H_ +#define _DUMP_H_ + +/** + Print all entry information in the database according to datatype. + + @param[in] DataType The value of EFI_IPSEC_CONFIG_DATA_TYPE. + @param[in] ParamPackage The pointer to the ParamPackage list. + + @retval EFI_SUCCESS Dump all information successfully. + @retval Others Some mistaken case. +**/ +EFI_STATUS +ListPolicyEntry ( + IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, + IN LIST_ENTRY *ParamPackage + ); + +#endif diff --git a/NetworkPkg/Application/IpsecConfig/ForEach.c b/NetworkPkg/Application/IpsecConfig/ForEach.c new file mode 100644 index 0000000000..7b3b9b17a8 --- /dev/null +++ b/NetworkPkg/Application/IpsecConfig/ForEach.c @@ -0,0 +1,115 @@ +/** @file + The implementation to go through each entry in IpSecConfig application. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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 "IpSecConfig.h" +#include "ForEach.h" + + +/** + Enumerate all entries in the database to execute specified operations according to datatype. + + @param[in] DataType The value of EFI_IPSEC_CONFIG_DATA_TYPE. + @param[in] Routine The pointer to the function of a specified operation. + @param[in] Context The pointer to the context of a function. + + @retval EFI_SUCCESS Execute specified operation successfully. +**/ +EFI_STATUS +ForeachPolicyEntry ( + IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, + IN VISIT_POLICY_ENTRY Routine, + IN VOID *Context + ) +{ + EFI_STATUS GetNextStatus; + EFI_STATUS GetDataStatus; + EFI_IPSEC_CONFIG_SELECTOR *Selector; + VOID *Data; + UINTN SelectorSize; + UINTN DataSize; + BOOLEAN FirstGetNext; + + FirstGetNext = TRUE; + SelectorSize = sizeof (EFI_IPSEC_CONFIG_SELECTOR); + Selector = AllocateZeroPool (SelectorSize); + + DataSize = 0; + Data = NULL; + + while (TRUE) { + GetNextStatus = mIpSecConfig->GetNextSelector ( + mIpSecConfig, + DataType, + &SelectorSize, + Selector + ); + if (GetNextStatus == EFI_BUFFER_TOO_SMALL) { + gBS->FreePool (Selector); + Selector = FirstGetNext ? AllocateZeroPool (SelectorSize) : AllocatePool (SelectorSize); + + GetNextStatus = mIpSecConfig->GetNextSelector ( + mIpSecConfig, + DataType, + &SelectorSize, + Selector + ); + } + + if (EFI_ERROR (GetNextStatus)) { + break; + } + + FirstGetNext = FALSE; + + GetDataStatus = mIpSecConfig->GetData ( + mIpSecConfig, + DataType, + Selector, + &DataSize, + Data + ); + if (GetDataStatus == EFI_BUFFER_TOO_SMALL) { + if (Data != NULL) { + gBS->FreePool (Data); + } + + Data = AllocateZeroPool (DataSize); + GetDataStatus = mIpSecConfig->GetData ( + mIpSecConfig, + DataType, + Selector, + &DataSize, + Data + ); + } + + ASSERT_EFI_ERROR (GetDataStatus); + + if (EFI_ERROR (Routine (Selector, Data, Context))) { + break; + } + } + + if (Data != NULL) { + gBS->FreePool (Data); + } + + if (Selector != NULL) { + gBS->FreePool (Selector); + } + + return EFI_SUCCESS; +} + diff --git a/NetworkPkg/Application/IpsecConfig/ForEach.h b/NetworkPkg/Application/IpsecConfig/ForEach.h new file mode 100644 index 0000000000..fc309300c0 --- /dev/null +++ b/NetworkPkg/Application/IpsecConfig/ForEach.h @@ -0,0 +1,54 @@ +/** @file + The internal structure and function declaration of the implementation + to go through each entry in IpSecConfig application. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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. + +**/ + +#ifndef _FOREACH_H_ +#define _FOREACH_H_ + +/** + The prototype for the DumpSpdEntry()/DumpSadEntry()/DumpPadEntry(). + Print EFI_IPSEC_CONFIG_SELECTOR and corresponding content. + + @param[in] Selector The pointer to the EFI_IPSEC_CONFIG_SELECTOR union. + @param[in] Data The pointer to the corresponding data. + @param[in] Context The pointer to the Index in SPD/SAD/PAD Database. + + @retval EFI_SUCCESS Dump SPD/SAD/PAD information successfully. +**/ +typedef +EFI_STATUS +(*VISIT_POLICY_ENTRY) ( + IN EFI_IPSEC_CONFIG_SELECTOR *Selector, + IN VOID *Data, + IN VOID *Context + ); + +/** + Enumerate all entry in the database to execute a specified operation according to datatype. + + @param[in] DataType The value of EFI_IPSEC_CONFIG_DATA_TYPE. + @param[in] Routine The pointer to function of a specified operation. + @param[in] Context The pointer to the context of a function. + + @retval EFI_SUCCESS Execute specified operation successfully. +**/ +EFI_STATUS +ForeachPolicyEntry ( + IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, + IN VISIT_POLICY_ENTRY Routine, + IN VOID *Context + ); + +#endif diff --git a/NetworkPkg/Application/IpsecConfig/Helper.c b/NetworkPkg/Application/IpsecConfig/Helper.c new file mode 100644 index 0000000000..5013ad9b76 --- /dev/null +++ b/NetworkPkg/Application/IpsecConfig/Helper.c @@ -0,0 +1,419 @@ +/** @file + The assistant function implementation for IpSecConfig application. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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 "IpSecConfig.h" +#include "Helper.h" + +/** + Helper function called to change an input parameter in the string format to a number. + + @param[in] FlagStr The pointer to the flag string. + @param[in] Maximum Greatest value number. + @param[in, out] ValuePtr The pointer to the input parameter in string format. + @param[in] ByteCount The valid byte count + @param[in] Map The pointer to the STR2INT table. + @param[in] ParamPackage The pointer to the ParamPackage list. + @param[in] FormatMask The bit mask. + BIT 0 set indicates the value of a flag might be a number. + BIT 1 set indicates the value of a flag might be a string that needs to be looked up. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_NOT_FOUND The input parameter can't be found. + @retval EFI_INVALID_PARAMETER The input parameter is an invalid input. +**/ +EFI_STATUS +GetNumber ( + IN CHAR16 *FlagStr, + IN UINT64 Maximum, + IN OUT VOID *ValuePtr, + IN UINTN ByteCount, + IN STR2INT *Map, + IN LIST_ENTRY *ParamPackage, + IN UINT32 FormatMask + ) +{ + EFI_STATUS Status; + UINT64 Value64; + BOOLEAN Converted; + UINTN Index; + CONST CHAR16 *ValueStr; + + ASSERT (FormatMask & (FORMAT_NUMBER | FORMAT_STRING)); + + Converted = FALSE; + Value64 = 0; + ValueStr = ShellCommandLineGetValue (ParamPackage, FlagStr); + + if (ValueStr == NULL) { + return EFI_NOT_FOUND; + } else { + // + // Try to convert to integer directly if MaybeNumber is TRUE. + // + if ((FormatMask & FORMAT_NUMBER) != 0) { + Value64 = StrToUInteger (ValueStr, &Status); + if (!EFI_ERROR (Status)) { + // + // Convert successfully. + // + if (Value64 > Maximum) { + // + // But the result is invalid + // + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE), + mHiiHandle, + mAppName, + FlagStr, + ValueStr + ); + return EFI_INVALID_PARAMETER; + } + + Converted = TRUE; + } + } + + if (!Converted && ((FormatMask & FORMAT_STRING) != 0)) { + // + // Convert falied, so use String->Integer map. + // + Value64 = MapStringToInteger (ValueStr, Map); + if (Value64 == (UINT32) -1) { + // + // Cannot find the string in the map. + // + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE), + mHiiHandle, + mAppName, + FlagStr, + ValueStr + ); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_ACCEPT_PARAMETERS), mHiiHandle); + for (Index = 0; Map[Index].String != NULL; Index++) { + Print (L" %s", Map[Index].String); + } + + Print (L"\n"); + return EFI_INVALID_PARAMETER; + } + } + + CopyMem (ValuePtr, &Value64, ByteCount); + return EFI_SUCCESS; + } +} + +/** + Helper function called to convert a string containing an Ipv4 or Ipv6 Internet Protocol address + into a proper address for the EFI_IP_ADDRESS structure. + + @param[in] Ptr The pointer to the string containing an Ipv4 or Ipv6 Internet Protocol address. + @param[out] Ip The pointer to the EFI_IP_ADDRESS structure to contain the result. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EfiInetAddr2 ( + IN CHAR16 *Ptr, + OUT EFI_IP_ADDRESS *Ip + ) +{ + EFI_STATUS Status; + + if ((Ptr == NULL) || (Ip == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Parse the input address as Ipv4 Address first. + // + Status = NetLibStrToIp4 (Ptr, &Ip->v4); + if (!EFI_ERROR (Status)) { + return Status; + } + + Status = NetLibStrToIp6 (Ptr, &Ip->v6); + return Status; +} + +/** + Helper function called to calculate the prefix length associated with the string + containing an Ipv4 or Ipv6 Internet Protocol address. + + @param[in] Ptr The pointer to the string containing an Ipv4 or Ipv6 Internet Protocol address. + @param[out] Addr The pointer to the EFI_IP_ADDRESS_INFO structure to contain the result. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval Others Other mistake case. +**/ +EFI_STATUS +EfiInetAddrRange ( + IN CHAR16 *Ptr, + OUT EFI_IP_ADDRESS_INFO *Addr + ) +{ + EFI_STATUS Status; + + if ((Ptr == NULL) || (Addr == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Status = NetLibStrToIp4 (Ptr, &Addr->Address.v4); + if (!EFI_ERROR (Status)) { + if ((UINT32)(*Addr->Address.v4.Addr) == 0) { + Addr->PrefixLength = 0; + } else { + Addr->PrefixLength = 32; + } + return Status; + } + + Status = NetLibStrToIp6andPrefix (Ptr, &Addr->Address.v6, &Addr->PrefixLength); + if (!EFI_ERROR (Status) && (Addr->PrefixLength == 0xFF)) { + Addr->PrefixLength = 128; + } + + return Status; +} + +/** + Helper function called to calculate the port range associated with the string. + + @param[in] Ptr The pointer to the string containing a port and range. + @param[out] Port The pointer to the Port to contain the result. + @param[out] PortRange The pointer to the PortRange to contain the result. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval Others Other mistake case. +**/ +EFI_STATUS +EfiInetPortRange ( + IN CHAR16 *Ptr, + OUT UINT16 *Port, + OUT UINT16 *PortRange + ) +{ + CHAR16 *BreakPtr; + CHAR16 Ch; + EFI_STATUS Status; + + for (BreakPtr = Ptr; (*BreakPtr != L'\0') && (*BreakPtr != L':'); BreakPtr++) { + ; + } + + Ch = *BreakPtr; + *BreakPtr = L'\0'; + *Port = (UINT16) StrToUInteger (Ptr, &Status); + *BreakPtr = Ch; + if (EFI_ERROR (Status)) { + return Status; + } + + *PortRange = 0; + if (*BreakPtr == L':') { + BreakPtr++; + *PortRange = (UINT16) StrToUInteger (BreakPtr, &Status); + if (EFI_ERROR (Status)) { + return Status; + } + + if (*PortRange < *Port) { + return EFI_INVALID_PARAMETER; + } + + *PortRange = (UINT16) (*PortRange - *Port); + } + + return EFI_SUCCESS; +} + +/** + Helper function called to transfer a string to an unsigned integer. + + @param[in] Str The pointer to the string. + @param[out] Status The operation status. + + @return The integer value of converted Str. +**/ +UINT64 +StrToUInteger ( + IN CONST CHAR16 *Str, + OUT EFI_STATUS *Status + ) +{ + UINT64 Value; + UINT64 NewValue; + CHAR16 *StrTail; + CHAR16 Char; + UINTN Base; + UINTN Len; + + Base = 10; + Value = 0; + *Status = EFI_ABORTED; + + // + // Skip leading white space. + // + while ((*Str != 0) && (*Str == ' ')) { + Str++; + } + // + // For NULL Str, just return. + // + if (*Str == 0) { + return 0; + } + // + // Skip white space in tail. + // + Len = StrLen (Str); + StrTail = (CHAR16 *) (Str + Len - 1); + while (*StrTail == ' ') { + *StrTail = 0; + StrTail--; + } + + Len = StrTail - Str + 1; + + // + // Check hex prefix '0x'. + // + if ((Len >= 2) && (*Str == '0') && ((*(Str + 1) == 'x') || (*(Str + 1) == 'X'))) { + Str += 2; + Len -= 2; + Base = 16; + } + + if (Len == 0) { + return 0; + } + // + // Convert the string to value. + // + for (; Str <= StrTail; Str++) { + + Char = *Str; + + if (Base == 16) { + if (RShiftU64 (Value, 60) != 0) { + // + // Overflow here x16. + // + return 0; + } + + NewValue = LShiftU64 (Value, 4); + } else { + if (RShiftU64 (Value, 61) != 0) { + // + // Overflow here x8. + // + return 0; + } + + NewValue = LShiftU64 (Value, 3); + Value = LShiftU64 (Value, 1); + NewValue += Value; + if (NewValue < Value) { + // + // Overflow here. + // + return 0; + } + } + + Value = NewValue; + + if ((Base == 16) && (Char >= 'a') && (Char <= 'f')) { + Char = (CHAR16) (Char - 'a' + 'A'); + } + + if ((Base == 16) && (Char >= 'A') && (Char <= 'F')) { + Value += (Char - 'A') + 10; + } else if ((Char >= '0') && (Char <= '9')) { + Value += (Char - '0'); + } else { + // + // Unexpected Char encountered. + // + return 0; + } + } + + *Status = EFI_SUCCESS; + return Value; +} + +/** + Helper function called to transfer a string to an unsigned integer according to the map table. + + @param[in] Str The pointer to the string. + @param[in] Map The pointer to the map table. + + @return The integer value of converted Str. If not found, then return -1. +**/ +UINT32 +MapStringToInteger ( + IN CONST CHAR16 *Str, + IN STR2INT *Map + ) +{ + STR2INT *Item; + + for (Item = Map; Item->String != NULL; Item++) { + if (StrCmp (Item->String, Str) == 0) { + return Item->Integer; + } + } + + return (UINT32) -1; +} + +/** + Helper function called to transfer an unsigned integer to a string according to the map table. + + @param[in] Integer The pointer to the string. + @param[in] Map The pointer to the map table. + + @return The converted Str. If not found, then return NULL. +**/ +CHAR16 * +MapIntegerToString ( + IN UINT32 Integer, + IN STR2INT *Map + ) +{ + STR2INT *Item; + + for (Item = Map; Item->String != NULL; Item++) { + if (Integer == Item->Integer) { + return Item->String; + } + } + + return NULL; +} diff --git a/NetworkPkg/Application/IpsecConfig/Helper.h b/NetworkPkg/Application/IpsecConfig/Helper.h new file mode 100644 index 0000000000..d893145a76 --- /dev/null +++ b/NetworkPkg/Application/IpsecConfig/Helper.h @@ -0,0 +1,143 @@ +/** @file + The assistant function declaration for IpSecConfig application. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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. + +**/ + +#ifndef _HELPER_H_ +#define _HELPER_H_ + +#define FORMAT_NUMBER 0x1 +#define FORMAT_STRING 0x2 + +/** + Helper function called to change input parameter in string format to number. + + @param[in] FlagStr The pointer to the flag string. + @param[in] Maximum most value number. + @param[in, out] ValuePtr The pointer to the input parameter in string format. + @param[in] ByteCount The valid byte count + @param[in] Map The pointer to the STR2INT table. + @param[in] ParamPackage The pointer to the ParamPackage list. + @param[in] FormatMask The bit mask. + BIT 0 set indicates the value of flag might be number. + BIT 1 set indicates the value of flag might be a string that needs to be looked up. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_NOT_FOUND The input parameter can't be found. + @retval EFI_INVALID_PARAMETER The input parameter is an invalid input. +**/ +EFI_STATUS +GetNumber ( + IN CHAR16 *FlagStr, + IN UINT64 Maximum, + IN OUT VOID *ValuePtr, + IN UINTN ByteCount, + IN STR2INT *Map, + IN LIST_ENTRY *ParamPackage, + IN UINT32 FormatMask + ); + +/** + Helper function called to convert a string containing an (Ipv4) Internet Protocol dotted address + into a proper address for the EFI_IP_ADDRESS structure. + + @param[in] Ptr The pointer to the string containing an (Ipv4) Internet Protocol dotted address. + @param[out] Ip The pointer to the Ip address structure to contain the result. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EfiInetAddr2 ( + IN CHAR16 *Ptr, + OUT EFI_IP_ADDRESS *Ip + ); + +/** + Helper function called to calculate the prefix length associated with the string + containing an Ipv4 or Ipv6 Internet Protocol address. + + @param[in] Ptr The pointer to the string containing an Ipv4 or Ipv6 Internet Protocol address. + @param[out] Addr The pointer to the EFI_IP_ADDRESS_INFO structure to contain the result. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval Others Other mistake case. +**/ +EFI_STATUS +EfiInetAddrRange ( + IN CHAR16 *Ptr, + OUT EFI_IP_ADDRESS_INFO *Addr + ); + +/** + Helper function called to calculate the port range associated with the string. + + @param[in] Ptr The pointer to the string containing a port and range. + @param[out] Port The pointer to the Port to contain the result. + @param[out] PortRange The pointer to the PortRange to contain the result. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval Others Other mistake case. +**/ +EFI_STATUS +EfiInetPortRange ( + IN CHAR16 *Ptr, + OUT UINT16 *Port, + OUT UINT16 *PortRange + ); + +/** + Helper function called to transfer a string to an unsigned integer. + + @param[in] Str The pointer to the string. + @param[out] Status The operation status. + + @return The integer value of a converted str. +**/ +UINT64 +StrToUInteger ( + IN CONST CHAR16 *Str, + OUT EFI_STATUS *Status + ); + +/** + Helper function called to transfer a string to an unsigned integer according to the map table. + + @param[in] Str The pointer to the string. + @param[in] Map The pointer to the map table. + + @return The integer value of converted str. If not found, then return -1. +**/ +UINT32 +MapStringToInteger ( + IN CONST CHAR16 *Str, + IN STR2INT *Map + ); + +/** + Helper function called to transfer an unsigned integer to a string according to the map table. + + @param[in] Integer The pointer to the string. + @param[in] Map The pointer to the map table. + + @return The converted str. If not found, then return NULL. +**/ +CHAR16 * +MapIntegerToString ( + IN UINT32 Integer, + IN STR2INT *Map + ); + +#endif diff --git a/NetworkPkg/Application/IpsecConfig/Indexer.c b/NetworkPkg/Application/IpsecConfig/Indexer.c new file mode 100644 index 0000000000..1762bbeb58 --- /dev/null +++ b/NetworkPkg/Application/IpsecConfig/Indexer.c @@ -0,0 +1,248 @@ +/** @file + The implementation of construct ENTRY_INDEXER in IpSecConfig application. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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 "IpSecConfig.h" +#include "Indexer.h" +#include "Helper.h" + +/** + Fill in SPD_ENTRY_INDEXER through ParamPackage list. + + @param[in, out] Indexer The pointer to the SPD_ENTRY_INDEXER structure. + @param[in] ParamPackage The pointer to the ParamPackage list. + + @retval EFI_SUCCESS Filled in SPD_ENTRY_INDEXER successfully. +**/ +EFI_STATUS +ConstructSpdIndexer ( + IN OUT SPD_ENTRY_INDEXER *Indexer, + IN LIST_ENTRY *ParamPackage + ) +{ + EFI_STATUS Status; + UINT64 Value64; + CONST CHAR16 *ValueStr; + + ValueStr = NULL; + + if (ShellCommandLineGetFlag (ParamPackage, L"-i")) { + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-i"); + } else if (ShellCommandLineGetFlag (ParamPackage, L"-d")) { + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-d"); + } else if (ShellCommandLineGetFlag (ParamPackage, L"-e")) { + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-e"); + } else { + ASSERT (FALSE); + } + + ASSERT (ValueStr != NULL); + + Value64 = StrToUInteger (ValueStr, &Status); + if (!EFI_ERROR (Status)) { + Indexer->Index = (UINTN) Value64; + Indexer->Name = NULL; + } else { + UnicodeStrToAsciiStr (ValueStr, (CHAR8 *) Indexer->Name); + } + + return EFI_SUCCESS; +} + +/** + Fill in SAD_ENTRY_INDEXER through ParamPackage list. + + @param[in, out] Indexer The pointer to the SAD_ENTRY_INDEXER structure. + @param[in] ParamPackage The pointer to the ParamPackage list. + + @retval EFI_SUCCESS Filled in SPD_ENTRY_INDEXER successfully. + @retval EFI_INVALID_PARAMETER The mistaken user input in ParamPackage list. +**/ +EFI_STATUS +ConstructSadIndexer ( + IN OUT SAD_ENTRY_INDEXER *Indexer, + IN LIST_ENTRY *ParamPackage + ) +{ + EFI_STATUS Status; + EFI_STATUS Status1; + UINT64 Value64; + CONST CHAR16 *ValueStr; + + ValueStr = NULL; + + if (ShellCommandLineGetFlag (ParamPackage, L"-i")) { + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-i"); + } else if (ShellCommandLineGetFlag (ParamPackage, L"-d")) { + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-d"); + } else if (ShellCommandLineGetFlag (ParamPackage, L"-e")) { + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-e"); + } else { + ASSERT (FALSE); + } + + ASSERT (ValueStr != NULL); + + Value64 = StrToUInteger (ValueStr, &Status); + if (!EFI_ERROR (Status)) { + Indexer->Index = (UINTN) Value64; + ZeroMem (&Indexer->SaId, sizeof (EFI_IPSEC_SA_ID)); + } else { + if ((!ShellCommandLineGetFlag (ParamPackage, L"--lookup-spi")) || + (!ShellCommandLineGetFlag (ParamPackage, L"--lookup-ipsec-proto")) || + (!ShellCommandLineGetFlag (ParamPackage, L"--lookup-dest"))) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS), + mHiiHandle, + mAppName, + L"--lookup-spi --lookup-ipsec-proto --lookup-dest" + ); + return EFI_INVALID_PARAMETER; + } + + Status = GetNumber ( + L"--lookup-spi", + (UINT32) -1, + &Indexer->SaId.Spi, + sizeof (UINT32), + NULL, + ParamPackage, + FORMAT_NUMBER + ); + Status1 = GetNumber ( + L"--lookup-ipsec-proto", + 0, + &Indexer->SaId.Proto, + sizeof (EFI_IPSEC_PROTOCOL_TYPE), + mMapIpSecProtocol, + ParamPackage, + FORMAT_STRING + ); + + if (EFI_ERROR (Status) || EFI_ERROR (Status1)) { + return EFI_INVALID_PARAMETER; + } + + ValueStr = ShellCommandLineGetValue (ParamPackage, L"--lookup-dest"); + ASSERT (ValueStr != NULL); + + Status = EfiInetAddr2 ((CHAR16 *) ValueStr, &Indexer->SaId.DestAddress); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE), + mHiiHandle, + mAppName, + L"--lookup-dest", + ValueStr + ); + return EFI_INVALID_PARAMETER; + } + } + + return EFI_SUCCESS; +} + +/** + Fill in PAD_ENTRY_INDEXER through ParamPackage list. + + @param[in, out] Indexer The pointer to the PAD_ENTRY_INDEXER structure. + @param[in] ParamPackage The pointer to the ParamPackage list. + + @retval EFI_SUCCESS Filled in PAD_ENTRY_INDEXER successfully. + @retval EFI_INVALID_PARAMETER The mistaken user input in ParamPackage list. +**/ +EFI_STATUS +ConstructPadIndexer ( + IN OUT PAD_ENTRY_INDEXER *Indexer, + IN LIST_ENTRY *ParamPackage + ) +{ + EFI_STATUS Status; + UINT64 Value64; + CONST CHAR16 *ValueStr; + + ValueStr = NULL; + + if (ShellCommandLineGetFlag (ParamPackage, L"-i")) { + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-i"); + } else if (ShellCommandLineGetFlag (ParamPackage, L"-d")) { + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-d"); + } else if (ShellCommandLineGetFlag (ParamPackage, L"-e")) { + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-e"); + } else { + ASSERT (FALSE); + } + + ASSERT (ValueStr != NULL); + + Value64 = StrToUInteger (ValueStr, &Status); + + if (!EFI_ERROR (Status)) { + Indexer->Index = (UINTN) Value64; + ZeroMem (&Indexer->PadId, sizeof (EFI_IPSEC_PAD_ID)); + } else { + + if (ShellCommandLineGetFlag (ParamPackage, L"--lookup-peer-address")) { + ValueStr = ShellCommandLineGetValue (ParamPackage, L"--lookup-peer-address"); + ASSERT (ValueStr != NULL); + + Indexer->PadId.PeerIdValid = FALSE; + Status = EfiInetAddrRange ((CHAR16 *) ValueStr, &Indexer->PadId.Id.IpAddress); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE), + mHiiHandle, + mAppName, + L"--lookup-peer-address", + ValueStr + ); + return EFI_INVALID_PARAMETER; + } + } else { + ValueStr = ShellCommandLineGetValue (ParamPackage, L"--lookup-peer-id"); + if (ValueStr == NULL) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS), + mHiiHandle, + mAppName, + L"--lookup-peer-address --lookup-peer-id" + ); + return EFI_INVALID_PARAMETER; + } + + Indexer->PadId.PeerIdValid = TRUE; + StrnCpy ((CHAR16 *) Indexer->PadId.Id.PeerId, ValueStr, ARRAY_SIZE (Indexer->PadId.Id.PeerId) - 1); + } + } + + return EFI_SUCCESS; +} + +CONSTRUCT_POLICY_ENTRY_INDEXER mConstructPolicyEntryIndexer[] = { + (CONSTRUCT_POLICY_ENTRY_INDEXER) ConstructSpdIndexer, + (CONSTRUCT_POLICY_ENTRY_INDEXER) ConstructSadIndexer, + (CONSTRUCT_POLICY_ENTRY_INDEXER) ConstructPadIndexer +}; diff --git a/NetworkPkg/Application/IpsecConfig/Indexer.h b/NetworkPkg/Application/IpsecConfig/Indexer.h new file mode 100644 index 0000000000..078f38a312 --- /dev/null +++ b/NetworkPkg/Application/IpsecConfig/Indexer.h @@ -0,0 +1,58 @@ +/** @file + The internal structure and function declaration to construct ENTRY_INDEXER in + IpSecConfig application. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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. + +**/ + +#ifndef _INDEXER_H_ +#define _INDEXER_H_ + +typedef struct { + UINT8 *Name; + UINTN Index; // Used only if Name is NULL. +} SPD_ENTRY_INDEXER; + +typedef struct { + EFI_IPSEC_SA_ID SaId; + UINTN Index; +} SAD_ENTRY_INDEXER; + +typedef struct { + EFI_IPSEC_PAD_ID PadId; + UINTN Index; +} PAD_ENTRY_INDEXER; + +typedef union { + SPD_ENTRY_INDEXER Spd; + SAD_ENTRY_INDEXER Sad; + PAD_ENTRY_INDEXER Pad; +} POLICY_ENTRY_INDEXER; + +/** + The prototype for the ConstructSpdIndexer()/ConstructSadIndexer()/ConstructPadIndexer(). + Fill in SPD_ENTRY_INDEXER/SAD_ENTRY_INDEXER/PAD_ENTRY_INDEXER through ParamPackage list. + + @param[in, out] Indexer The pointer to the POLICY_ENTRY_INDEXER union. + @param[in] ParamPackage The pointer to the ParamPackage list. + + @retval EFI_SUCCESS Filled in POLICY_ENTRY_INDEXER successfully. +**/ +typedef +EFI_STATUS +(* CONSTRUCT_POLICY_ENTRY_INDEXER) ( + IN POLICY_ENTRY_INDEXER *Indexer, + IN LIST_ENTRY *ParamPackage +); + +extern CONSTRUCT_POLICY_ENTRY_INDEXER mConstructPolicyEntryIndexer[]; +#endif diff --git a/NetworkPkg/Application/IpsecConfig/IpSecConfig.c b/NetworkPkg/Application/IpsecConfig/IpSecConfig.c new file mode 100644 index 0000000000..8006d84860 --- /dev/null +++ b/NetworkPkg/Application/IpsecConfig/IpSecConfig.c @@ -0,0 +1,809 @@ +/** @file + The main process for IpSecConfig application. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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 +#include + +#include + +#include "IpSecConfig.h" +#include "Dump.h" +#include "Indexer.h" +#include "PolicyEntryOperation.h" +#include "Delete.h" +#include "Helper.h" + +// +// Used for ShellCommandLineParseEx only +// and to ensure user inputs are in valid format +// +SHELL_PARAM_ITEM mIpSecConfigParamList[] = { + { L"-p", TypeValue }, + { L"-a", TypeValue }, + { L"-i", TypeValue }, + { L"-e", TypeValue }, + { L"-d", TypeValue }, + { L"-f", TypeFlag }, + { L"-l", TypeFlag }, + { L"-enable", TypeFlag }, + { L"-disable", TypeFlag }, + { L"-status", TypeFlag }, + { L"-?", TypeFlag }, + + // + // SPD Selector + // + { L"--local", TypeValue }, + { L"--remote", TypeValue }, + { L"--proto", TypeValue }, + { L"--local-port", TypeValue }, + { L"--remote-port", TypeValue }, + { L"--icmp-type", TypeValue }, + { L"--icmp-code", TypeValue }, + + // + // SPD Data + // + { L"--name", TypeValue }, + { L"--packet-flag", TypeValue }, + { L"--action", TypeValue }, + { L"--lifebyte", TypeValue }, + { L"--lifetime-soft", TypeValue }, + { L"--lifetime", TypeValue }, + { L"--mode", TypeValue }, + { L"--tunnel-local", TypeValue }, + { L"--tunnel-remote", TypeValue }, + { L"--dont-fragment", TypeValue }, + { L"--ipsec-proto", TypeValue }, + { L"--auth-algo", TypeValue }, + { L"--encrypt-algo", TypeValue }, + + { L"--ext-sequence", TypeFlag }, + { L"--sequence-overflow", TypeFlag }, + { L"--fragment-check", TypeFlag }, + { L"--ext-sequence-", TypeFlag }, + { L"--sequence-overflow-", TypeFlag }, + { L"--fragment-check-", TypeFlag }, + + // + // SA ID + // --ipsec-proto + // + { L"--spi", TypeValue }, + { L"--dest", TypeValue }, + { L"--lookup-spi", TypeValue }, + { L"--lookup-ipsec-proto", TypeValue }, + { L"--lookup-dest", TypeValue }, + + // + // SA DATA + // --mode + // --auth-algo + // --encrypt-algo + // + { L"--sequence-number", TypeValue }, + { L"--antireplay-window", TypeValue }, + { L"--auth-key", TypeValue }, + { L"--encrypt-key", TypeValue }, + { L"--path-mtu", TypeValue }, + + // + // PAD ID + // + { L"--peer-id", TypeValue }, + { L"--peer-address", TypeValue }, + { L"--auth-proto", TypeValue }, + { L"--auth-method", TypeValue }, + { L"--ike-id", TypeValue }, + { L"--ike-id-", TypeValue }, + { L"--auth-data", TypeValue }, + { L"--revocation-data", TypeValue }, + { L"--lookup-peer-id", TypeValue }, + { L"--lookup-peer-address", TypeValue }, + + { NULL, TypeMax }, +}; + +// +// -P +// +STR2INT mMapPolicy[] = { + { L"SPD", IPsecConfigDataTypeSpd }, + { L"SAD", IPsecConfigDataTypeSad }, + { L"PAD", IPsecConfigDataTypePad }, + { NULL, 0 }, +}; + +// +// --proto +// +STR2INT mMapIpProtocol[] = { + { L"TCP", EFI_IP4_PROTO_TCP }, + { L"UDP", EFI_IP4_PROTO_UDP }, + { L"ICMP", EFI_IP4_PROTO_ICMP }, + { NULL, 0 }, +}; + +// +// --action +// +STR2INT mMapIpSecAction[] = { + { L"Bypass", EfiIPsecActionBypass }, + { L"Discard", EfiIPsecActionDiscard }, + { L"Protect", EfiIPsecActionProtect }, + { NULL, 0 }, +}; + +// +// --mode +// +STR2INT mMapIpSecMode[] = { + { L"Transport", EfiIPsecTransport }, + { L"Tunnel", EfiIPsecTunnel }, + { NULL, 0 }, +}; + +// +// --dont-fragment +// +STR2INT mMapDfOption[] = { + { L"clear", EfiIPsecTunnelClearDf }, + { L"set", EfiIPsecTunnelSetDf }, + { L"copy", EfiIPsecTunnelCopyDf }, + { NULL, 0 }, +}; + +// +// --ipsec-proto +// +STR2INT mMapIpSecProtocol[] = { + { L"AH", EfiIPsecAH }, + { L"ESP", EfiIPsecESP }, + { NULL, 0 }, +}; + +// +// --auth-algo +// +STR2INT mMapAuthAlgo[] = { + { L"NONE", EFI_IPSEC_AALG_NONE }, + { L"MD5HMAC", EFI_IPSEC_AALG_MD5HMAC }, + { L"SHA1HMAC", EFI_IPSEC_AALG_SHA1HMAC }, + { L"SHA2-256HMAC", EFI_IPSEC_AALG_SHA2_256HMAC }, + { L"SHA2-384HMAC", EFI_IPSEC_AALG_SHA2_384HMAC }, + { L"SHA2-512HMAC", EFI_IPSEC_AALG_SHA2_512HMAC }, + { L"AES-XCBC-MAC", EFI_IPSEC_AALG_AES_XCBC_MAC }, + { L"NULL", EFI_IPSEC_AALG_NULL }, + { NULL, 0 }, +}; + +// +// --encrypt-algo +// +STR2INT mMapEncAlgo[] = { + { L"NONE", EFI_IPSEC_EALG_NONE }, + { L"DESCBC", EFI_IPSEC_EALG_DESCBC }, + { L"3DESCBC", EFI_IPSEC_EALG_3DESCBC }, + { L"CASTCBC", EFI_IPSEC_EALG_CASTCBC }, + { L"BLOWFISHCBC", EFI_IPSEC_EALG_BLOWFISHCBC }, + { L"NULL", EFI_IPSEC_EALG_NULL }, + { L"AESCBC", EFI_IPSEC_EALG_AESCBC }, + { L"AESCTR", EFI_IPSEC_EALG_AESCTR }, + { L"AES-CCM-ICV8", EFI_IPSEC_EALG_AES_CCM_ICV8 }, + { L"AES-CCM-ICV12",EFI_IPSEC_EALG_AES_CCM_ICV12 }, + { L"AES-CCM-ICV16",EFI_IPSEC_EALG_AES_CCM_ICV16 }, + { L"AES-GCM-ICV8", EFI_IPSEC_EALG_AES_GCM_ICV8 }, + { L"AES-GCM-ICV12",EFI_IPSEC_EALG_AES_GCM_ICV12 }, + { L"AES-GCM-ICV16",EFI_IPSEC_EALG_AES_GCM_ICV16 }, + { NULL, 0 }, +}; + +// +// --auth-proto +// +STR2INT mMapAuthProto[] = { + { L"IKEv1", EfiIPsecAuthProtocolIKEv1 }, + { L"IKEv2", EfiIPsecAuthProtocolIKEv2 }, + { NULL, 0 }, +}; + +// +// --auth-method +// +STR2INT mMapAuthMethod[] = { + { L"PreSharedSecret", EfiIPsecAuthMethodPreSharedSecret }, + { L"Certificates", EfiIPsecAuthMethodCertificates }, + { NULL, 0 }, +}; + +EFI_IPSEC_PROTOCOL *mIpSec; +EFI_IPSEC_CONFIG_PROTOCOL *mIpSecConfig; +EFI_HII_HANDLE mHiiHandle; +EFI_GUID mEfiIpSecConfigGuid = EFI_IPSEC_CONFIG_GUID; +CHAR16 mAppName[] = L"IpSecConfig"; + +// +// Used for IpSecConfigRetriveCheckListByName only to check the validation of user input +// +VAR_CHECK_ITEM mIpSecConfigVarCheckList[] = { + { L"-enable", BIT(1)|BIT(0), BIT(1), BIT(2)|BIT(1)|BIT(0), 0 }, + { L"-disable", BIT(1)|BIT(0), BIT(1), BIT(2)|BIT(1)|BIT(0), 0 }, + { L"-status", BIT(1)|BIT(0), BIT(1), BIT(2)|BIT(1)|BIT(0), 0 }, + { L"-p", BIT(1), 0, BIT(2)|BIT(1)|BIT(0), 0 }, + + { L"-a", BIT(0), 0, BIT(2)|BIT(1)|BIT(0), 0 }, + { L"-i", BIT(0), 0, BIT(2)|BIT(1)|BIT(0), 0 }, + { L"-d", BIT(0), 0, BIT(2)|BIT(1)|BIT(0), 0 }, + { L"-e", BIT(0), 0, BIT(2)|BIT(1)|BIT(0), 0 }, + { L"-l", BIT(0), 0, BIT(2)|BIT(1)|BIT(0), 0 }, + { L"-f", BIT(0), 0, BIT(2)|BIT(1)|BIT(0), 0 }, + + { L"-?", BIT(0), BIT(0), BIT(2)|BIT(1)|BIT(0), 0 }, + + // + // SPD Selector + // + { L"--local", 0, 0, BIT(2)|BIT(1), 0 }, + { L"--remote", 0, 0, BIT(2)|BIT(1), 0 }, + { L"--proto", 0, 0, BIT(2)|BIT(1), 0 }, + { L"--local-port", 0, 0, BIT(2)|BIT(1), BIT(0) }, + { L"--remote-port", 0, 0, BIT(2)|BIT(1), BIT(0) }, + { L"--icmp-type", 0, 0, BIT(2)|BIT(1), BIT(1) }, + { L"--icmp-code", 0, 0, BIT(2)|BIT(1), BIT(1) }, + + // + // SPD Data + // + { L"--name", 0, 0, BIT(2), 0 }, + { L"--packet-flag", 0, 0, BIT(2), 0 }, + { L"--action", 0, 0, BIT(2)|BIT(1), 0 }, + { L"--lifebyte", 0, 0, BIT(2)|BIT(1), 0 }, + { L"--lifetime-soft", 0, 0, BIT(2)|BIT(1), 0 }, + { L"--lifetime", 0, 0, BIT(2)|BIT(1), 0 }, + { L"--mode", 0, 0, BIT(2)|BIT(1), 0 }, + { L"--tunnel-local", 0, 0, BIT(2), 0 }, + { L"--tunnel-remote", 0, 0, BIT(2), 0 }, + { L"--dont-fragment", 0, 0, BIT(2), 0 }, + { L"--ipsec-proto", 0, 0, BIT(2)|BIT(1), 0 }, + { L"--auth-algo", 0, 0, BIT(2)|BIT(1), 0 }, + { L"--encrypt-algo", 0, 0, BIT(2)|BIT(1), 0 }, + + { L"--ext-sequence", 0, 0, BIT(2), BIT(2) }, + { L"--sequence-overflow", 0, 0, BIT(2), BIT(2) }, + { L"--fragment-check", 0, 0, BIT(2), BIT(2) }, + { L"--ext-sequence-", 0, 0, BIT(2), BIT(3) }, + { L"--sequence-overflow-", 0, 0, BIT(2), BIT(3) }, + { L"--fragment-check-", 0, 0, BIT(2), BIT(3) }, + + // + // SA ID + // --ipsec-proto + // + { L"--spi", 0, 0, BIT(1), 0 }, + { L"--dest", 0, 0, BIT(1), 0 }, + { L"--lookup-spi", 0, 0, BIT(1), 0 }, + { L"--lookup-ipsec-proto", 0, 0, BIT(1), 0 }, + { L"--lookup-dest", 0, 0, BIT(1), 0 }, + + // + // SA DATA + // --mode + // --auth-algo + // --encrypt-algo + // + { L"--sequence-number", 0, 0, BIT(1), 0 }, + { L"--antireplay-window", 0, 0, BIT(1), 0 }, + { L"--auth-key", 0, 0, BIT(1), 0 }, + { L"--encrypt-key", 0, 0, BIT(1), 0 }, + { L"--path-mtu", 0, 0, BIT(1), 0 }, + + // + // The example to add a PAD: + // "-A --peer-id Mike [--peer-address 10.23.2.2] --auth-proto IKE1/IKE2 + // --auth-method PreSharedSeceret/Certificate --ike-id + // --auth-data 343343 --revocation-data 2342432" + // The example to delete a PAD: + // "-D * --lookup-peer-id Mike [--lookup-peer-address 10.23.2.2]" + // "-D 1" + // The example to edit a PAD: + // "-E * --lookup-peer-id Mike --auth-method Certificate" + + // + // PAD ID + // + { L"--peer-id", 0, 0, BIT(0), BIT(4) }, + { L"--peer-address", 0, 0, BIT(0), BIT(5) }, + { L"--auth-proto", 0, 0, BIT(0), 0 }, + { L"--auth-method", 0, 0, BIT(0), 0 }, + { L"--IKE-ID", 0, 0, BIT(0), BIT(6) }, + { L"--IKE-ID-", 0, 0, BIT(0), BIT(7) }, + { L"--auth-data", 0, 0, BIT(0), 0 }, + { L"--revocation-data", 0, 0, BIT(0), 0 }, + { L"--lookup-peer-id", 0, 0, BIT(0), BIT(4) }, + { L"--lookup-peer-address",0, 0, BIT(0), BIT(5) }, + + { NULL, 0, 0, 0, 0 }, +}; + +/** + The function to allocate the proper sized buffer for various + EFI interfaces. + + @param[in, out] Status Current status. + @param[in, out] Buffer Current allocated buffer, or NULL. + @param[in] BufferSize Current buffer size needed + + @retval TRUE If the buffer was reallocated and the caller should try the API again. + @retval FALSE If the buffer was not reallocated successfully. +**/ +BOOLEAN +GrowBuffer ( + IN OUT EFI_STATUS *Status, + IN OUT VOID **Buffer, + IN UINTN BufferSize + ) +{ + BOOLEAN TryAgain; + + ASSERT (Status != NULL); + ASSERT (Buffer != NULL); + + // + // If this is an initial request, buffer will be null with a new buffer size. + // + if ((NULL == *Buffer) && (BufferSize != 0)) { + *Status = EFI_BUFFER_TOO_SMALL; + } + + // + // If the status code is "buffer too small", resize the buffer. + // + TryAgain = FALSE; + if (*Status == EFI_BUFFER_TOO_SMALL) { + + if (*Buffer != NULL) { + FreePool (*Buffer); + } + + *Buffer = AllocateZeroPool (BufferSize); + + if (*Buffer != NULL) { + TryAgain = TRUE; + } else { + *Status = EFI_OUT_OF_RESOURCES; + } + } + + // + // If there's an error, free the buffer. + // + if (!TryAgain && EFI_ERROR (*Status) && (*Buffer != NULL)) { + FreePool (*Buffer); + *Buffer = NULL; + } + + return TryAgain; +} + +/** + Function returns an array of handles that support the requested protocol + in a buffer allocated from a pool. + + @param[in] SearchType Specifies which handle(s) are to be returned. + @param[in] Protocol Provides the protocol to search by. + This parameter is only valid for SearchType ByProtocol. + + @param[in] SearchKey Supplies the search key depending on the SearchType. + @param[in, out] NoHandles The number of handles returned in Buffer. + @param[out] Buffer A pointer to the buffer to return the requested array of + handles that support Protocol. + + @retval EFI_SUCCESS The resulting array of handles was returned. + @retval Others Other mistake case. +**/ +EFI_STATUS +LocateHandle ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol OPTIONAL, + IN VOID *SearchKey OPTIONAL, + IN OUT UINTN *NoHandles, + OUT EFI_HANDLE **Buffer + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + + ASSERT (NoHandles != NULL); + ASSERT (Buffer != NULL); + + // + // Initialize for GrowBuffer loop. + // + Status = EFI_SUCCESS; + *Buffer = NULL; + BufferSize = 50 * sizeof (EFI_HANDLE); + + // + // Call the real function. + // + while (GrowBuffer (&Status, (VOID **) Buffer, BufferSize)) { + Status = gBS->LocateHandle ( + SearchType, + Protocol, + SearchKey, + &BufferSize, + *Buffer + ); + } + + *NoHandles = BufferSize / sizeof (EFI_HANDLE); + if (EFI_ERROR (Status)) { + *NoHandles = 0; + } + + return Status; +} + +/** + Find the first instance of this protocol in the system and return its interface. + + @param[in] ProtocolGuid The guid of the protocol. + @param[out] Interface The pointer to the first instance of the protocol. + + @retval EFI_SUCCESS A protocol instance matching ProtocolGuid was found. + @retval Others A protocol instance matching ProtocolGuid was not found. +**/ +EFI_STATUS +LocateProtocol ( + IN EFI_GUID *ProtocolGuid, + OUT VOID **Interface + ) + +{ + EFI_STATUS Status; + UINTN NumberHandles; + UINTN Index; + EFI_HANDLE *Handles; + + *Interface = NULL; + Handles = NULL; + NumberHandles = 0; + + Status = LocateHandle (ByProtocol, ProtocolGuid, NULL, &NumberHandles, &Handles); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "LibLocateProtocol: Handle not found\n")); + return Status; + } + + for (Index = 0; Index < NumberHandles; Index++) { + ASSERT (Handles != NULL); + Status = gBS->HandleProtocol ( + Handles[Index], + ProtocolGuid, + Interface + ); + + if (!EFI_ERROR (Status)) { + break; + } + } + + if (Handles != NULL) { + FreePool (Handles); + } + + return Status; +} + +/** + Helper function called to check the conflicted flags. + + @param[in] CheckList The pointer to the VAR_CHECK_ITEM table. + @param[in] ParamPackage The pointer to the ParamPackage list. + + @retval EFI_SUCCESS No conflicted flags. + @retval EFI_INVALID_PARAMETER The input parameter is erroroneous or there are some conflicted flags. +**/ +EFI_STATUS +IpSecConfigRetriveCheckListByName ( + IN VAR_CHECK_ITEM *CheckList, + IN LIST_ENTRY *ParamPackage +) +{ + + LIST_ENTRY *Node; + VAR_CHECK_ITEM *Item; + UINT32 Attribute1; + UINT32 Attribute2; + UINT32 Attribute3; + UINT32 Attribute4; + UINT32 Index; + + Attribute1 = 0; + Attribute2 = 0; + Attribute3 = 0; + Attribute4 = 0; + Index = 0; + Item = mIpSecConfigVarCheckList; + + if ((ParamPackage == NULL) || (CheckList == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Enumerate through the list of parameters that are input by user. + // + for (Node = GetFirstNode (ParamPackage); !IsNull (ParamPackage, Node); Node = GetNextNode (ParamPackage, Node)) { + if (((SHELL_PARAM_PACKAGE *) Node)->Name != NULL) { + // + // Enumerate the check list that defines the conflicted attributes of each flag. + // + for (; Item->VarName != NULL; Item++) { + if (StrCmp (((SHELL_PARAM_PACKAGE *) Node)->Name, Item->VarName) == 0) { + Index++; + if (Index == 1) { + Attribute1 = Item->Attribute1; + Attribute2 = Item->Attribute2; + Attribute3 = Item->Attribute3; + Attribute4 = Item->Attribute4; + } else { + Attribute1 &= Item->Attribute1; + Attribute2 |= Item->Attribute2; + Attribute3 &= Item->Attribute3; + Attribute4 |= Item->Attribute4; + if (Attribute1 != 0) { + return EFI_INVALID_PARAMETER; + } + + if (Attribute2 != 0) { + if ((Index == 2) && (StrCmp (Item->VarName, L"-p") == 0)) { + continue; + } + + return EFI_INVALID_PARAMETER; + } + + if (Attribute3 == 0) { + return EFI_INVALID_PARAMETER; + } + if (((Attribute4 & 0xFF) == 0x03) || ((Attribute4 & 0xFF) == 0x0C) || + ((Attribute4 & 0xFF) == 0x30) || ((Attribute4 & 0xFF) == 0xC0)) { + return EFI_INVALID_PARAMETER; + } + } + break; + } + } + + Item = mIpSecConfigVarCheckList; + } + } + + return EFI_SUCCESS; +} + +/** + This is the declaration of an EFI image entry point. This entry point is + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including + both device drivers and bus drivers. + + The entry point for IpSecConfig application that parse the command line input and call an IpSecConfig process. + + @param[in] ImageHandle The image handle of this application. + @param[in] SystemTable The pointer to the EFI System Table. + + @retval EFI_SUCCESS The operation completed successfully. + +**/ +EFI_STATUS +EFIAPI +InitializeIpSecConfig ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_IPSEC_CONFIG_DATA_TYPE DataType; + UINT8 Value; + LIST_ENTRY *ParamPackage; + CONST CHAR16 *ValueStr; + CHAR16 *ProblemParam; + UINTN NonOptionCount; + + // + // Register our string package with HII and return the handle to it. + // + mHiiHandle = HiiAddPackages (&gEfiCallerIdGuid, ImageHandle, IpSecConfigStrings, NULL); + ASSERT (mHiiHandle != NULL); + + Status = ShellCommandLineParseEx (mIpSecConfigParamList, &ParamPackage, &ProblemParam, TRUE, FALSE); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_UNKNOWN_OPERATION), mHiiHandle, ProblemParam); + goto Done; + } + + Status = IpSecConfigRetriveCheckListByName (mIpSecConfigVarCheckList, ParamPackage); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_MISTAKEN_OPTIONS), mHiiHandle); + goto Done; + } + + Status = LocateProtocol (&gEfiIpSecConfigProtocolGuid, (VOID **) &mIpSecConfig); + if (EFI_ERROR (Status) || mIpSecConfig == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_PROTOCOL_INEXISTENT), mHiiHandle, mAppName); + goto Done; + } + + Status = LocateProtocol (&gEfiIpSecProtocolGuid, (VOID **) &mIpSec); + if (EFI_ERROR (Status) || mIpSec == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_PROTOCOL_INEXISTENT), mHiiHandle, mAppName); + goto Done; + } + + // + // Enable IPsec. + // + if (ShellCommandLineGetFlag (ParamPackage, L"-enable")) { + if (!(mIpSec->DisabledFlag)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_ALREADY_ENABLE), mHiiHandle, mAppName); + } else { + // + // Set enable flag. + // + Value = IPSEC_STATUS_ENABLED; + Status = gRT->SetVariable ( + IPSECCONFIG_STATUS_NAME, + &gEfiIpSecConfigProtocolGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof (Value), + &Value + ); + if (!EFI_ERROR (Status)) { + mIpSec->DisabledFlag = FALSE; + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_ENABLE_SUCCESS), mHiiHandle, mAppName); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_ENABLE_FAILED), mHiiHandle, mAppName); + } + } + + goto Done; + } + + // + // Disable IPsec. + // + if (ShellCommandLineGetFlag (ParamPackage, L"-disable")) { + if (mIpSec->DisabledFlag) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_ALREADY_DISABLE), mHiiHandle, mAppName); + } else { + // + // Set disable flag; however, leave it to be disabled in the callback function of DisabledEvent. + // + gBS->SignalEvent (mIpSec->DisabledEvent); + if (mIpSec->DisabledFlag) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_DISABLE_SUCCESS), mHiiHandle, mAppName); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_DISABLE_FAILED), mHiiHandle, mAppName); + } + } + + goto Done; + } + + // + //IPsec Status. + // + if (ShellCommandLineGetFlag (ParamPackage, L"-status")) { + if (mIpSec->DisabledFlag) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_STATUS_DISABLE), mHiiHandle, mAppName); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_STATUS_ENABLE), mHiiHandle, mAppName); + } + + goto Done; + } + + // + // Try to get policy database type. + // + DataType = (EFI_IPSEC_CONFIG_DATA_TYPE) -1; + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-p"); + if (ValueStr != NULL) { + DataType = (EFI_IPSEC_CONFIG_DATA_TYPE) MapStringToInteger (ValueStr, mMapPolicy); + if (DataType == -1) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_DB), mHiiHandle, mAppName, ValueStr); + goto Done; + } + } + + if (ShellCommandLineGetFlag (ParamPackage, L"-?")) { + switch (DataType) { + case (EFI_IPSEC_CONFIG_DATA_TYPE) -1: + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_HELP), mHiiHandle); + break; + + case IPsecConfigDataTypeSpd: + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_SPD_HELP), mHiiHandle); + break; + + case IPsecConfigDataTypeSad: + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_SAD_HELP), mHiiHandle); + break; + + case IPsecConfigDataTypePad: + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_PAD_HELP), mHiiHandle); + break; + + default: + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_DB), mHiiHandle); + break; + } + + goto Done; + } + + NonOptionCount = ShellCommandLineGetCount (); + if ((NonOptionCount - 1) > 0) { + ValueStr = ShellCommandLineGetRawValue (ParamPackage, (UINT32) (NonOptionCount - 1)); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_REDUNDANCY_MANY), mHiiHandle, mAppName, ValueStr); + goto Done; + } + + if (DataType == -1) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_DB), mHiiHandle, mAppName); + goto Done; + } + + if (ShellCommandLineGetFlag (ParamPackage, L"-a")) { + Status = AddOrInsertPolicyEntry (DataType, ParamPackage); + if (EFI_ERROR (Status)) { + goto Done; + } + } else if (ShellCommandLineGetFlag (ParamPackage, L"-i")) { + Status = AddOrInsertPolicyEntry (DataType, ParamPackage); + if (EFI_ERROR (Status)) { + goto Done; + } + } else if (ShellCommandLineGetFlag (ParamPackage, L"-e")) { + Status = EditPolicyEntry (DataType, ParamPackage); + if (EFI_ERROR (Status)) { + goto Done; + } + } else if (ShellCommandLineGetFlag (ParamPackage, L"-d")) { + Status = FlushOrDeletePolicyEntry (DataType, ParamPackage); + if (EFI_ERROR (Status)) { + goto Done; + } + } else if (ShellCommandLineGetFlag (ParamPackage, L"-f")) { + Status = FlushOrDeletePolicyEntry (DataType, ParamPackage); + if (EFI_ERROR (Status)) { + goto Done; + } + } else if (ShellCommandLineGetFlag (ParamPackage, L"-l")) { + Status = ListPolicyEntry (DataType, ParamPackage); + if (EFI_ERROR (Status)) { + goto Done; + } + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_UNKNOWN_OPERATION), mHiiHandle, mAppName); + goto Done; + } + +Done: + ShellCommandLineFreeVarList (ParamPackage); + HiiRemovePackages (mHiiHandle); + + return EFI_SUCCESS; +} diff --git a/NetworkPkg/Application/IpsecConfig/IpSecConfig.h b/NetworkPkg/Application/IpsecConfig/IpSecConfig.h new file mode 100644 index 0000000000..d1a7681012 --- /dev/null +++ b/NetworkPkg/Application/IpsecConfig/IpSecConfig.h @@ -0,0 +1,123 @@ +/** @file + The internal structure and function declaration in IpSecConfig application. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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. + +**/ + +#ifndef _IPSEC_CONFIG_H_ +#define _IPSEC_CONFIG_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define EFI_IPSEC_CONFIG_GUID \ + { \ + 0x9db0c3ac, 0xd9d2, 0x4f96, {0x9e, 0xd7, 0x6d, 0xa6, 0x12, 0xa4, 0xf3, 0x27} \ + } + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + +#define IPSECCONFIG_STATUS_NAME L"IpSecStatus" + +#define BIT(x) (UINT32) (1 << (x)) + +#define IPSEC_STATUS_DISABLED 0x0 +#define IPSEC_STATUS_ENABLED 0x1 + +#define EFI_IP4_PROTO_ICMP 0x1 +#define EFI_IP4_PROTO_TCP 0x6 +#define EFI_IP4_PROTO_UDP 0x11 + +#define EFI_IPSEC_ANY_PROTOCOL 0xFFFF +#define EFI_IPSEC_ANY_PORT 0 + +typedef struct _VAR_CHECK_ITEM { + CHAR16 *VarName; + UINT32 Attribute1; + UINT32 Attribute2; + UINT32 Attribute3; + UINT32 Attribute4; +} VAR_CHECK_ITEM; + +typedef struct _SHELL_PARAM_PACKAGE{ + LIST_ENTRY Link; + CHAR16 *Name; + ParamType Type; + CHAR16 *Value; + UINTN OriginalPosition; +} SHELL_PARAM_PACKAGE; + +typedef struct _STR2INT { + CHAR16 *String; + UINT32 Integer; +} STR2INT; + +extern EFI_IPSEC_CONFIG_PROTOCOL *mIpSecConfig; +extern EFI_HII_HANDLE mHiiHandle; +extern CHAR16 mAppName[]; + +// +// -P +// +extern STR2INT mMapPolicy[]; + +// +// --proto +// +extern STR2INT mMapIpProtocol[]; + +// +// --action +// +extern STR2INT mMapIpSecAction[]; + +// +// --mode +// +extern STR2INT mMapIpSecMode[]; + +// +// --dont-fragment +// +extern STR2INT mMapDfOption[]; + +// +// --ipsec-proto +// +extern STR2INT mMapIpSecProtocol[]; +// +// --auth-algo +// +extern STR2INT mMapAuthAlgo[]; + +// +// --encrypt-algo +// +extern STR2INT mMapEncAlgo[]; +// +// --auth-proto +// +extern STR2INT mMapAuthProto[]; + +// +// --auth-method +// +extern STR2INT mMapAuthMethod[]; + +#endif diff --git a/NetworkPkg/Application/IpsecConfig/IpSecConfig.inf b/NetworkPkg/Application/IpsecConfig/IpSecConfig.inf new file mode 100644 index 0000000000..1e0d4f44db --- /dev/null +++ b/NetworkPkg/Application/IpsecConfig/IpSecConfig.inf @@ -0,0 +1,61 @@ +## @file +# Component description file for IpSecConfig6 application. +# +# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+# +# 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. +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = IpSecConfig + FILE_GUID = 0922E604-F5EC-42ef-980D-A35E9A2B1844 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeIpSecConfig + +[Sources] + IpSecConfigStrings.uni + IpSecConfig.c + IpSecConfig.h + Dump.c + Dump.h + Indexer.c + Indexer.h + Match.c + Match.h + Delete.h + Delete.c + Helper.c + Helper.h + ForEach.c + ForEach.h + PolicyEntryOperation.c + PolicyEntryOperation.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ShellPkg/ShellPkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + UefiApplicationEntryPoint + BaseMemoryLib + ShellLib + MemoryAllocationLib + DebugLib + HiiLib + NetLib + UefiLib + +[Protocols] + gEfiIpSecProtocolGuid ##CONSUMS + gEfiIpSecConfigProtocolGuid ##CONSUMS diff --git a/NetworkPkg/Application/IpsecConfig/IpSecConfigStrings.uni b/NetworkPkg/Application/IpsecConfig/IpSecConfigStrings.uni new file mode 100644 index 0000000000..fb0e27d802 Binary files /dev/null and b/NetworkPkg/Application/IpsecConfig/IpSecConfigStrings.uni differ diff --git a/NetworkPkg/Application/IpsecConfig/Match.c b/NetworkPkg/Application/IpsecConfig/Match.c new file mode 100644 index 0000000000..d6595ee8b8 --- /dev/null +++ b/NetworkPkg/Application/IpsecConfig/Match.c @@ -0,0 +1,163 @@ +/** @file + The implementation of match policy entry function in IpSecConfig application. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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 "IpSecConfig.h" +#include "Indexer.h" +#include "Match.h" + +/** + Private function to validate a buffer that should be filled with zero. + + @param[in] Memory The pointer to the buffer. + @param[in] Size The size of the buffer. + + @retval TRUE The memory is filled with zero. + @retval FALSE The memory isn't filled with zero. +**/ +BOOLEAN +IsMemoryZero ( + IN VOID *Memory, + IN UINTN Size + ) +{ + UINTN Index; + + for (Index = 0; Index < Size; Index++) { + if (*((UINT8 *) Memory + Index) != 0) { + return FALSE; + } + } + + return TRUE; +} + +/** + Find the matching SPD with Indexer. + + @param[in] Selector The pointer to the EFI_IPSEC_SPD_SELECTOR structure. + @param[in] Data The pointer to the EFI_IPSEC_SPD_DATA structure. + @param[in] Indexer The pointer to the SPD_ENTRY_INDEXER structure. + + @retval TRUE The matched SPD is found. + @retval FALSE The matched SPD is not found. +**/ +BOOLEAN +MatchSpdEntry ( + IN EFI_IPSEC_SPD_SELECTOR *Selector, + IN EFI_IPSEC_SPD_DATA *Data, + IN SPD_ENTRY_INDEXER *Indexer + ) +{ + BOOLEAN Match; + + Match = FALSE; + if (Indexer->Name != NULL) { + if ((Data->Name != NULL) && (AsciiStrCmp ((CHAR8 *) Indexer->Name, (CHAR8 *) Data->Name) == 0)) { + Match = TRUE; + } + } else { + if (Indexer->Index == 0) { + Match = TRUE; + } + + Indexer->Index--; + } + + return Match; +} + +/** + Find the matching SAD with Indexer. + + @param[in] SaId The pointer to the EFI_IPSEC_SA_ID structure. + @param[in] Data The pointer to the EFI_IPSEC_SA_DATA structure. + @param[in] Indexer The pointer to the SPD_ENTRY_INDEXER structure. + + @retval TRUE The matched SAD is found. + @retval FALSE The matched SAD is not found. +**/ +BOOLEAN +MatchSadEntry ( + IN EFI_IPSEC_SA_ID *SaId, + IN EFI_IPSEC_SA_DATA *Data, + IN SAD_ENTRY_INDEXER *Indexer + ) +{ + BOOLEAN Match; + + Match = FALSE; + if (!IsMemoryZero (&Indexer->SaId, sizeof (EFI_IPSEC_SA_ID))) { + Match = (BOOLEAN) (CompareMem (&Indexer->SaId, SaId, sizeof (EFI_IPSEC_SA_ID)) == 0); + } else { + if (Indexer->Index == 0) { + Match = TRUE; + } + Indexer->Index--; + } + + return Match; +} + +/** + Find the matching PAD with Indexer. + + @param[in] PadId The pointer to the EFI_IPSEC_PAD_ID structure. + @param[in] Data The pointer to the EFI_IPSEC_PAD_DATA structure. + @param[in] Indexer The pointer to the SPD_ENTRY_INDEXER structure. + + @retval TRUE The matched PAD is found. + @retval FALSE The matched PAD is not found. +**/ +BOOLEAN +MatchPadEntry ( + IN EFI_IPSEC_PAD_ID *PadId, + IN EFI_IPSEC_PAD_DATA *Data, + IN PAD_ENTRY_INDEXER *Indexer + ) +{ + BOOLEAN Match; + + Match = FALSE; + if (!IsMemoryZero (&Indexer->PadId, sizeof (EFI_IPSEC_PAD_ID))) { + Match = (BOOLEAN) ((Indexer->PadId.PeerIdValid == PadId->PeerIdValid) && + ((PadId->PeerIdValid && + (StrCmp ( + (CONST CHAR16 *) Indexer->PadId.Id.PeerId, + (CONST CHAR16 *) PadId->Id.PeerId + ) == 0)) || + ((!PadId->PeerIdValid) && + (Indexer->PadId.Id.IpAddress.PrefixLength == PadId->Id.IpAddress.PrefixLength) && + (CompareMem ( + &Indexer->PadId.Id.IpAddress.Address, + &PadId->Id.IpAddress.Address, + sizeof (EFI_IP_ADDRESS) + ) == 0)))); + } else { + if (Indexer->Index == 0) { + Match = TRUE; + } + + Indexer->Index--; + } + + return Match; +} + +MATCH_POLICY_ENTRY mMatchPolicyEntry[] = { + (MATCH_POLICY_ENTRY) MatchSpdEntry, + (MATCH_POLICY_ENTRY) MatchSadEntry, + (MATCH_POLICY_ENTRY) MatchPadEntry +}; + diff --git a/NetworkPkg/Application/IpsecConfig/Match.h b/NetworkPkg/Application/IpsecConfig/Match.h new file mode 100644 index 0000000000..1d73c5cfbc --- /dev/null +++ b/NetworkPkg/Application/IpsecConfig/Match.h @@ -0,0 +1,41 @@ +/** @file + The internal structure and function declaration of + match policy entry function in IpSecConfig application. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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. + +**/ + +#ifndef _MATCH_H_ +#define _MATCH_H_ + +/** + The prototype for the MatchSpdEntry()/MatchSadEntry()/MatchPadEntry(). + The functionality is to find the matching SPD/SAD/PAD with Indexer. + + @param[in] Selector The pointer to the EFI_IPSEC_CONFIG_SELECTOR union. + @param[in] Data The pointer to corresponding Data. + @param[in] Indexer The pointer to the POLICY_ENTRY_INDEXER union. + + @retval TRUE The matched SPD/SAD/PAD is found. + @retval FALSE The matched SPD/SAD/PAD is not found. +**/ +typedef +BOOLEAN +(* MATCH_POLICY_ENTRY) ( + IN EFI_IPSEC_CONFIG_SELECTOR *Selector, + IN VOID *Data, + IN POLICY_ENTRY_INDEXER *Indexer + ); + +extern MATCH_POLICY_ENTRY mMatchPolicyEntry[]; + +#endif diff --git a/NetworkPkg/Application/IpsecConfig/PolicyEntryOperation.c b/NetworkPkg/Application/IpsecConfig/PolicyEntryOperation.c new file mode 100644 index 0000000000..ddfbb4c504 --- /dev/null +++ b/NetworkPkg/Application/IpsecConfig/PolicyEntryOperation.c @@ -0,0 +1,2016 @@ +/** @file + The implementation of policy entry operation function in IpSecConfig application. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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 "IpSecConfig.h" +#include "Indexer.h" +#include "Match.h" +#include "Helper.h" +#include "ForEach.h" +#include "PolicyEntryOperation.h" + +/** + Fill in EFI_IPSEC_SPD_SELECTOR through ParamPackage list. + + @param[out] Selector The pointer to the EFI_IPSEC_SPD_SELECTOR structure. + @param[in] ParamPackage The pointer to the ParamPackage list. + @param[in, out] ParamPackage The pointer to the Mask. + + @retval EFI_SUCCESS Fill in EFI_IPSEC_SPD_SELECTOR successfully. + @retval EFI_INVALID_PARAMETER Invalid user input parameter. + +**/ +EFI_STATUS +CreateSpdSelector ( + OUT EFI_IPSEC_SPD_SELECTOR *Selector, + IN LIST_ENTRY *ParamPackage, + IN OUT UINT32 *Mask + ) +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + CONST CHAR16 *ValueStr; + + Status = EFI_SUCCESS; + ReturnStatus = EFI_SUCCESS; + + // + // Convert user imput from string to integer, and fill in the member in EFI_IPSEC_SPD_SELECTOR. + // + ValueStr = ShellCommandLineGetValue (ParamPackage, L"--local"); + if (ValueStr != NULL) { + Selector->LocalAddressCount = 1; + Status = EfiInetAddrRange ((CHAR16 *) ValueStr, Selector->LocalAddress); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE), + mHiiHandle, + mAppName, + L"--local", + ValueStr + ); + ReturnStatus = EFI_INVALID_PARAMETER; + } else { + *Mask |= LOCAL; + } + } + + // + // Convert user imput from string to integer, and fill in the member in EFI_IPSEC_SPD_SELECTOR. + // + ValueStr = ShellCommandLineGetValue (ParamPackage, L"--remote"); + if (ValueStr != NULL) { + Selector->RemoteAddressCount = 1; + Status = EfiInetAddrRange ((CHAR16 *) ValueStr, Selector->RemoteAddress); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE), + mHiiHandle, + mAppName, + L"--remote", + ValueStr + ); + ReturnStatus = EFI_INVALID_PARAMETER; + } else { + *Mask |= REMOTE; + } + } + + Selector->NextLayerProtocol = EFI_IPSEC_ANY_PROTOCOL; + + // + // Convert user imput from string to integer, and fill in the member in EFI_IPSEC_SPD_SELECTOR. + // + Status = GetNumber ( + L"--proto", + (UINT16) -1, + &Selector->NextLayerProtocol, + sizeof (UINT16), + mMapIpProtocol, + ParamPackage, + FORMAT_NUMBER | FORMAT_STRING + ); + if (!EFI_ERROR (Status)) { + *Mask |= PROTO; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + Selector->LocalPort = EFI_IPSEC_ANY_PORT; + Selector->RemotePort = EFI_IPSEC_ANY_PORT; + + // + // Convert user imput from string to integer, and fill in the member in EFI_IPSEC_SPD_SELECTOR. + // + ValueStr = ShellCommandLineGetValue (ParamPackage, L"--local-port"); + if (ValueStr != NULL) { + Status = EfiInetPortRange ((CHAR16 *) ValueStr, &Selector->LocalPort, &Selector->LocalPortRange); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE), + mHiiHandle, + mAppName, + L"--local-port", + ValueStr + ); + ReturnStatus = EFI_INVALID_PARAMETER; + } else { + *Mask |= LOCAL_PORT; + } + } + + // + // Convert user imput from string to integer, and fill in the member in EFI_IPSEC_SPD_SELECTOR. + // + ValueStr = ShellCommandLineGetValue (ParamPackage, L"--remote-port"); + if (ValueStr != NULL) { + Status = EfiInetPortRange ((CHAR16 *) ValueStr, &Selector->RemotePort, &Selector->RemotePortRange); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE), + mHiiHandle, + mAppName, + L"--remote-port", + ValueStr + ); + ReturnStatus = EFI_INVALID_PARAMETER; + } else { + *Mask |= REMOTE_PORT; + } + } + + // + // Convert user imput from string to integer, and fill in the member in EFI_IPSEC_SPD_SELECTOR. + // + Status = GetNumber ( + L"--icmp-type", + (UINT8) -1, + &Selector->LocalPort, + sizeof (UINT16), + NULL, + ParamPackage, + FORMAT_NUMBER + ); + if (!EFI_ERROR (Status)) { + *Mask |= ICMP_TYPE; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + // + // Convert user imput from string to integer, and fill in the member in EFI_IPSEC_SPD_SELECTOR. + // + Status = GetNumber ( + L"--icmp-code", + (UINT8) -1, + &Selector->RemotePort, + sizeof (UINT16), + NULL, + ParamPackage, + FORMAT_NUMBER + ); + if (!EFI_ERROR (Status)) { + *Mask |= ICMP_CODE; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + return ReturnStatus; +} + +/** + Fill in EFI_IPSEC_SPD_SELECTOR and EFI_IPSEC_SPD_DATA through ParamPackage list. + + @param[out] Selector The pointer to the EFI_IPSEC_SPD_SELECTOR structure. + @param[out] Data The pointer to the EFI_IPSEC_SPD_DATA structure. + @param[in] ParamPackage The pointer to the ParamPackage list. + @param[out] Mask The pointer to the Mask. + @param[in] CreateNew The switch to create new. + + @retval EFI_SUCCESS Fill in EFI_IPSEC_SPD_SELECTOR and EFI_IPSEC_SPD_DATA successfully. + @retval EFI_INVALID_PARAMETER Invalid user input parameter. + +**/ +EFI_STATUS +CreateSpdEntry ( + OUT EFI_IPSEC_SPD_SELECTOR **Selector, + OUT EFI_IPSEC_SPD_DATA **Data, + IN LIST_ENTRY *ParamPackage, + OUT UINT32 *Mask, + IN BOOLEAN CreateNew + ) +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + CONST CHAR16 *ValueStr; + UINTN DataSize; + + Status = EFI_SUCCESS; + *Mask = 0; + + *Selector = AllocateZeroPool (sizeof (EFI_IPSEC_SPD_SELECTOR) + 2 * sizeof (EFI_IP_ADDRESS_INFO)); + ASSERT (*Selector != NULL); + + (*Selector)->LocalAddress = (EFI_IP_ADDRESS_INFO *) (*Selector + 1); + (*Selector)->RemoteAddress = (*Selector)->LocalAddress + 1; + + ReturnStatus = CreateSpdSelector (*Selector, ParamPackage, Mask); + + // + // SPD DATA + // NOTE: Allocate enough memory and add padding for different arch. + // + DataSize = ALIGN_VARIABLE (sizeof (EFI_IPSEC_SPD_DATA)); + DataSize = ALIGN_VARIABLE (DataSize + sizeof (EFI_IPSEC_PROCESS_POLICY)); + DataSize += sizeof (EFI_IPSEC_TUNNEL_OPTION); + + *Data = AllocateZeroPool (DataSize); + ASSERT (*Data != NULL); + + (*Data)->ProcessingPolicy = (EFI_IPSEC_PROCESS_POLICY *) ALIGN_POINTER ( + (*Data + 1), + sizeof (UINTN) + ); + (*Data)->ProcessingPolicy->TunnelOption = (EFI_IPSEC_TUNNEL_OPTION *) ALIGN_POINTER ( + ((*Data)->ProcessingPolicy + 1), + sizeof (UINTN) + ); + + + // + // Convert user imput from string to integer, and fill in the Name in EFI_IPSEC_SPD_DATA. + // + ValueStr = ShellCommandLineGetValue (ParamPackage, L"--name"); + if (ValueStr != NULL) { + UnicodeStrToAsciiStr (ValueStr, (CHAR8 *) (*Data)->Name); + *Mask |= NAME; + } + + // + // Convert user imput from string to integer, and fill in the PackageFlag in EFI_IPSEC_SPD_DATA. + // + Status = GetNumber ( + L"--packet-flag", + (UINT8) -1, + &(*Data)->PackageFlag, + sizeof (UINT32), + NULL, + ParamPackage, + FORMAT_NUMBER + ); + if (!EFI_ERROR (Status)) { + *Mask |= PACKET_FLAG; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + // + // Convert user imput from string to integer, and fill in the Action in EFI_IPSEC_SPD_DATA. + // + Status = GetNumber ( + L"--action", + (UINT8) -1, + &(*Data)->Action, + sizeof (UINT32), + mMapIpSecAction, + ParamPackage, + FORMAT_STRING + ); + if (!EFI_ERROR (Status)) { + *Mask |= ACTION; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + // + // Convert user imput from string to integer, and fill in the ExtSeqNum in EFI_IPSEC_SPD_DATA. + // + if (ShellCommandLineGetFlag (ParamPackage, L"--ext-sequence")) { + (*Data)->ProcessingPolicy->ExtSeqNum = TRUE; + *Mask |= EXT_SEQUENCE; + } else if (ShellCommandLineGetFlag (ParamPackage, L"--ext-sequence-")) { + (*Data)->ProcessingPolicy->ExtSeqNum = FALSE; + *Mask |= EXT_SEQUENCE; + } + + // + // Convert user imput from string to integer, and fill in the SeqOverflow in EFI_IPSEC_SPD_DATA. + // + if (ShellCommandLineGetFlag (ParamPackage, L"--sequence-overflow")) { + (*Data)->ProcessingPolicy->SeqOverflow = TRUE; + *Mask |= SEQUENCE_OVERFLOW; + } else if (ShellCommandLineGetFlag (ParamPackage, L"--sequence-overflow-")) { + (*Data)->ProcessingPolicy->SeqOverflow = FALSE; + *Mask |= SEQUENCE_OVERFLOW; + } + + // + // Convert user imput from string to integer, and fill in the FragCheck in EFI_IPSEC_SPD_DATA. + // + if (ShellCommandLineGetFlag (ParamPackage, L"--fragment-check")) { + (*Data)->ProcessingPolicy->FragCheck = TRUE; + *Mask |= FRAGMENT_CHECK; + } else if (ShellCommandLineGetFlag (ParamPackage, L"--fragment-check-")) { + (*Data)->ProcessingPolicy->FragCheck = FALSE; + *Mask |= FRAGMENT_CHECK; + } + + // + // Convert user imput from string to integer, and fill in the ProcessingPolicy in EFI_IPSEC_SPD_DATA. + // + Status = GetNumber ( + L"--lifebyte", + (UINT64) -1, + &(*Data)->ProcessingPolicy->SaLifetime.ByteCount, + sizeof (UINT64), + NULL, + ParamPackage, + FORMAT_NUMBER + ); + if (!EFI_ERROR (Status)) { + *Mask |= LIFEBYTE; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + Status = GetNumber ( + L"--lifetime", + (UINT64) -1, + &(*Data)->ProcessingPolicy->SaLifetime.HardLifetime, + sizeof (UINT64), + NULL, + ParamPackage, + FORMAT_NUMBER + ); + if (!EFI_ERROR (Status)) { + *Mask |= LIFETIME; + } + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + Status = GetNumber ( + L"--lifetime-soft", + (UINT64) -1, + &(*Data)->ProcessingPolicy->SaLifetime.SoftLifetime, + sizeof (UINT64), + NULL, + ParamPackage, + FORMAT_NUMBER + ); + if (!EFI_ERROR (Status)) { + *Mask |= LIFETIME_SOFT; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + (*Data)->ProcessingPolicy->Mode = EfiIPsecTransport; + Status = GetNumber ( + L"--mode", + 0, + &(*Data)->ProcessingPolicy->Mode, + sizeof (UINT32), + mMapIpSecMode, + ParamPackage, + FORMAT_STRING + ); + if (!EFI_ERROR (Status)) { + *Mask |= MODE; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + ValueStr = ShellCommandLineGetValue (ParamPackage, L"--tunnel-local"); + if (ValueStr != NULL) { + Status = EfiInetAddr2 ((CHAR16 *) ValueStr, &(*Data)->ProcessingPolicy->TunnelOption->LocalTunnelAddress); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE), + mHiiHandle, + mAppName, + L"--tunnel-local", + ValueStr + ); + ReturnStatus = EFI_INVALID_PARAMETER; + } else { + *Mask |= TUNNEL_LOCAL; + } + } + + ValueStr = ShellCommandLineGetValue (ParamPackage, L"--tunnel-remote"); + if (ValueStr != NULL) { + Status = EfiInetAddr2 ((CHAR16 *) ValueStr, &(*Data)->ProcessingPolicy->TunnelOption->RemoteTunnelAddress); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE), + mHiiHandle, + mAppName, + L"--tunnel-remote", + ValueStr + ); + ReturnStatus = EFI_INVALID_PARAMETER; + } else { + *Mask |= TUNNEL_REMOTE; + } + } + + (*Data)->ProcessingPolicy->TunnelOption->DF = EfiIPsecTunnelCopyDf; + Status = GetNumber ( + L"--dont-fragment", + 0, + &(*Data)->ProcessingPolicy->TunnelOption->DF, + sizeof (UINT32), + mMapDfOption, + ParamPackage, + FORMAT_STRING + ); + if (!EFI_ERROR (Status)) { + *Mask |= DONT_FRAGMENT; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + (*Data)->ProcessingPolicy->Proto = EfiIPsecESP; + Status = GetNumber ( + L"--ipsec-proto", + 0, + &(*Data)->ProcessingPolicy->Proto, + sizeof (UINT32), + mMapIpSecProtocol, + ParamPackage, + FORMAT_STRING + ); + if (!EFI_ERROR (Status)) { + *Mask |= IPSEC_PROTO; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + Status = GetNumber ( + L"--encrypt-algo", + 0, + &(*Data)->ProcessingPolicy->EncAlgoId, + sizeof (UINT8), + mMapEncAlgo, + ParamPackage, + FORMAT_STRING + ); + if (!EFI_ERROR (Status)) { + *Mask |= ENCRYPT_ALGO; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + Status = GetNumber ( + L"--auth-algo", + 0, + &(*Data)->ProcessingPolicy->AuthAlgoId, + sizeof (UINT8), + mMapAuthAlgo, + ParamPackage, + FORMAT_STRING + ); + if (!EFI_ERROR (Status)) { + *Mask |= AUTH_ALGO; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + // + // Cannot check Mode against EfiIPsecTunnel, because user may want to change tunnel_remote only so the Mode is not set. + // + if ((*Mask & (TUNNEL_LOCAL | TUNNEL_REMOTE | DONT_FRAGMENT)) == 0) { + (*Data)->ProcessingPolicy->TunnelOption = NULL; + } + + if ((*Mask & (EXT_SEQUENCE | SEQUENCE_OVERFLOW | FRAGMENT_CHECK | LIFEBYTE | + LIFETIME_SOFT | LIFETIME | MODE | TUNNEL_LOCAL | TUNNEL_REMOTE | + DONT_FRAGMENT | IPSEC_PROTO | AUTH_ALGO | ENCRYPT_ALGO)) == 0) { + if ((*Data)->Action != EfiIPsecActionProtect) { + // + // User may not provide additional parameter for Protect action, so we cannot simply set ProcessingPolicy to NULL. + // + (*Data)->ProcessingPolicy = NULL; + } + } + + if (CreateNew) { + if ((*Mask & (LOCAL | REMOTE | PROTO | ACTION)) != (LOCAL | REMOTE | PROTO | ACTION)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS), + mHiiHandle, + mAppName, + L"--local --remote --proto --action" + ); + ReturnStatus = EFI_INVALID_PARAMETER; + } else if (((*Data)->Action == EfiIPsecActionProtect) && + ((*Data)->ProcessingPolicy->Mode == EfiIPsecTunnel) && + ((*Mask & (TUNNEL_LOCAL | TUNNEL_REMOTE)) != (TUNNEL_LOCAL | TUNNEL_REMOTE))) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS), + mHiiHandle, + mAppName, + L"--tunnel-local --tunnel-remote" + ); + ReturnStatus = EFI_INVALID_PARAMETER; + } + } + + return ReturnStatus; +} + +/** + Fill in EFI_IPSEC_SA_ID and EFI_IPSEC_SA_DATA through ParamPackage list. + + @param[out] SaId The pointer to the EFI_IPSEC_SA_ID structure. + @param[out] Data The pointer to the EFI_IPSEC_SA_DATA structure. + @param[in] ParamPackage The pointer to the ParamPackage list. + @param[out] Mask The pointer to the Mask. + @param[in] CreateNew The switch to create new. + + @retval EFI_SUCCESS Fill in EFI_IPSEC_SA_ID and EFI_IPSEC_SA_DATA successfully. + @retval EFI_INVALID_PARAMETER Invalid user input parameter. + +**/ +EFI_STATUS +CreateSadEntry ( + OUT EFI_IPSEC_SA_ID **SaId, + OUT EFI_IPSEC_SA_DATA **Data, + IN LIST_ENTRY *ParamPackage, + OUT UINT32 *Mask, + IN BOOLEAN CreateNew + ) +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + UINTN AuthKeyLength; + UINTN EncKeyLength; + CONST CHAR16 *ValueStr; + UINTN DataSize; + + Status = EFI_SUCCESS; + ReturnStatus = EFI_SUCCESS; + *Mask = 0; + AuthKeyLength = 0; + EncKeyLength = 0; + + *SaId = AllocateZeroPool (sizeof (EFI_IPSEC_SA_ID)); + ASSERT (*SaId != NULL); + + // + // Convert user imput from string to integer, and fill in the Spi in EFI_IPSEC_SA_ID. + // + Status = GetNumber (L"--spi", (UINT32) -1, &(*SaId)->Spi, sizeof (UINT32), NULL, ParamPackage, FORMAT_NUMBER); + if (!EFI_ERROR (Status)) { + *Mask |= SPI; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + // + // Convert user imput from string to integer, and fill in the Proto in EFI_IPSEC_SA_ID. + // + Status = GetNumber ( + L"--ipsec-proto", + 0, + &(*SaId)->Proto, + sizeof (EFI_IPSEC_PROTOCOL_TYPE), + mMapIpSecProtocol, + ParamPackage, + FORMAT_STRING + ); + if (!EFI_ERROR (Status)) { + *Mask |= IPSEC_PROTO; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + // + // Convert user imput from string to integer, and fill in the DestAddress in EFI_IPSEC_SA_ID. + // + ValueStr = ShellCommandLineGetValue (ParamPackage, L"--dest"); + if (ValueStr != NULL) { + Status = EfiInetAddr2 ((CHAR16 *) ValueStr, &(*SaId)->DestAddress); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE), + mHiiHandle, + mAppName, + L"--dest", + ValueStr + ); + ReturnStatus = EFI_INVALID_PARAMETER; + } else { + *Mask |= DEST; + } + } + + // + // Convert user imput from string to integer, and fill in EFI_IPSEC_SA_DATA. + // + ValueStr = ShellCommandLineGetValue (ParamPackage, L"--auth-key"); + if (ValueStr != NULL) { + AuthKeyLength = (StrLen (ValueStr) + 1) * sizeof (CHAR16); + } + + ValueStr = ShellCommandLineGetValue (ParamPackage, L"--encrypt-key"); + if (ValueStr != NULL) { + EncKeyLength = (StrLen (ValueStr) + 1) * sizeof (CHAR16); + } + + // + // EFI_IPSEC_SA_DATA: + // +------------ + // | EFI_IPSEC_SA_DATA + // +----------------------- + // | AuthKey + // +------------------------- + // | EncKey + // +------------------------- + // | SpdSelector + // + // Notes: To make sure the address alignment add padding after each data if needed. + // + DataSize = ALIGN_VARIABLE (sizeof (EFI_IPSEC_SA_DATA)); + DataSize = ALIGN_VARIABLE (DataSize + AuthKeyLength); + DataSize = ALIGN_VARIABLE (DataSize + EncKeyLength); + DataSize = ALIGN_VARIABLE (DataSize + sizeof (EFI_IPSEC_SPD_SELECTOR)); + DataSize = ALIGN_VARIABLE (DataSize + sizeof (EFI_IP_ADDRESS_INFO)); + DataSize += sizeof (EFI_IP_ADDRESS_INFO); + + + + *Data = AllocateZeroPool (DataSize); + ASSERT (*Data != NULL); + + (*Data)->ManualSet = TRUE; + (*Data)->AlgoInfo.EspAlgoInfo.AuthKey = (VOID *) ALIGN_POINTER (((*Data) + 1), sizeof (UINTN)); + (*Data)->AlgoInfo.EspAlgoInfo.EncKey = (VOID *) ALIGN_POINTER ( + ((UINT8 *) (*Data)->AlgoInfo.EspAlgoInfo.AuthKey + AuthKeyLength), + sizeof (UINTN) + ); + (*Data)->SpdSelector = (EFI_IPSEC_SPD_SELECTOR *) ALIGN_POINTER ( + ((UINT8 *) (*Data)->AlgoInfo.EspAlgoInfo.EncKey + EncKeyLength), + sizeof (UINTN) + ); + (*Data)->SpdSelector->LocalAddress = (EFI_IP_ADDRESS_INFO *) ALIGN_POINTER ( + ((UINT8 *) (*Data)->SpdSelector + sizeof (EFI_IPSEC_SPD_SELECTOR)), + sizeof (UINTN)); + (*Data)->SpdSelector->RemoteAddress = (EFI_IP_ADDRESS_INFO *) ALIGN_POINTER ( + (*Data)->SpdSelector->LocalAddress + 1, + sizeof (UINTN) + ); + + (*Data)->Mode = EfiIPsecTransport; + Status = GetNumber ( + L"--mode", + 0, + &(*Data)->Mode, + sizeof (EFI_IPSEC_MODE), + mMapIpSecMode, + ParamPackage, + FORMAT_STRING + ); + if (!EFI_ERROR (Status)) { + *Mask |= MODE; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + // + // According to RFC 4303-3.3.3. The first packet sent using a given SA + // will contain a sequence number of 1. + // + (*Data)->SNCount = 1; + Status = GetNumber ( + L"--sequence-number", + (UINT64) -1, + &(*Data)->SNCount, + sizeof (UINT64), + NULL, + ParamPackage, + FORMAT_NUMBER + ); + if (!EFI_ERROR (Status)) { + *Mask |= SEQUENCE_NUMBER; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + (*Data)->AntiReplayWindows = 0; + Status = GetNumber ( + L"--antireplay-window", + (UINT8) -1, + &(*Data)->AntiReplayWindows, + sizeof (UINT8), + NULL, + ParamPackage, + FORMAT_NUMBER + ); + if (!EFI_ERROR (Status)) { + *Mask |= SEQUENCE_NUMBER; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + Status = GetNumber ( + L"--encrypt-algo", + 0, + &(*Data)->AlgoInfo.EspAlgoInfo.EncAlgoId, + sizeof (UINT8), + mMapEncAlgo, + ParamPackage, + FORMAT_STRING + ); + if (!EFI_ERROR (Status)) { + *Mask |= ENCRYPT_ALGO; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + ValueStr = ShellCommandLineGetValue (ParamPackage, L"--encrypt-key"); + if (ValueStr != NULL ) { + (*Data)->AlgoInfo.EspAlgoInfo.EncKeyLength = EncKeyLength; + CopyMem ((*Data)->AlgoInfo.EspAlgoInfo.EncKey, ValueStr, EncKeyLength); + *Mask |= ENCRYPT_KEY; + } else { + (*Data)->AlgoInfo.EspAlgoInfo.EncKey = NULL; + } + + Status = GetNumber ( + L"--auth-algo", + 0, + &(*Data)->AlgoInfo.EspAlgoInfo.AuthAlgoId, + sizeof (UINT8), + mMapAuthAlgo, + ParamPackage, + FORMAT_STRING + ); + if (!EFI_ERROR (Status)) { + *Mask |= AUTH_ALGO; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + ValueStr = ShellCommandLineGetValue (ParamPackage, L"--auth-key"); + if (ValueStr != NULL) { + (*Data)->AlgoInfo.EspAlgoInfo.AuthKeyLength = AuthKeyLength; + CopyMem ((*Data)->AlgoInfo.EspAlgoInfo.AuthKey, ValueStr, AuthKeyLength); + *Mask |= AUTH_KEY; + } else { + (*Data)->AlgoInfo.EspAlgoInfo.AuthKey = NULL; + } + + Status = GetNumber ( + L"--lifebyte", + (UINT64) -1, + &(*Data)->SaLifetime.ByteCount, + sizeof (UINT64), + NULL, + ParamPackage, + FORMAT_NUMBER + ); + if (!EFI_ERROR (Status)) { + *Mask |= LIFEBYTE; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + Status = GetNumber ( + L"--lifetime", + (UINT64) -1, + &(*Data)->SaLifetime.HardLifetime, + sizeof (UINT64), + NULL, + ParamPackage, + FORMAT_NUMBER + ); + if (!EFI_ERROR (Status)) { + *Mask |= LIFETIME; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + Status = GetNumber ( + L"--lifetime-soft", + (UINT64) -1, + &(*Data)->SaLifetime.SoftLifetime, + sizeof (UINT64), + NULL, + ParamPackage, + FORMAT_NUMBER + ); + if (!EFI_ERROR (Status)) { + *Mask |= LIFETIME_SOFT; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + Status = GetNumber ( + L"--path-mtu", + (UINT32) -1, + &(*Data)->PathMTU, + sizeof (UINT32), + NULL, + ParamPackage, + FORMAT_NUMBER + ); + if (!EFI_ERROR (Status)) { + *Mask |= PATH_MTU; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + ReturnStatus = CreateSpdSelector ((*Data)->SpdSelector, ParamPackage, Mask); + + if (CreateNew) { + if ((*Mask & (SPI | IPSEC_PROTO | DEST)) != (SPI | IPSEC_PROTO | DEST)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS), + mHiiHandle, + mAppName, + L"--spi --ipsec-proto --dest" + ); + ReturnStatus = EFI_INVALID_PARAMETER; + } else { + if ((*SaId)->Proto == EfiIPsecAH) { + if ((*Mask & AUTH_ALGO) == 0) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_PARAMETER), + mHiiHandle, + mAppName, + L"--auth-algo" + ); + ReturnStatus = EFI_INVALID_PARAMETER; + } else if ((*Data)->AlgoInfo.EspAlgoInfo.AuthAlgoId != EFI_IPSEC_AALG_NONE && (*Mask & AUTH_KEY) == 0) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_PARAMETER), + mHiiHandle, + mAppName, + L"--auth-key" + ); + ReturnStatus = EFI_INVALID_PARAMETER; + } + } else { + if ((*Mask & ENCRYPT_ALGO) == 0) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_PARAMETER), + mHiiHandle, + mAppName, + L"--encrypt-algo" + ); + ReturnStatus = EFI_INVALID_PARAMETER; + } else if ((*Data)->AlgoInfo.EspAlgoInfo.EncAlgoId != EFI_IPSEC_EALG_NONE && (*Mask & ENCRYPT_KEY) == 0) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_PARAMETER), + mHiiHandle, + mAppName, + L"--encrypt-key" + ); + ReturnStatus = EFI_INVALID_PARAMETER; + } + } + } + } + + return ReturnStatus; +} + +/** + Fill in EFI_IPSEC_PAD_ID and EFI_IPSEC_PAD_DATA through ParamPackage list. + + @param[out] PadId The pointer to the EFI_IPSEC_PAD_ID structure. + @param[out] Data The pointer to the EFI_IPSEC_PAD_DATA structure. + @param[in] ParamPackage The pointer to the ParamPackage list. + @param[out] Mask The pointer to the Mask. + @param[in] CreateNew The switch to create new. + + @retval EFI_SUCCESS Fill in EFI_IPSEC_PAD_ID and EFI_IPSEC_PAD_DATA successfully. + @retval EFI_INVALID_PARAMETER Invalid user input parameter. + +**/ +EFI_STATUS +CreatePadEntry ( + OUT EFI_IPSEC_PAD_ID **PadId, + OUT EFI_IPSEC_PAD_DATA **Data, + IN LIST_ENTRY *ParamPackage, + OUT UINT32 *Mask, + IN BOOLEAN CreateNew + ) +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + EFI_FILE_HANDLE FileHandle; + UINT64 FileSize; + UINTN AuthDataLength; + UINTN RevocationDataLength; + UINTN DataLength; + UINTN Index; + CONST CHAR16 *ValueStr; + UINTN DataSize; + + Status = EFI_SUCCESS; + ReturnStatus = EFI_SUCCESS; + *Mask = 0; + AuthDataLength = 0; + RevocationDataLength = 0; + + *PadId = AllocateZeroPool (sizeof (EFI_IPSEC_PAD_ID)); + ASSERT (*PadId != NULL); + + // + // Convert user imput from string to integer, and fill in EFI_IPSEC_PAD_ID. + // + ValueStr = ShellCommandLineGetValue (ParamPackage, L"--peer-address"); + if (ValueStr != NULL) { + (*PadId)->PeerIdValid = FALSE; + Status = EfiInetAddrRange ((CHAR16 *) ValueStr, &(*PadId)->Id.IpAddress); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE), + mHiiHandle, + mAppName, + L"--peer-address", + ValueStr + ); + ReturnStatus = EFI_INVALID_PARAMETER; + } else { + *Mask |= PEER_ADDRESS; + } + } + + ValueStr = ShellCommandLineGetValue (ParamPackage, L"--peer-id"); + if (ValueStr != NULL) { + (*PadId)->PeerIdValid = TRUE; + StrnCpy ((CHAR16 *) (*PadId)->Id.PeerId, ValueStr, ARRAY_SIZE ((*PadId)->Id.PeerId) - 1); + *Mask |= PEER_ID; + } + + ValueStr = ShellCommandLineGetValue (ParamPackage, L"--auth-data"); + if (ValueStr != NULL) { + if (ValueStr[0] == L'@') { + // + // Input is a file: --auth-data "@fs1:\My Certificates\tom.dat" + // + Status = ShellOpenFileByName (&ValueStr[1], &FileHandle, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_FILE_OPEN_FAILED), + mHiiHandle, + mAppName, + &ValueStr[1] + ); + ReturnStatus = EFI_INVALID_PARAMETER; + } else { + Status = ShellGetFileSize (FileHandle, &FileSize); + ShellCloseFile (&FileHandle); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_FILE_OPEN_FAILED), + mHiiHandle, + mAppName, + &ValueStr[1] + ); + ReturnStatus = EFI_INVALID_PARAMETER; + } else { + AuthDataLength = (UINTN) FileSize; + } + } + } else { + AuthDataLength = StrLen (ValueStr); + } + } + + ValueStr = ShellCommandLineGetValue (ParamPackage, L"--revocation-data"); + if (ValueStr != NULL) { + RevocationDataLength = (StrLen (ValueStr) + 1) * sizeof (CHAR16); + } + + // + // Allocate Buffer for Data. Add padding after each struct to make sure the alignment + // in different Arch. + // + DataSize = ALIGN_VARIABLE (sizeof (EFI_IPSEC_PAD_DATA)); + DataSize = ALIGN_VARIABLE (DataSize + AuthDataLength); + DataSize += RevocationDataLength; + + *Data = AllocateZeroPool (DataSize); + ASSERT (*Data != NULL); + + (*Data)->AuthData = (VOID *) ALIGN_POINTER ((*Data + 1), sizeof (UINTN)); + (*Data)->RevocationData = (VOID *) ALIGN_POINTER (((UINT8 *) (*Data + 1) + AuthDataLength), sizeof (UINTN)); + (*Data)->AuthProtocol = EfiIPsecAuthProtocolIKEv1; + + // + // Convert user imput from string to integer, and fill in EFI_IPSEC_PAD_DATA. + // + Status = GetNumber ( + L"--auth-proto", + 0, + &(*Data)->AuthProtocol, + sizeof (EFI_IPSEC_AUTH_PROTOCOL_TYPE), + mMapAuthProto, + ParamPackage, + FORMAT_STRING + ); + if (!EFI_ERROR (Status)) { + *Mask |= AUTH_PROTO; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + Status = GetNumber ( + L"--auth-method", + 0, + &(*Data)->AuthMethod, + sizeof (EFI_IPSEC_AUTH_METHOD), + mMapAuthMethod, + ParamPackage, + FORMAT_STRING + ); + if (!EFI_ERROR (Status)) { + *Mask |= AUTH_METHOD; + } + + if (Status == EFI_INVALID_PARAMETER) { + ReturnStatus = EFI_INVALID_PARAMETER; + } + + if (ShellCommandLineGetFlag (ParamPackage, L"--ike-id")) { + (*Data)->IkeIdFlag = TRUE; + *Mask |= IKE_ID; + } + + if (ShellCommandLineGetFlag (ParamPackage, L"--ike-id-")) { + (*Data)->IkeIdFlag = FALSE; + *Mask |= IKE_ID; + } + + ValueStr = ShellCommandLineGetValue (ParamPackage, L"--auth-data"); + if (ValueStr != NULL) { + if (ValueStr[0] == L'@') { + // + // Input is a file: --auth-data "@fs1:\My Certificates\tom.dat" + // + + Status = ShellOpenFileByName (&ValueStr[1], &FileHandle, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_FILE_OPEN_FAILED), + mHiiHandle, + mAppName, + &ValueStr[1] + ); + ReturnStatus = EFI_INVALID_PARAMETER; + (*Data)->AuthData = NULL; + } else { + DataLength = AuthDataLength; + Status = ShellReadFile (FileHandle, &DataLength, (*Data)->AuthData); + ShellCloseFile (&FileHandle); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_FILE_OPEN_FAILED), + mHiiHandle, + mAppName, + &ValueStr[1] + ); + ReturnStatus = EFI_INVALID_PARAMETER; + (*Data)->AuthData = NULL; + } else { + ASSERT (DataLength == AuthDataLength); + *Mask |= AUTH_DATA; + } + } + } else { + for (Index = 0; Index < AuthDataLength; Index++) { + ((CHAR8 *) (*Data)->AuthData)[Index] = (CHAR8) ValueStr[Index]; + } + (*Data)->AuthDataSize = AuthDataLength; + *Mask |= AUTH_DATA; + } + } + + ValueStr = ShellCommandLineGetValue (ParamPackage, L"--revocation-data"); + if (ValueStr != NULL) { + CopyMem ((*Data)->RevocationData, ValueStr, RevocationDataLength); + (*Data)->RevocationDataSize = RevocationDataLength; + *Mask |= REVOCATION_DATA; + } else { + (*Data)->RevocationData = NULL; + } + + if (CreateNew) { + if ((*Mask & (PEER_ID | PEER_ADDRESS)) == 0) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS), + mHiiHandle, + mAppName, + L"--peer-id --peer-address" + ); + ReturnStatus = EFI_INVALID_PARAMETER; + } else if ((*Mask & (AUTH_METHOD | AUTH_DATA)) != (AUTH_METHOD | AUTH_DATA)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS), + mHiiHandle, + mAppName, + L"--auth-method --auth-data" + ); + ReturnStatus = EFI_INVALID_PARAMETER; + } + } + + return ReturnStatus; +} + +CREATE_POLICY_ENTRY mCreatePolicyEntry[] = { + (CREATE_POLICY_ENTRY) CreateSpdEntry, + (CREATE_POLICY_ENTRY) CreateSadEntry, + (CREATE_POLICY_ENTRY) CreatePadEntry +}; + +/** + Combine old SPD entry with new SPD entry. + + @param[in, out] OldSelector The pointer to the EFI_IPSEC_SPD_SELECTOR structure. + @param[in, out] OldData The pointer to the EFI_IPSEC_SPD_DATA structure. + @param[in] NewSelector The pointer to the EFI_IPSEC_SPD_SELECTOR structure. + @param[in] NewData The pointer to the EFI_IPSEC_SPD_DATA structure. + @param[in] Mask The pointer to the Mask. + @param[out] CreateNew The switch to create new. + + @retval EFI_SUCCESS Combined successfully. + @retval EFI_INVALID_PARAMETER Invalid user input parameter. + +**/ +EFI_STATUS +CombineSpdEntry ( + IN OUT EFI_IPSEC_SPD_SELECTOR *OldSelector, + IN OUT EFI_IPSEC_SPD_DATA *OldData, + IN EFI_IPSEC_SPD_SELECTOR *NewSelector, + IN EFI_IPSEC_SPD_DATA *NewData, + IN UINT32 Mask, + OUT BOOLEAN *CreateNew + ) +{ + + // + // Process Selector + // + *CreateNew = FALSE; + if ((Mask & LOCAL) == 0) { + NewSelector->LocalAddressCount = OldSelector->LocalAddressCount; + NewSelector->LocalAddress = OldSelector->LocalAddress; + } else if ((NewSelector->LocalAddressCount != OldSelector->LocalAddressCount) || + (CompareMem (NewSelector->LocalAddress, OldSelector->LocalAddress, NewSelector->LocalAddressCount * sizeof (EFI_IP_ADDRESS_INFO)) != 0)) { + *CreateNew = TRUE; + } + + if ((Mask & REMOTE) == 0) { + NewSelector->RemoteAddressCount = OldSelector->RemoteAddressCount; + NewSelector->RemoteAddress = OldSelector->RemoteAddress; + } else if ((NewSelector->RemoteAddressCount != OldSelector->RemoteAddressCount) || + (CompareMem (NewSelector->RemoteAddress, OldSelector->RemoteAddress, NewSelector->RemoteAddressCount * sizeof (EFI_IP_ADDRESS_INFO)) != 0)) { + *CreateNew = TRUE; + } + + if ((Mask & PROTO) == 0) { + NewSelector->NextLayerProtocol = OldSelector->NextLayerProtocol; + } else if (NewSelector->NextLayerProtocol != OldSelector->NextLayerProtocol) { + *CreateNew = TRUE; + } + + switch (NewSelector->NextLayerProtocol) { + case EFI_IP4_PROTO_TCP: + case EFI_IP4_PROTO_UDP: + if ((Mask & LOCAL_PORT) == 0) { + NewSelector->LocalPort = OldSelector->LocalPort; + NewSelector->LocalPortRange = OldSelector->LocalPortRange; + } else if ((NewSelector->LocalPort != OldSelector->LocalPort) || + (NewSelector->LocalPortRange != OldSelector->LocalPortRange)) { + *CreateNew = TRUE; + } + + if ((Mask & REMOTE_PORT) == 0) { + NewSelector->RemotePort = OldSelector->RemotePort; + NewSelector->RemotePortRange = OldSelector->RemotePortRange; + } else if ((NewSelector->RemotePort != OldSelector->RemotePort) || + (NewSelector->RemotePortRange != OldSelector->RemotePortRange)) { + *CreateNew = TRUE; + } + break; + + case EFI_IP4_PROTO_ICMP: + if ((Mask & ICMP_TYPE) == 0) { + NewSelector->LocalPort = OldSelector->LocalPort; + } else if (NewSelector->LocalPort != OldSelector->LocalPort) { + *CreateNew = TRUE; + } + + if ((Mask & ICMP_CODE) == 0) { + NewSelector->RemotePort = OldSelector->RemotePort; + } else if (NewSelector->RemotePort != OldSelector->RemotePort) { + *CreateNew = TRUE; + } + break; + } + // + // Process Data + // + if ((Mask & NAME) != 0) { + AsciiStrCpy ((CHAR8 *) OldData->Name, (CHAR8 *) NewData->Name); + } + + if ((Mask & PACKET_FLAG) != 0) { + OldData->PackageFlag = NewData->PackageFlag; + } + + if ((Mask & ACTION) != 0) { + OldData->Action = NewData->Action; + } + + if (OldData->Action != EfiIPsecActionProtect) { + OldData->ProcessingPolicy = NULL; + } else { + // + // Protect + // + if (OldData->ProcessingPolicy == NULL) { + // + // Just point to new data if originally NULL. + // + OldData->ProcessingPolicy = NewData->ProcessingPolicy; + if (OldData->ProcessingPolicy->Mode == EfiIPsecTunnel && + (Mask & (TUNNEL_LOCAL | TUNNEL_REMOTE)) != (TUNNEL_LOCAL | TUNNEL_REMOTE) + ) { + // + // Change to Protect action and Tunnel mode, but without providing local/remote tunnel address. + // + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS), + mHiiHandle, + mAppName, + L"--tunnel-local --tunnel-remote" + ); + return EFI_INVALID_PARAMETER; + } + } else { + // + // Modify some of the data. + // + if ((Mask & EXT_SEQUENCE) != 0) { + OldData->ProcessingPolicy->ExtSeqNum = NewData->ProcessingPolicy->ExtSeqNum; + } + + if ((Mask & SEQUENCE_OVERFLOW) != 0) { + OldData->ProcessingPolicy->SeqOverflow = NewData->ProcessingPolicy->SeqOverflow; + } + + if ((Mask & FRAGMENT_CHECK) != 0) { + OldData->ProcessingPolicy->FragCheck = NewData->ProcessingPolicy->FragCheck; + } + + if ((Mask & LIFEBYTE) != 0) { + OldData->ProcessingPolicy->SaLifetime.ByteCount = NewData->ProcessingPolicy->SaLifetime.ByteCount; + } + + if ((Mask & LIFETIME_SOFT) != 0) { + OldData->ProcessingPolicy->SaLifetime.SoftLifetime = NewData->ProcessingPolicy->SaLifetime.SoftLifetime; + } + + if ((Mask & LIFETIME) != 0) { + OldData->ProcessingPolicy->SaLifetime.HardLifetime = NewData->ProcessingPolicy->SaLifetime.HardLifetime; + } + + if ((Mask & MODE) != 0) { + OldData->ProcessingPolicy->Mode = NewData->ProcessingPolicy->Mode; + } + + if ((Mask & IPSEC_PROTO) != 0) { + OldData->ProcessingPolicy->Proto = NewData->ProcessingPolicy->Proto; + } + + if ((Mask & AUTH_ALGO) != 0) { + OldData->ProcessingPolicy->AuthAlgoId = NewData->ProcessingPolicy->AuthAlgoId; + } + + if ((Mask & ENCRYPT_ALGO) != 0) { + OldData->ProcessingPolicy->EncAlgoId = NewData->ProcessingPolicy->EncAlgoId; + } + + if (OldData->ProcessingPolicy->Mode != EfiIPsecTunnel) { + OldData->ProcessingPolicy->TunnelOption = NULL; + } else { + if (OldData->ProcessingPolicy->TunnelOption == NULL) { + // + // Set from Transport mode to Tunnel mode, should ensure TUNNEL_LOCAL & TUNNEL_REMOTE both exists. + // + if ((Mask & (TUNNEL_LOCAL | TUNNEL_REMOTE)) != (TUNNEL_LOCAL | TUNNEL_REMOTE)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS), + mHiiHandle, + mAppName, + L"--tunnel-local --tunnel-remote" + ); + return EFI_INVALID_PARAMETER; + } + + OldData->ProcessingPolicy->TunnelOption = NewData->ProcessingPolicy->TunnelOption; + } else { + if ((Mask & TUNNEL_LOCAL) != 0) { + CopyMem ( + &OldData->ProcessingPolicy->TunnelOption->LocalTunnelAddress, + &NewData->ProcessingPolicy->TunnelOption->LocalTunnelAddress, + sizeof (EFI_IP_ADDRESS) + ); + } + + if ((Mask & TUNNEL_REMOTE) != 0) { + CopyMem ( + &OldData->ProcessingPolicy->TunnelOption->RemoteTunnelAddress, + &NewData->ProcessingPolicy->TunnelOption->RemoteTunnelAddress, + sizeof (EFI_IP_ADDRESS) + ); + } + + if ((Mask & DONT_FRAGMENT) != 0) { + OldData->ProcessingPolicy->TunnelOption->DF = NewData->ProcessingPolicy->TunnelOption->DF; + } + } + } + } + } + + return EFI_SUCCESS; +} + +/** + Combine old SAD entry with new SAD entry. + + @param[in, out] OldSaId The pointer to the EFI_IPSEC_SA_ID structure. + @param[in, out] OldData The pointer to the EFI_IPSEC_SA_DATA structure. + @param[in] NewSaId The pointer to the EFI_IPSEC_SA_ID structure. + @param[in] NewData The pointer to the EFI_IPSEC_SA_DATA structure. + @param[in] Mask The pointer to the Mask. + @param[out] CreateNew The switch to create new. + + @retval EFI_SUCCESS Combined successfully. + @retval EFI_INVALID_PARAMETER Invalid user input parameter. + +**/ +EFI_STATUS +CombineSadEntry ( + IN OUT EFI_IPSEC_SA_ID *OldSaId, + IN OUT EFI_IPSEC_SA_DATA *OldData, + IN EFI_IPSEC_SA_ID *NewSaId, + IN EFI_IPSEC_SA_DATA *NewData, + IN UINT32 Mask, + OUT BOOLEAN *CreateNew + ) +{ + + *CreateNew = FALSE; + + if ((Mask & SPI) == 0) { + NewSaId->Spi = OldSaId->Spi; + } else if (NewSaId->Spi != OldSaId->Spi) { + *CreateNew = TRUE; + } + + if ((Mask & IPSEC_PROTO) == 0) { + NewSaId->Proto = OldSaId->Proto; + } else if (NewSaId->Proto != OldSaId->Proto) { + *CreateNew = TRUE; + } + + if ((Mask & DEST) == 0) { + CopyMem (&NewSaId->DestAddress, &OldSaId->DestAddress, sizeof (EFI_IP_ADDRESS)); + } else if (CompareMem (&NewSaId->DestAddress, &OldSaId->DestAddress, sizeof (EFI_IP_ADDRESS)) != 0) { + *CreateNew = TRUE; + } + + // + // Process SA_DATA. + // + if ((Mask & MODE) != 0) { + OldData->Mode = NewData->Mode; + } + + if ((Mask & SEQUENCE_NUMBER) != 0) { + OldData->SNCount = NewData->SNCount; + } + + if ((Mask & ANTIREPLAY_WINDOW) != 0) { + OldData->AntiReplayWindows = NewData->AntiReplayWindows; + } + + if ((Mask & AUTH_ALGO) != 0) { + OldData->AlgoInfo.EspAlgoInfo.AuthAlgoId = NewData->AlgoInfo.EspAlgoInfo.AuthAlgoId; + } + + if ((Mask & AUTH_KEY) != 0) { + OldData->AlgoInfo.EspAlgoInfo.AuthKey = NewData->AlgoInfo.EspAlgoInfo.AuthKey; + OldData->AlgoInfo.EspAlgoInfo.AuthKeyLength = NewData->AlgoInfo.EspAlgoInfo.AuthKeyLength; + } + + if ((Mask & ENCRYPT_ALGO) != 0) { + OldData->AlgoInfo.EspAlgoInfo.EncAlgoId = NewData->AlgoInfo.EspAlgoInfo.EncAlgoId; + } + + if ((Mask & ENCRYPT_KEY) != 0) { + OldData->AlgoInfo.EspAlgoInfo.EncKey = NewData->AlgoInfo.EspAlgoInfo.EncKey; + OldData->AlgoInfo.EspAlgoInfo.EncKeyLength = NewData->AlgoInfo.EspAlgoInfo.EncKeyLength; + } + + if (NewSaId->Proto == EfiIPsecAH) { + if ((Mask & (ENCRYPT_ALGO | ENCRYPT_KEY)) != 0) { + // + // Should not provide encrypt_* if AH. + // + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_UNWANTED_PARAMETER), + mHiiHandle, + mAppName, + L"--encrypt-algo --encrypt-key" + ); + return EFI_INVALID_PARAMETER; + } + } + + if (NewSaId->Proto == EfiIPsecESP && OldSaId->Proto == EfiIPsecAH) { + // + // AH -> ESP + // Should provide encrypt_algo at least. + // + if ((Mask & ENCRYPT_ALGO) == 0) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_PARAMETER), + mHiiHandle, + mAppName, + L"--encrypt-algo" + ); + return EFI_INVALID_PARAMETER; + } + + // + // Encrypt_key should be provided if algorithm is not NONE. + // + if (NewData->AlgoInfo.EspAlgoInfo.EncAlgoId != EFI_IPSEC_EALG_NONE && (Mask & ENCRYPT_KEY) == 0) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_PARAMETER), + mHiiHandle, + mAppName, + L"--encrypt-algo" + ); + return EFI_INVALID_PARAMETER; + } + } + + if ((Mask & LIFEBYTE) != 0) { + OldData->SaLifetime.ByteCount = NewData->SaLifetime.ByteCount; + } + + if ((Mask & LIFETIME_SOFT) != 0) { + OldData->SaLifetime.SoftLifetime = NewData->SaLifetime.SoftLifetime; + } + + if ((Mask & LIFETIME) != 0) { + OldData->SaLifetime.HardLifetime = NewData->SaLifetime.HardLifetime; + } + + if ((Mask & PATH_MTU) != 0) { + OldData->PathMTU = NewData->PathMTU; + } + // + // Process SpdSelector. + // + if (OldData->SpdSelector == NULL) { + if ((Mask & (LOCAL | REMOTE | PROTO | LOCAL_PORT | REMOTE_PORT | ICMP_TYPE | ICMP_CODE)) != 0) { + if ((Mask & (LOCAL | REMOTE | PROTO)) != (LOCAL | REMOTE | PROTO)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS), + mHiiHandle, + mAppName, + L"--local --remote --proto" + ); + return EFI_INVALID_PARAMETER; + } + + OldData->SpdSelector = NewData->SpdSelector; + } + } else { + if ((Mask & LOCAL) != 0) { + OldData->SpdSelector->LocalAddressCount = NewData->SpdSelector->LocalAddressCount; + OldData->SpdSelector->LocalAddress = NewData->SpdSelector->LocalAddress; + } + + if ((Mask & REMOTE) != 0) { + OldData->SpdSelector->RemoteAddressCount = NewData->SpdSelector->RemoteAddressCount; + OldData->SpdSelector->RemoteAddress = NewData->SpdSelector->RemoteAddress; + } + + if ((Mask & PROTO) != 0) { + OldData->SpdSelector->NextLayerProtocol = NewData->SpdSelector->NextLayerProtocol; + } + + if (OldData->SpdSelector != NULL) { + switch (OldData->SpdSelector->NextLayerProtocol) { + case EFI_IP4_PROTO_TCP: + case EFI_IP4_PROTO_UDP: + if ((Mask & LOCAL_PORT) != 0) { + OldData->SpdSelector->LocalPort = NewData->SpdSelector->LocalPort; + } + + if ((Mask & REMOTE_PORT) != 0) { + OldData->SpdSelector->RemotePort = NewData->SpdSelector->RemotePort; + } + break; + + case EFI_IP4_PROTO_ICMP: + if ((Mask & ICMP_TYPE) != 0) { + OldData->SpdSelector->LocalPort = (UINT8) NewData->SpdSelector->LocalPort; + } + + if ((Mask & ICMP_CODE) != 0) { + OldData->SpdSelector->RemotePort = (UINT8) NewData->SpdSelector->RemotePort; + } + break; + } + } + } + + return EFI_SUCCESS; +} + +/** + Combine old PAD entry with new PAD entry. + + @param[in, out] OldPadId The pointer to the EFI_IPSEC_PAD_ID structure. + @param[in, out] OldData The pointer to the EFI_IPSEC_PAD_DATA structure. + @param[in] NewPadId The pointer to the EFI_IPSEC_PAD_ID structure. + @param[in] NewData The pointer to the EFI_IPSEC_PAD_DATA structure. + @param[in] Mask The pointer to the Mask. + @param[out] CreateNew The switch to create new. + + @retval EFI_SUCCESS Combined successfully. + @retval EFI_INVALID_PARAMETER Invalid user input parameter. + +**/ +EFI_STATUS +CombinePadEntry ( + IN OUT EFI_IPSEC_PAD_ID *OldPadId, + IN OUT EFI_IPSEC_PAD_DATA *OldData, + IN EFI_IPSEC_PAD_ID *NewPadId, + IN EFI_IPSEC_PAD_DATA *NewData, + IN UINT32 Mask, + OUT BOOLEAN *CreateNew + ) +{ + + *CreateNew = FALSE; + + if ((Mask & (PEER_ID | PEER_ADDRESS)) == 0) { + CopyMem (NewPadId, OldPadId, sizeof (EFI_IPSEC_PAD_ID)); + } else { + if ((Mask & PEER_ID) != 0) { + if (OldPadId->PeerIdValid) { + if (StrCmp ((CONST CHAR16 *) OldPadId->Id.PeerId, (CONST CHAR16 *) NewPadId->Id.PeerId) != 0) { + *CreateNew = TRUE; + } + } else { + *CreateNew = TRUE; + } + } else { + // + // MASK & PEER_ADDRESS + // + if (OldPadId->PeerIdValid) { + *CreateNew = TRUE; + } else { + if ((CompareMem (&OldPadId->Id.IpAddress.Address, &NewPadId->Id.IpAddress.Address, sizeof (EFI_IP_ADDRESS)) != 0) || + (OldPadId->Id.IpAddress.PrefixLength != NewPadId->Id.IpAddress.PrefixLength)) { + *CreateNew = TRUE; + } + } + } + } + + if ((Mask & AUTH_PROTO) != 0) { + OldData->AuthProtocol = NewData->AuthProtocol; + } + + if ((Mask & AUTH_METHOD) != 0) { + OldData->AuthMethod = NewData->AuthMethod; + } + + if ((Mask & IKE_ID) != 0) { + OldData->IkeIdFlag = NewData->IkeIdFlag; + } + + if ((Mask & AUTH_DATA) != 0) { + OldData->AuthDataSize = NewData->AuthDataSize; + OldData->AuthData = NewData->AuthData; + } + + if ((Mask & REVOCATION_DATA) != 0) { + OldData->RevocationDataSize = NewData->RevocationDataSize; + OldData->RevocationData = NewData->RevocationData; + } + + return EFI_SUCCESS; +} + +COMBINE_POLICY_ENTRY mCombinePolicyEntry[] = { + (COMBINE_POLICY_ENTRY) CombineSpdEntry, + (COMBINE_POLICY_ENTRY) CombineSadEntry, + (COMBINE_POLICY_ENTRY) CombinePadEntry +}; + +/** + Edit entry information in the database. + + @param[in] Selector The pointer to the EFI_IPSEC_CONFIG_SELECTOR structure. + @param[in] Data The pointer to the data. + @param[in] Context The pointer to the INSERT_POLICY_ENTRY_CONTEXT structure. + + @retval EFI_SUCCESS Continue the iteration. + @retval EFI_ABORTED Abort the iteration. +**/ +EFI_STATUS +EditOperatePolicyEntry ( + IN EFI_IPSEC_CONFIG_SELECTOR *Selector, + IN VOID *Data, + IN EDIT_POLICY_ENTRY_CONTEXT *Context + ) +{ + EFI_STATUS Status; + BOOLEAN CreateNew; + + if (mMatchPolicyEntry[Context->DataType] (Selector, Data, &Context->Indexer)) { + ASSERT (Context->DataType < 3); + + Status = mCombinePolicyEntry[Context->DataType] ( + Selector, + Data, + Context->Selector, + Context->Data, + Context->Mask, + &CreateNew + ); + if (!EFI_ERROR (Status)) { + if (CreateNew) { + // + // Insert new entry before old entry + // + Status = mIpSecConfig->SetData ( + mIpSecConfig, + Context->DataType, + Context->Selector, + Data, + Selector + ); + ASSERT_EFI_ERROR (Status); + // + // Delete old entry + // + Status = mIpSecConfig->SetData ( + mIpSecConfig, + Context->DataType, + Selector, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + } else { + Status = mIpSecConfig->SetData ( + mIpSecConfig, + Context->DataType, + Context->Selector, + Data, + NULL + ); + } + } + + Context->Status = Status; + return EFI_ABORTED; + } + + return EFI_SUCCESS; +} + +/** + Edit entry information in database according to datatype. + + @param[in] DataType The value of EFI_IPSEC_CONFIG_DATA_TYPE. + @param[in] ParamPackage The pointer to the ParamPackage list. + + @retval EFI_SUCCESS Edit entry information successfully. + @retval EFI_NOT_FOUND Can't find the specified entry. + @retval Others Some mistaken case. +**/ +EFI_STATUS +EditPolicyEntry ( + IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, + IN LIST_ENTRY *ParamPackage + ) +{ + EFI_STATUS Status; + EDIT_POLICY_ENTRY_CONTEXT Context; + CONST CHAR16 *ValueStr; + + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-e"); + if (ValueStr == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INDEX_NOT_SPECIFIED), mHiiHandle, mAppName, ValueStr); + return EFI_NOT_FOUND; + } + + Status = mConstructPolicyEntryIndexer[DataType] (&Context.Indexer, ParamPackage); + if (!EFI_ERROR (Status)) { + Context.DataType = DataType; + Context.Status = EFI_NOT_FOUND; + Status = mCreatePolicyEntry[DataType] (&Context.Selector, &Context.Data, ParamPackage, &Context.Mask, FALSE); + if (!EFI_ERROR (Status)) { + ForeachPolicyEntry (DataType, (VISIT_POLICY_ENTRY) EditOperatePolicyEntry, &Context); + Status = Context.Status; + } + + if (Context.Selector != NULL) { + gBS->FreePool (Context.Selector); + } + + if (Context.Data != NULL) { + gBS->FreePool (Context.Data); + } + } + + if (Status == EFI_NOT_FOUND) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INDEX_NOT_FOUND), mHiiHandle, mAppName, ValueStr); + } else if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_EDIT_FAILED), mHiiHandle, mAppName); + } + + return Status; + +} + +/** + Insert entry information in database. + + @param[in] Selector The pointer to the EFI_IPSEC_CONFIG_SELECTOR structure. + @param[in] Data The pointer to the data. + @param[in] Context The pointer to the INSERT_POLICY_ENTRY_CONTEXT structure. + + @retval EFI_SUCCESS Continue the iteration. + @retval EFI_ABORTED Abort the iteration. +**/ +EFI_STATUS +InsertPolicyEntry ( + IN EFI_IPSEC_CONFIG_SELECTOR *Selector, + IN VOID *Data, + IN INSERT_POLICY_ENTRY_CONTEXT *Context + ) +{ + // + // Found the entry which we want to insert before. + // + if (mMatchPolicyEntry[Context->DataType] (Selector, Data, &Context->Indexer)) { + + Context->Status = mIpSecConfig->SetData ( + mIpSecConfig, + Context->DataType, + Context->Selector, + Context->Data, + Selector + ); + // + // Abort the iteration after the insertion. + // + return EFI_ABORTED; + } + + return EFI_SUCCESS; +} + +/** + Insert or add entry information in database according to datatype. + + @param[in] DataType The value of EFI_IPSEC_CONFIG_DATA_TYPE. + @param[in] ParamPackage The pointer to the ParamPackage list. + + @retval EFI_SUCCESS Insert or add entry information successfully. + @retval EFI_NOT_FOUND Can't find the specified entry. + @retval EFI_BUFFER_TOO_SMALL The entry already existed. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval Others Some mistaken case. +**/ +EFI_STATUS +AddOrInsertPolicyEntry ( + IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, + IN LIST_ENTRY *ParamPackage + ) +{ + EFI_STATUS Status; + EFI_IPSEC_CONFIG_SELECTOR *Selector; + VOID *Data; + INSERT_POLICY_ENTRY_CONTEXT Context; + UINT32 Mask; + UINTN DataSize; + CONST CHAR16 *ValueStr; + + Status = mCreatePolicyEntry[DataType] (&Selector, &Data, ParamPackage, &Mask, TRUE); + if (!EFI_ERROR (Status)) { + // + // Find if the Selector to be inserted already exists. + // + DataSize = 0; + Status = mIpSecConfig->GetData ( + mIpSecConfig, + DataType, + Selector, + &DataSize, + NULL + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_ALREADY_EXISTS), mHiiHandle, mAppName); + } else if (ShellCommandLineGetFlag (ParamPackage, L"-a")) { + Status = mIpSecConfig->SetData ( + mIpSecConfig, + DataType, + Selector, + Data, + NULL + ); + } else { + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-i"); + if (ValueStr == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INDEX_NOT_SPECIFIED), mHiiHandle, mAppName, ValueStr); + return EFI_NOT_FOUND; + } + + Status = mConstructPolicyEntryIndexer[DataType] (&Context.Indexer, ParamPackage); + if (!EFI_ERROR (Status)) { + Context.DataType = DataType; + Context.Status = EFI_NOT_FOUND; + Context.Selector = Selector; + Context.Data = Data; + + ForeachPolicyEntry (DataType, (VISIT_POLICY_ENTRY) InsertPolicyEntry, &Context); + Status = Context.Status; + if (Status == EFI_NOT_FOUND) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INDEX_NOT_FOUND), mHiiHandle, mAppName, ValueStr); + } + } + } + + gBS->FreePool (Selector); + gBS->FreePool (Data); + } + + if (Status == EFI_UNSUPPORTED) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INSERT_UNSUPPORT), mHiiHandle, mAppName); + } else if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INSERT_FAILED), mHiiHandle, mAppName); + } + + return Status; +} diff --git a/NetworkPkg/Application/IpsecConfig/PolicyEntryOperation.h b/NetworkPkg/Application/IpsecConfig/PolicyEntryOperation.h new file mode 100644 index 0000000000..5161bacccb --- /dev/null +++ b/NetworkPkg/Application/IpsecConfig/PolicyEntryOperation.h @@ -0,0 +1,158 @@ +/** @file + The function declaration of policy entry operation in IpSecConfig application. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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. + +**/ + +#ifndef _POLICY_ENTRY_OPERATION_H_ +#define _POLICY_ENTRY_OPERATION_H_ + +#define LOCAL BIT(0) +#define REMOTE BIT(1) +#define PROTO BIT(2) +#define LOCAL_PORT BIT(3) +#define REMOTE_PORT BIT(4) +#define ICMP_TYPE BIT(5) +#define ICMP_CODE BIT(6) +#define NAME BIT(7) +#define PACKET_FLAG BIT(8) +#define ACTION BIT(9) +#define EXT_SEQUENCE BIT(10) +#define SEQUENCE_OVERFLOW BIT(11) +#define FRAGMENT_CHECK BIT(12) +#define LIFEBYTE BIT(13) +#define LIFETIME_SOFT BIT(14) +#define LIFETIME BIT(15) +#define MODE BIT(16) +#define TUNNEL_LOCAL BIT(17) +#define TUNNEL_REMOTE BIT(18) +#define DONT_FRAGMENT BIT(19) +#define IPSEC_PROTO BIT(20) +#define AUTH_ALGO BIT(21) +#define ENCRYPT_ALGO BIT(22) +#define SPI BIT(23) +#define DEST BIT(24) +#define SEQUENCE_NUMBER BIT(25) +#define ANTIREPLAY_WINDOW BIT(26) +#define AUTH_KEY BIT(27) +#define ENCRYPT_KEY BIT(28) +#define PATH_MTU BIT(29) + +#define PEER_ID BIT(0) +#define PEER_ADDRESS BIT(1) +#define AUTH_PROTO BIT(2) +#define AUTH_METHOD BIT(3) +#define IKE_ID BIT(4) +#define AUTH_DATA BIT(5) +#define REVOCATION_DATA BIT(6) + +typedef struct { + EFI_IPSEC_CONFIG_DATA_TYPE DataType; + EFI_IPSEC_CONFIG_SELECTOR *Selector; // Data to be inserted. + VOID *Data; + UINT32 Mask; + POLICY_ENTRY_INDEXER Indexer; + EFI_STATUS Status; // Indicate whether insertion succeeds. +} EDIT_POLICY_ENTRY_CONTEXT; + +typedef struct { + EFI_IPSEC_CONFIG_DATA_TYPE DataType; + EFI_IPSEC_CONFIG_SELECTOR *Selector; // Data to be inserted. + VOID *Data; + POLICY_ENTRY_INDEXER Indexer; + EFI_STATUS Status; // Indicate whether insertion succeeds. +} INSERT_POLICY_ENTRY_CONTEXT; + +/** + The prototype for the CreateSpdEntry()/CreateSadEntry()/CreatePadEntry(). + Fill in EFI_IPSEC_CONFIG_SELECTOR and corresponding data thru ParamPackage list. + + @param[out] Selector The pointer to the EFI_IPSEC_CONFIG_SELECTOR union. + @param[out] Data The pointer to corresponding data. + @param[in] ParamPackage The pointer to the ParamPackage list. + @param[out] Mask The pointer to the Mask. + @param[in] CreateNew The switch to create new. + + @retval EFI_SUCCESS Filled in EFI_IPSEC_CONFIG_SELECTOR and corresponding data successfully. + @retval EFI_INVALID_PARAMETER Invalid user input parameter. + +**/ +typedef +EFI_STATUS +(*CREATE_POLICY_ENTRY) ( + OUT EFI_IPSEC_CONFIG_SELECTOR **Selector, + OUT VOID **Data, + IN LIST_ENTRY *ParamPackage, + OUT UINT32 *Mask, + IN BOOLEAN CreateNew + ); + +/** + The prototype for the CombineSpdEntry()/CombineSadEntry()/CombinePadEntry(). + Combine old SPD/SAD/PAD entry with new SPD/SAD/PAD entry. + + @param[in, out] OldSelector The pointer to the old EFI_IPSEC_CONFIG_SELECTOR union. + @param[in, out] OldData The pointer to the corresponding old data. + @param[in] NewSelector The pointer to the new EFI_IPSEC_CONFIG_SELECTOR union. + @param[in] NewData The pointer to the corresponding new data. + @param[in] Mask The pointer to the Mask. + @param[out] CreateNew The switch to create new. + + @retval EFI_SUCCESS Combined successfully. + @retval EFI_INVALID_PARAMETER Invalid user input parameter. + +**/ +typedef +EFI_STATUS +(* COMBINE_POLICY_ENTRY) ( + EFI_IPSEC_CONFIG_SELECTOR *OldSelector, + VOID *OldData, + EFI_IPSEC_CONFIG_SELECTOR *NewSelector, + VOID *NewData, + UINT32 Mask, + BOOLEAN *CreateNew + ); + +/** + Insert or add entry information in database according to datatype. + + @param[in] DataType The value of EFI_IPSEC_CONFIG_DATA_TYPE. + @param[in] ParamPackage The pointer to the ParamPackage list. + + @retval EFI_SUCCESS Insert or add entry information successfully. + @retval EFI_NOT_FOUND Can't find the specified entry. + @retval EFI_BUFFER_TOO_SMALL The entry already existed. + @retval EFI_UNSUPPORTED The operation is not supported./ + @retval Others Some mistaken case. +**/ +EFI_STATUS +AddOrInsertPolicyEntry ( + IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, + IN LIST_ENTRY *ParamPackage + ); + +/** + Edit entry information in the database according to datatype. + + @param[in] DataType The value of EFI_IPSEC_CONFIG_DATA_TYPE. + @param[in] ParamPackage The pointer to the ParamPackage list. + + @retval EFI_SUCCESS Edit entry information successfully. + @retval EFI_NOT_FOUND Can't find the specified entry. + @retval Others Some mistaken case. +**/ +EFI_STATUS +EditPolicyEntry ( + IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, + IN LIST_ENTRY *ParamPackage + ); +#endif diff --git a/NetworkPkg/Application/Ping6/Ia32/Tsc.c b/NetworkPkg/Application/Ping6/Ia32/Tsc.c new file mode 100644 index 0000000000..e2eae99077 --- /dev/null +++ b/NetworkPkg/Application/Ping6/Ia32/Tsc.c @@ -0,0 +1,28 @@ +/** @file + The implement to read TSC in IA32 platform. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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 + +/** + Reads and returns the current value of the Time Stamp Counter (TSC). + + @return The current value of TSC. + +**/ +UINT64 +ReadTime () +{ + return AsmReadTsc (); +} diff --git a/NetworkPkg/Application/Ping6/Ipf/Itc.c b/NetworkPkg/Application/Ping6/Ipf/Itc.c new file mode 100644 index 0000000000..131e5c0e30 --- /dev/null +++ b/NetworkPkg/Application/Ping6/Ipf/Itc.c @@ -0,0 +1,28 @@ +/** @file + The implement to read ITC in IA64 platform. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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 + +/** + Reads and returns the current value of the Interval Timer Counter Register (ITC). + + @return The current value of ITC. + +**/ +UINT64 +ReadTime () +{ + return AsmReadItc (); +} diff --git a/NetworkPkg/Application/Ping6/Ping6.c b/NetworkPkg/Application/Ping6/Ping6.c new file mode 100644 index 0000000000..b783c5a027 --- /dev/null +++ b/NetworkPkg/Application/Ping6/Ping6.c @@ -0,0 +1,1179 @@ +/** @file + The implementation for Ping6 application. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "Ping6.h" + +SHELL_PARAM_ITEM Ping6ParamList[] = { + { + L"-l", + TypeValue + }, + { + L"-n", + TypeValue + }, + { + L"-s", + TypeValue + }, + { + L"-?", + TypeFlag + }, + { + NULL, + TypeMax + }, +}; + +// +// Global Variables in Ping6 application. +// +EFI_HII_HANDLE mHiiHandle; +CONST CHAR16 *mIp6DstString; +CONST CHAR16 *mIp6SrcString; +EFI_GUID mEfiPing6Guid = EFI_PING6_GUID; +UINT32 mFrequency = 0; +/** + Get and caculate the frequency in tick/ms. + The result is saved in the globle variable mFrequency + + @retval EFI_SUCCESS Caculated the frequency successfully. + @retval Others Failed to caculate the frequency. + +**/ +EFI_STATUS +Ping6GetFrequency ( + VOID + ) +{ + EFI_STATUS Status; + EFI_CPU_ARCH_PROTOCOL *Cpu; + UINT64 CurrentTick; + UINT32 TimerPeriod; + + Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &Cpu); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = Cpu->GetTimerValue (Cpu, 0, &CurrentTick, (UINT64 *) &TimerPeriod); + + if (EFI_ERROR (Status)) { + // + // For NT32 Simulator only. 358049 is a similar value to keep timer granularity. + // Set the timer period by ourselves. + // + TimerPeriod = NTTIMERPERIOD; + } + // + // The timer period is in femtosecond (1 femtosecond is 1e-15 second). + // So 1e+12 is divided by timer period to produce the freq in tick/ms. + // + mFrequency = (UINT32) DivU64x32 (1000000000000ULL, TimerPeriod); + + return EFI_SUCCESS; +} + +/** + Get and caculate the duration in ms. + + @param[in] Begin The start point of time. + @param[in] End The end point of time. + + @return The duration in ms. + +**/ +UINT32 +Ping6CalculateTick ( + IN UINT64 Begin, + IN UINT64 End + ) +{ + ASSERT (End > Begin); + return (UINT32) DivU64x32 (End - Begin, mFrequency); +} + +/** + Destroy IPING6_ICMP6_TX_INFO, and recollect the memory. + + @param[in] TxInfo The pointer to PING6_ICMP6_TX_INFO. + +**/ +VOID +Ping6DestroyTxInfo ( + IN PING6_ICMP6_TX_INFO *TxInfo + ) +{ + EFI_IP6_TRANSMIT_DATA *TxData; + EFI_IP6_FRAGMENT_DATA *FragData; + UINTN Index; + + ASSERT (TxInfo != NULL); + + if (TxInfo->Token != NULL) { + + if (TxInfo->Token->Event != NULL) { + gBS->CloseEvent (TxInfo->Token->Event); + } + + TxData = TxInfo->Token->Packet.TxData; + if (TxData != NULL) { + + if (TxData->OverrideData != NULL) { + FreePool (TxData->OverrideData); + } + + if (TxData->ExtHdrs != NULL) { + FreePool (TxData->ExtHdrs); + } + + for (Index = 0; Index < TxData->FragmentCount; Index++) { + FragData = TxData->FragmentTable[Index].FragmentBuffer; + if (FragData != NULL) { + FreePool (FragData); + } + } + } + + FreePool (TxInfo->Token); + } + + FreePool (TxInfo); +} + +/** + Match the request, and reply with SequenceNum/TimeStamp. + + @param[in] Private The pointer to PING6_PRIVATE_DATA. + @param[in] Packet The pointer to ICMP6_ECHO_REQUEST_REPLY. + + @retval EFI_SUCCESS The match is successful. + @retval EFI_NOT_FOUND The reply can't be matched with any request. + +**/ +EFI_STATUS +Ping6MatchEchoReply ( + IN PING6_PRIVATE_DATA *Private, + IN ICMP6_ECHO_REQUEST_REPLY *Packet + ) +{ + PING6_ICMP6_TX_INFO *TxInfo; + LIST_ENTRY *Entry; + LIST_ENTRY *NextEntry; + + NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) { + TxInfo = BASE_CR (Entry, PING6_ICMP6_TX_INFO, Link); + + if ((TxInfo->SequenceNum == Packet->SequenceNum) && (TxInfo->TimeStamp == Packet->TimeStamp)) { + Private->RxCount++; + RemoveEntryList (&TxInfo->Link); + Ping6DestroyTxInfo (TxInfo); + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +/** + The original intention is to send a request. + Currently, the application retransmits an icmp6 echo request packet + per second in sendnumber times that is specified by the user. + Because nothing can be done here, all things move to the timer rountine. + + @param[in] Event A EFI_EVENT type event. + @param[in] Context The pointer to Context. + +**/ +VOID +EFIAPI +Ping6OnEchoRequestSent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ +} + +/** + receive reply, match and print reply infomation. + + @param[in] Event A EFI_EVENT type event. + @param[in] Context The pointer to context. + +**/ +VOID +EFIAPI +Ping6OnEchoReplyReceived ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + PING6_PRIVATE_DATA *Private; + EFI_IP6_COMPLETION_TOKEN *RxToken; + EFI_IP6_RECEIVE_DATA *RxData; + ICMP6_ECHO_REQUEST_REPLY *Reply; + UINT32 PayLoad; + UINT32 Rtt; + CHAR8 Near; + + Private = (PING6_PRIVATE_DATA *) Context; + + if (Private->Status == EFI_ABORTED) { + return; + } + + RxToken = &Private->RxToken; + RxData = RxToken->Packet.RxData; + Reply = RxData->FragmentTable[0].FragmentBuffer; + PayLoad = RxData->DataLength; + + if (RxData->Header->NextHeader != IP6_ICMP) { + goto ON_EXIT; + } + + if (!IP6_IS_MULTICAST (&Private->DstAddress) && + !EFI_IP6_EQUAL (&RxData->Header->SourceAddress, &Private->DstAddress)) { + goto ON_EXIT; + } + + if ((Reply->Type != ICMP_V6_ECHO_REPLY) || (Reply->Code != 0)) { + goto ON_EXIT; + } + + if (PayLoad != Private->BufferSize) { + goto ON_EXIT; + } + // + // Check whether the reply matches the sent request before. + // + Status = Ping6MatchEchoReply (Private, Reply); + if (EFI_ERROR(Status)) { + goto ON_EXIT; + } + // + // Display statistics on this icmp6 echo reply packet. + // + Rtt = Ping6CalculateTick (Reply->TimeStamp, ReadTime ()); + if (Rtt != 0) { + Near = (CHAR8) '='; + } else { + Near = (CHAR8) '<'; + } + + Private->RttSum += Rtt; + Private->RttMin = Private->RttMin > Rtt ? Rtt : Private->RttMin; + Private->RttMax = Private->RttMax < Rtt ? Rtt : Private->RttMax; + + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_PING6_REPLY_INFO), + mHiiHandle, + PayLoad, + mIp6DstString, + Reply->SequenceNum, + RxData->Header->HopLimit, + Near, + Rtt + ); + +ON_EXIT: + + if (Private->RxCount < Private->SendNum) { + // + // Continue to receive icmp6 echo reply packets. + // + RxToken->Status = EFI_ABORTED; + + Status = Private->Ip6->Receive (Private->Ip6, RxToken); + + if (EFI_ERROR (Status)) { + Private->Status = EFI_ABORTED; + } + } else { + // + // All reply have already been received from the dest host. + // + Private->Status = EFI_SUCCESS; + } + // + // Singal to recycle the each rxdata here, not at the end of process. + // + gBS->SignalEvent (RxData->RecycleSignal); +} + +/** + Initial EFI_IP6_COMPLETION_TOKEN. + + @param[in] Private The pointer of PING6_PRIVATE_DATA. + @param[in] TimeStamp The TimeStamp of request. + @param[in] SequenceNum The SequenceNum of request. + + @return The pointer of EFI_IP6_COMPLETION_TOKEN. + +**/ +EFI_IP6_COMPLETION_TOKEN * +Ping6GenerateToken ( + IN PING6_PRIVATE_DATA *Private, + IN UINT64 TimeStamp, + IN UINT16 SequenceNum + ) +{ + EFI_STATUS Status; + EFI_IP6_COMPLETION_TOKEN *Token; + EFI_IP6_TRANSMIT_DATA *TxData; + ICMP6_ECHO_REQUEST_REPLY *Request; + + Request = AllocateZeroPool (Private->BufferSize); + + if (Request == NULL) { + return NULL; + } + // + // Assembly icmp6 echo request packet. + // + Request->Type = ICMP_V6_ECHO_REQUEST; + Request->Code = 0; + Request->SequenceNum = SequenceNum; + Request->TimeStamp = TimeStamp; + Request->Identifier = 0; + // + // Leave check sum to ip6 layer, since it has no idea of source address + // selection. + // + Request->Checksum = 0; + + TxData = AllocateZeroPool (sizeof (EFI_IP6_TRANSMIT_DATA)); + + if (TxData == NULL) { + FreePool (Request); + return NULL; + } + // + // Assembly ipv6 token for transmit. + // + TxData->OverrideData = 0; + TxData->ExtHdrsLength = 0; + TxData->ExtHdrs = NULL; + TxData->DataLength = Private->BufferSize; + TxData->FragmentCount = 1; + TxData->FragmentTable[0].FragmentBuffer = (VOID *) Request; + TxData->FragmentTable[0].FragmentLength = Private->BufferSize; + + Token = AllocateZeroPool (sizeof (EFI_IP6_COMPLETION_TOKEN)); + + if (Token == NULL) { + FreePool (Request); + FreePool (TxData); + return NULL; + } + + Token->Status = EFI_ABORTED; + Token->Packet.TxData = TxData; + + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + Ping6OnEchoRequestSent, + Private, + &Token->Event + ); + + if (EFI_ERROR (Status)) { + FreePool (Request); + FreePool (TxData); + FreePool (Token); + return NULL; + } + + return Token; +} + +/** + Transmit the EFI_IP6_COMPLETION_TOKEN. + + @param[in] Private The pointer of PING6_PRIVATE_DATA. + + @retval EFI_SUCCESS Transmitted successfully. + @retval EFI_OUT_OF_RESOURCES No memory is available on the platform. + @retval others Transmitted unsuccessfully. + +**/ +EFI_STATUS +Ping6SendEchoRequest ( + IN PING6_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + PING6_ICMP6_TX_INFO *TxInfo; + + TxInfo = AllocateZeroPool (sizeof (PING6_ICMP6_TX_INFO)); + + if (TxInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + TxInfo->TimeStamp = ReadTime (); + TxInfo->SequenceNum = (UINT16) (Private->TxCount + 1); + + TxInfo->Token = Ping6GenerateToken ( + Private, + TxInfo->TimeStamp, + TxInfo->SequenceNum + ); + + if (TxInfo->Token == NULL) { + Ping6DestroyTxInfo (TxInfo); + return EFI_OUT_OF_RESOURCES; + } + + Status = Private->Ip6->Transmit (Private->Ip6, TxInfo->Token); + + if (EFI_ERROR (Status)) { + Ping6DestroyTxInfo (TxInfo); + return Status; + } + + InsertTailList (&Private->TxList, &TxInfo->Link); + Private->TxCount++; + + return EFI_SUCCESS; +} + +/** + Place a completion token into the receive packet queue to receive the echo reply. + + @param[in] Private The pointer of PING6_PRIVATE_DATA. + + @retval EFI_SUCCESS Put the token into the receive packet queue successfully. + @retval others Put the token into the receive packet queue unsuccessfully. + +**/ +EFI_STATUS +Ping6ReceiveEchoReply ( + IN PING6_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + + ZeroMem (&Private->RxToken, sizeof (EFI_IP6_COMPLETION_TOKEN)); + + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + Ping6OnEchoReplyReceived, + Private, + &Private->RxToken.Event + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Private->RxToken.Status = EFI_NOT_READY; + + return Private->Ip6->Receive (Private->Ip6, &Private->RxToken); +} + +/** + Remove the timeout request from the list. + + @param[in] Event A EFI_EVENT type event. + @param[in] Context The pointer to Context. + +**/ +VOID +EFIAPI +Ping6OnTimerRoutine ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + PING6_PRIVATE_DATA *Private; + PING6_ICMP6_TX_INFO *TxInfo; + LIST_ENTRY *Entry; + LIST_ENTRY *NextEntry; + UINT32 Time; + + Private = (PING6_PRIVATE_DATA *) Context; + + // + // Retransmit icmp6 echo request packets per second in sendnumber times. + // + if (Private->TxCount < Private->SendNum) { + + Status = Ping6SendEchoRequest (Private); + if (Private->TxCount != 0){ + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_SEND_REQUEST), mHiiHandle, Private->TxCount + 1); + } + } + } + // + // Check whether any icmp6 echo request in the list timeout. + // + NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) { + TxInfo = BASE_CR (Entry, PING6_ICMP6_TX_INFO, Link); + Time = Ping6CalculateTick (TxInfo->TimeStamp, ReadTime ()); + + // + // Remove the timeout echo request from txlist. + // + if (Time > PING6_DEFAULT_TIMEOUT) { + + if (EFI_ERROR (TxInfo->Token->Status)) { + Private->Ip6->Cancel (Private->Ip6, TxInfo->Token); + } + // + // Remove the timeout icmp6 echo request from list. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_TIMEOUT), mHiiHandle, TxInfo->SequenceNum); + + RemoveEntryList (&TxInfo->Link); + Ping6DestroyTxInfo (TxInfo); + + if (IsListEmpty (&Private->TxList) && (Private->TxCount == Private->SendNum)) { + // + // All the left icmp6 echo request in the list timeout. + // + Private->Status = EFI_TIMEOUT; + } + } + } +} + +/** + Create a valid IP6 instance. + + @param[in] Private The pointer of PING6_PRIVATE_DATA. + + @retval EFI_SUCCESS Create a valid IP6 instance successfully. + @retval EFI_ABORTED Locate handle with ip6 service binding protocol unsuccessfully. + @retval EFI_INVALID_PARAMETER The source address is unspecified when the destination address is a link -ocal address. + @retval EFI_OUT_OF_RESOURCES No memory is available on the platform. + @retval EFI_NOT_FOUND The source address is not found. +**/ +EFI_STATUS +Ping6CreateIp6Instance ( + IN PING6_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + UINTN HandleIndex; + UINTN HandleNum; + EFI_HANDLE *HandleBuffer; + EFI_SERVICE_BINDING_PROTOCOL *Ip6Sb; + EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg; + EFI_IP6_CONFIG_DATA Ip6Config; + EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo; + UINTN IfInfoSize; + EFI_IPv6_ADDRESS *Addr; + UINTN AddrIndex; + + HandleBuffer = NULL; + Ip6Sb = NULL; + IfInfo = NULL; + IfInfoSize = 0; + + // + // Locate all the handles with ip6 service binding protocol. + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiIp6ServiceBindingProtocolGuid, + NULL, + &HandleNum, + &HandleBuffer + ); + if (EFI_ERROR (Status) || (HandleNum == 0)) { + return EFI_ABORTED; + } + // + // Source address is required when pinging a link-local address on multi- + // interfaces host. + // + if (NetIp6IsLinkLocalAddr (&Private->DstAddress) && + NetIp6IsUnspecifiedAddr (&Private->SrcAddress) && + (HandleNum > 1)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_SOURCE), mHiiHandle); + Status = EFI_INVALID_PARAMETER; + goto ON_ERROR; + } + // + // For each ip6 protocol, check interface addresses list. + // + for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) { + + Ip6Sb = NULL; + IfInfo = NULL; + IfInfoSize = 0; + + Status = gBS->HandleProtocol ( + HandleBuffer[HandleIndex], + &gEfiIp6ServiceBindingProtocolGuid, + (VOID **) &Ip6Sb + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + if (NetIp6IsUnspecifiedAddr (&Private->SrcAddress)) { + // + // No need to match interface address. + // + break; + } else { + // + // Ip6config protocol and ip6 service binding protocol are installed + // on the same handle. + // + 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, + &IfInfoSize, + NULL + ); + + if (Status != EFI_BUFFER_TOO_SMALL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), mHiiHandle, Status); + goto ON_ERROR; + } + + IfInfo = AllocateZeroPool (IfInfoSize); + + if (IfInfo == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_ERROR; + } + // + // Get the interface info. + // + Status = Ip6Cfg->GetData ( + Ip6Cfg, + Ip6ConfigDataTypeInterfaceInfo, + &IfInfoSize, + IfInfo + ); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), mHiiHandle, Status); + goto ON_ERROR; + } + // + // Check whether the source address is one of the interface addresses. + // + for (AddrIndex = 0; AddrIndex < IfInfo->AddressInfoCount; AddrIndex++) { + + Addr = &(IfInfo->AddressInfo[AddrIndex].Address); + if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) { + // + // Match a certain interface address. + // + break; + } + } + + if (AddrIndex < IfInfo->AddressInfoCount) { + // + // Found a nic handle with right interface address. + // + break; + } + } + + FreePool (IfInfo); + IfInfo = NULL; + } + // + // No exact interface address matched. + // + + if (HandleIndex == HandleNum) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_SOURCE_NOT_FOUND), mHiiHandle, mIp6SrcString); + Status = EFI_NOT_FOUND; + goto ON_ERROR; + } + + Private->NicHandle = HandleBuffer[HandleIndex]; + + ASSERT (Ip6Sb != NULL); + Status = Ip6Sb->CreateChild (Ip6Sb, &Private->Ip6ChildHandle); + + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + Status = gBS->OpenProtocol ( + Private->Ip6ChildHandle, + &gEfiIp6ProtocolGuid, + (VOID **) &Private->Ip6, + Private->ImageHandle, + Private->Ip6ChildHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + ZeroMem (&Ip6Config, sizeof (EFI_IP6_CONFIG_DATA)); + + // + // Configure the ip6 instance for icmp6 packet exchange. + // + Ip6Config.DefaultProtocol = 58; + Ip6Config.AcceptAnyProtocol = FALSE; + Ip6Config.AcceptIcmpErrors = TRUE; + Ip6Config.AcceptPromiscuous = FALSE; + Ip6Config.TrafficClass = 0; + Ip6Config.HopLimit = 128; + Ip6Config.FlowLabel = 0; + Ip6Config.ReceiveTimeout = 0; + Ip6Config.TransmitTimeout = 0; + + IP6_COPY_ADDRESS (&Ip6Config.StationAddress, &Private->SrcAddress); + + IP6_COPY_ADDRESS (&Ip6Config.DestinationAddress, &Private->DstAddress); + + Status = Private->Ip6->Configure (Private->Ip6, &Ip6Config); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6_CONFIG), mHiiHandle, Status); + goto ON_ERROR; + } + + return EFI_SUCCESS; + +ON_ERROR: + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + if (IfInfo != NULL) { + FreePool (IfInfo); + } + + if ((Ip6Sb != NULL) && (Private->Ip6ChildHandle != NULL)) { + Ip6Sb->DestroyChild (Ip6Sb, Private->Ip6ChildHandle); + } + + return Status; +} + +/** + Destory the IP6 instance. + + @param[in] Private The pointer of PING6_PRIVATE_DATA. + +**/ +VOID +Ping6DestoryIp6Instance ( + IN PING6_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + EFI_SERVICE_BINDING_PROTOCOL *Ip6Sb; + + gBS->CloseProtocol ( + Private->Ip6ChildHandle, + &gEfiIp6ProtocolGuid, + Private->ImageHandle, + Private->Ip6ChildHandle + ); + + Status = gBS->HandleProtocol ( + Private->NicHandle, + &gEfiIp6ServiceBindingProtocolGuid, + (VOID **) &Ip6Sb + ); + + if (!EFI_ERROR(Status)) { + Ip6Sb->DestroyChild (Ip6Sb, Private->Ip6ChildHandle); + } +} + +/** + The Ping6 Process. + + @param[in] ImageHandle The firmware allocated handle for the UEFI image. + @param[in] SendNumber The send request count. + @param[in] BufferSize The send buffer size. + @param[in] SrcAddress The source IPv6 address. + @param[in] DstAddress The destination IPv6 address. + + @retval EFI_SUCCESS The ping6 processed successfullly. + @retval others The ping6 processed unsuccessfully. + +**/ +EFI_STATUS +Ping6 ( + IN EFI_HANDLE ImageHandle, + IN UINT32 SendNumber, + IN UINT32 BufferSize, + IN EFI_IPv6_ADDRESS *SrcAddress, + IN EFI_IPv6_ADDRESS *DstAddress + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + PING6_PRIVATE_DATA *Private; + PING6_ICMP6_TX_INFO *TxInfo; + LIST_ENTRY *Entry; + LIST_ENTRY *NextEntry; + + Private = AllocateZeroPool (sizeof (PING6_PRIVATE_DATA)); + + ASSERT (Private != NULL); + + Private->ImageHandle = ImageHandle; + Private->SendNum = SendNumber; + Private->BufferSize = BufferSize; + Private->RttMin = 0xFFFF; + Private->Status = EFI_NOT_READY; + + InitializeListHead (&Private->TxList); + + IP6_COPY_ADDRESS (&Private->SrcAddress, SrcAddress); + IP6_COPY_ADDRESS (&Private->DstAddress, DstAddress); + + // + // Open and configure a ip6 instance for ping6. + // + Status = Ping6CreateIp6Instance (Private); + + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + // + // Print the command line itself. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_START), mHiiHandle, mIp6DstString, Private->BufferSize); + // + // Create a ipv6 token to receive the first icmp6 echo reply packet. + // + Status = Ping6ReceiveEchoReply (Private); + + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + // + // Create and start timer to send icmp6 echo request packet per second. + // + Status = gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + Ping6OnTimerRoutine, + Private, + &Private->Timer + ); + + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + // + // Create a ipv6 token to send the first icmp6 echo request packet. + // + Status = Ping6SendEchoRequest (Private); + // + // EFI_NOT_READY for IPsec is enable and IKE is not established. + // + if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) { + if(Status == EFI_NOT_FOUND) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_NOSOURCE_INDOMAIN), mHiiHandle, mIp6DstString); + } + + goto ON_EXIT; + } + + Status = gBS->SetTimer ( + Private->Timer, + TimerPeriodic, + PING6_ONE_SECOND + ); + + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + // + // Control the ping6 process by two factors: + // 1. Hot key + // 2. Private->Status + // 2.1. success means all icmp6 echo request packets get reply packets. + // 2.2. timeout means the last icmp6 echo reply request timeout to get reply. + // 2.3. noready means ping6 process is on-the-go. + // + while (Private->Status == EFI_NOT_READY) { + Private->Ip6->Poll (Private->Ip6); + + // + // Terminate the ping6 process by 'esc' or 'ctl-c'. + // + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + + if (!EFI_ERROR(Status)) { + if ((Key.UnicodeChar == 0x1b) || (Key.UnicodeChar == 0x03) || + ((Key.UnicodeChar == 0) && (Key.ScanCode == SCAN_ESC))) { + goto ON_STAT; + } + } + } + +ON_STAT: + // + // Display the statistics in all. + // + gBS->SetTimer (Private->Timer, TimerCancel, 0); + + if (Private->TxCount != 0) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_PING6_STAT), + mHiiHandle, + Private->TxCount, + Private->RxCount, + (100 * (Private->TxCount - Private->RxCount)) / Private->TxCount, + Private->RttSum + ); + } + + if (Private->RxCount != 0) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_PING6_RTT), + mHiiHandle, + Private->RttMin, + Private->RttMax, + Private->RttSum / Private->RxCount + ); + } + +ON_EXIT: + + if (Private != NULL) { + Private->Status = EFI_ABORTED; + + NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) { + TxInfo = BASE_CR (Entry, PING6_ICMP6_TX_INFO, Link); + + Status = Private->Ip6->Cancel (Private->Ip6, TxInfo->Token); + + RemoveEntryList (&TxInfo->Link); + Ping6DestroyTxInfo (TxInfo); + } + + if (Private->Timer != NULL) { + gBS->CloseEvent (Private->Timer); + } + + if (Private->Ip6 != NULL) { + Status = Private->Ip6->Cancel (Private->Ip6, &Private->RxToken); + } + + if (Private->RxToken.Event != NULL) { + gBS->CloseEvent (Private->RxToken.Event); + } + + if (Private->Ip6ChildHandle != NULL) { + Ping6DestoryIp6Instance (Private); + } + + FreePool (Private); + } + + return Status; +} + +/** + This is the declaration of an EFI image entry point. This entry point is + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including + both device drivers and bus drivers. + + The entry point for the Ping6 application that parses the command line input and calls the Ping6 process. + + @param[in] ImageHandle The firmware allocated handle for the UEFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETETR Input parameters combination is invalid. + @retval Others Some errors occur. + +**/ +EFI_STATUS +EFIAPI +InitializePing6 ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_IPv6_ADDRESS DstAddress; + EFI_IPv6_ADDRESS SrcAddress; + UINT64 BufferSize; + UINTN SendNumber; + LIST_ENTRY *ParamPackage; + CONST CHAR16 *ValueStr; + CONST CHAR16 *ValueStrPtr; + UINTN NonOptionCount; + + // + // Register our string package with HII and return the handle to it. + // + mHiiHandle = HiiAddPackages (&gEfiCallerIdGuid, ImageHandle, Ping6Strings, NULL); + ASSERT (mHiiHandle != NULL); + + Status = ShellCommandLineParseEx (Ping6ParamList, &ParamPackage, NULL, TRUE, FALSE); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_INPUT), mHiiHandle); + goto ON_EXIT; + } + + if (ShellCommandLineGetFlag (ParamPackage, L"-?")) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_HELP), mHiiHandle); + goto ON_EXIT; + } + + SendNumber = 10; + BufferSize = 16; + + // + // Parse the paramter of count number. + // + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-n"); + ValueStrPtr = ValueStr; + if (ValueStr != NULL) { + SendNumber = ShellStrToUintn (ValueStrPtr); + + // + // ShellStrToUintn will return 0 when input is 0 or an invalid input string. + // + if ((SendNumber == 0) || (SendNumber > PING6_MAX_SEND_NUMBER)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_SEND_NUMBER), mHiiHandle, ValueStr); + Status = EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + } + // + // Parse the paramter of buffer size. + // + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l"); + ValueStrPtr = ValueStr; + if (ValueStr != NULL) { + BufferSize = ShellStrToUintn (ValueStrPtr); + + // + // ShellStrToUintn will return 0 when input is 0 or an invalid input string. + // + if ((BufferSize < 16) || (BufferSize > PING6_MAX_BUFFER_SIZE)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_BUFFER_SIZE), mHiiHandle, ValueStr); + Status = EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + } + + ZeroMem (&SrcAddress, sizeof (EFI_IPv6_ADDRESS)); + ZeroMem (&DstAddress, sizeof (EFI_IPv6_ADDRESS)); + + // + // Parse the paramter of source ip address. + // + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s"); + ValueStrPtr = ValueStr; + if (ValueStr != NULL) { + mIp6SrcString = ValueStr; + Status = NetLibStrToIp6 (ValueStrPtr, &SrcAddress); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_IP), mHiiHandle, ValueStr); + Status = EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + } + // + // Parse the paramter of destination ip address. + // + NonOptionCount = ShellCommandLineGetCount(); + ValueStr = ShellCommandLineGetRawValue (ParamPackage, (UINT32)(NonOptionCount-1)); + if (NonOptionCount != 2) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_INPUT), mHiiHandle); + Status = EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + ValueStrPtr = ValueStr; + if (ValueStr != NULL) { + mIp6DstString = ValueStr; + Status = NetLibStrToIp6 (ValueStrPtr, &DstAddress); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_IP), mHiiHandle, ValueStr); + Status = EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + } + // + // Get frequency to calculate the time from ticks. + // + Status = Ping6GetFrequency (); + + if (EFI_ERROR(Status)) { + goto ON_EXIT; + } + // + // Enter into ping6 process. + // + Status = Ping6 ( + ImageHandle, + (UINT32)SendNumber, + (UINT32)BufferSize, + &SrcAddress, + &DstAddress + ); + +ON_EXIT: + ShellCommandLineFreeVarList (ParamPackage); + HiiRemovePackages (mHiiHandle); + return Status; +} diff --git a/NetworkPkg/Application/Ping6/Ping6.h b/NetworkPkg/Application/Ping6/Ping6.h new file mode 100644 index 0000000000..02271e1b58 --- /dev/null +++ b/NetworkPkg/Application/Ping6/Ping6.h @@ -0,0 +1,92 @@ +/** @file + The interface function declaration of shell application Ping6 (Ping for v6 series). + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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. + +**/ + +#ifndef _PING6_H_ +#define _PING6_H_ + +#define EFI_PING6_GUID \ + { \ + 0x3f0b2478, 0x3619, 0x46c5, {0x81, 0x50, 0xa5, 0xab, 0xdd, 0xb6, 0x6b, 0xd9} \ + } + +#define PING6_DEFAULT_TIMEOUT 5000 +#define PING6_MAX_SEND_NUMBER 10000 +#define PING6_MAX_BUFFER_SIZE 32768 +#define PING6_ONE_SECOND 10000000 + +// +// A similar amount of time that passes in femtoseconds +// for each increment of TimerValue. It is for NT32 only. +// +#define NTTIMERPERIOD 358049 + +#pragma pack(1) + +typedef struct _ICMP6_ECHO_REQUEST_REPLY { + UINT8 Type; + UINT8 Code; + UINT16 Checksum; + UINT16 Identifier; + UINT16 SequenceNum; + UINT64 TimeStamp; + UINT8 Data[1]; +} ICMP6_ECHO_REQUEST_REPLY; + +#pragma pack() + +typedef struct _PING6_ICMP6_TX_INFO { + LIST_ENTRY Link; + UINT16 SequenceNum; + UINT64 TimeStamp; + EFI_IP6_COMPLETION_TOKEN *Token; +} PING6_ICMP6_TX_INFO; + +typedef struct _PING6_PRIVATE_DATA { + EFI_HANDLE ImageHandle; + EFI_HANDLE NicHandle; + EFI_HANDLE Ip6ChildHandle; + EFI_IP6_PROTOCOL *Ip6; + EFI_EVENT Timer; + + EFI_STATUS Status; + LIST_ENTRY TxList; + EFI_IP6_COMPLETION_TOKEN RxToken; + UINT16 RxCount; + UINT16 TxCount; + UINT32 RttSum; + UINT32 RttMin; + UINT32 RttMax; + UINT32 SequenceNum; + + EFI_IPv6_ADDRESS SrcAddress; + EFI_IPv6_ADDRESS DstAddress; + UINT32 SendNum; + UINT32 BufferSize; +} PING6_PRIVATE_DATA; + +/** + Reads and returns the current value of register. + In IA64, the register is the Interval Timer Vector (ITV). + In X86(IA32/X64), the register is the Time Stamp Counter (TSC) + + @return The current value of the register. + +**/ +UINT64 +ReadTime ( + VOID + ); + +#endif diff --git a/NetworkPkg/Application/Ping6/Ping6.inf b/NetworkPkg/Application/Ping6/Ping6.inf new file mode 100644 index 0000000000..56b2163ead --- /dev/null +++ b/NetworkPkg/Application/Ping6/Ping6.inf @@ -0,0 +1,64 @@ +## @file +# Component description file for Ping6 application. +# +# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+# +# 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. +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = Ping6 + FILE_GUID = F35F733F-5235-4d7b-83FA-97780CEBCB20 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = InitializePing6 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF +# + +[Sources] + Ping6.c + Ping6Strings.uni + Ping6.h + +[Sources.IA32] + Ia32/Tsc.c + +[Sources.X64] + X64/Tsc.c + +[Sources.IPF] + Ipf/Itc.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ShellPkg/ShellPkg.dec + +[LibraryClasses] + BaseLib + UefiBootServicesTableLib + UefiApplicationEntryPoint + BaseMemoryLib + ShellLib + MemoryAllocationLib + DebugLib + HiiLib + NetLib + +[Protocols] + gEfiCpuArchProtocolGuid ## CONSUMS + gEfiIp6ProtocolGuid ## CONSUMS + gEfiIp6ServiceBindingProtocolGuid ## CONSUMS + gEfiIp6ConfigProtocolGuid ## CONSUMS diff --git a/NetworkPkg/Application/Ping6/Ping6Strings.uni b/NetworkPkg/Application/Ping6/Ping6Strings.uni new file mode 100644 index 0000000000..c8b919c4ce Binary files /dev/null and b/NetworkPkg/Application/Ping6/Ping6Strings.uni differ diff --git a/NetworkPkg/Application/Ping6/X64/Tsc.c b/NetworkPkg/Application/Ping6/X64/Tsc.c new file mode 100644 index 0000000000..b3e7bdbb96 --- /dev/null +++ b/NetworkPkg/Application/Ping6/X64/Tsc.c @@ -0,0 +1,28 @@ +/** @file + The implement to read TSC in X64 platform. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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 + +/** + Reads and returns the current value of Time Stamp Counter (TSC). + + @return The current value of TSC + +**/ +UINT64 +ReadTime () +{ + return AsmReadTsc (); +} diff --git a/NetworkPkg/Application/VConfig/VConfig.c b/NetworkPkg/Application/VConfig/VConfig.c new file mode 100644 index 0000000000..c948131ffc --- /dev/null +++ b/NetworkPkg/Application/VConfig/VConfig.c @@ -0,0 +1,668 @@ +/** @file + Shell application for VLAN configuration. + + Copyright (C) 2009 - 2010, Intel Corporation. All rights reserved.
+ + 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 + +#include + +#include +#include +#include +#include +#include +#include +#include + +#define INVALID_NIC_INDEX 0xffff +#define INVALID_VLAN_ID 0xffff + +// +// This is the generated String package data for all .UNI files. +// This data array is ready to be used as input of HiiAddPackages() to +// create a packagelist (which contains Form packages, String packages, etc). +// +extern UINT8 VConfigStrings[]; + +EFI_HANDLE mImageHandle = NULL; +EFI_HII_HANDLE mHiiHandle = NULL; + +SHELL_PARAM_ITEM mParamList[] = { + { + L"-l", + TypeValue + }, + { + L"-a", + TypeMaxValue + }, + { + L"-d", + TypeValue + }, + { + NULL, + TypeMax + } +}; + +/** + Locate the network interface handle buffer. + + @param[out] NumberOfHandles Pointer to the number of handles. + @param[out] HandleBuffer Pointer to the buffer to store the returned handles. + +**/ +VOID +LocateNicHandleBuffer ( + OUT UINTN *NumberOfHandles, + OUT EFI_HANDLE **HandleBuffer + ) +{ + EFI_STATUS Status; + + *NumberOfHandles = 0; + *HandleBuffer = NULL; + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiVlanConfigProtocolGuid, + NULL, + NumberOfHandles, + HandleBuffer + ); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_LOCATE_FAIL), mHiiHandle, Status); + } +} + +/** + Extract the decimal index from the network interface name. + + @param[in] Name Name of the network interface. + + @retval INVALID_NIC_INDEX Failed to extract the network interface index. + @return others The network interface index. + +**/ +UINTN +NicNameToIndex ( + IN CHAR16 *Name + ) +{ + CHAR16 *Str; + + Str = Name + 3; + if ((StrnCmp (Name, L"eth", 3) != 0) || (*Str == 0)) { + return INVALID_NIC_INDEX; + } + + while (*Str != 0) { + if ((*Str < L'0') || (*Str > L'9')) { + return INVALID_NIC_INDEX; + } + + Str++; + } + + return (UINT16) StrDecimalToUintn (Name + 3); +} + +/** + Find network interface device handle by its name. + + @param[in] Name Name of the network interface. + + @retval NULL Cannot find the network interface. + @return others Handle of the network interface. + +**/ +EFI_HANDLE +NicNameToHandle ( + IN CHAR16 *Name + ) +{ + UINTN NumberOfHandles; + EFI_HANDLE *HandleBuffer; + UINTN Index; + EFI_HANDLE Handle; + + // + // Find all NIC handles. + // + LocateNicHandleBuffer (&NumberOfHandles, &HandleBuffer); + if (NumberOfHandles == 0) { + return NULL; + } + + Index = NicNameToIndex (Name); + if (Index >= NumberOfHandles) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_IF), mHiiHandle, Name); + Handle = NULL; + } else { + Handle = HandleBuffer[Index]; + } + + FreePool (HandleBuffer); + return Handle; +} + +/** + Open VlanConfig protocol from a handle. + + @param[in] Handle The handle to open the VlanConfig protocol. + + @return The VlanConfig protocol interface. + +**/ +EFI_VLAN_CONFIG_PROTOCOL * +OpenVlanConfigProtocol ( + IN EFI_HANDLE Handle + ) +{ + EFI_VLAN_CONFIG_PROTOCOL *VlanConfig; + + VlanConfig = NULL; + gBS->OpenProtocol ( + Handle, + &gEfiVlanConfigProtocolGuid, + (VOID **) &VlanConfig, + mImageHandle, + Handle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + return VlanConfig; +} + +/** + Close VlanConfig protocol of a handle. + + @param[in] Handle The handle to close the VlanConfig protocol. + +**/ +VOID +CloseVlanConfigProtocol ( + IN EFI_HANDLE Handle + ) +{ + gBS->CloseProtocol ( + Handle, + &gEfiVlanConfigProtocolGuid, + mImageHandle, + Handle + ); +} + +/** + Display VLAN configuration of a network interface. + + @param[in] Handle Handle of the network interface. + @param[in] NicIndex Index of the network interface. + +**/ +VOID +ShowNicVlanInfo ( + IN EFI_HANDLE Handle, + IN UINTN NicIndex + ) +{ + CHAR16 *MacStr; + EFI_STATUS Status; + UINTN Index; + EFI_VLAN_CONFIG_PROTOCOL *VlanConfig; + UINT16 NumberOfVlan; + EFI_VLAN_FIND_DATA *VlanData; + + VlanConfig = OpenVlanConfigProtocol (Handle); + if (VlanConfig == NULL) { + return ; + } + + MacStr = NULL; + Status = NetLibGetMacString (Handle, mImageHandle, &MacStr); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_MAC_FAIL), mHiiHandle, Status); + goto Exit; + } + + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_ETH_MAC), mHiiHandle, NicIndex, MacStr); + + Status = VlanConfig->Find (VlanConfig, NULL, &NumberOfVlan, &VlanData); + if (EFI_ERROR (Status)) { + if (Status == EFI_NOT_FOUND) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_VLAN), mHiiHandle); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_FIND_FAIL), mHiiHandle, Status); + } + + goto Exit; + } + + for (Index = 0; Index < NumberOfVlan; Index++) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_VCONFIG_VLAN_DISPLAY), + mHiiHandle, + VlanData[Index].VlanId, + VlanData[Index].Priority + ); + } + + FreePool (VlanData); + +Exit: + CloseVlanConfigProtocol (Handle); + + if (MacStr != NULL) { + FreePool (MacStr); + } +} + +/** + Display the VLAN configuration of all, or a specified network interface. + + @param[in] Name Name of the network interface. If NULL, the VLAN + configuration of all network will be displayed. + +**/ +VOID +DisplayVlan ( + IN CHAR16 *Name OPTIONAL + ) +{ + UINTN NumberOfHandles; + EFI_HANDLE *HandleBuffer; + UINTN Index; + EFI_HANDLE NicHandle; + + if (Name != NULL) { + // + // Display specified NIC + // + NicHandle = NicNameToHandle (Name); + if (NicHandle == NULL) { + return ; + } + + ShowNicVlanInfo (NicHandle, 0); + return ; + } + + // + // Find all NIC handles + // + LocateNicHandleBuffer (&NumberOfHandles, &HandleBuffer); + if (NumberOfHandles == 0) { + return ; + } + + for (Index = 0; Index < NumberOfHandles; Index++) { + ShowNicVlanInfo (HandleBuffer[Index], Index); + } + + FreePool (HandleBuffer); +} + +/** + Convert a NULL-terminated unicode decimal VLAN ID string to VLAN ID. + + @param[in] String Pointer to VLAN ID string from user input. + + @retval Value translated from String, or INVALID_VLAN_ID is string is invalid. + +**/ +UINT16 +StrToVlanId ( + IN CHAR16 *String + ) +{ + CHAR16 *Str; + + if (String == NULL) { + return INVALID_VLAN_ID; + } + + Str = String; + while ((*Str >= '0') && (*Str <= '9')) { + Str++; + } + + if (*Str != 0) { + return INVALID_VLAN_ID; + } + + return (UINT16) StrDecimalToUintn (String); +} + +/** + Add a VLAN device. + + @param[in] ParamStr Parameter string from user input. + +**/ +VOID +AddVlan ( + IN CHAR16 *ParamStr + ) +{ + CHAR16 *Name; + CHAR16 *VlanIdStr; + CHAR16 *PriorityStr; + CHAR16 *StrPtr; + BOOLEAN IsSpace; + UINTN VlanId; + UINTN Priority; + EFI_HANDLE Handle; + EFI_HANDLE VlanHandle; + EFI_VLAN_CONFIG_PROTOCOL *VlanConfig; + EFI_STATUS Status; + + VlanConfig = NULL; + Priority = 0; + + if (ParamStr == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_IF), mHiiHandle); + return ; + } + + StrPtr = AllocateCopyPool (StrSize (ParamStr), ParamStr); + if (StrPtr == NULL) { + return ; + } + + Name = StrPtr; + VlanIdStr = NULL; + PriorityStr = NULL; + IsSpace = FALSE; + while (*StrPtr != 0) { + if (*StrPtr == L' ') { + *StrPtr = 0; + IsSpace = TRUE; + } else { + if (IsSpace) { + // + // Start of a parameter. + // + if (VlanIdStr == NULL) { + // + // 2nd parameter is VLAN ID. + // + VlanIdStr = StrPtr; + } else if (PriorityStr == NULL) { + // + // 3rd parameter is Priority. + // + PriorityStr = StrPtr; + } else { + // + // Ignore else parameters. + // + break; + } + } + + IsSpace = FALSE; + } + + StrPtr++; + } + + Handle = NicNameToHandle (Name); + if (Handle == NULL) { + goto Exit; + } + + VlanConfig = OpenVlanConfigProtocol (Handle); + if (VlanConfig == NULL) { + goto Exit; + } + + // + // Check VLAN ID. + // + if ((VlanIdStr == NULL) || (*VlanIdStr == 0)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_VID), mHiiHandle); + goto Exit; + } + + VlanId = StrToVlanId (VlanIdStr); + if (VlanId > 4094) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_VID), mHiiHandle, VlanIdStr); + goto Exit; + } + + // + // Check Priority. + // + if ((PriorityStr != NULL) && (*PriorityStr != 0)) { + Priority = StrDecimalToUintn (PriorityStr); + if (Priority > 7) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_PRIORITY), mHiiHandle, PriorityStr); + goto Exit; + } + } + + // + // Set VLAN + // + Status = VlanConfig->Set (VlanConfig, (UINT16) VlanId, (UINT8) Priority); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_SET_FAIL), mHiiHandle, Status); + goto Exit; + } + + // + // Connect the VLAN device. + // + VlanHandle = NetLibGetVlanHandle (Handle, (UINT16) VlanId); + if (VlanHandle != NULL) { + gBS->ConnectController (VlanHandle, NULL, NULL, TRUE); + } + + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_SET_SUCCESS), mHiiHandle); + +Exit: + if (VlanConfig != NULL) { + CloseVlanConfigProtocol (Handle); + } + + FreePool (Name); +} + +/** + Remove a VLAN device. + + @param[in] ParamStr Parameter string from user input. + +**/ +VOID +DeleteVlan ( + CHAR16 *ParamStr + ) +{ + CHAR16 *Name; + CHAR16 *VlanIdStr; + CHAR16 *StrPtr; + UINTN VlanId; + EFI_HANDLE Handle; + EFI_VLAN_CONFIG_PROTOCOL *VlanConfig; + EFI_STATUS Status; + UINT16 NumberOfVlan; + EFI_VLAN_FIND_DATA *VlanData; + + VlanConfig = NULL; + + if (ParamStr == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_IF), mHiiHandle); + return ; + } + + StrPtr = AllocateCopyPool (StrSize (ParamStr), ParamStr); + if (StrPtr == NULL) { + return ; + } + + Name = StrPtr; + VlanIdStr = NULL; + while (*StrPtr != 0) { + if (*StrPtr == L'.') { + *StrPtr = 0; + VlanIdStr = StrPtr + 1; + break; + } + + StrPtr++; + } + + Handle = NicNameToHandle (Name); + if (Handle == NULL) { + goto Exit; + } + + VlanConfig = OpenVlanConfigProtocol (Handle); + if (VlanConfig == NULL) { + goto Exit; + } + + // + // Check VLAN ID + // + if (VlanIdStr == NULL || *VlanIdStr == 0) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_VID), mHiiHandle); + goto Exit; + } + + VlanId = StrToVlanId (VlanIdStr); + if (VlanId > 4094) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_VID), mHiiHandle, VlanIdStr); + goto Exit; + } + + // + // Delete VLAN. + // + Status = VlanConfig->Remove (VlanConfig, (UINT16) VlanId); + if (EFI_ERROR (Status)) { + if (Status == EFI_NOT_FOUND) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NOT_FOUND), mHiiHandle); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_REMOVE_FAIL), mHiiHandle, Status); + } + + goto Exit; + } + + // + // Check whether this is the last VLAN to remove. + // + Status = VlanConfig->Find (VlanConfig, NULL, &NumberOfVlan, &VlanData); + if (EFI_ERROR (Status)) { + // + // This is the last VLAN to remove, try to connect the controller handle. + // + gBS->ConnectController (Handle, NULL, NULL, TRUE); + } else { + FreePool (VlanData); + } + + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_REMOVE_SUCCESS), mHiiHandle); + +Exit: + if (VlanConfig != NULL) { + CloseVlanConfigProtocol (Handle); + } + + FreePool (Name); +} + +/** + The actual entry point for the application. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point executed successfully. + @retval other Some error occur when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +VlanConfigMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + LIST_ENTRY *List; + CONST CHAR16 *Str; + + mImageHandle = ImageHandle; + + // + // Register our string package to HII database. + // + mHiiHandle = HiiAddPackages (&gEfiCallerIdGuid, ImageHandle, VConfigStrings, NULL); + if (mHiiHandle == NULL) { + return EFI_SUCCESS; + } + + List = NULL; + ShellCommandLineParseEx (mParamList, &List, NULL, FALSE, FALSE); + if (List == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_ARG), mHiiHandle); + goto Exit; + } + + if (ShellCommandLineGetFlag (List, L"-?")) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_HELP), mHiiHandle); + goto Exit; + } + + if (ShellCommandLineGetFlag (List, L"-l")) { + Str = ShellCommandLineGetValue (List, L"-l"); + DisplayVlan ((CHAR16 *) Str); + goto Exit; + } + + if (ShellCommandLineGetFlag (List, L"-a")) { + Str = ShellCommandLineGetValue (List, L"-a"); + AddVlan ((CHAR16 *) Str); + goto Exit; + } + + if (ShellCommandLineGetFlag (List, L"-d")) { + Str = ShellCommandLineGetValue (List, L"-d"); + DeleteVlan ((CHAR16 *) Str); + goto Exit; + } + + // + // No valid argument till now. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_ARG), mHiiHandle); + +Exit: + if (List != NULL) { + ShellCommandLineFreeVarList (List); + } + + // + // Remove our string package from HII database. + // + HiiRemovePackages (mHiiHandle); + + return EFI_SUCCESS; +} diff --git a/NetworkPkg/Application/VConfig/VConfig.inf b/NetworkPkg/Application/VConfig/VConfig.inf new file mode 100644 index 0000000000..e69da02f7b --- /dev/null +++ b/NetworkPkg/Application/VConfig/VConfig.inf @@ -0,0 +1,47 @@ +## @file +# Component files for VLAN configuration shell application. +# +# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+# +# 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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = VConfig + FILE_GUID = 87E36301-0406-44db-AAF3-9E0E591F3725 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = VlanConfigMain + +# +# VALID_ARCHITECTURES = IA32 X64 IPF +# + +[Sources] + VConfigStrings.uni + VConfig.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ShellPkg/ShellPkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiBootServicesTableLib + UefiLib + ShellLib + NetLib + MemoryAllocationLib + HiiLib + +[Protocols] + gEfiVlanConfigProtocolGuid diff --git a/NetworkPkg/Application/VConfig/VConfigStrings.uni b/NetworkPkg/Application/VConfig/VConfigStrings.uni new file mode 100644 index 0000000000..e8bdcefee8 Binary files /dev/null and b/NetworkPkg/Application/VConfig/VConfigStrings.uni differ -- cgit v1.2.3