From dbba246f9a3259392e27c499633c680b8412d528 Mon Sep 17 00:00:00 2001 From: Kiyomichi Kosaka Date: Mon, 11 Aug 2025 15:28:26 +0200 Subject: [PATCH] Add sudo support in all places. --- src/cli/mod.rs | 10 +++++++++ src/main.rs | 17 +++++++++------ src/network/icmp.rs | 50 ++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 68 insertions(+), 9 deletions(-) diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 2a01cf2..3e0c53e 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -41,6 +41,11 @@ pub enum Commands { target: String, #[arg(short, long, value_enum, default_value = "both")] ip_version: IpVersionArg, + #[arg( + long, + help = "Use sudo for more accurate ICMP and MTU testing (requires interactive password prompt)" + )] + sudo: bool, }, } @@ -69,6 +74,11 @@ pub enum NetworkCommands { count: u32, #[arg(short, long, value_enum, default_value = "both")] ip_version: IpVersionArg, + #[arg( + long, + help = "Use sudo for more accurate ICMP testing (requires interactive password prompt)" + )] + sudo: bool, }, #[command(about = "Test common ports")] Ports { diff --git a/src/main.rs b/src/main.rs index 0751966..ddff6ff 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,9 +24,11 @@ async fn main() { cli::Commands::Network { command } => handle_network_command(command, timeout).await, cli::Commands::Dns { command } => handle_dns_command(command, timeout).await, cli::Commands::Mtu { command } => handle_mtu_command(command, timeout).await, - cli::Commands::Full { target, ip_version } => { - handle_full_test(target, ip_version, timeout).await - } + cli::Commands::Full { + target, + ip_version, + sudo, + } => handle_full_test(target, ip_version, timeout, sudo).await, }; if cli.json { @@ -86,10 +88,12 @@ async fn handle_network_command( target, count, ip_version, + sudo, } => { let mut results = Vec::new(); for version in ip_version.to_versions() { - let ping_results = network::ping_test(&target, version, count).await; + let ping_results = + network::ping_test_with_sudo(&target, version, count, sudo).await; results.extend(ping_results); } results @@ -268,6 +272,7 @@ async fn handle_full_test( target: String, ip_version: cli::IpVersionArg, timeout: Duration, + sudo: bool, ) -> Vec { let versions = ip_version.to_versions(); let total_tests = versions.len() * 10; // Rough estimate @@ -303,7 +308,7 @@ async fn handle_full_test( pb.inc(1); // ICMP test - let ping_results = network::ping_test(&target, version, 3).await; + let ping_results = network::ping_test_with_sudo(&target, version, 3, sudo).await; all_results.extend(ping_results); pb.inc(3); @@ -314,7 +319,7 @@ async fn handle_full_test( pb.inc(1); // Common MTU sizes - let mtu_common = mtu::test_common_mtu_sizes(&target, version, false).await; + let mtu_common = mtu::test_common_mtu_sizes(&target, version, sudo).await; all_results.extend(mtu_common); pb.inc(1); } diff --git a/src/network/icmp.rs b/src/network/icmp.rs index d72d3b6..ebe8090 100644 --- a/src/network/icmp.rs +++ b/src/network/icmp.rs @@ -5,6 +5,10 @@ use tokio::time::Duration; impl NetworkTest { pub async fn test_icmp(&self) -> Result { + self.test_icmp_with_sudo(false).await + } + + pub async fn test_icmp_with_sudo(&self, use_sudo: bool) -> Result { // Resolve the target to an IP address first let target_ip = self.resolve_target_to_ip().await?; @@ -13,7 +17,13 @@ impl NetworkTest { IpVersion::V6 => "ping6", }; - let mut cmd = tokio::process::Command::new(ping_cmd); + let mut cmd = if use_sudo { + let mut sudo_cmd = tokio::process::Command::new("sudo"); + sudo_cmd.arg(ping_cmd); + sudo_cmd + } else { + tokio::process::Command::new(ping_cmd) + }; cmd.args(&["-c", "1"]); // Add timeout for IPv4 ping, but not for ping6 on macOS (it uses different syntax) @@ -103,13 +113,47 @@ impl NetworkTest { } pub async fn ping_test(target: &str, ip_version: IpVersion, count: u32) -> Vec { + ping_test_with_sudo(target, ip_version, count, false).await +} + +pub async fn ping_test_with_sudo( + target: &str, + ip_version: IpVersion, + count: u32, + use_sudo: bool, +) -> Vec { let mut results = Vec::new(); for i in 0..count { let test = NetworkTest::new(target.to_string(), ip_version, super::NetworkProtocol::Icmp); - let mut result = test.run().await; - result.test_name = format!("ICMP ping #{} to {} ({:?})", i + 1, target, ip_version); + let result = if use_sudo { + let start = std::time::Instant::now(); + let icmp_result = test.test_icmp_with_sudo(use_sudo).await; + let duration = start.elapsed(); + + match icmp_result { + Ok(details) => crate::utils::TestResult::new(format!( + "ICMP ping #{} to {} ({:?})", + i + 1, + target, + ip_version + )) + .success(duration, details), + Err(error) => crate::utils::TestResult::new(format!( + "ICMP ping #{} to {} ({:?})", + i + 1, + target, + ip_version + )) + .failure(duration, error), + } + } else { + let mut result = test.run().await; + result.test_name = format!("ICMP ping #{} to {} ({:?})", i + 1, target, ip_version); + result + }; + results.push(result); if i < count - 1 {