Reviewed-by: Fu Siyuan <[email protected]>

> -----Original Message-----
> From: Wu, Jiaxin
> Sent: Thursday, April 28, 2016 4:18 PM
> To: [email protected]
> Cc: David Van Arnem <[email protected]>; Bhupesh Sharma
> <[email protected]>; Carsey, Jaben <[email protected]>; Ye,
> Ting <[email protected]>; Fu, Siyuan <[email protected]>
> Subject: [PATCH v2] 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 <[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:&gEfiIp4ServiceBi
> ndingProtocolGuid,
>                      (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:&gEfiIp4Config2ProtocolG
> uid,
> -                      (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:&gEfiIp4Config2ProtocolG
> uid,
> +                    (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/UefiShellNetwork1Com
> mandsLib.uni
> b/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1Com
> mandsLib.uni
> index 7d6f2da..c9c0319 100644
> ---
> a/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1Com
> mandsLib.uni
> +++
> b/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1Com
> mandsLib.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