use crate::constants;
use crate::platform::DnsResolver;
use std::process::Command;
pub struct LinuxDns;
impl DnsResolver for LinuxDns {
fn get_dns_server() -> Option<String> {
try_get_dns_resolvectl()
.or_else(try_get_dns_nmcli)
.or_else(try_get_dns_resolv_conf)
}
}
fn try_get_dns_resolvectl() -> Option<String> {
let output = Command::new("resolvectl").args(["status"]).output().ok()?;
if !output.status.success() {
return None;
}
let stdout = String::from_utf8_lossy(&output.stdout);
for line in stdout.lines() {
let trimmed = line.trim();
if trimmed.starts_with("DNS Servers:") || trimmed.starts_with("Current DNS Server:") {
if let Some(dns) = trimmed.split(':').nth(1) {
let dns = dns.trim().to_string();
let first = dns.split_whitespace().next().unwrap_or("").to_string();
if !first.is_empty() {
return Some(first);
}
}
}
}
None
}
fn try_get_dns_nmcli() -> Option<String> {
let output = Command::new("nmcli").args(["dev", "show"]).output().ok()?;
if !output.status.success() {
return None;
}
let stdout = String::from_utf8_lossy(&output.stdout);
for line in stdout.lines() {
let trimmed = line.trim();
if trimmed.starts_with("IP4.DNS") {
if let Some(dns) = trimmed.split(':').nth(1) {
let dns = dns.trim().to_string();
if !dns.is_empty() {
return Some(dns);
}
}
}
}
None
}
fn try_get_dns_resolv_conf() -> Option<String> {
let content = std::fs::read_to_string(constants::RESOLV_CONF_PATH).ok()?;
for line in content.lines() {
let trimmed = line.trim();
if trimmed.starts_with("nameserver") {
let dns = trimmed.trim_start_matches("nameserver").trim().to_string();
if !dns.is_empty() {
return Some(dns);
}
}
}
None
}
#[cfg(test)]
mod tests {
#[test]
fn test_parse_resolv_conf() {
let content = "# Generated by NetworkManager\nnameserver 1.1.1.1\nnameserver 8.8.8.8\n";
let mut result = None;
for line in content.lines() {
let trimmed = line.trim();
if trimmed.starts_with("nameserver") {
let dns = trimmed.trim_start_matches("nameserver").trim().to_string();
if !dns.is_empty() {
result = Some(dns);
break;
}
}
}
assert_eq!(result, Some("1.1.1.1".to_string()));
}
}