github.com/kelleygo/clashcore@v1.0.2/dns/system_windows.go (about)

     1  //go:build windows
     2  
     3  package dns
     4  
     5  import (
     6  	"net"
     7  	"os"
     8  	"syscall"
     9  	"unsafe"
    10  
    11  	"golang.org/x/sys/windows"
    12  )
    13  
    14  func dnsReadConfig() (servers []string, err error) {
    15  	aas, err := adapterAddresses()
    16  	if err != nil {
    17  		return
    18  	}
    19  	for _, aa := range aas {
    20  		for dns := aa.FirstDnsServerAddress; dns != nil; dns = dns.Next {
    21  			sa, err := dns.Address.Sockaddr.Sockaddr()
    22  			if err != nil {
    23  				continue
    24  			}
    25  			var ip net.IP
    26  			switch sa := sa.(type) {
    27  			case *syscall.SockaddrInet4:
    28  				ip = net.IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])
    29  			case *syscall.SockaddrInet6:
    30  				ip = make(net.IP, net.IPv6len)
    31  				copy(ip, sa.Addr[:])
    32  				if ip[0] == 0xfe && ip[1] == 0xc0 {
    33  					// Ignore these fec0/10 ones. Windows seems to
    34  					// populate them as defaults on its misc rando
    35  					// interfaces.
    36  					continue
    37  				}
    38  				//continue
    39  			default:
    40  				// Unexpected type.
    41  				continue
    42  			}
    43  			servers = append(servers, ip.String())
    44  		}
    45  	}
    46  	return
    47  }
    48  
    49  // adapterAddresses returns a list of IP adapter and address
    50  // structures. The structure contains an IP adapter and flattened
    51  // multiple IP addresses including unicast, anycast and multicast
    52  // addresses.
    53  func adapterAddresses() ([]*windows.IpAdapterAddresses, error) {
    54  	var b []byte
    55  	l := uint32(15000) // recommended initial size
    56  	for {
    57  		b = make([]byte, l)
    58  		err := windows.GetAdaptersAddresses(syscall.AF_UNSPEC, windows.GAA_FLAG_INCLUDE_PREFIX, 0, (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])), &l)
    59  		if err == nil {
    60  			if l == 0 {
    61  				return nil, nil
    62  			}
    63  			break
    64  		}
    65  		if err.(syscall.Errno) != syscall.ERROR_BUFFER_OVERFLOW {
    66  			return nil, os.NewSyscallError("getadaptersaddresses", err)
    67  		}
    68  		if l <= uint32(len(b)) {
    69  			return nil, os.NewSyscallError("getadaptersaddresses", err)
    70  		}
    71  	}
    72  	var aas []*windows.IpAdapterAddresses
    73  	for aa := (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])); aa != nil; aa = aa.Next {
    74  		aas = append(aas, aa)
    75  	}
    76  	return aas, nil
    77  }