From 1a35b5aa2b4a891dc4bfbe27eee67c7c18b82fe4 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Sun, 26 Apr 2015 11:20:44 +0100 Subject: [PATCH 1/3] align queryHandler and rdnsHandler increasing their similarity in preparation of refactor --- nameserver/server.go | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/nameserver/server.go b/nameserver/server.go index 2aada3c3..19b6e261 100644 --- a/nameserver/server.go +++ b/nameserver/server.go @@ -215,12 +215,15 @@ func (s *DNSServer) Stop() error { } func (s *DNSServer) queryHandler(proto dnsProtocol) dns.HandlerFunc { + fallback := func(w dns.ResponseWriter, r *dns.Msg) { + w.WriteMsg(makeDNSFailResponse(r)) + } return func(w dns.ResponseWriter, r *dns.Msg) { - now := time.Now() q := r.Question[0] + Debug.Printf("[dns msgid %d] Query: %+v", r.MsgHdr.Id, q) + now := time.Now() maxLen := getMaxReplyLen(r, proto) lookups := []ZoneLookup{s.Zone, s.mdnsCli} - Debug.Printf("Query: %+v", q) reply, err := s.cache.Get(r, maxLen, time.Now()) if err != nil { @@ -242,7 +245,7 @@ func (s *DNSServer) queryHandler(proto dnsProtocol) dns.HandlerFunc { // catch unsupported queries if q.Qtype != dns.TypeA { - Debug.Printf("[dns msgid %d] Unsuported query type %s", r.MsgHdr.Id, dns.TypeToString[q.Qtype]) + Debug.Printf("[dns msgid %d] Unsupported query type %s", r.MsgHdr.Id, dns.TypeToString[q.Qtype]) m := makeDNSNotImplResponse(r) s.cache.Put(r, m, negLocalTTL, 0, now) w.WriteMsg(m) @@ -254,7 +257,7 @@ func (s *DNSServer) queryHandler(proto dnsProtocol) dns.HandlerFunc { m := makeAddressReply(r, &q, ips) m.Authoritative = true - Debug.Printf("[dns msgid %d] Caching response for %s-query for \"%s\": %s [code:%s]", + Debug.Printf("[dns msgid %d] Caching response for type %s query for '%s': %s [code:%s]", m.MsgHdr.Id, dns.TypeToString[q.Qtype], q.Name, ips, dns.RcodeToString[m.Rcode]) s.cache.Put(r, m, nullTTL, 0, now) w.WriteMsg(m) @@ -263,22 +266,27 @@ func (s *DNSServer) queryHandler(proto dnsProtocol) dns.HandlerFunc { now = time.Now() } - Info.Printf("[dns msgid %d] No results for type %s query %s [caching no-local]", + Info.Printf("[dns msgid %d] No results for type %s query for '%s' [caching no-local]", r.MsgHdr.Id, dns.TypeToString[q.Qtype], q.Name) s.cache.Put(r, nil, negLocalTTL, CacheNoLocalReplies, now) - w.WriteMsg(makeDNSFailResponse(r)) + + fallback(w, r) } } func (s *DNSServer) rdnsHandler(proto dnsProtocol) dns.HandlerFunc { - fallback := s.notUsHandler(proto) + notUsHandler := s.notUsHandler(proto) + fallback := func(w dns.ResponseWriter, r *dns.Msg) { + Info.Printf("[dns msgid %d] -> sending to fallback server", r.MsgHdr.Id) + notUsHandler(w, r) + } return func(w dns.ResponseWriter, r *dns.Msg) { - now := time.Now() q := r.Question[0] - lookups := []ZoneLookup{s.Zone, s.mdnsCli} + Debug.Printf("[dns msgid %d] Reverse query: %+v", r.MsgHdr.Id, q) + now := time.Now() maxLen := getMaxReplyLen(r, proto) + lookups := []ZoneLookup{s.Zone, s.mdnsCli} - Debug.Printf("Reverse query: %+v", q) reply, err := s.cache.Get(r, maxLen, time.Now()) if err != nil { if err == errNoLocalReplies { @@ -299,8 +307,7 @@ func (s *DNSServer) rdnsHandler(proto dnsProtocol) dns.HandlerFunc { // catch unsupported queries if q.Qtype != dns.TypePTR { - Warning.Printf("[dns msgid %d] Unexpected reverse query type %s: %+v", - r.MsgHdr.Id, dns.TypeToString[q.Qtype], q) + Debug.Printf("[dns msgid %d] Unsupported query type %s", r.MsgHdr.Id, dns.TypeToString[q.Qtype]) m := makeDNSNotImplResponse(r) s.cache.Put(r, m, negLocalTTL, 0, now) w.WriteMsg(m) @@ -312,7 +319,7 @@ func (s *DNSServer) rdnsHandler(proto dnsProtocol) dns.HandlerFunc { m := makePTRReply(r, &q, names) m.Authoritative = true - Debug.Printf("[dns msgid %d] Caching response for %s-query for \"%s\": %s [code:%s]", + Debug.Printf("[dns msgid %d] Caching response for type %s query for '%s': %s [code:%s]", m.MsgHdr.Id, dns.TypeToString[q.Qtype], q.Name, names, dns.RcodeToString[m.Rcode]) s.cache.Put(r, m, nullTTL, 0, now) w.WriteMsg(m) @@ -321,9 +328,10 @@ func (s *DNSServer) rdnsHandler(proto dnsProtocol) dns.HandlerFunc { now = time.Now() } - Info.Printf("[dns msgid %d] No results for %s-query about '%s' [caching no-local] -> sending to fallback server", + Info.Printf("[dns msgid %d] No results for type %s query for '%s' [caching no-local]", r.MsgHdr.Id, dns.TypeToString[q.Qtype], q.Name) s.cache.Put(r, nil, negLocalTTL, CacheNoLocalReplies, now) + fallback(w, r) } } From cb42ec358e1d959c185050f5bb1091ea70348a42 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Sun, 26 Apr 2015 11:40:28 +0100 Subject: [PATCH 2/3] even more alignment between queryHandler and rdnsHandler in preparation of extracting common helper function --- nameserver/server.go | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/nameserver/server.go b/nameserver/server.go index 19b6e261..dfc7e880 100644 --- a/nameserver/server.go +++ b/nameserver/server.go @@ -215,9 +215,18 @@ func (s *DNSServer) Stop() error { } func (s *DNSServer) queryHandler(proto dnsProtocol) dns.HandlerFunc { + zoneLookup := func(lookup ZoneLookup, q *dns.Question, r *dns.Msg) (*dns.Msg, []ZoneRecord, error) { + if ips, err := lookup.LookupName(q.Name); err != nil { + return nil, nil, err + } else { + return makeAddressReply(r, q, ips), ips, nil + } + } + fallback := func(w dns.ResponseWriter, r *dns.Msg) { w.WriteMsg(makeDNSFailResponse(r)) } + return func(w dns.ResponseWriter, r *dns.Msg) { q := r.Question[0] Debug.Printf("[dns msgid %d] Query: %+v", r.MsgHdr.Id, q) @@ -253,12 +262,10 @@ func (s *DNSServer) queryHandler(proto dnsProtocol) dns.HandlerFunc { } for _, lookup := range lookups { - if ips, err := lookup.LookupName(q.Name); err == nil { - m := makeAddressReply(r, &q, ips) + if m, answers, err := zoneLookup(lookup, &q, r); err == nil { m.Authoritative = true - Debug.Printf("[dns msgid %d] Caching response for type %s query for '%s': %s [code:%s]", - m.MsgHdr.Id, dns.TypeToString[q.Qtype], q.Name, ips, dns.RcodeToString[m.Rcode]) + m.MsgHdr.Id, dns.TypeToString[q.Qtype], q.Name, answers, dns.RcodeToString[m.Rcode]) s.cache.Put(r, m, nullTTL, 0, now) w.WriteMsg(m) return @@ -275,11 +282,20 @@ func (s *DNSServer) queryHandler(proto dnsProtocol) dns.HandlerFunc { } func (s *DNSServer) rdnsHandler(proto dnsProtocol) dns.HandlerFunc { + zoneLookup := func(lookup ZoneLookup, q *dns.Question, r *dns.Msg) (*dns.Msg, []ZoneRecord, error) { + if names, err := lookup.LookupInaddr(q.Name); err != nil { + return nil, nil, err + } else { + return makePTRReply(r, q, names), names, nil + } + } + notUsHandler := s.notUsHandler(proto) fallback := func(w dns.ResponseWriter, r *dns.Msg) { Info.Printf("[dns msgid %d] -> sending to fallback server", r.MsgHdr.Id) notUsHandler(w, r) } + return func(w dns.ResponseWriter, r *dns.Msg) { q := r.Question[0] Debug.Printf("[dns msgid %d] Reverse query: %+v", r.MsgHdr.Id, q) @@ -315,12 +331,10 @@ func (s *DNSServer) rdnsHandler(proto dnsProtocol) dns.HandlerFunc { } for _, lookup := range lookups { - if names, err := lookup.LookupInaddr(q.Name); err == nil { - m := makePTRReply(r, &q, names) + if m, answers, err := zoneLookup(lookup, &q, r); err == nil { m.Authoritative = true - Debug.Printf("[dns msgid %d] Caching response for type %s query for '%s': %s [code:%s]", - m.MsgHdr.Id, dns.TypeToString[q.Qtype], q.Name, names, dns.RcodeToString[m.Rcode]) + m.MsgHdr.Id, dns.TypeToString[q.Qtype], q.Name, answers, dns.RcodeToString[m.Rcode]) s.cache.Put(r, m, nullTTL, 0, now) w.WriteMsg(m) return From ce4c79ed936c1e1589be6cbc9ac438bbcb32b1da Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Sun, 26 Apr 2015 12:40:34 +0100 Subject: [PATCH 3/3] refactor: extract commonQueryHandler to remove duplication between queryHandler and rdnsHandler --- nameserver/server.go | 63 +++++++------------------------------------- 1 file changed, 9 insertions(+), 54 deletions(-) diff --git a/nameserver/server.go b/nameserver/server.go index dfc7e880..d80846fb 100644 --- a/nameserver/server.go +++ b/nameserver/server.go @@ -227,58 +227,7 @@ func (s *DNSServer) queryHandler(proto dnsProtocol) dns.HandlerFunc { w.WriteMsg(makeDNSFailResponse(r)) } - return func(w dns.ResponseWriter, r *dns.Msg) { - q := r.Question[0] - Debug.Printf("[dns msgid %d] Query: %+v", r.MsgHdr.Id, q) - now := time.Now() - maxLen := getMaxReplyLen(r, proto) - lookups := []ZoneLookup{s.Zone, s.mdnsCli} - - reply, err := s.cache.Get(r, maxLen, time.Now()) - if err != nil { - if err == errNoLocalReplies { - Debug.Printf("[dns msgid %d] Cached 'no local replies' - skipping local lookup", r.MsgHdr.Id) - lookups = []ZoneLookup{s.Zone} - } else { - Debug.Printf("[dns msgid %d] Error from cache: %s", r.MsgHdr.Id, err) - w.WriteMsg(makeDNSFailResponse(r)) - return - } - } - if reply != nil { - Debug.Printf("[dns msgid %d] Returning reply from cache: %s/%d answers", - r.MsgHdr.Id, dns.RcodeToString[reply.MsgHdr.Rcode], len(reply.Answer)) - w.WriteMsg(reply) - return - } - - // catch unsupported queries - if q.Qtype != dns.TypeA { - Debug.Printf("[dns msgid %d] Unsupported query type %s", r.MsgHdr.Id, dns.TypeToString[q.Qtype]) - m := makeDNSNotImplResponse(r) - s.cache.Put(r, m, negLocalTTL, 0, now) - w.WriteMsg(m) - return - } - - for _, lookup := range lookups { - if m, answers, err := zoneLookup(lookup, &q, r); err == nil { - m.Authoritative = true - Debug.Printf("[dns msgid %d] Caching response for type %s query for '%s': %s [code:%s]", - m.MsgHdr.Id, dns.TypeToString[q.Qtype], q.Name, answers, dns.RcodeToString[m.Rcode]) - s.cache.Put(r, m, nullTTL, 0, now) - w.WriteMsg(m) - return - } - now = time.Now() - } - - Info.Printf("[dns msgid %d] No results for type %s query for '%s' [caching no-local]", - r.MsgHdr.Id, dns.TypeToString[q.Qtype], q.Name) - s.cache.Put(r, nil, negLocalTTL, CacheNoLocalReplies, now) - - fallback(w, r) - } + return s.commonQueryHandler(proto, "Query", dns.TypeA, zoneLookup, fallback) } func (s *DNSServer) rdnsHandler(proto dnsProtocol) dns.HandlerFunc { @@ -296,9 +245,15 @@ func (s *DNSServer) rdnsHandler(proto dnsProtocol) dns.HandlerFunc { notUsHandler(w, r) } + return s.commonQueryHandler(proto, "Reverse query", dns.TypePTR, zoneLookup, fallback) +} + +func (s *DNSServer) commonQueryHandler(proto dnsProtocol, kind string, qtype uint16, + zoneLookup func(ZoneLookup, *dns.Question, *dns.Msg) (*dns.Msg, []ZoneRecord, error), fallback dns.HandlerFunc) dns.HandlerFunc { + return func(w dns.ResponseWriter, r *dns.Msg) { q := r.Question[0] - Debug.Printf("[dns msgid %d] Reverse query: %+v", r.MsgHdr.Id, q) + Debug.Printf("[dns msgid %d] %s: %+v", r.MsgHdr.Id, kind, q) now := time.Now() maxLen := getMaxReplyLen(r, proto) lookups := []ZoneLookup{s.Zone, s.mdnsCli} @@ -322,7 +277,7 @@ func (s *DNSServer) rdnsHandler(proto dnsProtocol) dns.HandlerFunc { } // catch unsupported queries - if q.Qtype != dns.TypePTR { + if q.Qtype != qtype { Debug.Printf("[dns msgid %d] Unsupported query type %s", r.MsgHdr.Id, dns.TypeToString[q.Qtype]) m := makeDNSNotImplResponse(r) s.cache.Put(r, m, negLocalTTL, 0, now)