package main import ( "fmt" "log" "net" "os/exec" "strings" ) 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) if err != nil { log.Printf("dns lookup failed: %s", err) // enforce update, it's better than not trying at all return true } // check if the current ip matches for _, ip := range addrs { if ip.Equal(addr) { // the ip seems to be still up-to-date -> no update required return false } } return true } func updateRR(entry *RRConfig, addr net.IP) error { query := generateQuery(entry, addr) return executeQuery(query) } func generateQuery(entry *RRConfig, addr net.IP) string { var q strings.Builder fmt.Fprintf(&q, "key %s:%s %s\n", entry.Tsigalgo, entry.Tsigid, entry.Tsigkey) fmt.Fprintf(&q, "server %s\n", entry.Nameserver) fmt.Fprintf(&q, "zone %s\n", entry.Zonename) // TODO: check if addr is ipv4 or ipv6 (-> update A or AAAA) fmt.Fprintf(&q, "add %s. %d A %s\n", entry.Recordname, entry.Ttl, addr.String()) fmt.Fprintf(&q, "send\n") return q.String() } func executeQuery(query string) error { cmd := exec.Command("knsupdate", "-v") cmd.Stdin = strings.NewReader(query) output, err := cmd.CombinedOutput() // TODO: is outputting stdout+stderr on failure even necessary? if err != nil { log.Printf("executeQuery failed: %s", output) } return err }