mirror of
				https://github.com/coredns/coredns.git
				synced 2025-10-30 17:53:21 -04:00 
			
		
		
		
	Get positive dnssec stuff going
This commit is contained in:
		| @@ -21,8 +21,7 @@ func TestCnameLookup(t *testing.T) { | |||||||
| 		defer delete(t, etc, serv.Key) | 		defer delete(t, etc, serv.Key) | ||||||
| 	} | 	} | ||||||
| 	for _, tc := range dnsTestCasesCname { | 	for _, tc := range dnsTestCasesCname { | ||||||
| 		m := new(dns.Msg) | 		m := tc.Msg() | ||||||
| 		m.SetQuestion(dns.Fqdn(tc.Qname), tc.Qtype) |  | ||||||
|  |  | ||||||
| 		rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{}) | 		rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{}) | ||||||
| 		_, err := etc.ServeDNS(ctx, rec, m) | 		_, err := etc.ServeDNS(ctx, rec, m) | ||||||
|   | |||||||
| @@ -23,8 +23,7 @@ func TestGroupLookup(t *testing.T) { | |||||||
| 		defer delete(t, etc, serv.Key) | 		defer delete(t, etc, serv.Key) | ||||||
| 	} | 	} | ||||||
| 	for _, tc := range dnsTestCasesGroup { | 	for _, tc := range dnsTestCasesGroup { | ||||||
| 		m := new(dns.Msg) | 		m := tc.Msg() | ||||||
| 		m.SetQuestion(dns.Fqdn(tc.Qname), tc.Qtype) |  | ||||||
|  |  | ||||||
| 		rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{}) | 		rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{}) | ||||||
| 		_, err := etc.ServeDNS(ctx, rec, m) | 		_, err := etc.ServeDNS(ctx, rec, m) | ||||||
|   | |||||||
| @@ -26,8 +26,7 @@ func TestMultiLookup(t *testing.T) { | |||||||
| 		defer delete(t, etcMulti, serv.Key) | 		defer delete(t, etcMulti, serv.Key) | ||||||
| 	} | 	} | ||||||
| 	for _, tc := range dnsTestCasesMulti { | 	for _, tc := range dnsTestCasesMulti { | ||||||
| 		m := new(dns.Msg) | 		m := tc.Msg() | ||||||
| 		m.SetQuestion(dns.Fqdn(tc.Qname), tc.Qtype) |  | ||||||
|  |  | ||||||
| 		rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{}) | 		rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{}) | ||||||
| 		_, err := etcMulti.ServeDNS(ctx, rec, m) | 		_, err := etcMulti.ServeDNS(ctx, rec, m) | ||||||
|   | |||||||
| @@ -25,8 +25,7 @@ func TestOtherLookup(t *testing.T) { | |||||||
| 		defer delete(t, etc, serv.Key) | 		defer delete(t, etc, serv.Key) | ||||||
| 	} | 	} | ||||||
| 	for _, tc := range dnsTestCasesOther { | 	for _, tc := range dnsTestCasesOther { | ||||||
| 		m := new(dns.Msg) | 		m := tc.Msg() | ||||||
| 		m.SetQuestion(dns.Fqdn(tc.Qname), tc.Qtype) |  | ||||||
|  |  | ||||||
| 		rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{}) | 		rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{}) | ||||||
| 		_, err := etc.ServeDNS(ctx, rec, m) | 		_, err := etc.ServeDNS(ctx, rec, m) | ||||||
|   | |||||||
| @@ -65,8 +65,7 @@ func TestLookup(t *testing.T) { | |||||||
| 		defer delete(t, etc, serv.Key) | 		defer delete(t, etc, serv.Key) | ||||||
| 	} | 	} | ||||||
| 	for _, tc := range dnsTestCases { | 	for _, tc := range dnsTestCases { | ||||||
| 		m := new(dns.Msg) | 		m := tc.Msg() | ||||||
| 		m.SetQuestion(dns.Fqdn(tc.Qname), tc.Qtype) |  | ||||||
|  |  | ||||||
| 		rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{}) | 		rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{}) | ||||||
| 		_, err := etc.ServeDNS(ctx, rec, m) | 		_, err := etc.ServeDNS(ctx, rec, m) | ||||||
|   | |||||||
| @@ -14,44 +14,50 @@ import ( | |||||||
|  |  | ||||||
| var dnssecTestCases = []coretest.Case{ | var dnssecTestCases = []coretest.Case{ | ||||||
| 	{ | 	{ | ||||||
| 		Qname: "miek.nl.", Qtype: dns.TypeSOA, | 		Qname: "miek.nl.", Qtype: dns.TypeSOA, Do: true, | ||||||
| 		Answer: []dns.RR{ | 		Answer: []dns.RR{ | ||||||
|  | 			// because we sort, this look fishy, but it is OK. | ||||||
|  | 			coretest.RRSIG("miek.nl.	1800	IN	RRSIG	SOA 8 2 1800 20160426031301 20160327031301 12051 miek.nl. FIrzy07acBbtyQczy1dc="), | ||||||
| 			coretest.SOA("miek.nl.	1800	IN	SOA	linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"), | 			coretest.SOA("miek.nl.	1800	IN	SOA	linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"), | ||||||
| 		}, | 		}, | ||||||
| 	}, | 	}, | ||||||
| 	{ | 	{ | ||||||
| 		Qname: "miek.nl.", Qtype: dns.TypeAAAA, | 		Qname: "miek.nl.", Qtype: dns.TypeAAAA, Do: true, | ||||||
| 		Answer: []dns.RR{ | 		Answer: []dns.RR{ | ||||||
| 			coretest.AAAA("miek.nl.	1800	IN	AAAA	2a01:7e00::f03c:91ff:fef1:6735"), | 			coretest.AAAA("miek.nl.	1800	IN	AAAA	2a01:7e00::f03c:91ff:fef1:6735"), | ||||||
|  | 			coretest.RRSIG("miek.nl.	1800	IN	RRSIG	AAAA 8 2 1800 20160426031301 20160327031301 12051 miek.nl. SsRT="), | ||||||
| 		}, | 		}, | ||||||
| 	}, | 	}, | ||||||
| 	{ | 	{ | ||||||
| 		Qname: "miek.nl.", Qtype: dns.TypeMX, | 		Qname: "miek.nl.", Qtype: dns.TypeMX, Do: true, | ||||||
| 		Answer: []dns.RR{ | 		Answer: []dns.RR{ | ||||||
| 			coretest.MX("miek.nl.	1800	IN	MX	1 aspmx.l.google.com."), | 			coretest.MX("miek.nl.	1800	IN	MX	1 aspmx.l.google.com."), | ||||||
| 			coretest.MX("miek.nl.	1800	IN	MX	10 aspmx2.googlemail.com."), | 			coretest.MX("miek.nl.	1800	IN	MX	10 aspmx2.googlemail.com."), | ||||||
| 			coretest.MX("miek.nl.	1800	IN	MX	10 aspmx3.googlemail.com."), | 			coretest.MX("miek.nl.	1800	IN	MX	10 aspmx3.googlemail.com."), | ||||||
| 			coretest.MX("miek.nl.	1800	IN	MX	5 alt1.aspmx.l.google.com."), | 			coretest.MX("miek.nl.	1800	IN	MX	5 alt1.aspmx.l.google.com."), | ||||||
| 			coretest.MX("miek.nl.	1800	IN	MX	5 alt2.aspmx.l.google.com."), | 			coretest.MX("miek.nl.	1800	IN	MX	5 alt2.aspmx.l.google.com."), | ||||||
|  | 			coretest.RRSIG("miek.nl.	1800	IN	RRSIG	MX 8 2 1800 20160426031301 20160327031301 12051 miek.nl. kLqG+iOr="), | ||||||
| 		}, | 		}, | ||||||
| 	}, | 	}, | ||||||
| 	{ | 	{ | ||||||
| 		Qname: "www.miek.nl.", Qtype: dns.TypeA, | 		Qname: "www.miek.nl.", Qtype: dns.TypeA, Do: true, | ||||||
| 		Answer: []dns.RR{ | 		Answer: []dns.RR{ | ||||||
| 			coretest.CNAME("www.miek.nl.	1800	IN	CNAME	a.miek.nl."), | 			coretest.CNAME("www.miek.nl.	1800	IN	CNAME	a.miek.nl."), | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
| 		Extra: []dns.RR{ | 		Extra: []dns.RR{ | ||||||
| 			coretest.A("a.miek.nl.	1800	IN	A	139.162.196.78"), | 			coretest.A("a.miek.nl.	1800	IN	A	139.162.196.78"), | ||||||
| 			coretest.AAAA("a.miek.nl.	1800	IN	AAAA	2a01:7e00::f03c:91ff:fef1:6735"), | 			coretest.RRSIG("a.miek.nl.	1800	IN	RRSIG	A 8 3 1800 20160426031301 20160327031301 12051 miek.nl. lxLotCjWZ3kihTxk="), | ||||||
| 		}, | 		}, | ||||||
| 	}, | 	}, | ||||||
| 	{ | 	{ | ||||||
| 		Qname: "a.miek.nl.", Qtype: dns.TypeSRV, | 		Qname: "a.miek.nl.", Qtype: dns.TypeSRV, Do: true, | ||||||
| 		Ns: []dns.RR{ | 		Ns: []dns.RR{ | ||||||
|  | 			coretest.RRSIG("miek.nl.	1800	IN	RRSIG	SOA 8 2 1800 20160426031301 20160327031301 12051 miek.nl. FIrzy07acBbtyQczy1dc="), | ||||||
| 			coretest.SOA("miek.nl.	1800	IN	SOA	linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"), | 			coretest.SOA("miek.nl.	1800	IN	SOA	linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"), | ||||||
| 		}, | 		}, | ||||||
| 	}, | 	}, | ||||||
|  | 	/* HAHA nsec... shit. | ||||||
| 	{ | 	{ | ||||||
| 		Qname: "b.miek.nl.", Qtype: dns.TypeA, | 		Qname: "b.miek.nl.", Qtype: dns.TypeA, | ||||||
| 		Rcode: dns.RcodeNameError, | 		Rcode: dns.RcodeNameError, | ||||||
| @@ -59,10 +65,10 @@ var dnssecTestCases = []coretest.Case{ | |||||||
| 			coretest.SOA("miek.nl.	1800	IN	SOA	linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"), | 			coretest.SOA("miek.nl.	1800	IN	SOA	linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"), | ||||||
| 		}, | 		}, | ||||||
| 	}, | 	}, | ||||||
|  | 	*/ | ||||||
| } | } | ||||||
|  |  | ||||||
| // TODO(miek): enable | func TestLookupDNSSEC(t *testing.T) { | ||||||
| func testLookupDNSSEC(t *testing.T) { |  | ||||||
| 	zone, err := Parse(strings.NewReader(dbMiekNL_signed), testzone, "stdin") | 	zone, err := Parse(strings.NewReader(dbMiekNL_signed), testzone, "stdin") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Fatalf("expect no error when reading zone, got %q", err) | 		t.Fatalf("expect no error when reading zone, got %q", err) | ||||||
| @@ -72,8 +78,7 @@ func testLookupDNSSEC(t *testing.T) { | |||||||
| 	ctx := context.TODO() | 	ctx := context.TODO() | ||||||
|  |  | ||||||
| 	for _, tc := range dnssecTestCases { | 	for _, tc := range dnssecTestCases { | ||||||
| 		m := new(dns.Msg) | 		m := tc.Msg() | ||||||
| 		m.SetQuestion(dns.Fqdn(tc.Qname), tc.Qtype) |  | ||||||
|  |  | ||||||
| 		rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{}) | 		rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{}) | ||||||
| 		_, err := fm.ServeDNS(ctx, rec, m) | 		_, err := fm.ServeDNS(ctx, rec, m) | ||||||
|   | |||||||
| @@ -78,6 +78,11 @@ func Parse(f io.Reader, origin, fileName string) (*Zone, error) { | |||||||
| 			z.SOA = x.RR.(*dns.SOA) | 			z.SOA = x.RR.(*dns.SOA) | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
|  | 		if x.RR.Header().Rrtype == dns.TypeRRSIG { | ||||||
|  | 			if x, ok := x.RR.(*dns.RRSIG); ok && x.TypeCovered == dns.TypeSOA { | ||||||
|  | 				z.SIG = append(z.SIG, x) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 		z.Insert(x.RR) | 		z.Insert(x.RR) | ||||||
| 	} | 	} | ||||||
| 	return z, nil | 	return z, nil | ||||||
|   | |||||||
| @@ -14,16 +14,17 @@ const ( | |||||||
| // Lookup looks up qname and qtype in the zone, when do is true DNSSEC are included as well. | // Lookup looks up qname and qtype in the zone, when do is true DNSSEC are included as well. | ||||||
| // Two sets of records are returned, one for the answer and one for the additional section. | // Two sets of records are returned, one for the answer and one for the additional section. | ||||||
| func (z *Zone) Lookup(qname string, qtype uint16, do bool) ([]dns.RR, []dns.RR, Result) { | func (z *Zone) Lookup(qname string, qtype uint16, do bool) ([]dns.RR, []dns.RR, Result) { | ||||||
| 	// TODO(miek): implement DNSSEC |  | ||||||
| 	var rr dns.RR | 	var rr dns.RR | ||||||
| 	mk, known := dns.TypeToRR[qtype] | 	mk, known := dns.TypeToRR[qtype] | ||||||
| 	if !known { | 	if !known { | ||||||
| 		return nil, nil, NameError | 		an, ad, _ := z.lookupSOA(do) | ||||||
| 		// Uhm...? | 		return an, ad, NameError | ||||||
| 		// rr = new(RFC3597) | 		// Uhm...? rr = new(RFC3597) ?? | ||||||
| 	} else { | 	} else { | ||||||
| 		rr = mk() | 		rr = mk() | ||||||
| 	} | 	} | ||||||
|  | 	rr.Header().Rrtype = qtype // this is pretty nonobvious | ||||||
|  |  | ||||||
| 	if qtype == dns.TypeSOA { | 	if qtype == dns.TypeSOA { | ||||||
| 		return z.lookupSOA(do) | 		return z.lookupSOA(do) | ||||||
| 	} | 	} | ||||||
| @@ -31,38 +32,68 @@ func (z *Zone) Lookup(qname string, qtype uint16, do bool) ([]dns.RR, []dns.RR, | |||||||
| 	rr.Header().Name = qname | 	rr.Header().Name = qname | ||||||
| 	elem := z.Tree.Get(rr) | 	elem := z.Tree.Get(rr) | ||||||
| 	if elem == nil { | 	if elem == nil { | ||||||
| 		return []dns.RR{z.SOA}, nil, NameError | 		an, ad, _ := z.lookupSOA(do) | ||||||
|  | 		return an, ad, NameError | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	rrs := elem.Types(dns.TypeCNAME) | 	rrs := elem.Types(dns.TypeCNAME) | ||||||
| 	if len(rrs) > 0 { // should only ever be 1 actually; TODO(miek) check for this? | 	if len(rrs) > 0 { // should only ever be 1 actually; TODO(miek) check for this? | ||||||
| 		// lookup target from the cname |  | ||||||
| 		rr.Header().Name = rrs[0].(*dns.CNAME).Target | 		rr.Header().Name = rrs[0].(*dns.CNAME).Target | ||||||
| 		elem := z.Tree.Get(rr) | 		return z.lookupCNAME(rrs, rr, do) | ||||||
| 		if elem == nil { |  | ||||||
| 			return rrs, nil, Success |  | ||||||
| 		} |  | ||||||
| 		return rrs, elem.All(), Success |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	rrs = elem.Types(qtype) | 	rrs = elem.Types(qtype) | ||||||
| 	if len(rrs) == 0 { | 	if len(rrs) == 0 { | ||||||
| 		return []dns.RR{z.SOA}, nil, NoData | 		an, ad, _ := z.lookupSOA(do) | ||||||
|  | 		return an, ad, NoData | ||||||
|  | 	} | ||||||
|  | 	if do { | ||||||
|  | 		sigs := elem.Types(dns.TypeRRSIG) | ||||||
|  | 		sigs = signatureForSubType(sigs, qtype) | ||||||
|  | 		if len(sigs) > 0 { | ||||||
|  | 			rrs = append(rrs, sigs...) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	// Need to check sub-type on RRSIG records to only include the correctly |  | ||||||
| 	// typed ones. |  | ||||||
| 	return rrs, nil, Success | 	return rrs, nil, Success | ||||||
| } | } | ||||||
|  |  | ||||||
| func (z *Zone) lookupSOA(do bool) ([]dns.RR, []dns.RR, Result) { | func (z *Zone) lookupSOA(do bool) ([]dns.RR, []dns.RR, Result) { | ||||||
|  | 	if do { | ||||||
|  | 		ret := append([]dns.RR{z.SOA}, z.SIG...) | ||||||
|  | 		return ret, nil, Success | ||||||
|  | 	} | ||||||
| 	return []dns.RR{z.SOA}, nil, Success | 	return []dns.RR{z.SOA}, nil, Success | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (z *Zone) lookupCNAME(rrs []dns.RR, rr dns.RR, do bool) ([]dns.RR, []dns.RR, Result) { | ||||||
|  | 	elem := z.Tree.Get(rr) | ||||||
|  | 	if elem == nil { | ||||||
|  | 		return rrs, nil, Success | ||||||
|  | 	} | ||||||
|  | 	extra := cnameForType(elem.All(), rr.Header().Rrtype) | ||||||
|  | 	if do { | ||||||
|  | 		sigs := elem.Types(dns.TypeRRSIG) | ||||||
|  | 		sigs = signatureForSubType(sigs, rr.Header().Rrtype) | ||||||
|  | 		if len(sigs) > 0 { | ||||||
|  | 			extra = append(extra, sigs...) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return rrs, extra, Success | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func cnameForType(targets []dns.RR, origQtype uint16) []dns.RR { | ||||||
|  | 	ret := []dns.RR{} | ||||||
|  | 	for _, target := range targets { | ||||||
|  | 		if target.Header().Rrtype == origQtype { | ||||||
|  | 			ret = append(ret, target) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return ret | ||||||
|  | } | ||||||
|  |  | ||||||
| // signatureForSubType range through the signature and return the correct | // signatureForSubType range through the signature and return the correct | ||||||
| // ones for the subtype. | // ones for the subtype. | ||||||
| func (z *Zone) signatureForSubType(rrs []dns.RR, subtype uint16, do bool) []dns.RR { | func signatureForSubType(rrs []dns.RR, subtype uint16) []dns.RR { | ||||||
| 	if !do { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| 	sigs := []dns.RR{} | 	sigs := []dns.RR{} | ||||||
| 	for _, sig := range rrs { | 	for _, sig := range rrs { | ||||||
| 		if s, ok := sig.(*dns.RRSIG); ok { | 		if s, ok := sig.(*dns.RRSIG); ok { | ||||||
|   | |||||||
| @@ -43,7 +43,6 @@ var dnsTestCases = []coretest.Case{ | |||||||
|  |  | ||||||
| 		Extra: []dns.RR{ | 		Extra: []dns.RR{ | ||||||
| 			coretest.A("a.miek.nl.	1800	IN	A	139.162.196.78"), | 			coretest.A("a.miek.nl.	1800	IN	A	139.162.196.78"), | ||||||
| 			coretest.AAAA("a.miek.nl.	1800	IN	AAAA	2a01:7e00::f03c:91ff:fef1:6735"), |  | ||||||
| 		}, | 		}, | ||||||
| 	}, | 	}, | ||||||
| 	{ | 	{ | ||||||
| @@ -73,8 +72,7 @@ func TestLookup(t *testing.T) { | |||||||
| 	ctx := context.TODO() | 	ctx := context.TODO() | ||||||
|  |  | ||||||
| 	for _, tc := range dnsTestCases { | 	for _, tc := range dnsTestCases { | ||||||
| 		m := new(dns.Msg) | 		m := tc.Msg() | ||||||
| 		m.SetQuestion(dns.Fqdn(tc.Qname), tc.Qtype) |  | ||||||
|  |  | ||||||
| 		rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{}) | 		rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{}) | ||||||
| 		_, err := fm.ServeDNS(ctx, rec, m) | 		_, err := fm.ServeDNS(ctx, rec, m) | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ func newElem(rr dns.RR) *Elem { | |||||||
| 	return &e | 	return &e | ||||||
| } | } | ||||||
|  |  | ||||||
| // Types returns the types from with type qtype from e. | // Types returns the RRs with type qtype from e. | ||||||
| func (e *Elem) Types(qtype uint16) []dns.RR { | func (e *Elem) Types(qtype uint16) []dns.RR { | ||||||
| 	if rrs, ok := e.m[qtype]; ok { | 	if rrs, ok := e.m[qtype]; ok { | ||||||
| 		// TODO(miek): length should never be zero here. | 		// TODO(miek): length should never be zero here. | ||||||
| @@ -56,6 +56,7 @@ func (e *Elem) Types(qtype uint16) []dns.RR { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // All returns all RRs from e, regardless of type. | ||||||
| func (e *Elem) All() []dns.RR { | func (e *Elem) All() []dns.RR { | ||||||
| 	list := []dns.RR{} | 	list := []dns.RR{} | ||||||
| 	for _, rrs := range e.m { | 	for _, rrs := range e.m { | ||||||
| @@ -64,6 +65,7 @@ func (e *Elem) All() []dns.RR { | |||||||
| 	return list | 	return list | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Insert inserts rr into e. If rr is equal to existing rrs this is a noop. | ||||||
| func (e *Elem) Insert(rr dns.RR) { | func (e *Elem) Insert(rr dns.RR) { | ||||||
| 	t := rr.Header().Rrtype | 	t := rr.Header().Rrtype | ||||||
| 	if e.m == nil { | 	if e.m == nil { | ||||||
| @@ -130,6 +132,7 @@ func Less(a *Elem, rr dns.RR) int { | |||||||
| // Assuming the same type and name this will check if the rdata is equal as well. | // Assuming the same type and name this will check if the rdata is equal as well. | ||||||
| func equalRdata(a, b dns.RR) bool { | func equalRdata(a, b dns.RR) bool { | ||||||
| 	switch x := a.(type) { | 	switch x := a.(type) { | ||||||
|  | 	// TODO(miek): more types, i.e. all types. | ||||||
| 	case *dns.A: | 	case *dns.A: | ||||||
| 		return x.A.Equal(b.(*dns.A).A) | 		return x.A.Equal(b.(*dns.A).A) | ||||||
| 	case *dns.AAAA: | 	case *dns.AAAA: | ||||||
| @@ -259,8 +262,7 @@ func (t *Tree) Len() int { | |||||||
| 	return t.Count | 	return t.Count | ||||||
| } | } | ||||||
|  |  | ||||||
| // Get returns the first match of q in the Tree. If insertion without | // Get returns the first match of rr in the Tree. | ||||||
| // replacement is used, this is probably not what you want. |  | ||||||
| func (t *Tree) Get(rr dns.RR) *Elem { | func (t *Tree) Get(rr dns.RR) *Elem { | ||||||
| 	if t.Root == nil { | 	if t.Root == nil { | ||||||
| 		return nil | 		return nil | ||||||
| @@ -287,11 +289,8 @@ func (n *Node) search(rr dns.RR) *Node { | |||||||
| 	return n | 	return n | ||||||
| } | } | ||||||
|  |  | ||||||
| // Insert inserts the Comparable e into the Tree at the first match found | // Insert inserts rr into the Tree at the first match found | ||||||
| // with e or when a nil node is reached. Insertion without replacement can | // with e or when a nil node is reached. | ||||||
| // specified by ensuring that e.Compare() never returns 0. If insert without |  | ||||||
| // replacement is performed, a distinct query Comparable must be used that |  | ||||||
| // can return 0 with a Compare() call. |  | ||||||
| func (t *Tree) Insert(rr dns.RR) { | func (t *Tree) Insert(rr dns.RR) { | ||||||
| 	var d int | 	var d int | ||||||
| 	t.Root, d = t.Root.insert(rr) | 	t.Root, d = t.Root.insert(rr) | ||||||
| @@ -340,8 +339,7 @@ func (n *Node) insert(rr dns.RR) (root *Node, d int) { | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  |  | ||||||
| // DeleteMin deletes the node with the minimum value in the tree. If insertion without | // DeleteMin deletes the node with the minimum value in the tree. | ||||||
| // replacement has been used, the left-most minimum will be deleted. |  | ||||||
| func (t *Tree) DeleteMin() { | func (t *Tree) DeleteMin() { | ||||||
| 	if t.Root == nil { | 	if t.Root == nil { | ||||||
| 		return | 		return | ||||||
| @@ -369,8 +367,7 @@ func (n *Node) deleteMin() (root *Node, d int) { | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  |  | ||||||
| // DeleteMax deletes the node with the maximum value in the tree. If insertion without | // DeleteMax deletes the node with the maximum value in the tree. | ||||||
| // replacement has been used, the right-most maximum will be deleted. |  | ||||||
| func (t *Tree) DeleteMax() { | func (t *Tree) DeleteMax() { | ||||||
| 	if t.Root == nil { | 	if t.Root == nil { | ||||||
| 		return | 		return | ||||||
| @@ -401,7 +398,7 @@ func (n *Node) deleteMax() (root *Node, d int) { | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  |  | ||||||
| // Delete removes rr from the tree, is the node turns empty, that node is return with DeleteNode. | // Delete removes rr from the tree, is the node turns empty, that node is deleted with DeleteNode. | ||||||
| func (t *Tree) Delete(rr dns.RR) { | func (t *Tree) Delete(rr dns.RR) { | ||||||
| 	if t.Root == nil { | 	if t.Root == nil { | ||||||
| 		return | 		return | ||||||
| @@ -420,9 +417,7 @@ func (t *Tree) Delete(rr dns.RR) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // DeleteNode deletes the node that matches e according to Compare(). Note that Compare must | // DeleteNode deletes the node that matches rr according to Less(). | ||||||
| // identify the target node uniquely and in cases where non-unique keys are used, |  | ||||||
| // attributes used to break ties must be used to determine tree ordering during insertion. |  | ||||||
| func (t *Tree) DeleteNode(rr dns.RR) { | func (t *Tree) DeleteNode(rr dns.RR) { | ||||||
| 	if t.Root == nil { | 	if t.Root == nil { | ||||||
| 		return | 		return | ||||||
| @@ -469,8 +464,7 @@ func (n *Node) delete(rr dns.RR) (root *Node, d int) { | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  |  | ||||||
| // Return the minimum value stored in the tree. This will be the left-most minimum value if | // Min returns the minimum value stored in the tree. | ||||||
| // insertion without replacement has been used. |  | ||||||
| func (t *Tree) Min() *Elem { | func (t *Tree) Min() *Elem { | ||||||
| 	if t.Root == nil { | 	if t.Root == nil { | ||||||
| 		return nil | 		return nil | ||||||
| @@ -484,8 +478,7 @@ func (n *Node) min() *Node { | |||||||
| 	return n | 	return n | ||||||
| } | } | ||||||
|  |  | ||||||
| // Return the maximum value stored in the tree. This will be the right-most maximum value if | // Max returns the maximum value stored in the tree. | ||||||
| // insertion without replacement has been used. |  | ||||||
| func (t *Tree) Max() *Elem { | func (t *Tree) Max() *Elem { | ||||||
| 	if t.Root == nil { | 	if t.Root == nil { | ||||||
| 		return nil | 		return nil | ||||||
| @@ -499,7 +492,7 @@ func (n *Node) max() *Node { | |||||||
| 	return n | 	return n | ||||||
| } | } | ||||||
|  |  | ||||||
| // Floor returns the greatest value equal to or less than the query q according to q.Compare(). | // Floor returns the greatest value equal to or less than the rr according to Less(). | ||||||
| func (t *Tree) Floor(rr dns.RR) *Elem { | func (t *Tree) Floor(rr dns.RR) *Elem { | ||||||
| 	if t.Root == nil { | 	if t.Root == nil { | ||||||
| 		return nil | 		return nil | ||||||
| @@ -528,9 +521,7 @@ func (n *Node) floor(rr dns.RR) *Node { | |||||||
| 	return n | 	return n | ||||||
| } | } | ||||||
|  |  | ||||||
| // TODO(successor, predecessor) | // Ceil returns the smallest value equal to or greater than the rr according to Less(). | ||||||
|  |  | ||||||
| // Ceil returns the smallest value equal to or greater than the query q according to q.Compare(). |  | ||||||
| func (t *Tree) Ceil(rr dns.RR) *Elem { | func (t *Tree) Ceil(rr dns.RR) *Elem { | ||||||
| 	if t.Root == nil { | 	if t.Root == nil { | ||||||
| 		return nil | 		return nil | ||||||
|   | |||||||
| @@ -27,11 +27,26 @@ type Case struct { | |||||||
| 	Qname  string | 	Qname  string | ||||||
| 	Qtype  uint16 | 	Qtype  uint16 | ||||||
| 	Rcode  int | 	Rcode  int | ||||||
|  | 	Do     bool | ||||||
| 	Answer []dns.RR | 	Answer []dns.RR | ||||||
| 	Ns     []dns.RR | 	Ns     []dns.RR | ||||||
| 	Extra  []dns.RR | 	Extra  []dns.RR | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (c Case) Msg() *dns.Msg { | ||||||
|  | 	m := new(dns.Msg) | ||||||
|  | 	m.SetQuestion(dns.Fqdn(c.Qname), c.Qtype) | ||||||
|  | 	if c.Do { | ||||||
|  | 		o := new(dns.OPT) | ||||||
|  | 		o.Hdr.Name = "." | ||||||
|  | 		o.Hdr.Rrtype = dns.TypeOPT | ||||||
|  | 		o.SetDo() | ||||||
|  | 		o.SetUDPSize(4096) | ||||||
|  | 		m.Extra = []dns.RR{o} | ||||||
|  | 	} | ||||||
|  | 	return m | ||||||
|  | } | ||||||
|  |  | ||||||
| func A(rr string) *dns.A         { r, _ := dns.NewRR(rr); return r.(*dns.A) } | func A(rr string) *dns.A         { r, _ := dns.NewRR(rr); return r.(*dns.A) } | ||||||
| func AAAA(rr string) *dns.AAAA   { r, _ := dns.NewRR(rr); return r.(*dns.AAAA) } | func AAAA(rr string) *dns.AAAA   { r, _ := dns.NewRR(rr); return r.(*dns.AAAA) } | ||||||
| func CNAME(rr string) *dns.CNAME { r, _ := dns.NewRR(rr); return r.(*dns.CNAME) } | func CNAME(rr string) *dns.CNAME { r, _ := dns.NewRR(rr); return r.(*dns.CNAME) } | ||||||
| @@ -41,6 +56,8 @@ func NS(rr string) *dns.NS       { r, _ := dns.NewRR(rr); return r.(*dns.NS) } | |||||||
| func PTR(rr string) *dns.PTR     { r, _ := dns.NewRR(rr); return r.(*dns.PTR) } | func PTR(rr string) *dns.PTR     { r, _ := dns.NewRR(rr); return r.(*dns.PTR) } | ||||||
| func TXT(rr string) *dns.TXT     { r, _ := dns.NewRR(rr); return r.(*dns.TXT) } | func TXT(rr string) *dns.TXT     { r, _ := dns.NewRR(rr); return r.(*dns.TXT) } | ||||||
| func MX(rr string) *dns.MX       { r, _ := dns.NewRR(rr); return r.(*dns.MX) } | func MX(rr string) *dns.MX       { r, _ := dns.NewRR(rr); return r.(*dns.MX) } | ||||||
|  | func RRSIG(rr string) *dns.RRSIG { r, _ := dns.NewRR(rr); return r.(*dns.RRSIG) } | ||||||
|  | func NSEC(rr string) *dns.NSEC   { r, _ := dns.NewRR(rr); return r.(*dns.NSEC) } | ||||||
|  |  | ||||||
| func CheckSection(t *testing.T, tc Case, sect Section, rr []dns.RR) bool { | func CheckSection(t *testing.T, tc Case, sect Section, rr []dns.RR) bool { | ||||||
| 	section := []dns.RR{} | 	section := []dns.RR{} | ||||||
| @@ -86,6 +103,25 @@ func CheckSection(t *testing.T, tc Case, sect Section, rr []dns.RR) bool { | |||||||
| 				t.Errorf("rr %d should have a Target of %q, but has %q", i, section[i].(*dns.SRV).Target, x.Target) | 				t.Errorf("rr %d should have a Target of %q, but has %q", i, section[i].(*dns.SRV).Target, x.Target) | ||||||
| 				return false | 				return false | ||||||
| 			} | 			} | ||||||
|  | 		case *dns.RRSIG: | ||||||
|  | 			if x.TypeCovered != section[i].(*dns.RRSIG).TypeCovered { | ||||||
|  | 				t.Errorf("rr %d should have a TypeCovered of %d, but has %d", i, section[i].(*dns.RRSIG).TypeCovered, x.TypeCovered) | ||||||
|  | 				return false | ||||||
|  | 			} | ||||||
|  | 			if x.Labels != section[i].(*dns.RRSIG).Labels { | ||||||
|  | 				t.Errorf("rr %d should have a Labels of %d, but has %d", i, section[i].(*dns.RRSIG).Labels, x.Labels) | ||||||
|  | 				return false | ||||||
|  | 			} | ||||||
|  | 			if x.SignerName != section[i].(*dns.RRSIG).SignerName { | ||||||
|  | 				t.Errorf("rr %d should have a SignerName of %d, but has %d", i, section[i].(*dns.RRSIG).SignerName, x.SignerName) | ||||||
|  | 				return false | ||||||
|  | 			} | ||||||
|  | 		case *dns.NSEC: | ||||||
|  | 			if x.NextDomain != section[i].(*dns.NSEC).NextDomain { | ||||||
|  | 				t.Errorf("rr %d should have a NextDomain of %d, but has %d", i, section[i].(*dns.NSEC).NextDomain, x.NextDomain) | ||||||
|  | 				return false | ||||||
|  | 			} | ||||||
|  | 			// TypeBitMap | ||||||
| 		case *dns.A: | 		case *dns.A: | ||||||
| 			if x.A.String() != section[i].(*dns.A).A.String() { | 			if x.A.String() != section[i].(*dns.A).A.String() { | ||||||
| 				t.Errorf("rr %d should have a Address of %q, but has %q", i, section[i].(*dns.A).A.String(), x.A.String()) | 				t.Errorf("rr %d should have a Address of %q, but has %q", i, section[i].(*dns.A).A.String(), x.A.String()) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user