feat: Handle nameserver parsing on Windows
* system default nameserver in windows * changepull/14/head
parent
250591098b
commit
3019f1cee6
|
@ -1,18 +1,14 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
"github.com/mr-karan/doggo/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
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 specifies the default port for a DNS server connecting over TCP over TLS
|
||||||
DefaultTLSPort = "853"
|
DefaultTLSPort = "853"
|
||||||
// DefaultUDPPort specifies the default port for a DNS server connecting over UDP
|
// DefaultUDPPort specifies the default port for a DNS server connecting over UDP
|
||||||
|
@ -58,28 +54,20 @@ func (hub *Hub) loadNameservers() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getDefaultServers reads the `resolv.conf`
|
|
||||||
// file and returns a list of nameservers with it's config.
|
|
||||||
func getDefaultServers() ([]Nameserver, int, []string, error) {
|
func getDefaultServers() ([]Nameserver, int, []string, error) {
|
||||||
if runtime.GOOS == "windows" {
|
dnsServers, ndots, search, err := config.GetDefaultServers()
|
||||||
// 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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, nil, err
|
return nil, 0, nil, err
|
||||||
}
|
}
|
||||||
servers := make([]Nameserver, 0, len(cfg.Servers))
|
servers := make([]Nameserver, 0, len(dnsServers))
|
||||||
for _, s := range cfg.Servers {
|
for _, s := range dnsServers {
|
||||||
addr := net.JoinHostPort(s, cfg.Port)
|
|
||||||
ns := Nameserver{
|
ns := Nameserver{
|
||||||
Type: UDPResolver,
|
Type: UDPResolver,
|
||||||
Address: addr,
|
Address: net.JoinHostPort(s, DefaultUDPPort),
|
||||||
}
|
}
|
||||||
servers = append(servers, ns)
|
servers = append(servers, ns)
|
||||||
}
|
}
|
||||||
return servers, cfg.Ndots, cfg.Search, nil
|
return servers, ndots, search, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func initNameserver(n string) (Nameserver, error) {
|
func initNameserver(n string) (Nameserver, error) {
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -11,4 +11,5 @@ require (
|
||||||
github.com/sirupsen/logrus v1.7.0
|
github.com/sirupsen/logrus v1.7.0
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/stretchr/testify v1.6.1 // indirect
|
github.com/stretchr/testify v1.6.1 // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
// the whole `FEC0::/10` prefix is deprecated.
|
||||||
|
// [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
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/miekg/dns"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultResolvConfPath specifies path to default resolv config file on UNIX.
|
||||||
|
const DefaultResolvConfPath = "/etc/resolv.conf"
|
||||||
|
|
||||||
|
// GetDefaultServers get system default nameserver
|
||||||
|
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
|
||||||
|
}
|
||||||
|
servers := make([]string, 0)
|
||||||
|
for _, server := range cfg.Servers {
|
||||||
|
ip := net.ParseIP(server)
|
||||||
|
if isUnicastLinkLocal(ip) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
servers = append(servers, server)
|
||||||
|
}
|
||||||
|
return servers, cfg.Ndots, cfg.Search, nil
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GAA_FLAG_INCLUDE_GATEWAYS Return the addresses of default gateways.
|
||||||
|
// This flag is supported on Windows Vista and later.
|
||||||
|
const GAA_FLAG_INCLUDE_GATEWAYS = 0x00000080
|
||||||
|
|
||||||
|
// IpAdapterWinsServerAddress structure in a linked list of Windows Internet Name Service (WINS) server addresses for the adapter.
|
||||||
|
type IpAdapterWinsServerAddress struct {
|
||||||
|
Length uint32
|
||||||
|
_ uint32
|
||||||
|
Next *IpAdapterWinsServerAddress
|
||||||
|
Address windows.SocketAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
// IpAdapterGatewayAddress structure in a linked list of gateways for the adapter.
|
||||||
|
type IpAdapterGatewayAddress struct {
|
||||||
|
Length uint32
|
||||||
|
_ uint32
|
||||||
|
Next *IpAdapterGatewayAddress
|
||||||
|
Address windows.SocketAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
// IpAdapterAddresses structure is the header node for a linked list of addresses for a particular adapter.
|
||||||
|
// This structure can simultaneously be used as part of a linked list of IP_ADAPTER_ADDRESSES structures.
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDefaultServers get system default nameserver
|
||||||
|
func GetDefaultServers() ([]string, int, []string, error) {
|
||||||
|
// TODO: DNS Suffix
|
||||||
|
servers, err := getDefaultDNSServers()
|
||||||
|
return servers, 0, nil, err
|
||||||
|
}
|
Loading…
Reference in New Issue