system default nameserver in windows

This commit is contained in:
huangnauh 2021-01-19 19:35:53 +08:00
parent 250591098b
commit d873dc5b35
4 changed files with 149 additions and 18 deletions

View file

@ -1,18 +1,14 @@
package main
import (
"errors"
"fmt"
"net"
"net/url"
"runtime"
"github.com/miekg/dns"
"github.com/mr-karan/doggo/pkg/config"
)
const (
//DefaultResolvConfPath specifies path to default resolv config file on UNIX.
DefaultResolvConfPath = "/etc/resolv.conf"
// DefaultTLSPort specifies the default port for a DNS server connecting over TCP over TLS
DefaultTLSPort = "853"
// DefaultUDPPort specifies the default port for a DNS server connecting over UDP
@ -58,28 +54,20 @@ func (hub *Hub) loadNameservers() error {
return nil
}
// getDefaultServers reads the `resolv.conf`
// file and returns a list of nameservers with it's config.
func getDefaultServers() ([]Nameserver, int, []string, error) {
if runtime.GOOS == "windows" {
// TODO: Add a method for reading system default nameserver in windows.
return nil, 0, nil, errors.New(`unable to read default nameservers in this machine`)
}
// if no nameserver is provided, take it from `resolv.conf`
cfg, err := dns.ClientConfigFromFile(DefaultResolvConfPath)
dnsServers, ndots, search, err := config.GetDefaultServers()
if err != nil {
return nil, 0, nil, err
}
servers := make([]Nameserver, 0, len(cfg.Servers))
for _, s := range cfg.Servers {
addr := net.JoinHostPort(s, cfg.Port)
servers := make([]Nameserver, 0, len(dnsServers))
for _, s := range dnsServers {
ns := Nameserver{
Type: UDPResolver,
Address: addr,
Address: net.JoinHostPort(s, DefaultUDPPort),
}
servers = append(servers, ns)
}
return servers, cfg.Ndots, cfg.Search, nil
return servers, ndots, search, nil
}
func initNameserver(n string) (Nameserver, error) {

1
go.mod
View file

@ -11,4 +11,5 @@ require (
github.com/sirupsen/logrus v1.7.0
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.6.1 // indirect
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d
)

19
pkg/config/config_unix.go Normal file
View file

@ -0,0 +1,19 @@
// +build !windows
package config
import (
"github.com/miekg/dns"
)
//DefaultResolvConfPath specifies path to default resolv config file on UNIX.
const DefaultResolvConfPath = "/etc/resolv.conf"
func GetDefaultServers() ([]string, int, []string, error) {
// if no nameserver is provided, take it from `resolv.conf`
cfg, err := dns.ClientConfigFromFile(DefaultResolvConfPath)
if err != nil {
return nil, 0, nil, err
}
return cfg.Servers, cfg.Ndots, cfg.Search, nil
}

View file

@ -0,0 +1,123 @@
package config
import (
"net"
"os"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
const GAA_FLAG_INCLUDE_GATEWAYS = 0x00000080
type IpAdapterWinsServerAddress struct {
Length uint32
_ uint32
Next *IpAdapterWinsServerAddress
Address windows.SocketAddress
}
type IpAdapterGatewayAddress struct {
Length uint32
_ uint32
Next *IpAdapterGatewayAddress
Address windows.SocketAddress
}
type IpAdapterAddresses struct {
Length uint32
IfIndex uint32
Next *IpAdapterAddresses
AdapterName *byte
FirstUnicastAddress *windows.IpAdapterUnicastAddress
FirstAnycastAddress *windows.IpAdapterAnycastAddress
FirstMulticastAddress *windows.IpAdapterMulticastAddress
FirstDnsServerAddress *windows.IpAdapterDnsServerAdapter
DnsSuffix *uint16
Description *uint16
FriendlyName *uint16
PhysicalAddress [syscall.MAX_ADAPTER_ADDRESS_LENGTH]byte
PhysicalAddressLength uint32
Flags uint32
Mtu uint32
IfType uint32
OperStatus uint32
Ipv6IfIndex uint32
ZoneIndices [16]uint32
FirstPrefix *windows.IpAdapterPrefix
/* more fields might be present here. */
TransmitLinkSpeed uint64
ReceiveLinkSpeed uint64
FirstWINSServerAddress *IpAdapterWinsServerAddress
FirstGatewayAddress *IpAdapterGatewayAddress
}
func adapterAddresses() ([]*IpAdapterAddresses, error) {
var b []byte
// https://docs.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getadaptersaddresses
// #define WORKING_BUFFER_SIZE 15000
l := uint32(15000)
for {
b = make([]byte, l)
err := windows.GetAdaptersAddresses(syscall.AF_UNSPEC, GAA_FLAG_INCLUDE_GATEWAYS|windows.GAA_FLAG_INCLUDE_PREFIX, 0, (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])), &l)
if err == nil {
if l == 0 {
return nil, nil
}
break
}
if err.(syscall.Errno) != syscall.ERROR_BUFFER_OVERFLOW {
return nil, os.NewSyscallError("getadaptersaddresses", err)
}
if l <= uint32(len(b)) {
return nil, os.NewSyscallError("getadaptersaddresses", err)
}
}
aas := make([]*IpAdapterAddresses, 0, uintptr(l)/unsafe.Sizeof(IpAdapterAddresses{}))
for aa := (*IpAdapterAddresses)(unsafe.Pointer(&b[0])); aa != nil; aa = aa.Next {
aas = append(aas, aa)
}
return aas, nil
}
/// As per [RFC 3879], the whole `FEC0::/10` prefix is
/// deprecated. New software must not support site-local
/// addresses.
///
/// [RFC 3879]: https://tools.ietf.org/html/rfc3879
func isUnicastLinkLocal(ip net.IP) bool {
return len(ip) == net.IPv6len && ip[0] == 0xfe && ip[1] == 0xc0
}
func GetDefaultDnsServers() ([]string, error) {
ifs, err := adapterAddresses()
if err != nil {
return nil, err
}
dnsServers := make([]string, 0)
for _, ifi := range ifs {
if ifi.OperStatus != windows.IfOperStatusUp {
continue
}
if ifi.FirstGatewayAddress == nil {
continue
}
for dnsServer := ifi.FirstDnsServerAddress; dnsServer != nil; dnsServer = dnsServer.Next {
ip := dnsServer.Address.IP()
if isUnicastLinkLocal(ip) {
continue
}
dnsServers = append(dnsServers, ip.String())
}
}
return dnsServers, nil
}
func GetDefaultServers() ([]string, int, []string, error) {
// TODO: DNS Suffix
servers, err := GetDefaultDnsServers()
return servers, 0, nil, err
}