diff --git a/nameserver.go b/nameserver.go index a329252..e976afb 100644 --- a/nameserver.go +++ b/nameserver.go @@ -1,17 +1,37 @@ package main import ( + "context" "fmt" "log" "net" "os/exec" "strings" + "time" ) -func requiresRRUpdate(entry *RRConfig, addr net.IP) bool { - // TODO: use custom resolver to query authoritive nameserver instead of - // local resolver - addrs, err := net.LookupIP(entry.Recordname) +const ( + resolverTimeout = time.Millisecond * time.Duration(8000) +) + +func getResolver(nameserver string) *net.Resolver { + return &net.Resolver{ + // use go's built-in dns resolver + PreferGo: true, + // specify alternate dialer for go's dns resolver + Dial: func(ctx context.Context, network, address string) (net.Conn, error) { + d := net.Dialer{ + Timeout: resolverTimeout, + } + return d.DialContext(ctx, network, nameserver) + }, + } +} + +func requiresRRUpdate(record string, addr net.IP, resolver *net.Resolver) bool { + // TODO: the context could be replaced in order to allow cancelling the dns + // query if the user disconnects prematurely + addrs, err := resolver.LookupIP(context.Background(), "ip", record) if err != nil { log.Printf("dns lookup failed: %s", err) // enforce update, it's better than not trying at all diff --git a/web.go b/web.go index 0d7caf2..eeba733 100644 --- a/web.go +++ b/web.go @@ -124,7 +124,7 @@ func RequestHandler(cfg *Config) func(w http.ResponseWriter, r *http.Request) { return } - if !requiresRRUpdate(entry, ipaddr) { + if !requiresRRUpdate(entry.Recordname, ipaddr, getResolver(entry.Nameserver)) { fmt.Fprintf(w, "nochg %s\n", ipaddr.String()) return }