mirror of
https://github.com/miekg/dns.git
synced 2025-10-15 11:51:00 +02:00
Responder channel is now os.Error
to make it possible to send errors back
This commit is contained in:
parent
44c00e1b57
commit
896df96f94
@ -223,7 +223,7 @@ func main() {
|
|||||||
s.Address = addr
|
s.Address = addr
|
||||||
s.Port = port
|
s.Port = port
|
||||||
var srv *server
|
var srv *server
|
||||||
rs := make(chan bool)
|
rs := make(chan os.Error)
|
||||||
go s.NewResponder(srv, rs)
|
go s.NewResponder(srv, rs)
|
||||||
|
|
||||||
forever:
|
forever:
|
||||||
@ -236,7 +236,7 @@ forever:
|
|||||||
break forever
|
break forever
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rs <- true // shutdown responder
|
rs <- nil // shutdown responder
|
||||||
<-rs // wait for confirmation
|
<-rs // wait for confirmation
|
||||||
// And the resolvers
|
// And the resolvers
|
||||||
for _, q := range qr {
|
for _, q := range qr {
|
||||||
|
@ -17,115 +17,118 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
|
||||||
"dns"
|
"dns"
|
||||||
"dns/responder"
|
"strconv"
|
||||||
"runtime"
|
"dns/responder"
|
||||||
"os/signal"
|
"runtime"
|
||||||
|
"os/signal"
|
||||||
)
|
)
|
||||||
|
|
||||||
type server responder.Server
|
type server responder.Server
|
||||||
|
|
||||||
func reply(a net.Addr, in []byte, tcp bool) *dns.Msg {
|
func reply(a net.Addr, in []byte, tcp bool) *dns.Msg {
|
||||||
inmsg := new(dns.Msg)
|
inmsg := new(dns.Msg)
|
||||||
if !inmsg.Unpack(in) {
|
if !inmsg.Unpack(in) {
|
||||||
println("Unpacking failed")
|
println("Unpacking failed")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if inmsg.MsgHdr.Response == true {
|
if inmsg.MsgHdr.Response == true {
|
||||||
return nil // Don't answer responses
|
return nil // Don't answer responses
|
||||||
}
|
}
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
m.MsgHdr.Id = inmsg.MsgHdr.Id
|
m.MsgHdr.Id = inmsg.MsgHdr.Id
|
||||||
m.MsgHdr.Authoritative = true
|
m.MsgHdr.Authoritative = true
|
||||||
m.MsgHdr.Response = true
|
m.MsgHdr.Response = true
|
||||||
m.MsgHdr.Opcode = dns.OpcodeQuery
|
m.MsgHdr.Opcode = dns.OpcodeQuery
|
||||||
|
|
||||||
m.MsgHdr.Rcode = dns.RcodeSuccess
|
m.MsgHdr.Rcode = dns.RcodeSuccess
|
||||||
m.Question = make([]dns.Question, 1)
|
m.Question = make([]dns.Question, 1)
|
||||||
m.Answer = make([]dns.RR, 1)
|
m.Answer = make([]dns.RR, 1)
|
||||||
m.Extra = make([]dns.RR, 1)
|
m.Extra = make([]dns.RR, 1)
|
||||||
|
|
||||||
r := new(dns.RR_A)
|
r := new(dns.RR_A)
|
||||||
r.Hdr = dns.RR_Header{Name: "whoami.miek.nl.", Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 0}
|
r.Hdr = dns.RR_Header{Name: "whoami.miek.nl.", Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 0}
|
||||||
ip, _ := net.ResolveUDPAddr(a.String()) // No general variant for both upd and tcp
|
ip, _ := net.ResolveUDPAddr(a.String()) // No general variant for both upd and tcp
|
||||||
r.A = ip.IP.To4() // To4 very important
|
r.A = ip.IP.To4() // To4 very important
|
||||||
|
|
||||||
t := new(dns.RR_TXT)
|
t := new(dns.RR_TXT)
|
||||||
t.Hdr = dns.RR_Header{Name: "whoami.miek.nl.", Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0}
|
t.Hdr = dns.RR_Header{Name: "whoami.miek.nl.", Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0}
|
||||||
if tcp {
|
if tcp {
|
||||||
t.Txt = "Port: " + strconv.Itoa(ip.Port) + " (tcp)"
|
t.Txt = "Port: " + strconv.Itoa(ip.Port) + " (tcp)"
|
||||||
} else {
|
} else {
|
||||||
t.Txt = "Port: " + strconv.Itoa(ip.Port) + " (udp)"
|
t.Txt = "Port: " + strconv.Itoa(ip.Port) + " (udp)"
|
||||||
}
|
}
|
||||||
|
|
||||||
m.Question[0] = inmsg.Question[0]
|
m.Question[0] = inmsg.Question[0]
|
||||||
m.Answer[0] = r
|
m.Answer[0] = r
|
||||||
m.Extra[0] = t
|
m.Extra[0] = t
|
||||||
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) ResponderUDP(c *net.UDPConn, a net.Addr, in []byte) {
|
func (s *server) ResponderUDP(c *net.UDPConn, a net.Addr, in []byte) {
|
||||||
m := reply(a, in, false)
|
m := reply(a, in, false)
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
out, ok := m.Pack()
|
out, ok := m.Pack()
|
||||||
if !ok {
|
if !ok {
|
||||||
println("Failed to pack")
|
println("Failed to pack")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
responder.SendUDP(out, c, a)
|
responder.SendUDP(out, c, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) ResponderTCP(c *net.TCPConn, in []byte) {
|
func (s *server) ResponderTCP(c *net.TCPConn, in []byte) {
|
||||||
m := reply(c.RemoteAddr(), in, true)
|
m := reply(c.RemoteAddr(), in, true)
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
out, ok := m.Pack()
|
out, ok := m.Pack()
|
||||||
if !ok {
|
if !ok {
|
||||||
println("Failed to pack")
|
println("Failed to pack")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
responder.SendTCP(out, c)
|
responder.SendTCP(out, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
runtime.GOMAXPROCS(10) // Be bold
|
runtime.GOMAXPROCS(10) // Be bold
|
||||||
|
|
||||||
s := new(responder.Server)
|
s := new(responder.Server)
|
||||||
s.Address = "127.0.0.1"
|
s.Address = "127.0.0.1"
|
||||||
s.Port = "8053"
|
s.Port = "8053"
|
||||||
var srv *server
|
var srv *server
|
||||||
ch := make(chan bool)
|
ch := make(chan os.Error)
|
||||||
go s.NewResponder(srv, ch)
|
go s.NewResponder(srv, ch)
|
||||||
|
|
||||||
t := new(responder.Server)
|
t := new(responder.Server)
|
||||||
t.Address = "127.0.0.1"
|
t.Address = "127.0.0.1"
|
||||||
t.Port = "8053"
|
t.Port = "8053"
|
||||||
t.Tcp = true
|
t.Tcp = true
|
||||||
var srvt *server
|
var srvt *server
|
||||||
cht := make(chan bool)
|
cht := make(chan os.Error)
|
||||||
go t.NewResponder(srvt, cht)
|
go t.NewResponder(srvt, cht)
|
||||||
|
|
||||||
forever:
|
forever:
|
||||||
for {
|
for {
|
||||||
// Wait for a signal to stop
|
// Wait for a signal to stop
|
||||||
select {
|
select {
|
||||||
case <-signal.Incoming:
|
case <-signal.Incoming:
|
||||||
println("Signal received, stopping")
|
println("Signal received, stopping")
|
||||||
ch <- true
|
ch <- nil
|
||||||
cht <- true
|
cht <- nil
|
||||||
break forever
|
break forever
|
||||||
case <-cht:
|
case e := <-cht:
|
||||||
// last message from tcp channel
|
// last message from tcp channel
|
||||||
case <-ch:
|
println(e.String())
|
||||||
// last message from udp channel
|
case e := <-ch:
|
||||||
}
|
// last message from udp channel
|
||||||
}
|
println(e.String())
|
||||||
close(cht)
|
}
|
||||||
close(ch)
|
}
|
||||||
|
close(cht)
|
||||||
|
close(ch)
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"os"
|
||||||
|
"net"
|
||||||
"dns"
|
"dns"
|
||||||
"dns/responder"
|
"dns/responder"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
@ -25,9 +26,9 @@ func (s *server) ResponderUDP(c *net.UDPConn, a net.Addr, in []byte) {
|
|||||||
// NXdomain 'n stuff
|
// NXdomain 'n stuff
|
||||||
println("Unpacking failed")
|
println("Unpacking failed")
|
||||||
}
|
}
|
||||||
if inmsg.MsgHdr.Response == true {
|
if inmsg.MsgHdr.Response == true {
|
||||||
return // don't answer responses
|
return // don't answer responses
|
||||||
}
|
}
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
m.MsgHdr.Id = inmsg.MsgHdr.Id
|
m.MsgHdr.Id = inmsg.MsgHdr.Id
|
||||||
m.MsgHdr.Response = true
|
m.MsgHdr.Response = true
|
||||||
@ -52,7 +53,7 @@ func main() {
|
|||||||
s.Address = "127.0.0.1"
|
s.Address = "127.0.0.1"
|
||||||
s.Port = "8053"
|
s.Port = "8053"
|
||||||
var srv *server
|
var srv *server
|
||||||
ch := make(chan bool)
|
ch := make(chan os.Error)
|
||||||
go s.NewResponder(srv, ch)
|
go s.NewResponder(srv, ch)
|
||||||
|
|
||||||
forever:
|
forever:
|
||||||
@ -61,9 +62,13 @@ forever:
|
|||||||
select {
|
select {
|
||||||
case <-signal.Incoming:
|
case <-signal.Incoming:
|
||||||
println("Signal received, stopping")
|
println("Signal received, stopping")
|
||||||
ch <- true
|
ch <- nil
|
||||||
<-ch
|
<-ch
|
||||||
break forever
|
break forever
|
||||||
|
case e := <-cht:
|
||||||
|
println(e.String())
|
||||||
|
case e := <-ch:
|
||||||
|
println(e.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,12 +59,12 @@ type Responder interface {
|
|||||||
ResponderTCP(c *net.TCPConn, in []byte)
|
ResponderTCP(c *net.TCPConn, in []byte)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start a new responder. The returned channel is only used to stop the responder.
|
// Start a new responder. The returned channel is used to stop the responder.
|
||||||
// Send 'true' to make it stop
|
// Send 'nil' to make it stop. It can also return error via the channel.
|
||||||
func (res *Server) NewResponder(h Responder, stop chan bool) {
|
func (res *Server) NewResponder(h Responder, stop chan os.Error) {
|
||||||
var port string
|
var port string
|
||||||
if len(res.Address) == 0 {
|
if len(res.Address) == 0 {
|
||||||
// We cannot start responding without an addresss
|
stop <- &dns.Error{Error: "No addresses"}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if res.Port == "" {
|
if res.Port == "" {
|
||||||
@ -83,14 +83,12 @@ func (res *Server) NewResponder(h Responder, stop chan bool) {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-stop:
|
||||||
stop <- true
|
stop <- nil
|
||||||
listener.Close()
|
listener.Close()
|
||||||
break foreverTCP
|
break foreverTCP
|
||||||
case s := <-tch:
|
case s := <-tch:
|
||||||
if s.err != nil {
|
if s.err != nil {
|
||||||
// always fatal??
|
stop <- s.err
|
||||||
stop <- false
|
|
||||||
println(s.err.String())
|
|
||||||
} else {
|
} else {
|
||||||
go h.ResponderTCP(s.tcp, s.msg)
|
go h.ResponderTCP(s.tcp, s.msg)
|
||||||
}
|
}
|
||||||
@ -105,13 +103,11 @@ func (res *Server) NewResponder(h Responder, stop chan bool) {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-stop:
|
||||||
stop <- true
|
stop <- nil
|
||||||
break foreverUDP
|
break foreverUDP
|
||||||
case s := <-uch:
|
case s := <-uch:
|
||||||
if s.err != nil {
|
if s.err != nil {
|
||||||
//continue
|
stop <- s.err
|
||||||
stop <- false
|
|
||||||
println(s.err.String())
|
|
||||||
} else {
|
} else {
|
||||||
go h.ResponderUDP(s.udp, s.addr, s.msg)
|
go h.ResponderUDP(s.udp, s.addr, s.msg)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package responder
|
package responder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
"fmt"
|
"fmt"
|
||||||
"dns"
|
"dns"
|
||||||
@ -66,7 +67,7 @@ func TestResponder(t *testing.T) {
|
|||||||
su.Address = "127.0.0.1"
|
su.Address = "127.0.0.1"
|
||||||
su.Port = "8053"
|
su.Port = "8053"
|
||||||
var us *myserv
|
var us *myserv
|
||||||
uch := make(chan bool)
|
uch := make(chan os.Error)
|
||||||
go su.NewResponder(us, uch)
|
go su.NewResponder(us, uch)
|
||||||
|
|
||||||
/* tcp servertje */
|
/* tcp servertje */
|
||||||
@ -75,23 +76,23 @@ func TestResponder(t *testing.T) {
|
|||||||
st.Port = "8053"
|
st.Port = "8053"
|
||||||
st.Tcp = true
|
st.Tcp = true
|
||||||
var ts *myserv
|
var ts *myserv
|
||||||
tch := make(chan bool)
|
tch := make(chan os.Error)
|
||||||
go st.NewResponder(ts, tch)
|
go st.NewResponder(ts, tch)
|
||||||
time.Sleep(1 * 1e9)
|
time.Sleep(1 * 1e9)
|
||||||
uch <- true
|
uch <- nil
|
||||||
tch <- true
|
tch <- nil
|
||||||
<-uch
|
<-uch
|
||||||
<-tch
|
<-tch
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
func TestReflectorResponder(t *testing.T) {
|
func TestReflectorResponder(t *testing.T) {
|
||||||
stop := make(chan bool)
|
stop := make(chan os.Error)
|
||||||
s := new(Server)
|
s := new(Server)
|
||||||
s.Port = "8053"
|
s.Port = "8053"
|
||||||
s.Address = "127.0.0.1"
|
s.Address = "127.0.0.1"
|
||||||
|
|
||||||
stoptcp := make(chan bool)
|
stoptcp := make(chan os.Error)
|
||||||
stcp := new(Server)
|
stcp := new(Server)
|
||||||
stcp.Port = "8053"
|
stcp.Port = "8053"
|
||||||
stcp.Address = "127.0.0.1"
|
stcp.Address = "127.0.0.1"
|
||||||
@ -101,8 +102,8 @@ func TestReflectorResponder(t *testing.T) {
|
|||||||
go s.NewResponder(Reflector, stop)
|
go s.NewResponder(Reflector, stop)
|
||||||
|
|
||||||
time.Sleep(1 * 1e9)
|
time.Sleep(1 * 1e9)
|
||||||
stop <- true
|
stop <- nil
|
||||||
stoptcp <- true
|
stoptcp <- nil
|
||||||
<-stop
|
<-stop
|
||||||
<-stoptcp
|
<-stoptcp
|
||||||
}
|
}
|
||||||
@ -175,7 +176,7 @@ func TestResponderTsig(t *testing.T) {
|
|||||||
su.Address = "127.0.0.1"
|
su.Address = "127.0.0.1"
|
||||||
su.Port = "8053"
|
su.Port = "8053"
|
||||||
var us *servtsig
|
var us *servtsig
|
||||||
uch := make(chan bool)
|
uch := make(chan os.Error)
|
||||||
go su.NewResponder(us, uch)
|
go su.NewResponder(us, uch)
|
||||||
|
|
||||||
/* tcp servertje */
|
/* tcp servertje */
|
||||||
@ -184,11 +185,11 @@ func TestResponderTsig(t *testing.T) {
|
|||||||
st.Port = "8053"
|
st.Port = "8053"
|
||||||
st.Tcp = true
|
st.Tcp = true
|
||||||
var ts *servtsig
|
var ts *servtsig
|
||||||
tch := make(chan bool)
|
tch := make(chan os.Error)
|
||||||
go st.NewResponder(ts, tch)
|
go st.NewResponder(ts, tch)
|
||||||
time.Sleep(1 * 1e9)
|
time.Sleep(1 * 1e9)
|
||||||
uch <- true
|
uch <- nil
|
||||||
tch <- true
|
tch <- nil
|
||||||
<-uch
|
<-uch
|
||||||
<-tch
|
<-tch
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user