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 <[email protected]>
Cc: Bhupesh Sharma <[email protected]>
Cc: Jaben Carsey <[email protected]>
Cc: Ye Ting <[email protected]>
Cc: Fu Siyuan <[email protected]>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiaxin Wu <[email protected]>
---
 .../Library/UefiShellNetwork1CommandsLib/Ping.c    | 229 ++++++++++++---------
 .../UefiShellNetwork1CommandsLib.uni               |   1 +
 2 files changed, 129 insertions(+), 101 deletions(-)

diff --git a/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c 
b/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c
index 13bcdde..abd2f6b 100644
--- a/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c
+++ b/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c
@@ -874,20 +874,24 @@ PingCreateIpInstance (
 {
   EFI_STATUS                       Status;
   UINTN                            HandleIndex;
   UINTN                            HandleNum;
   EFI_HANDLE                       *HandleBuffer;
+  BOOLEAN                          UnspecifiedSrc;
+  BOOLEAN                          MediaPresent;
   EFI_SERVICE_BINDING_PROTOCOL     *EfiSb;
   VOID                             *IpXCfg;
   EFI_IP6_CONFIG_DATA              Ip6Config;
   EFI_IP4_CONFIG_DATA              Ip4Config;
   VOID                             *IpXInterfaceInfo;
   UINTN                            IfInfoSize;
   EFI_IPv6_ADDRESS                 *Addr;
   UINTN                            AddrIndex;
 
   HandleBuffer      = NULL;
+  UnspecifiedSrc    = FALSE;
+  MediaPresent      = TRUE;
   EfiSb             = NULL;
   IpXInterfaceInfo  = NULL;
   IfInfoSize        = 0;
 
   //
@@ -901,160 +905,183 @@ PingCreateIpInstance (
                   &HandleBuffer
                   );
   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,
                     (VOID **) &EfiSb
                     );
     if (EFI_ERROR (Status)) {
       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;
       }
     }
 
     FreePool (IpXInterfaceInfo);
     IpXInterfaceInfo = NULL;
diff --git 
a/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni
 
b/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni
index 7d6f2da..c9c0319 100644
--- 
a/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni
+++ 
b/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni
@@ -42,10 +42,11 @@
 #string STR_GEN_DIR_NF            #language en-US "%H%s%N: Directory not found 
- '%H%s%N'\r\n"
 #string STR_GEN_FILE_NF           #language en-US "%H%s%N: File not found - 
'%H%s%N'\r\n"
 #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"
 #string STR_PING_SEND_REQUEST        #language en-US "Echo request sequence %d 
did not complete successfully.\r\n"
 #string STR_PING_NOSOURCE_INDO       #language en-US "There are no sources in 
%s's multicast domain.\r\n"
-- 
1.9.5.msysgit.1

_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to