Make auto-discovery cross-platform (Windows + Linux)

This commit is contained in:
mikisoq
2026-07-29 01:59:02 -01:00
parent b6a57a104e
commit e1f45bc60b
+150 -29
View File
@@ -1,4 +1,6 @@
using System.Net;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using ADBulkTool.Models;
using DnsClient;
@@ -16,7 +18,7 @@ public static class DomainDiscovery
if (string.IsNullOrWhiteSpace(domain))
{
return new DiscoveryResult(null, null, null, null, null,
"Could not detect a DNS domain from this machine. Check that you are on a domain-joined network and that /etc/resolv.conf has a search or domain entry.");
"Could not detect a DNS domain. Ensure the machine is on a domain network with a proper DNS configuration.");
}
steps.Add($"Detected domain: {domain}");
@@ -27,8 +29,8 @@ public static class DomainDiscovery
var dnsServers = GetDnsServers();
var dnsServer = dnsServers.FirstOrDefault();
steps.Add(dnsServer is not null
? $"DNS server from /etc/resolv.conf: {dnsServer}"
: "No DNS server found in /etc/resolv.conf, using system default.");
? $"DNS server found: {dnsServer}"
: "No DNS server found, using system default resolver.");
var ldapHost = await FindDomainControllerViaSrvAsync(domain, dnsServer, timeout);
@@ -62,29 +64,12 @@ public static class DomainDiscovery
public static List<string> GetDnsServers()
{
var servers = new List<string>();
try
{
var lines = File.ReadAllLines("/etc/resolv.conf");
foreach (var line in lines)
{
var trimmed = line.Trim();
if (trimmed.StartsWith("nameserver ", StringComparison.OrdinalIgnoreCase))
{
var parts = trimmed.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (parts.Length >= 2 && IPAddress.TryParse(parts[1], out _))
{
servers.Add(parts[1]);
}
}
}
}
catch
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return GetDnsServersWindows();
}
return servers;
return GetDnsServersLinux();
}
public static string? DomainToSearchBase(string? domain)
@@ -109,10 +94,22 @@ public static class DomainDiscovery
{
using var cts = new CancellationTokenSource(timeout);
var resolvDomain = await Task.Run(() => GetDomainFromResolvConf(), cts.Token);
if (!string.IsNullOrWhiteSpace(resolvDomain))
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return resolvDomain;
var resolvDomain = await Task.Run(() => GetDomainFromResolvConf(), cts.Token);
if (!string.IsNullOrWhiteSpace(resolvDomain))
{
return resolvDomain;
}
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
var winDomain = await Task.Run(() => GetDomainFromWindows(), cts.Token);
if (!string.IsNullOrWhiteSpace(winDomain))
{
return winDomain;
}
}
var hostDomain = await Task.Run(() => GetDomainFromHostname(), cts.Token);
@@ -123,8 +120,14 @@ public static class DomainDiscovery
var ipDomain = await Task.Run(() =>
{
try { return System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName; }
catch { return string.Empty; }
try
{
return IPGlobalProperties.GetIPGlobalProperties().DomainName;
}
catch
{
return string.Empty;
}
}, cts.Token);
if (!string.IsNullOrWhiteSpace(ipDomain) && !string.Equals(ipDomain, "localdomain", StringComparison.OrdinalIgnoreCase))
{
@@ -139,6 +142,68 @@ public static class DomainDiscovery
}
}
private static List<string> GetDnsServersWindows()
{
var servers = new List<string>();
try
{
foreach (var ni in NetworkInterface.GetAllNetworkInterfaces())
{
if (ni.OperationalStatus != OperationalStatus.Up)
{
continue;
}
var props = ni.GetIPProperties();
if (props is null)
{
continue;
}
foreach (var dns in props.DnsAddresses)
{
if (dns.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork && !servers.Contains(dns.ToString()))
{
servers.Add(dns.ToString());
}
}
}
}
catch
{
}
return servers;
}
private static List<string> GetDnsServersLinux()
{
var servers = new List<string>();
try
{
var lines = File.ReadAllLines("/etc/resolv.conf");
foreach (var line in lines)
{
var trimmed = line.Trim();
if (trimmed.StartsWith("nameserver ", StringComparison.OrdinalIgnoreCase))
{
var parts = trimmed.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (parts.Length >= 2 && IPAddress.TryParse(parts[1], out _))
{
servers.Add(parts[1]);
}
}
}
}
catch
{
}
return servers;
}
private static string? GetDomainFromResolvConf()
{
try
@@ -174,6 +239,62 @@ public static class DomainDiscovery
return null;
}
private static string? GetDomainFromWindows()
{
try
{
foreach (var ni in NetworkInterface.GetAllNetworkInterfaces())
{
if (ni.OperationalStatus != OperationalStatus.Up)
{
continue;
}
var props = ni.GetIPProperties();
if (props is null)
{
continue;
}
var suffix = props.DnsSuffix;
if (!string.IsNullOrWhiteSpace(suffix))
{
return suffix.TrimEnd('.');
}
}
}
catch
{
}
#pragma warning disable CA1416 // Registry access is guarded by platform check
try
{
using var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(
@"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters");
if (key is not null)
{
var domain = key.GetValue("Domain") as string;
if (!string.IsNullOrWhiteSpace(domain))
{
return domain.TrimEnd('.');
}
var dhcpDomain = key.GetValue("DhcpDomain") as string;
if (!string.IsNullOrWhiteSpace(dhcpDomain))
{
return dhcpDomain.TrimEnd('.');
}
}
}
catch
{
}
#pragma warning restore CA1416
return null;
}
private static string? GetDomainFromHostname()
{
try
@@ -192,7 +313,7 @@ public static class DomainDiscovery
try
{
var fullHostname = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().HostName;
var fullHostname = IPGlobalProperties.GetIPGlobalProperties().HostName;
var dotIndex = fullHostname.IndexOf('.');
if (dotIndex > 0 && dotIndex < fullHostname.Length - 1)
{