]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c
ShellPkg: Enhance ping6 to select the interface automatically
[mirror_edk2.git] / ShellPkg / Library / UefiShellNetwork2CommandsLib / Ping6.c
index af7d08f3ec516bfd3932d0715fcaafe86850fee0..e4ae977eb579822622c6016e4aba73ef6fbd1950 100644 (file)
@@ -663,6 +663,8 @@ Ping6CreateIpInstance (
   UINTN                            HandleIndex;\r
   UINTN                            HandleNum;\r
   EFI_HANDLE                       *HandleBuffer;\r
+  BOOLEAN                          UnspecifiedSrc;\r
+  BOOLEAN                          MediaPresent;\r
   EFI_SERVICE_BINDING_PROTOCOL     *Ip6Sb;\r
   EFI_IP6_CONFIG_PROTOCOL          *Ip6Cfg;\r
   EFI_IP6_CONFIG_DATA              Ip6Config;\r
@@ -671,10 +673,12 @@ Ping6CreateIpInstance (
   EFI_IPv6_ADDRESS                 *Addr;\r
   UINTN                            AddrIndex;\r
 \r
-  HandleBuffer = NULL;\r
-  Ip6Sb        = NULL;\r
-  IfInfo       = NULL;\r
-  IfInfoSize   = 0;\r
+  HandleBuffer      = NULL;\r
+  UnspecifiedSrc    = FALSE;\r
+  MediaPresent      = TRUE;\r
+  Ip6Sb             = NULL;\r
+  IfInfo            = NULL;\r
+  IfInfoSize        = 0;\r
 \r
   //\r
   // Locate all the handles with ip6 service binding protocol.\r
@@ -689,17 +693,23 @@ Ping6CreateIpInstance (
   if (EFI_ERROR (Status) || (HandleNum == 0)) {\r
     return EFI_ABORTED;\r
   }\r
+\r
+  if (NetIp6IsUnspecifiedAddr (&Private->SrcAddress)) {\r
+    //\r
+    // SrcAddress is unspecified. So, both connected and configured interface will be automatic selected. \r
+    //\r
+    UnspecifiedSrc = TRUE;\r
+  }\r
+  \r
   //\r
-  // Source address is required when pinging a link-local address on multi-\r
-  // interfaces host.\r
+  // Source address is required when pinging a link-local address.\r
   //\r
-  if (NetIp6IsLinkLocalAddr (&Private->DstAddress) &&\r
-      NetIp6IsUnspecifiedAddr (&Private->SrcAddress) &&\r
-      (HandleNum > 1)) {\r
+  if (NetIp6IsLinkLocalAddr (&Private->DstAddress) && UnspecifiedSrc) {\r
     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_SOURCE), gShellNetwork2HiiHandle);\r
     Status = EFI_INVALID_PARAMETER;\r
     goto ON_ERROR;\r
   }\r
+  \r
   //\r
   // For each ip6 protocol, check interface addresses list.\r
   //\r
@@ -709,6 +719,19 @@ Ping6CreateIpInstance (
     IfInfo     = NULL;\r
     IfInfoSize = 0;\r
 \r
+    if (UnspecifiedSrc) {\r
+      //\r
+      // Check media.\r
+      //\r
+      NetLibDetectMedia (HandleBuffer[HandleIndex], &MediaPresent);\r
+      if (!MediaPresent) {\r
+        //\r
+        // Skip this one.\r
+        //\r
+        continue;\r
+      }\r
+    }\r
+\r
     Status = gBS->HandleProtocol (\r
                     HandleBuffer[HandleIndex],\r
                     &gEfiIp6ServiceBindingProtocolGuid,\r
@@ -718,80 +741,81 @@ Ping6CreateIpInstance (
       goto ON_ERROR;\r
     }\r
 \r
-    if (NetIp6IsUnspecifiedAddr (&Private->SrcAddress)) {\r
-      //\r
-      // No need to match interface address.\r
-      //\r
-      break;\r
-    } else {\r
-      //\r
-      // Ip6config protocol and ip6 service binding protocol are installed\r
-      // on the same handle.\r
-      //\r
-      Status = gBS->HandleProtocol (\r
-                      HandleBuffer[HandleIndex],\r
-                      &gEfiIp6ConfigProtocolGuid,\r
-                      (VOID **) &Ip6Cfg\r
-                      );\r
+    //\r
+    // Ip6config protocol and ip6 service binding protocol are installed\r
+    // on the same handle.\r
+    //\r
+    Status = gBS->HandleProtocol (\r
+                    HandleBuffer[HandleIndex],\r
+                    &gEfiIp6ConfigProtocolGuid,\r
+                    (VOID **) &Ip6Cfg\r
+                    );\r
 \r
-      if (EFI_ERROR (Status)) {\r
-        goto ON_ERROR;\r
-      }\r
-      //\r
-      // Get the interface information size.\r
-      //\r
-      Status = Ip6Cfg->GetData (\r
-                         Ip6Cfg,\r
-                         Ip6ConfigDataTypeInterfaceInfo,\r
-                         &IfInfoSize,\r
-                         NULL\r
-                         );\r
-\r
-      if (Status != EFI_BUFFER_TOO_SMALL) {\r
-        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);\r
-        goto ON_ERROR;\r
-      }\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_ERROR;\r
+    }\r
+    //\r
+    // Get the interface information size.\r
+    //\r
+    Status = Ip6Cfg->GetData (\r
+                       Ip6Cfg,\r
+                       Ip6ConfigDataTypeInterfaceInfo,\r
+                       &IfInfoSize,\r
+                       NULL\r
+                       );\r
+\r
+    if (Status != EFI_BUFFER_TOO_SMALL) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);\r
+      goto ON_ERROR;\r
+    }\r
 \r
-      IfInfo = AllocateZeroPool (IfInfoSize);\r
+    IfInfo = AllocateZeroPool (IfInfoSize);\r
 \r
-      if (IfInfo == NULL) {\r
-        Status = EFI_OUT_OF_RESOURCES;\r
-        goto ON_ERROR;\r
-      }\r
-      //\r
-      // Get the interface info.\r
-      //\r
-      Status = Ip6Cfg->GetData (\r
-                         Ip6Cfg,\r
-                         Ip6ConfigDataTypeInterfaceInfo,\r
-                         &IfInfoSize,\r
-                         IfInfo\r
-                         );\r
+    if (IfInfo == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto ON_ERROR;\r
+    }\r
+    //\r
+    // Get the interface info.\r
+    //\r
+    Status = Ip6Cfg->GetData (\r
+                       Ip6Cfg,\r
+                       Ip6ConfigDataTypeInterfaceInfo,\r
+                       &IfInfoSize,\r
+                       IfInfo\r
+                       );\r
 \r
-      if (EFI_ERROR (Status)) {\r
-        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);\r
-        goto ON_ERROR;\r
-      }\r
-      //\r
-      // Check whether the source address is one of the interface addresses.\r
-      //\r
-      for (AddrIndex = 0; AddrIndex < IfInfo->AddressInfoCount; AddrIndex++) {\r
+    if (EFI_ERROR (Status)) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);\r
+      goto ON_ERROR;\r
+    }\r
+    //\r
+    // Check whether the source address is one of the interface addresses.\r
+    //\r
+    for (AddrIndex = 0; AddrIndex < IfInfo->AddressInfoCount; AddrIndex++) {\r
+      Addr = &(IfInfo->AddressInfo[AddrIndex].Address);\r
 \r
-        Addr = &(IfInfo->AddressInfo[AddrIndex].Address);\r
-        if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) {\r
+      if (UnspecifiedSrc) {\r
+        if (!NetIp6IsUnspecifiedAddr (Addr) && !NetIp6IsLinkLocalAddr (Addr)) {\r
           //\r
-          // Match a certain interface address.\r
+          // Select the interface automatically.\r
           //\r
+          CopyMem(&Private->SrcAddress, Addr, sizeof(Private->SrcAddress));\r
           break;\r
         }\r
-      }\r
-\r
-      if (AddrIndex < IfInfo->AddressInfoCount) {\r
+      } else if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) {\r
         //\r
-        // Found a nic handle with right interface address.\r
+        // Match a certain interface address.\r
         //\r
         break;\r
-      }\r
+      } \r
+    }\r
+\r
+    if (AddrIndex < IfInfo->AddressInfoCount) {\r
+      //\r
+      // Found a nic handle with right interface address.\r
+      //\r
+      break;\r
     }\r
 \r
     FreePool (IfInfo);\r