Commit e4c72719 authored by Miek Gieben's avatar Miek Gieben

Test and fix notify

More tests and add RemoteAddr to State, prolly LocalAddr will be

useful as well.

Fixed and tested IsNotify method.
parent 225cdd1c
...@@ -19,7 +19,7 @@ func (z *Zone) isNotify(state middleware.State) bool { ...@@ -19,7 +19,7 @@ func (z *Zone) isNotify(state middleware.State) bool {
if len(z.TransferFrom) == 0 { if len(z.TransferFrom) == 0 {
return false return false
} }
remote := middleware.Addr(state.IP()).Normalize() remote := state.RemoteAddr()
for _, from := range z.TransferFrom { for _, from := range z.TransferFrom {
if from == remote { if from == remote {
return true return true
......
package file package file
import ( import (
"net" "fmt"
"sync"
"testing" "testing"
"time"
"github.com/miekg/coredns/middleware"
coretest "github.com/miekg/coredns/middleware/testing"
"github.com/miekg/dns" "github.com/miekg/dns"
) )
...@@ -35,80 +36,56 @@ func TestLess(t *testing.T) { ...@@ -35,80 +36,56 @@ func TestLess(t *testing.T) {
} }
} }
func TCPServer(laddr string) (*dns.Server, string, error) {
l, err := net.Listen("tcp", laddr)
if err != nil {
return nil, "", err
}
server := &dns.Server{Listener: l, ReadTimeout: time.Hour, WriteTimeout: time.Hour}
waitLock := sync.Mutex{}
waitLock.Lock()
server.NotifyStartedFunc = waitLock.Unlock
go func() {
server.ActivateAndServe()
l.Close()
}()
waitLock.Lock()
return server, l.Addr().String(), nil
}
func UDPServer(laddr string) (*dns.Server, string, chan bool, error) {
pc, err := net.ListenPacket("udp", laddr)
if err != nil {
return nil, "", nil, err
}
server := &dns.Server{PacketConn: pc, ReadTimeout: time.Hour, WriteTimeout: time.Hour}
waitLock := sync.Mutex{}
waitLock.Lock()
server.NotifyStartedFunc = waitLock.Unlock
stop := make(chan bool)
go func() {
server.ActivateAndServe()
close(stop)
pc.Close()
}()
waitLock.Lock()
return server, pc.LocalAddr().String(), stop, nil
}
type soa struct { type soa struct {
serial uint32 serial uint32
} }
func (s *soa) Handler(w dns.ResponseWriter, req *dns.Msg) { func (s *soa) Handler(w dns.ResponseWriter, req *dns.Msg) {
m := new(dns.Msg)
m.SetReply(req)
switch req.Question[0].Qtype {
case dns.TypeSOA:
m.Answer = make([]dns.RR, 1)
m.Answer[0] = coretest.SOA(fmt.Sprintf("%s IN SOA bla. bla. %d 0 0 0 0 ", testZone, s.serial))
w.WriteMsg(m)
case dns.TypeAXFR:
m.Answer = make([]dns.RR, 4)
m.Answer[0] = coretest.SOA(fmt.Sprintf("%s IN SOA bla. bla. %d 0 0 0 0 ", testZone, s.serial))
m.Answer[1] = coretest.A(fmt.Sprintf("%s IN A 127.0.0.1", testZone))
m.Answer[2] = coretest.A(fmt.Sprintf("%s IN A 127.0.0.1", testZone))
m.Answer[3] = coretest.SOA(fmt.Sprintf("%s IN SOA bla. bla. %d 0 0 0 0 ", testZone, s.serial))
w.WriteMsg(m)
}
}
func (s *soa) TransferHandler(w dns.ResponseWriter, req *dns.Msg) {
m := new(dns.Msg) m := new(dns.Msg)
m.SetReply(req) m.SetReply(req)
m.Answer = make([]dns.RR, 1) m.Answer = make([]dns.RR, 1)
m.Answer[0] = &dns.SOA{Hdr: dns.RR_Header{Name: m.Question[0].Name, Rrtype: dns.TypeSOA, Class: dns.ClassINET, Ttl: 100}, Ns: "bla.", Mbox: "bla.", Serial: s.serial} m.Answer[0] = coretest.SOA(fmt.Sprintf("%s IN SOA bla. bla. %d 0 0 0 0 ", testZone, s.serial))
w.WriteMsg(m) w.WriteMsg(m)
} }
const testZone = "secondary.miek.nl."
func TestShouldTransfer(t *testing.T) { func TestShouldTransfer(t *testing.T) {
soa := soa{250} soa := soa{250}
dns.HandleFunc("secondary.miek.nl.", soa.Handler) dns.HandleFunc(testZone, soa.Handler)
defer dns.HandleRemove("secondary.miek.nl.") defer dns.HandleRemove(testZone)
s, addrstr, err := TCPServer("127.0.0.1:0") s, addrstr, err := coretest.TCPServer("127.0.0.1:0")
if err != nil { if err != nil {
t.Fatalf("unable to run test server: %v", err) t.Fatalf("unable to run test server: %v", err)
} }
defer s.Shutdown() defer s.Shutdown()
z := new(Zone) z := new(Zone)
z.name = "secondary.miek.nl." z.name = testZone
z.TransferFrom = []string{addrstr} z.TransferFrom = []string{addrstr}
// Serial smaller // Serial smaller
z.SOA = &dns.SOA{Hdr: dns.RR_Header{Name: "secondary.miek.nl.", Rrtype: dns.TypeSOA, Class: dns.ClassINET, Ttl: 100}, Ns: "bla.", Mbox: "bla.", Serial: soa.serial - 1} z.SOA = coretest.SOA(fmt.Sprintf("%s IN SOA bla. bla. %d 0 0 0 0 ", testZone, soa.serial-1))
should, err := z.shouldTransfer() should, err := z.shouldTransfer()
if err != nil { if err != nil {
t.Fatalf("unable to run shouldTransfer: %v", err) t.Fatalf("unable to run shouldTransfer: %v", err)
...@@ -117,7 +94,7 @@ func TestShouldTransfer(t *testing.T) { ...@@ -117,7 +94,7 @@ func TestShouldTransfer(t *testing.T) {
t.Fatalf("shouldTransfer should return true for serial: %q", soa.serial-1) t.Fatalf("shouldTransfer should return true for serial: %q", soa.serial-1)
} }
// Serial equal // Serial equal
z.SOA = &dns.SOA{Hdr: dns.RR_Header{Name: "secondary.miek.nl.", Rrtype: dns.TypeSOA, Class: dns.ClassINET, Ttl: 100}, Ns: "bla.", Mbox: "bla.", Serial: soa.serial} z.SOA = coretest.SOA(fmt.Sprintf("%s IN SOA bla. bla. %d 0 0 0 0 ", testZone, soa.serial))
should, err = z.shouldTransfer() should, err = z.shouldTransfer()
if err != nil { if err != nil {
t.Fatalf("unable to run shouldTransfer: %v", err) t.Fatalf("unable to run shouldTransfer: %v", err)
...@@ -126,3 +103,54 @@ func TestShouldTransfer(t *testing.T) { ...@@ -126,3 +103,54 @@ func TestShouldTransfer(t *testing.T) {
t.Fatalf("shouldTransfer should return false for serial: %d", soa.serial) t.Fatalf("shouldTransfer should return false for serial: %d", soa.serial)
} }
} }
func TestTransferIn(t *testing.T) {
soa := soa{250}
dns.HandleFunc(testZone, soa.Handler)
defer dns.HandleRemove(testZone)
s, addrstr, err := coretest.TCPServer("127.0.0.1:0")
if err != nil {
t.Fatalf("unable to run test server: %v", err)
}
defer s.Shutdown()
z := new(Zone)
z.Expired = new(bool)
z.name = testZone
z.TransferFrom = []string{addrstr}
err = z.TransferIn()
if err != nil {
t.Fatalf("unable to run TransferIn: %v", err)
}
if z.SOA.String() != fmt.Sprintf("%s 3600 IN SOA bla. bla. 250 0 0 0 0", testZone) {
t.Fatalf("unknown SOA transferred")
}
}
func TestIsNotify(t *testing.T) {
z := new(Zone)
z.Expired = new(bool)
z.name = testZone
state := NewState(testZone, dns.TypeSOA)
// need to set opcode
state.Req.Opcode = dns.OpcodeNotify
z.TransferFrom = []string{"10.240.0.1:40212"} // IP from from testing/responseWriter
if !z.isNotify(state) {
t.Fatal("should have been valid notify")
}
z.TransferFrom = []string{"10.240.0.2:40212"}
if z.isNotify(state) {
t.Fatal("should have been invalid notify")
}
}
func NewState(zone string, qtype uint16) middleware.State {
m := new(dns.Msg)
m.SetQuestion("example.com.", dns.TypeA)
m.SetEdns0(4097, true)
return middleware.State{W: &coretest.ResponseWriter{}, Req: m}
}
...@@ -31,6 +31,8 @@ func (z *Zone) Copy() *Zone { ...@@ -31,6 +31,8 @@ func (z *Zone) Copy() *Zone {
z1.TransferTo = z.TransferTo z1.TransferTo = z.TransferTo
z1.TransferFrom = z.TransferFrom z1.TransferFrom = z.TransferFrom
z1.Expired = z.Expired z1.Expired = z.Expired
z1.SOA = z.SOA
z1.SIG = z.SIG
return z1 return z1
} }
......
...@@ -50,6 +50,11 @@ func (s *State) Port() (string, error) { ...@@ -50,6 +50,11 @@ func (s *State) Port() (string, error) {
return port, nil return port, nil
} }
// RemoteAddr returns the net.Addr of the client that sent the current request.
func (s *State) RemoteAddr() string {
return s.W.RemoteAddr().String()
}
// Proto gets the protocol used as the transport. This // Proto gets the protocol used as the transport. This
// will be udp or tcp. // will be udp or tcp.
func (s *State) Proto() string { func (s *State) Proto() string {
......
...@@ -17,6 +17,20 @@ func TestStateDo(t *testing.T) { ...@@ -17,6 +17,20 @@ func TestStateDo(t *testing.T) {
} }
} }
func TestStateRemote(t *testing.T) {
st := testState()
if st.IP() != "10.240.0.1" {
t.Fatalf("wrong IP from state")
}
p, err := st.Port()
if err != nil {
t.Fatalf("failed to get Port from state")
}
if p != "40212" {
t.Fatalf("wrong port from state")
}
}
func BenchmarkStateDo(b *testing.B) { func BenchmarkStateDo(b *testing.B) {
st := testState() st := testState()
...@@ -37,7 +51,6 @@ func testState() State { ...@@ -37,7 +51,6 @@ func testState() State {
m := new(dns.Msg) m := new(dns.Msg)
m.SetQuestion("example.com.", dns.TypeA) m.SetQuestion("example.com.", dns.TypeA)
m.SetEdns0(4097, true) m.SetEdns0(4097, true)
return State{W: &coretest.ResponseWriter{}, Req: m} return State{W: &coretest.ResponseWriter{}, Req: m}
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment