diff options
| author | Tero Marttila <[email protected]> | 2016-06-19 20:05:55 +0300 |
|---|---|---|
| committer | Tero Marttila <[email protected]> | 2016-06-19 20:05:55 +0300 |
| commit | b2f9c977719626bebd9c9f9f7e52e50f2514ace7 (patch) | |
| tree | 70d9fd46fd2582d7390c41917114de4ef4c76117 | |
| parent | 9026b24cc14cbf8806b1d706e3768169dcc4d0c8 (diff) | |
autodiscover server from zone SOA
| -rw-r--r-- | dns.go | 51 | ||||
| -rw-r--r-- | main.go | 2 | ||||
| -rw-r--r-- | update.go | 34 |
3 files changed, 82 insertions, 5 deletions
@@ -3,6 +3,9 @@ package main import ( "github.com/miekg/dns" "fmt" + "time" + "log" + "net" ) const TSIG_FUDGE_SECONDS = 300 @@ -24,3 +27,51 @@ func (t *TSIGAlgorithm) UnmarshalFlag(value string) error { return nil } + +func query(query *dns.Msg) (*dns.Msg, error) { + clientConfig, err := dns.ClientConfigFromFile("/etc/resolv.conf") + if err != nil { + return nil, err + } + + timeout := time.Duration(clientConfig.Timeout * int(time.Second)) + + var client = new(dns.Client) + + client.DialTimeout = timeout + client.ReadTimeout = timeout + client.WriteTimeout = timeout + + for _, server := range clientConfig.Servers { + addr := net.JoinHostPort(server, "53") + + if answer, _, err := client.Exchange(query, addr); err != nil { + log.Printf("query %v: %v", server, err) + continue + } else { + return answer, nil + } + } + + return nil, fmt.Errorf("DNS query failed") +} + +// Discover likely master NS for zone +func discoverZoneServer(zone string) (string, error) { + var q = new(dns.Msg) + + q.SetQuestion(zone, dns.TypeSOA) + + r, err := query(q) + if err != nil { + return "", err + } + + for _, rr := range r.Answer { + if soa, ok := rr.(*dns.SOA); ok { + return soa.Ns, nil + } + } + + return "", fmt.Errorf("No SOA response") +} @@ -62,5 +62,7 @@ func main() { // update if err := update.Update(addrs, options.Verbose); err != nil { log.Fatalf("update: %v", err) + } else { + log.Printf("update: ok") } } @@ -20,13 +20,37 @@ type Update struct { } func (u *Update) Init(name string, zone string, server string) error { - u.name = dns.Fqdn(name) - u.zone = dns.Fqdn(zone) + if name == "" { + return fmt.Errorf("Missing name") + } else { + u.name = dns.Fqdn(name) + } - if _, _, err := net.SplitHostPort(server); err == nil { - u.server = server + if zone == "" { + // guess + if labels := dns.Split(u.name); len(labels) > 1 { + u.zone = u.name[labels[1]:] + } else { + return fmt.Errorf("Missing zone") + } } else { - u.server = net.JoinHostPort(server, "53") + u.zone = dns.Fqdn(zone) + } + + if server == "" { + if server, err := discoverZoneServer(u.zone); err != nil { + return fmt.Errorf("Failed to discver server") + } else { + log.Printf("discover server=%v", server) + + u.server = net.JoinHostPort(server, "53") + } + } else { + if _, _, err := net.SplitHostPort(server); err == nil { + u.server = server + } else { + u.server = net.JoinHostPort(server, "53") + } } return nil |
