1package dns
2
3import (
4	"net"
5	"sync"
6	"testing"
7	"time"
8)
9
10var (
11	tsigSecret  = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
12	xfrSoa      = testRR(`miek.nl.	0	IN	SOA	linode.atoom.net. miek.miek.nl. 2009032802 21600 7200 604800 3600`)
13	xfrA        = testRR(`x.miek.nl.	1792	IN	A	10.0.0.1`)
14	xfrMX       = testRR(`miek.nl.	1800	IN	MX	1	x.miek.nl.`)
15	xfrTestData = []RR{xfrSoa, xfrA, xfrMX, xfrSoa}
16)
17
18func InvalidXfrServer(w ResponseWriter, req *Msg) {
19	ch := make(chan *Envelope)
20	tr := new(Transfer)
21
22	go tr.Out(w, req, ch)
23	ch <- &Envelope{RR: []RR{}}
24	close(ch)
25	w.Hijack()
26}
27
28func SingleEnvelopeXfrServer(w ResponseWriter, req *Msg) {
29	ch := make(chan *Envelope)
30	tr := new(Transfer)
31
32	go tr.Out(w, req, ch)
33	ch <- &Envelope{RR: xfrTestData}
34	close(ch)
35	w.Hijack()
36}
37
38func MultipleEnvelopeXfrServer(w ResponseWriter, req *Msg) {
39	ch := make(chan *Envelope)
40	tr := new(Transfer)
41
42	go tr.Out(w, req, ch)
43
44	for _, rr := range xfrTestData {
45		ch <- &Envelope{RR: []RR{rr}}
46	}
47	close(ch)
48	w.Hijack()
49}
50
51func TestInvalidXfr(t *testing.T) {
52	HandleFunc("miek.nl.", InvalidXfrServer)
53	defer HandleRemove("miek.nl.")
54
55	s, addrstr, err := RunLocalTCPServer(":0")
56	if err != nil {
57		t.Fatalf("unable to run test server: %s", err)
58	}
59	defer s.Shutdown()
60
61	tr := new(Transfer)
62	m := new(Msg)
63	m.SetAxfr("miek.nl.")
64
65	c, err := tr.In(m, addrstr)
66	if err != nil {
67		t.Fatal("failed to zone transfer in", err)
68	}
69
70	for msg := range c {
71		if msg.Error == nil {
72			t.Fatal("failed to catch 'no SOA' error")
73		}
74	}
75}
76
77func TestSingleEnvelopeXfr(t *testing.T) {
78	HandleFunc("miek.nl.", SingleEnvelopeXfrServer)
79	defer HandleRemove("miek.nl.")
80
81	s, addrstr, err := RunLocalTCPServerWithTsig(":0", tsigSecret)
82	if err != nil {
83		t.Fatalf("unable to run test server: %s", err)
84	}
85	defer s.Shutdown()
86
87	axfrTestingSuite(addrstr)
88}
89
90func TestMultiEnvelopeXfr(t *testing.T) {
91	HandleFunc("miek.nl.", MultipleEnvelopeXfrServer)
92	defer HandleRemove("miek.nl.")
93
94	s, addrstr, err := RunLocalTCPServerWithTsig(":0", tsigSecret)
95	if err != nil {
96		t.Fatalf("unable to run test server: %s", err)
97	}
98	defer s.Shutdown()
99
100	axfrTestingSuite(addrstr)
101}
102
103func RunLocalTCPServerWithTsig(laddr string, tsig map[string]string) (*Server, string, error) {
104	server, l, _, err := RunLocalTCPServerWithFinChanWithTsig(laddr, tsig)
105
106	return server, l, err
107}
108
109func RunLocalTCPServerWithFinChanWithTsig(laddr string, tsig map[string]string) (*Server, string, chan error, error) {
110	l, err := net.Listen("tcp", laddr)
111	if err != nil {
112		return nil, "", nil, err
113	}
114
115	server := &Server{Listener: l, ReadTimeout: time.Hour, WriteTimeout: time.Hour, TsigSecret: tsig}
116
117	waitLock := sync.Mutex{}
118	waitLock.Lock()
119	server.NotifyStartedFunc = waitLock.Unlock
120
121	// See the comment in RunLocalUDPServerWithFinChan as to
122	// why fin must be buffered.
123	fin := make(chan error, 1)
124
125	go func() {
126		fin <- server.ActivateAndServe()
127		l.Close()
128	}()
129
130	waitLock.Lock()
131	return server, l.Addr().String(), fin, nil
132}
133
134func axfrTestingSuite(addrstr string) func(*testing.T) {
135	return func(t *testing.T) {
136		tr := new(Transfer)
137		m := new(Msg)
138		m.SetAxfr("miek.nl.")
139
140		c, err := tr.In(m, addrstr)
141		if err != nil {
142			t.Fatal("failed to zone transfer in", err)
143		}
144
145		var records []RR
146		for msg := range c {
147			if msg.Error != nil {
148				t.Fatal(msg.Error)
149			}
150			records = append(records, msg.RR...)
151		}
152
153		if len(records) != len(xfrTestData) {
154			t.Fatalf("bad axfr: expected %v, got %v", records, xfrTestData)
155		}
156
157		for i := range records {
158			if !IsDuplicate(records[i], xfrTestData[i]) {
159				t.Fatalf("bad axfr: expected %v, got %v", records, xfrTestData)
160			}
161		}
162	}
163}
164