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>
This commit is contained in:
Jiaxin Wu
2016-04-19 09:49:01 +08:00
parent 5db1ac89be
commit 9ce14ca124
2 changed files with 134 additions and 106 deletions

View File

@ -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)) {
//
// Source address is required when pinging a link-local address on multi-
// interfaces host.
// 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.
//
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,12 +964,6 @@ 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.
@ -1027,9 +1042,17 @@ PingCreateIpInstance (
//
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);
if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) {
if (UnspecifiedSrc) {
if (!NetIp6IsUnspecifiedAddr (Addr) && !NetIp6IsLinkLocalAddr (Addr)) {
//
// Select the interface automatically.
//
CopyMem(&Private->SrcAddress, Addr, sizeof(Private->SrcAddress));
break;
}
} else if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) {
//
// Match a certain interface address.
//
@ -1044,17 +1067,21 @@ PingCreateIpInstance (
break;
}
} else {
if (UnspecifiedSrc) {
if (!PingNetIp4IsUnspecifiedAddr (&((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress) &&
!PingNetIp4IsLinkLocalAddr (&((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress)) {
//
// IP4 address check
// Select the interface automatically.
//
if (EFI_IP4_EQUAL (&Private->SrcAddress, &((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress)) {
break;
}
} else if (EFI_IP4_EQUAL (&Private->SrcAddress, &((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress)) {
//
// Match a certain interface address.
//
break;
}
}
}
FreePool (IpXInterfaceInfo);
IpXInterfaceInfo = NULL;

View File

@ -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"