golang.zx2c4.com/wireguard/windows@v0.5.4-0.20230123132234-dcc0eb72a04b/conf/dnsresolver_windows.go (about) 1 /* SPDX-License-Identifier: MIT 2 * 3 * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. 4 */ 5 6 package conf 7 8 import ( 9 "log" 10 "net/netip" 11 "time" 12 "unsafe" 13 14 "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" 15 16 "golang.org/x/sys/windows" 17 "golang.zx2c4.com/wireguard/windows/services" 18 ) 19 20 func resolveHostname(name string) (resolvedIPString string, err error) { 21 maxTries := 10 22 if services.StartedAtBoot() { 23 maxTries *= 3 24 } 25 for i := 0; i < maxTries; i++ { 26 if i > 0 { 27 time.Sleep(time.Second * 4) 28 } 29 resolvedIPString, err = resolveHostnameOnce(name) 30 if err == nil { 31 return 32 } 33 if err == windows.WSATRY_AGAIN { 34 log.Printf("Temporary DNS error when resolving %s, so sleeping for 4 seconds", name) 35 continue 36 } 37 if err == windows.WSAHOST_NOT_FOUND && services.StartedAtBoot() { 38 log.Printf("Host not found when resolving %s at boot time, so sleeping for 4 seconds", name) 39 continue 40 } 41 return 42 } 43 return 44 } 45 46 func resolveHostnameOnce(name string) (resolvedIPString string, err error) { 47 hints := windows.AddrinfoW{ 48 Family: windows.AF_UNSPEC, 49 Socktype: windows.SOCK_DGRAM, 50 Protocol: windows.IPPROTO_IP, 51 } 52 var result *windows.AddrinfoW 53 name16, err := windows.UTF16PtrFromString(name) 54 if err != nil { 55 return 56 } 57 err = windows.GetAddrInfoW(name16, nil, &hints, &result) 58 if err != nil { 59 return 60 } 61 if result == nil { 62 err = windows.WSAHOST_NOT_FOUND 63 return 64 } 65 defer windows.FreeAddrInfoW(result) 66 var v6 netip.Addr 67 for ; result != nil; result = result.Next { 68 if result.Family != windows.AF_INET && result.Family != windows.AF_INET6 { 69 continue 70 } 71 addr := (*winipcfg.RawSockaddrInet)(unsafe.Pointer(result.Addr)).Addr() 72 if addr.Is4() { 73 return addr.String(), nil 74 } else if !v6.IsValid() && addr.Is6() { 75 v6 = addr 76 } 77 } 78 if v6.IsValid() { 79 return v6.String(), nil 80 } 81 err = windows.WSAHOST_NOT_FOUND 82 return 83 } 84 85 func (config *Config) ResolveEndpoints() error { 86 for i := range config.Peers { 87 if config.Peers[i].Endpoint.IsEmpty() { 88 continue 89 } 90 var err error 91 config.Peers[i].Endpoint.Host, err = resolveHostname(config.Peers[i].Endpoint.Host) 92 if err != nil { 93 return err 94 } 95 } 96 return nil 97 }