-
Notifications
You must be signed in to change notification settings - Fork 0
/
handler.go
77 lines (66 loc) · 1.81 KB
/
handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package main
import "github.com/miekg/dns"
func (s *Server) recurse(w dns.ResponseWriter, req *dns.Msg) {
if s.recurseTo == "" {
dns.HandleFailed(w, req)
return
}
c := new(dns.Client)
in, _, err := c.Exchange(req, s.recurseTo)
if err == nil {
if in.MsgHdr.Truncated {
c.Net = "tcp"
in, _, err = c.Exchange(req, s.recurseTo)
}
w.WriteMsg(in)
return
}
log.Warnf("Recursive error: %+v", err)
dns.HandleFailed(w, req)
}
func (s *Server) do(Net string, w dns.ResponseWriter, req *dns.Msg) {
if len(req.Question) != 1 {
dns.HandleFailed(w, req)
return
}
zone, name := s.zones.match(req.Question[0].Name, req.Question[0].Qtype)
if zone == nil {
s.recurse(w, req)
return
}
s.zones.Lock()
defer s.zones.Unlock()
m := new(dns.Msg)
m.SetReply(req)
var answerKnown bool
dnsreq := dns.RR_Header{Name: req.Question[0].Name, Rrtype: req.Question[0].Qtype, Class: req.Question[0].Qclass}
for _, r := range (*zone)[dnsreq] {
m.Answer = append(m.Answer, r)
answerKnown = true
}
// TODO: more logs here
s.roundRobin(zone, dnsreq)
if !answerKnown && s.recurseTo != "" {
s.recurse(w, req)
return
}
// Add Authority section
for _, r := range (*zone)[dns.RR_Header{Name: name, Rrtype: dns.TypeNS, Class: dns.ClassINET}] {
m.Ns = append(m.Ns, r)
// Resolve Authority if possible and serve as Extra
for _, r := range (*zone)[dns.RR_Header{Name: r.(*dns.NS).Ns, Rrtype: dns.TypeA, Class: dns.ClassINET}] {
m.Extra = append(m.Extra, r)
}
for _, r := range (*zone)[dns.RR_Header{Name: r.(*dns.NS).Ns, Rrtype: dns.TypeAAAA, Class: dns.ClassINET}] {
m.Extra = append(m.Extra, r)
}
}
m.Authoritative = true
w.WriteMsg(m)
}
func (s *Server) DoTCP(w dns.ResponseWriter, req *dns.Msg) {
s.do("tcp", w, req)
}
func (s *Server) DoUDP(w dns.ResponseWriter, req *dns.Msg) {
s.do("udp", w, req)
}