summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiaxin Wu <jiaxin.wu@intel.com>2016-04-19 09:49:01 +0800
committerHao Wu <hao.a.wu@intel.com>2016-07-13 20:43:11 +0800
commitc1aeb860436f9776f053f55b5f835b9550d6957a (patch)
treeaf56c3476bb24594e7b089f7ff3c6d72b00cfff1
parentc092d71a89f68ceb4386f0dc7a0ef1f606ee5deb (diff)
downloadedk2-platforms-c1aeb860436f9776f053f55b5f835b9550d6957a.tar.xz
ShellPkg: Enhance ping to select the interface automatically
v2: * A. Refine the code to make it more readable. * B. Add hint message for link local address case. This patch is used to support no source IP specified case while multiple NICs existed in the platform. The command will select the first both connected and configured interface automatically. Note: Source address is always required when pinging a link-local address. Cc: David Van Arnem <dvanarnem@cmlab.biz> Cc: Bhupesh Sharma <bhupesh.sharma@nxp.com> Cc: Jaben Carsey <jaben.carsey@intel.com> Cc: Ye Ting <ting.ye@intel.com> Cc: Fu Siyuan <siyuan.fu@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiaxin Wu <jiaxin.wu@intel.com> Reviewed-by: Jaben Carsey <jaben.carsey@intel.com> Reviewed-by: Fu Siyuan <siyuan.fu@intel.com> (cherry picked from commit 9ce14ca124dd4ef1ae1f4e7c55840a13f1a6c0b7)
-rw-r--r--ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c229
-rw-r--r--ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni1
2 files changed, 129 insertions, 101 deletions
diff --git a/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c b/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c
index 13bcdde6b5..abd2f6b04e 100644
--- a/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c
+++ b/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c
@@ -876,6 +876,8 @@ PingCreateIpInstance (
UINTN HandleIndex;
UINTN HandleNum;
EFI_HANDLE *HandleBuffer;
+ BOOLEAN UnspecifiedSrc;
+ BOOLEAN MediaPresent;
EFI_SERVICE_BINDING_PROTOCOL *EfiSb;
VOID *IpXCfg;
EFI_IP6_CONFIG_DATA Ip6Config;
@@ -886,6 +888,8 @@ PingCreateIpInstance (
UINTN AddrIndex;
HandleBuffer = NULL;
+ UnspecifiedSrc = FALSE;
+ MediaPresent = TRUE;
EfiSb = NULL;
IpXInterfaceInfo = NULL;
IfInfoSize = 0;
@@ -903,37 +907,54 @@ PingCreateIpInstance (
if (EFI_ERROR (Status) || (HandleNum == 0) || (HandleBuffer == NULL)) {
return EFI_ABORTED;
}
+
+ if (Private->IpChoice == PING_IP_CHOICE_IP6 ? NetIp6IsUnspecifiedAddr ((EFI_IPv6_ADDRESS*)&Private->SrcAddress) : \
+ PingNetIp4IsUnspecifiedAddr ((EFI_IPv4_ADDRESS*)&Private->SrcAddress)) {
+ //
+ // SrcAddress is unspecified. So, both connected and configured interface will be automatic selected.
+ //
+ UnspecifiedSrc = TRUE;
+ }
+
//
- // Source address is required when pinging a link-local address on multi-
- // interfaces host.
+ // Source address is required when pinging a link-local address.
//
if (Private->IpChoice == PING_IP_CHOICE_IP6) {
- if (NetIp6IsLinkLocalAddr ((EFI_IPv6_ADDRESS*)&Private->DstAddress) &&
- NetIp6IsUnspecifiedAddr ((EFI_IPv6_ADDRESS*)&Private->SrcAddress) &&
- (HandleNum > 1)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", mSrcString);
+ if (NetIp6IsLinkLocalAddr ((EFI_IPv6_ADDRESS*)&Private->DstAddress) && UnspecifiedSrc) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_INVALID_SOURCE), gShellNetwork1HiiHandle);
Status = EFI_INVALID_PARAMETER;
goto ON_ERROR;
}
} else {
ASSERT(Private->IpChoice == PING_IP_CHOICE_IP4);
- if (PingNetIp4IsLinkLocalAddr ((EFI_IPv4_ADDRESS*)&Private->DstAddress) &&
- PingNetIp4IsUnspecifiedAddr ((EFI_IPv4_ADDRESS*)&Private->SrcAddress) &&
- (HandleNum > 1)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", mSrcString);
+ if (PingNetIp4IsLinkLocalAddr ((EFI_IPv4_ADDRESS*)&Private->DstAddress) && UnspecifiedSrc) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_INVALID_SOURCE), gShellNetwork1HiiHandle);
Status = EFI_INVALID_PARAMETER;
goto ON_ERROR;
}
}
+
//
// For each ip6 protocol, check interface addresses list.
//
for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {
-
EfiSb = NULL;
IpXInterfaceInfo = NULL;
IfInfoSize = 0;
+ if (UnspecifiedSrc) {
+ //
+ // Check media.
+ //
+ NetLibDetectMedia (HandleBuffer[HandleIndex], &MediaPresent);
+ if (!MediaPresent) {
+ //
+ // Skip this one.
+ //
+ continue;
+ }
+ }
+
Status = gBS->HandleProtocol (
HandleBuffer[HandleIndex],
Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ServiceBindingProtocolGuid:&gEfiIp4ServiceBindingProtocolGuid,
@@ -943,116 +964,122 @@ PingCreateIpInstance (
goto ON_ERROR;
}
- if (Private->IpChoice == PING_IP_CHOICE_IP6?NetIp6IsUnspecifiedAddr ((EFI_IPv6_ADDRESS*)&Private->SrcAddress):PingNetIp4IsUnspecifiedAddr ((EFI_IPv4_ADDRESS*)&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],
- Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ConfigProtocolGuid:&gEfiIp4Config2ProtocolGuid,
- (VOID **) &IpXCfg
- );
+ //
+ // Ip6config protocol and ip6 service binding protocol are installed
+ // on the same handle.
+ //
+ Status = gBS->HandleProtocol (
+ HandleBuffer[HandleIndex],
+ Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ConfigProtocolGuid:&gEfiIp4Config2ProtocolGuid,
+ (VOID **) &IpXCfg
+ );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- //
- // Get the interface information size.
- //
- if (Private->IpChoice == PING_IP_CHOICE_IP6) {
- Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (
- IpXCfg,
- Ip6ConfigDataTypeInterfaceInfo,
- &IfInfoSize,
- NULL
- );
- } else {
- Status = ((EFI_IP4_CONFIG2_PROTOCOL*)IpXCfg)->GetData (
- IpXCfg,
- Ip4Config2DataTypeInterfaceInfo,
- &IfInfoSize,
- NULL
- );
- }
-
- //
- // Skip the ones not in current use.
- //
- if (Status == EFI_NOT_STARTED) {
- continue;
- }
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ //
+ // Get the interface information size.
+ //
+ if (Private->IpChoice == PING_IP_CHOICE_IP6) {
+ Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (
+ IpXCfg,
+ Ip6ConfigDataTypeInterfaceInfo,
+ &IfInfoSize,
+ NULL
+ );
+ } else {
+ Status = ((EFI_IP4_CONFIG2_PROTOCOL*)IpXCfg)->GetData (
+ IpXCfg,
+ Ip4Config2DataTypeInterfaceInfo,
+ &IfInfoSize,
+ NULL
+ );
+ }
+
+ //
+ // Skip the ones not in current use.
+ //
+ if (Status == EFI_NOT_STARTED) {
+ continue;
+ }
- if (Status != EFI_BUFFER_TOO_SMALL) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);
- goto ON_ERROR;
- }
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);
+ goto ON_ERROR;
+ }
- IpXInterfaceInfo = AllocateZeroPool (IfInfoSize);
+ IpXInterfaceInfo = AllocateZeroPool (IfInfoSize);
- if (IpXInterfaceInfo == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto ON_ERROR;
- }
- //
- // Get the interface info.
- //
- if (Private->IpChoice == PING_IP_CHOICE_IP6) {
- Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (
- IpXCfg,
- Ip6ConfigDataTypeInterfaceInfo,
- &IfInfoSize,
- IpXInterfaceInfo
- );
- } else {
- Status = ((EFI_IP4_CONFIG2_PROTOCOL*)IpXCfg)->GetData (
- IpXCfg,
- Ip4Config2DataTypeInterfaceInfo,
- &IfInfoSize,
- IpXInterfaceInfo
- );
- }
+ if (IpXInterfaceInfo == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_ERROR;
+ }
+ //
+ // Get the interface info.
+ //
+ if (Private->IpChoice == PING_IP_CHOICE_IP6) {
+ Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (
+ IpXCfg,
+ Ip6ConfigDataTypeInterfaceInfo,
+ &IfInfoSize,
+ IpXInterfaceInfo
+ );
+ } else {
+ Status = ((EFI_IP4_CONFIG2_PROTOCOL*)IpXCfg)->GetData (
+ IpXCfg,
+ Ip4Config2DataTypeInterfaceInfo,
+ &IfInfoSize,
+ IpXInterfaceInfo
+ );
+ }
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);
- goto ON_ERROR;
- }
- //
- // Check whether the source address is one of the interface addresses.
- //
- if (Private->IpChoice == PING_IP_CHOICE_IP6) {
- for (AddrIndex = 0; AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount; AddrIndex++) {
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);
+ goto ON_ERROR;
+ }
+ //
+ // Check whether the source address is one of the interface addresses.
+ //
+ if (Private->IpChoice == PING_IP_CHOICE_IP6) {
+ for (AddrIndex = 0; AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount; AddrIndex++) {
+ Addr = &(((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfo[AddrIndex].Address);
- Addr = &(((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfo[AddrIndex].Address);
- if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) {
+ if (UnspecifiedSrc) {
+ if (!NetIp6IsUnspecifiedAddr (Addr) && !NetIp6IsLinkLocalAddr (Addr)) {
//
- // Match a certain interface address.
+ // Select the interface automatically.
//
+ CopyMem(&Private->SrcAddress, Addr, sizeof(Private->SrcAddress));
break;
}
- }
-
- if (AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount) {
+ } else if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) {
//
- // Found a nic handle with right interface address.
+ // Match a certain interface address.
//
break;
}
- } else {
+ }
+
+ if (AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount) {
//
- // IP4 address check
+ // Found a nic handle with right interface address.
//
- if (EFI_IP4_EQUAL (&Private->SrcAddress, &((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress)) {
+ break;
+ }
+ } else {
+ if (UnspecifiedSrc) {
+ if (!PingNetIp4IsUnspecifiedAddr (&((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress) &&
+ !PingNetIp4IsLinkLocalAddr (&((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress)) {
//
- // Match a certain interface address.
+ // Select the interface automatically.
//
break;
}
+ } else if (EFI_IP4_EQUAL (&Private->SrcAddress, &((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress)) {
+ //
+ // Match a certain interface address.
+ //
+ break;
}
}
diff --git a/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni b/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni
index 7d6f2da301..c9c031951e 100644
--- a/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni
+++ b/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni
@@ -44,6 +44,7 @@
#string STR_GEN_IS_DIR #language en-US "%H%s%N: '%H%s%N' is a directory\r\n"
#string STR_GEN_PROTOCOL_NF #language en-US "%H%s%N: The protocol '%H%s%N' is required and not found (%g).\r\n"
+#string STR_PING_INVALID_SOURCE #language en-US "%Ping: Require source interface option\r\n"
#string STR_PING_CONFIG #language en-US "Config %r\r\n"
#string STR_PING_GETMODE #language en-US "GetModeData %r\r\n"
#string STR_PING_GETDATA #language en-US "GetData %r\r\n"