mirror of
https://github.com/fosrl/olm.git
synced 2026-02-08 05:56:41 +00:00
159 lines
4.2 KiB
Go
159 lines
4.2 KiB
Go
//go:build (linux && !android) || freebsd
|
|
|
|
package dns
|
|
|
|
import (
|
|
"bufio"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/fosrl/newt/logger"
|
|
)
|
|
|
|
const defaultResolvConfPath = "/etc/resolv.conf"
|
|
|
|
// DNSManagerType represents the type of DNS manager detected
|
|
type DNSManagerType int
|
|
|
|
const (
|
|
// UnknownManager indicates we couldn't determine the DNS manager
|
|
UnknownManager DNSManagerType = iota
|
|
// SystemdResolvedManager indicates systemd-resolved is managing DNS
|
|
SystemdResolvedManager
|
|
// NetworkManagerManager indicates NetworkManager is managing DNS
|
|
NetworkManagerManager
|
|
// ResolvconfManager indicates resolvconf is managing DNS
|
|
ResolvconfManager
|
|
// FileManager indicates direct file management (no DNS manager)
|
|
FileManager
|
|
)
|
|
|
|
// DetectDNSManagerFromFile reads /etc/resolv.conf to determine which DNS manager is in use
|
|
// This provides a hint based on comments in the file, similar to Netbird's approach
|
|
func DetectDNSManagerFromFile() DNSManagerType {
|
|
file, err := os.Open(defaultResolvConfPath)
|
|
if err != nil {
|
|
return UnknownManager
|
|
}
|
|
defer file.Close()
|
|
|
|
scanner := bufio.NewScanner(file)
|
|
for scanner.Scan() {
|
|
text := scanner.Text()
|
|
if len(text) == 0 {
|
|
continue
|
|
}
|
|
|
|
// If we hit a non-comment line, default to file-based
|
|
if text[0] != '#' {
|
|
return FileManager
|
|
}
|
|
|
|
// Check for DNS manager signatures in comments
|
|
if strings.Contains(text, "NetworkManager") {
|
|
return NetworkManagerManager
|
|
}
|
|
|
|
if strings.Contains(text, "systemd-resolved") {
|
|
return SystemdResolvedManager
|
|
}
|
|
|
|
if strings.Contains(text, "resolvconf") {
|
|
return ResolvconfManager
|
|
}
|
|
}
|
|
|
|
if err := scanner.Err(); err != nil && err != io.EOF {
|
|
return UnknownManager
|
|
}
|
|
|
|
// No indicators found, assume file-based management
|
|
return FileManager
|
|
}
|
|
|
|
// String returns a human-readable name for the DNS manager type
|
|
func (d DNSManagerType) String() string {
|
|
switch d {
|
|
case SystemdResolvedManager:
|
|
return "systemd-resolved"
|
|
case NetworkManagerManager:
|
|
return "NetworkManager"
|
|
case ResolvconfManager:
|
|
return "resolvconf"
|
|
case FileManager:
|
|
return "file"
|
|
default:
|
|
return "unknown"
|
|
}
|
|
}
|
|
|
|
// DetectDNSManager combines file detection with runtime availability checks
|
|
// to determine the best DNS configurator to use
|
|
func DetectDNSManager(interfaceName string) DNSManagerType {
|
|
// First check what the file suggests
|
|
fileHint := DetectDNSManagerFromFile()
|
|
|
|
// Verify the hint with runtime checks
|
|
switch fileHint {
|
|
case SystemdResolvedManager:
|
|
// Verify systemd-resolved is actually running
|
|
if IsSystemdResolvedAvailable() {
|
|
return SystemdResolvedManager
|
|
}
|
|
logger.Warn("dns platform: Found systemd-resolved but it is not running. Falling back to file...")
|
|
os.Exit(0)
|
|
return FileManager
|
|
|
|
case NetworkManagerManager:
|
|
// Verify NetworkManager is actually running
|
|
if IsNetworkManagerAvailable() {
|
|
// Check if NetworkManager is delegating to systemd-resolved
|
|
if !IsNetworkManagerDNSModeSupported() {
|
|
logger.Info("NetworkManager is delegating DNS to systemd-resolved, using systemd-resolved configurator")
|
|
if IsSystemdResolvedAvailable() {
|
|
return SystemdResolvedManager
|
|
}
|
|
}
|
|
return NetworkManagerManager
|
|
}
|
|
logger.Warn("dns platform: Found network manager but it is not running. Falling back to file...")
|
|
return FileManager
|
|
|
|
case ResolvconfManager:
|
|
// Verify resolvconf is available
|
|
if IsResolvconfAvailable() {
|
|
return ResolvconfManager
|
|
}
|
|
// If resolvconf is mentioned but not available, fall back to file
|
|
return FileManager
|
|
|
|
case FileManager:
|
|
// File suggests direct file management
|
|
// But we should still check if a manager is available that wasn't mentioned
|
|
if IsSystemdResolvedAvailable() && interfaceName != "" {
|
|
return SystemdResolvedManager
|
|
}
|
|
if IsNetworkManagerAvailable() && interfaceName != "" {
|
|
return NetworkManagerManager
|
|
}
|
|
if IsResolvconfAvailable() && interfaceName != "" {
|
|
return ResolvconfManager
|
|
}
|
|
return FileManager
|
|
|
|
default:
|
|
// Unknown - do runtime detection
|
|
if IsSystemdResolvedAvailable() && interfaceName != "" {
|
|
return SystemdResolvedManager
|
|
}
|
|
if IsNetworkManagerAvailable() && interfaceName != "" {
|
|
return NetworkManagerManager
|
|
}
|
|
if IsResolvconfAvailable() && interfaceName != "" {
|
|
return ResolvconfManager
|
|
}
|
|
return FileManager
|
|
}
|
|
}
|