This commit is contained in:
Miek Gieben 2011-07-26 19:16:28 +02:00
parent 2a19a54a9c
commit 47cc5b3e77
5 changed files with 154 additions and 8 deletions

View File

@ -4,7 +4,9 @@ key2ds \
axfr \
reflect \
q \
funkensturm
funkensturm \
ns \
all:
for i in $(EXAMPLES); do gomake -C $$i; done

View File

@ -1,9 +1,128 @@
package main
import (
"dns"
import (
"os"
"dns"
"fmt"
"bufio"
"os/signal"
)
func main() {
// A small nameserver implementation.
// Not too fast.
var zone *dns.Zone
func send(w dns.ResponseWriter, m *dns.Msg) {
buf, _ := m.Pack()
w.Write(buf)
}
func handleQueryCHAOS(w dns.ResponseWriter, req *dns.Msg) {
m := new(dns.Msg)
qname := req.Question[0].Name
qtype := req.Question[0].Qtype
qclass := req.Question[0].Qclass
println(req.String())
if qclass != dns.ClassCHAOS {
m.SetRcode(req, dns.RcodeServerFailure)
send(w, m)
return
}
if qname == "version.bind." && qtype == dns.TypeTXT {
m.SetReply(req)
m.Answer = make([]dns.RR, 1)
m.Answer[0] = &dns.RR_TXT{Hdr: dns.RR_Header{Name: qname,
Rrtype: qtype, Class: qclass}, Txt: "NS 0.0.1"}
send(w, m)
return
}
if qname == "authors.bind." && qtype == dns.TypeTXT {
m.SetReply(req)
m.Answer = make([]dns.RR, 1)
m.Answer[0] = &dns.RR_TXT{Hdr: dns.RR_Header{Name: qname,
Rrtype: qtype, Class: qclass}, Txt: "Miek Gieben"}
send(w, m)
return
}
m.SetRcode(req, dns.RcodeServerFailure)
send(w, m)
return
}
func handleQuery(w dns.ResponseWriter, req *dns.Msg) {
m := new(dns.Msg)
qname := req.Question[0].Name
qtype := req.Question[0].Qtype
qclass := req.Question[0].Qclass
println(req.String())
if qclass != dns.ClassINET {
m.SetRcode(req, dns.RcodeServerFailure)
send(w, m)
return
}
m.SetReply(req)
// Create AUTH section
m.Ns = make([]dns.RR, 0)
for i := 0; i < zone.Len(); i++ {
if zone.At(i).Header().Name == "miek.nl." && zone.At(i).Header().Rrtype == dns.TypeNS {
m.Ns = append(m.Ns, zone.At(i))
}
}
// Save the name
m.Answer = make([]dns.RR, 0)
for i := 0; i < zone.Len(); i++ {
if zone.At(i).Header().Name == qname {
// Name found
if zone.At(i).Header().Rrtype == qtype {
// Type also found, exact match
m.Answer = append(m.Answer, zone.At(i))
}
}
}
// Glue??
send(w, m)
}
func main() {
file, err := os.Open("miek.nl.signed")
defer file.Close()
if err != nil {
return
}
p := dns.NewParser(bufio.NewReader(file))
zone, err = p.Zone()
if err != nil {
}
dns.HandleFunc("miek.nl.", handleQuery)
dns.HandleFunc("bind.", handleQueryCHAOS)
go func() {
err := dns.ListenAndServe(":8053", "udp", nil)
if err != nil {
}
}()
go func() {
err := dns.ListenAndServe(":8053", "tcp", nil)
if err != nil {
}
}()
forever:
for {
select {
case <-signal.Incoming:
fmt.Printf("Signal received, stopping\n")
break forever
}
}
}

View File

@ -105,6 +105,7 @@ Flags:
m.Question = make([]dns.Question, 1)
if *dnssec || *nsid {
opt := dns.NewRR(dns.TypeOPT).(*dns.RR_OPT)
opt.Hdr.Rrtype = 0
opt.SetDo()
opt.SetVersion(0)
opt.SetUDPSize(dns.DefaultMsgSize)

View File

@ -31,6 +31,27 @@ func (dns *Msg) SetNotify(z string) {
dns.Question[0] = Question{z, TypeSOA, ClassINET}
}
// Create an error packet.
func (dns *Msg) SetRcode(request *Msg, rcode int) {
dns.MsgHdr.Rcode = rcode
dns.MsgHdr.Opcode = OpcodeQuery
dns.MsgHdr.Response = true
dns.MsgHdr.Authoritative = false
dns.MsgHdr.Id = request.MsgHdr.Id
dns.Question = make([]Question, 1)
dns.Question[0] = request.Question[0]
}
// TODO isRcode for symmetry
// Create a FormError packet.
func (dns *Msg) SetRcodeFormatError(request *Msg) {
dns.MsgHdr.Rcode = RcodeFormatError
dns.MsgHdr.Opcode = OpcodeQuery
dns.MsgHdr.Response = true
dns.MsgHdr.Authoritative = false
dns.MsgHdr.Id = request.MsgHdr.Id
}
// Is the message a dynamic update packet?
func (dns *Msg) IsUpdate() (ok bool) {
if len(dns.Question) == 0 {

View File

@ -70,10 +70,8 @@ func (f HandlerFunc) ServeDNS(w ResponseWriter, r *Msg) {
// RCODE = refused for every request.
func Refused(w ResponseWriter, r *Msg) {
m := new(Msg)
m.SetReply(r)
m.MsgHdr.Rcode = RcodeRefused
m.MsgHdr.Authoritative = false
buf, _ := m.Pack()
m.SetRcode(r, RcodeRefused)
buf, _ := m.Pack()
w.Write(buf)
}
@ -313,6 +311,11 @@ func (c *conn) serve() {
w.conn = c
req := new(Msg)
if !req.Unpack(c.request) {
// Send a format error back
x := new(Msg)
x.SetRcodeFormatError(req)
buf, _ := x.Pack()
w.Write(buf)
break
}
w.req = req