diff --git a/src/system_dns.rs b/src/system_dns.rs index 7840c7f..382ce0a 100644 --- a/src/system_dns.rs +++ b/src/system_dns.rs @@ -472,6 +472,60 @@ fn windows_backup_path() -> std::path::PathBuf { .join("original-dns.json") } +#[cfg(windows)] +fn disable_dnscache() -> Result { + // Check if Dnscache is running (it holds port 53 at kernel level) + let output = std::process::Command::new("sc") + .args(["query", "Dnscache"]) + .output() + .map_err(|e| format!("failed to query Dnscache: {}", e))?; + let text = String::from_utf8_lossy(&output.stdout); + if !text.contains("RUNNING") { + return Ok(false); + } + + eprintln!(" Disabling DNS Client (Dnscache) to free port 53..."); + // Dnscache can't be stopped via sc/net stop — must disable via registry + let status = std::process::Command::new("reg") + .args([ + "add", + "HKLM\\SYSTEM\\CurrentControlSet\\Services\\Dnscache", + "/v", + "Start", + "/t", + "REG_DWORD", + "/d", + "4", + "/f", + ]) + .status() + .map_err(|e| format!("failed to disable Dnscache: {}", e))?; + + if !status.success() { + return Err("failed to disable Dnscache via registry (run as Administrator?)".into()); + } + + eprintln!(" Dnscache disabled. A reboot is required to free port 53."); + Ok(true) +} + +#[cfg(windows)] +fn enable_dnscache() { + let _ = std::process::Command::new("reg") + .args([ + "add", + "HKLM\\SYSTEM\\CurrentControlSet\\Services\\Dnscache", + "/v", + "Start", + "/t", + "REG_DWORD", + "/d", + "2", + "/f", + ]) + .status(); +} + #[cfg(windows)] fn install_windows() -> Result<(), String> { let interfaces = get_windows_interfaces()?; @@ -513,9 +567,15 @@ fn install_windows() -> Result<(), String> { } } + let needs_reboot = disable_dnscache()?; + eprintln!("\n Original DNS saved to {}", path.display()); - eprintln!(" Run 'numa uninstall' to restore."); - eprintln!(" Note: run Numa manually with 'numa' in a terminal.\n"); + eprintln!(" Run 'numa uninstall' to restore.\n"); + if needs_reboot { + eprintln!(" *** Reboot required, then run 'numa' in an Administrator terminal. ***\n"); + } else { + eprintln!(" Run 'numa' in an Administrator terminal to start.\n"); + } eprintln!(" Want full DNS sovereignty? Add to numa.toml:"); eprintln!(" [upstream]"); eprintln!(" mode = \"recursive\"\n"); @@ -585,7 +645,11 @@ fn uninstall_windows() -> Result<(), String> { } std::fs::remove_file(&path).ok(); - eprintln!("\n System DNS restored. Backup removed.\n"); + + // Re-enable Dnscache + enable_dnscache(); + eprintln!("\n System DNS restored. DNS Client re-enabled."); + eprintln!(" Reboot to fully restore the DNS Client service.\n"); Ok(()) }