doggo/pkg/config/config_windows.go
2021-01-19 20:00:05 +08:00

123 lines
3.3 KiB
Go

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
}