private Process GetPingProcess(IPAddress address, byte[] buffer, int timeout, PingOptions?options) { bool isIpv4 = address.AddressFamily == AddressFamily.InterNetwork; string?pingExecutable = isIpv4 ? UnixCommandLinePing.Ping4UtilityPath : UnixCommandLinePing.Ping6UtilityPath; if (pingExecutable == null) { throw new PlatformNotSupportedException(SR.net_ping_utility_not_found); } UnixCommandLinePing.PingFragmentOptions fragmentOption = UnixCommandLinePing.PingFragmentOptions.Default; if (options != null && address.AddressFamily == AddressFamily.InterNetwork) { fragmentOption = options.DontFragment ? UnixCommandLinePing.PingFragmentOptions.Do : UnixCommandLinePing.PingFragmentOptions.Dont; } string processArgs = UnixCommandLinePing.ConstructCommandLine(buffer.Length, timeout, address.ToString(), isIpv4, options?.Ttl ?? 0, fragmentOption); ProcessStartInfo psi = new ProcessStartInfo(pingExecutable, processArgs); psi.RedirectStandardOutput = true; psi.RedirectStandardError = true; return(new Process() { StartInfo = psi }); }
private Process GetPingProcess(IPAddress address, byte[] buffer, int timeout, PingOptions?options) { bool isIpv4 = address.AddressFamily == AddressFamily.InterNetwork; string?pingExecutable = isIpv4 ? UnixCommandLinePing.Ping4UtilityPath : UnixCommandLinePing.Ping6UtilityPath; if (pingExecutable == null) { throw new PlatformNotSupportedException(SR.net_ping_utility_not_found); } UnixCommandLinePing.PingFragmentOptions fragmentOption = UnixCommandLinePing.PingFragmentOptions.Default; if (options != null && address.AddressFamily == AddressFamily.InterNetwork) { fragmentOption = options.DontFragment ? UnixCommandLinePing.PingFragmentOptions.Do : UnixCommandLinePing.PingFragmentOptions.Dont; } string processArgs = UnixCommandLinePing.ConstructCommandLine(buffer.Length, timeout, address.ToString(), isIpv4, options?.Ttl ?? 0, fragmentOption); ProcessStartInfo psi = new ProcessStartInfo(pingExecutable, processArgs); psi.RedirectStandardOutput = true; psi.RedirectStandardError = true; // Set LC_ALL=C to make sure to get ping output which is not affected by locale environment variables such as LANG and LC_MESSAGES. psi.EnvironmentVariables["LC_ALL"] = "C"; return(new Process() { StartInfo = psi }); }
private Process GetPingProcess(IPAddress address, byte[] buffer) { bool isIpv4 = address.AddressFamily == AddressFamily.InterNetwork; string pingExecutable = isIpv4 ? UnixCommandLinePing.Ping4UtilityPath : UnixCommandLinePing.Ping6UtilityPath; if (pingExecutable == null) { throw new PlatformNotSupportedException(SR.net_ping_utility_not_found); } string processArgs = UnixCommandLinePing.ConstructCommandLine(buffer.Length, address.ToString(), isIpv4); ProcessStartInfo psi = new ProcessStartInfo(pingExecutable, processArgs); psi.RedirectStandardOutput = true; psi.RedirectStandardError = true; return(new Process() { StartInfo = psi }); }
private Process GetPingProcess(IPAddress address, byte[] buffer, int timeout, PingOptions?options) { bool isIpv4 = address.AddressFamily == AddressFamily.InterNetwork; string?pingExecutable = isIpv4 ? UnixCommandLinePing.Ping4UtilityPath : UnixCommandLinePing.Ping6UtilityPath; if (pingExecutable == null) { throw new PlatformNotSupportedException(SR.net_ping_utility_not_found); } // although the ping utility supports custom pattern via -p option, it supports // specifying only up to 16B pattern which repeats in the payload. The option also might // not be present in all distributions, so we forbid ping payload in general. if (buffer != DefaultSendBuffer && buffer != Array.Empty <byte>()) { throw new PlatformNotSupportedException(SR.net_ping_utility_custom_payload); } UnixCommandLinePing.PingFragmentOptions fragmentOption = UnixCommandLinePing.PingFragmentOptions.Default; if (options != null && address.AddressFamily == AddressFamily.InterNetwork) { fragmentOption = options.DontFragment ? UnixCommandLinePing.PingFragmentOptions.Do : UnixCommandLinePing.PingFragmentOptions.Dont; } string processArgs = UnixCommandLinePing.ConstructCommandLine(buffer.Length, timeout, address.ToString(), isIpv4, options?.Ttl ?? 0, fragmentOption); ProcessStartInfo psi = new ProcessStartInfo(pingExecutable, processArgs); psi.RedirectStandardOutput = true; psi.RedirectStandardError = true; // Set LC_ALL=C to make sure to get ping output which is not affected by locale environment variables such as LANG and LC_MESSAGES. psi.EnvironmentVariables["LC_ALL"] = "C"; return(new Process() { StartInfo = psi }); }
private async Task <PingReply> SendWithPingUtility(IPAddress address, byte[] buffer, int timeout, PingOptions options) { bool isIpv4 = address.AddressFamily == AddressFamily.InterNetwork; string pingExecutable = isIpv4 ? UnixCommandLinePing.Ping4UtilityPath : UnixCommandLinePing.Ping6UtilityPath; if (pingExecutable == null) { throw new PlatformNotSupportedException(SR.net_ping_utility_not_found); } string processArgs = UnixCommandLinePing.ConstructCommandLine(buffer.Length, address.ToString(), isIpv4); ProcessStartInfo psi = new ProcessStartInfo(pingExecutable, processArgs); psi.RedirectStandardOutput = true; psi.RedirectStandardError = true; Process p = new Process() { StartInfo = psi }; var processCompletion = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously); p.EnableRaisingEvents = true; p.Exited += (s, e) => processCompletion.SetResult(true); p.Start(); var cts = new CancellationTokenSource(); Task timeoutTask = Task.Delay(timeout, cts.Token); Task finished = await Task.WhenAny(processCompletion.Task, timeoutTask).ConfigureAwait(false); if (finished == timeoutTask && !p.HasExited) { // Try to kill the ping process if it didn't return. If it is already in the process of exiting, a Win32Exception will be thrown. try { p.Kill(); } catch (Win32Exception) { } return(CreateTimedOutPingReply()); } else { cts.Cancel(); if (p.ExitCode != 0) { // This means no reply was received, although transmission may have been successful. return(CreateTimedOutPingReply()); } try { string output = await p.StandardOutput.ReadToEndAsync().ConfigureAwait(false); long rtt = UnixCommandLinePing.ParseRoundTripTime(output); return(new PingReply( address, null, // Ping utility cannot accomodate these, return null to indicate they were ignored. IPStatus.Success, rtt, Array.Empty <byte>())); // Ping utility doesn't deliver this info. } catch (Exception) { // If the standard output cannot be successfully parsed, throw a generic PingException. throw new PingException(SR.net_ping); } } }