mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-02-03 22:18:39 +00:00
On some platforms, the gateway may not be a usable DNS. So extending the current approach to allow retrieving DNS from many sources.
76 lines
1.4 KiB
Go
76 lines
1.4 KiB
Go
//go:build darwin || dragonfly || freebsd || netbsd || openbsd
|
|
|
|
package ctrld
|
|
|
|
import (
|
|
"net"
|
|
"os/exec"
|
|
"runtime"
|
|
"strings"
|
|
"syscall"
|
|
|
|
"golang.org/x/net/route"
|
|
)
|
|
|
|
func dnsFns() []dnsFn {
|
|
return []dnsFn{dnsFromRIB, dnsFromIPConfig}
|
|
}
|
|
|
|
func dnsFromRIB() []string {
|
|
var dns []string
|
|
rib, err := route.FetchRIB(syscall.AF_UNSPEC, route.RIBTypeRoute, 0)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
messages, err := route.ParseRIB(route.RIBTypeRoute, rib)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
for _, message := range messages {
|
|
message, ok := message.(*route.RouteMessage)
|
|
if !ok {
|
|
continue
|
|
}
|
|
addresses := message.Addrs
|
|
if len(addresses) < 2 {
|
|
continue
|
|
}
|
|
dst, gw := toNetIP(addresses[0]), toNetIP(addresses[1])
|
|
if dst == nil || gw == nil {
|
|
continue
|
|
}
|
|
if gw.IsLoopback() {
|
|
continue
|
|
}
|
|
if dst.Equal(net.IPv4zero) || dst.Equal(net.IPv6zero) {
|
|
dns = append(dns, gw.String())
|
|
}
|
|
}
|
|
return dns
|
|
}
|
|
|
|
func dnsFromIPConfig() []string {
|
|
if runtime.GOOS != "darwin" {
|
|
return nil
|
|
}
|
|
cmd := exec.Command("ipconfig", "getoption", "", "domain_name_server")
|
|
out, _ := cmd.Output()
|
|
if ip := net.ParseIP(strings.TrimSpace(string(out))); ip != nil {
|
|
return []string{ip.String()}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func toNetIP(addr route.Addr) net.IP {
|
|
switch t := addr.(type) {
|
|
case *route.Inet4Addr:
|
|
return net.IPv4(t.IP[0], t.IP[1], t.IP[2], t.IP[3])
|
|
case *route.Inet6Addr:
|
|
ip := make(net.IP, net.IPv6len)
|
|
copy(ip, t.IP[:])
|
|
return ip
|
|
default:
|
|
return nil
|
|
}
|
|
}
|