This repository was archived by the owner on Jan 16, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathhandler.go
110 lines (98 loc) · 2.9 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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package main
import (
"net"
"github.com/miekg/dns"
)
type question struct {
qname string
qtype string
qclass string
}
func (q *question) String() string {
return q.qname + " " + q.qclass + " " + q.qtype
}
type gnoccoHandler struct {
Cache *cache
Resolver *resolver
MaxJobs int
Jobs int
}
func newHandler(m int) *gnoccoHandler {
c := newCache(int64(mainconfig.Cache.MaxCount), int32(mainconfig.Cache.Expire))
r := initResolver()
return &gnoccoHandler{c, r, m, 0}
}
func (h *gnoccoHandler) do(Net string, w dns.ResponseWriter, req *dns.Msg) {
if h.Jobs < h.MaxJobs {
q := req.Question[0]
Q := question{q.Name, dns.TypeToString[q.Qtype], dns.ClassToString[q.Qclass]}
var remote net.IP
if Net == "tcp" {
remote = w.RemoteAddr().(*net.TCPAddr).IP
} else {
remote = w.RemoteAddr().(*net.UDPAddr).IP
}
logger.Info("%s lookup %s", remote, Q.String())
h.Jobs++
switch {
case Q.qclass == "IN":
if recs, err := h.Cache.get(h.Cache.makeKey(Q.qname, Q.qtype)); err == nil {
//we have an answer now construct a dns.Msg
result := new(dns.Msg)
result.SetReply(req)
for _, z := range recs.Value {
rec, _ := dns.NewRR(dns.Fqdn(Q.qname) + " " + Q.qtype + " " + z)
result.Answer = append(result.Answer, rec)
}
w.WriteMsg(result)
} else {
if rcs, err := h.Cache.get(h.Cache.makeKey(Q.qname, "CNAME")); err == nil {
logger.Info("Found CNAME %s", rcs.String())
result := new(dns.Msg)
result.SetReply(req)
for _, z := range rcs.Value {
rc, _ := dns.NewRR(dns.Fqdn(Q.qname) + " " + "CNAME" + " " + z)
result.Answer = append(result.Answer, rc)
if rt, err := h.Cache.get(h.Cache.makeKey(z, Q.qtype)); err == nil {
for _, ey := range rt.Value {
gg, _ := dns.NewRR(z + " " + Q.qtype + " " + ey)
result.Answer = append(result.Answer, gg)
}
}
}
w.WriteMsg(result)
} else {
h.Resolver.Lookup(h.Cache, w, req)
}
}
case Q.qclass == "CH", Q.qtype == "TXT":
m := new(dns.Msg)
m.SetReply(req)
hdr := dns.RR_Header{Name: Q.qname, Rrtype: dns.TypeTXT, Class: dns.ClassCHAOS, Ttl: 0}
switch Q.qname {
case "authors.bind.":
m.Answer = append(m.Answer, &dns.TXT{Hdr: hdr, Txt: []string{"Nagy Karoly Gabriel <[email protected]>"}})
case "version.bind.", "version.server.":
m.Answer = []dns.RR{&dns.TXT{Hdr: hdr, Txt: []string{"Version " + Version + " built on " + BuildDate}}}
case "hostname.bind.", "id.server.":
m.Answer = []dns.RR{&dns.TXT{Hdr: hdr, Txt: []string{"localhost"}}}
default:
m.SetRcode(req, dns.RcodeNotImplemented)
w.WriteMsg(m)
}
w.WriteMsg(m)
default:
}
h.Jobs--
} else {
m := new(dns.Msg)
m.SetRcode(req, dns.RcodeServerFailure)
w.WriteMsg(m)
}
}
func (h *gnoccoHandler) doTCP(w dns.ResponseWriter, req *dns.Msg) {
h.do("tcp", w, req)
}
func (h *gnoccoHandler) doUDP(w dns.ResponseWriter, req *dns.Msg) {
h.do("udp", w, req)
}