2014-11-09 20:56:22 +11:00
|
|
|
package dns
|
|
|
|
|
2014-11-12 18:57:04 +11:00
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"testing"
|
|
|
|
)
|
2014-11-09 20:57:06 +11:00
|
|
|
|
2014-11-09 20:56:22 +11:00
|
|
|
func TestDynamicUpdateParsing(t *testing.T) {
|
Support parsing known RR types in RFC 3597 format (#1211)
* Support parsing known RR types in RFC 3597 format
This is the format used for "Unknown DNS Resource Records", but it's
also useful to support parsing known RR types in this way.
RFC 3597 says:
An implementation MAY also choose to represent some RRs of known type
using the above generic representations for the type, class and/or
RDATA, which carries the benefit of making the resulting master file
portable to servers where these types are unknown. Using the generic
representation for the RDATA of an RR of known type can also be
useful in the case of an RR type where the text format varies
depending on a version, protocol, or similar field (or several)
embedded in the RDATA when such a field has a value for which no text
format is known, e.g., a LOC RR [RFC1876] with a VERSION other than
0.
Even though an RR of known type represented in the \# format is
effectively treated as an unknown type for the purpose of parsing the
RDATA text representation, all further processing by the server MUST
treat it as a known type and take into account any applicable type-
specific rules regarding compression, canonicalization, etc.
* Correct mistakes in TestZoneParserAddressAAAA
This was spotted when writing TestParseKnownRRAsRFC3597.
* Eliminate canParseAsRR
This has the advantage that concrete types will now be returned for
parsed ANY, NULL, OPT and TSIG records.
* Expand TestDynamicUpdateParsing for RFC 3597
This ensures we're properly handling empty RDATA for RFC 3597 parsed
records.
2021-01-31 00:05:25 +11:00
|
|
|
const prefix = "example.com. IN "
|
|
|
|
|
|
|
|
for typ, name := range TypeToString {
|
|
|
|
switch typ {
|
|
|
|
case TypeNone, TypeReserved:
|
|
|
|
continue
|
|
|
|
case TypeANY:
|
|
|
|
// ANY is ambiguous here and ends up parsed as a CLASS.
|
|
|
|
//
|
|
|
|
// TODO(tmthrgd): Using TYPE255 here doesn't seem to work and also
|
|
|
|
// seems to fail for some other record types. Investigate.
|
2014-11-09 20:56:22 +11:00
|
|
|
continue
|
|
|
|
}
|
Support parsing known RR types in RFC 3597 format (#1211)
* Support parsing known RR types in RFC 3597 format
This is the format used for "Unknown DNS Resource Records", but it's
also useful to support parsing known RR types in this way.
RFC 3597 says:
An implementation MAY also choose to represent some RRs of known type
using the above generic representations for the type, class and/or
RDATA, which carries the benefit of making the resulting master file
portable to servers where these types are unknown. Using the generic
representation for the RDATA of an RR of known type can also be
useful in the case of an RR type where the text format varies
depending on a version, protocol, or similar field (or several)
embedded in the RDATA when such a field has a value for which no text
format is known, e.g., a LOC RR [RFC1876] with a VERSION other than
0.
Even though an RR of known type represented in the \# format is
effectively treated as an unknown type for the purpose of parsing the
RDATA text representation, all further processing by the server MUST
treat it as a known type and take into account any applicable type-
specific rules regarding compression, canonicalization, etc.
* Correct mistakes in TestZoneParserAddressAAAA
This was spotted when writing TestParseKnownRRAsRFC3597.
* Eliminate canParseAsRR
This has the advantage that concrete types will now be returned for
parsed ANY, NULL, OPT and TSIG records.
* Expand TestDynamicUpdateParsing for RFC 3597
This ensures we're properly handling empty RDATA for RFC 3597 parsed
records.
2021-01-31 00:05:25 +11:00
|
|
|
|
|
|
|
s := prefix + name
|
|
|
|
if _, err := NewRR(s); err != nil {
|
|
|
|
t.Errorf("failure to parse: %s: %v", s, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
s += " \\# 0"
|
|
|
|
if _, err := NewRR(s); err != nil {
|
|
|
|
t.Errorf("failure to parse: %s: %v", s, err)
|
2014-11-09 20:56:22 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-09 21:04:46 +11:00
|
|
|
func TestDynamicUpdateUnpack(t *testing.T) {
|
|
|
|
// From https://github.com/miekg/dns/issues/150#issuecomment-62296803
|
2014-11-10 03:09:49 +11:00
|
|
|
// It should be an update message for the zone "example.",
|
|
|
|
// deleting the A RRset "example." and then adding an A record at "example.".
|
|
|
|
// class ANY, TYPE A
|
2014-11-09 21:04:46 +11:00
|
|
|
buf := []byte{171, 68, 40, 0, 0, 1, 0, 0, 0, 2, 0, 0, 7, 101, 120, 97, 109, 112, 108, 101, 0, 0, 6, 0, 1, 192, 12, 0, 1, 0, 255, 0, 0, 0, 0, 0, 0, 192, 12, 0, 1, 0, 1, 0, 0, 0, 0, 0, 4, 127, 0, 0, 1}
|
|
|
|
msg := new(Msg)
|
|
|
|
err := msg.Unpack(buf)
|
|
|
|
if err != nil {
|
2015-02-26 17:23:47 +11:00
|
|
|
t.Errorf("failed to unpack: %v\n%s", err, msg.String())
|
2014-11-09 21:04:46 +11:00
|
|
|
}
|
|
|
|
}
|
2014-11-12 10:32:03 +11:00
|
|
|
|
|
|
|
func TestDynamicUpdateZeroRdataUnpack(t *testing.T) {
|
|
|
|
m := new(Msg)
|
|
|
|
rr := &RR_Header{Name: ".", Rrtype: 0, Class: 1, Ttl: ^uint32(0), Rdlength: 0}
|
|
|
|
m.Answer = []RR{rr, rr, rr, rr, rr}
|
|
|
|
m.Ns = m.Answer
|
|
|
|
for n, s := range TypeToString {
|
|
|
|
rr.Rrtype = n
|
|
|
|
bytes, err := m.Pack()
|
|
|
|
if err != nil {
|
2015-02-21 16:03:02 +11:00
|
|
|
t.Errorf("failed to pack %s: %v", s, err)
|
2014-11-12 10:32:03 +11:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
if err := new(Msg).Unpack(bytes); err != nil {
|
2015-02-21 16:03:02 +11:00
|
|
|
t.Errorf("failed to unpack %s: %v", s, err)
|
2014-11-12 10:32:03 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-11-12 18:57:04 +11:00
|
|
|
|
|
|
|
func TestRemoveRRset(t *testing.T) {
|
|
|
|
// Should add a zero data RR in Class ANY with a TTL of 0
|
|
|
|
// for each set mentioned in the RRs provided to it.
|
2017-11-08 21:01:19 +11:00
|
|
|
rr := testRR(". 100 IN A 127.0.0.1")
|
2014-11-12 18:57:04 +11:00
|
|
|
m := new(Msg)
|
|
|
|
m.Ns = []RR{&RR_Header{Name: ".", Rrtype: TypeA, Class: ClassANY, Ttl: 0, Rdlength: 0}}
|
|
|
|
expectstr := m.String()
|
|
|
|
expect, err := m.Pack()
|
|
|
|
if err != nil {
|
2015-11-27 01:12:38 +11:00
|
|
|
t.Fatalf("error packing expected msg: %v", err)
|
2014-11-12 18:57:04 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
m.Ns = nil
|
|
|
|
m.RemoveRRset([]RR{rr})
|
|
|
|
actual, err := m.Pack()
|
|
|
|
if err != nil {
|
2015-11-27 01:12:38 +11:00
|
|
|
t.Fatalf("error packing actual msg: %v", err)
|
2014-11-12 18:57:04 +11:00
|
|
|
}
|
|
|
|
if !bytes.Equal(actual, expect) {
|
|
|
|
tmp := new(Msg)
|
|
|
|
if err := tmp.Unpack(actual); err != nil {
|
2016-05-15 02:56:20 +10:00
|
|
|
t.Fatalf("error unpacking actual msg: %v\nexpected: %v\ngot: %v\n", err, expect, actual)
|
2014-11-12 18:57:04 +11:00
|
|
|
}
|
2015-11-27 01:12:38 +11:00
|
|
|
t.Errorf("expected msg:\n%s", expectstr)
|
|
|
|
t.Errorf("actual msg:\n%v", tmp)
|
2014-11-12 18:57:04 +11:00
|
|
|
}
|
|
|
|
}
|
2016-02-27 12:44:33 +11:00
|
|
|
|
|
|
|
func TestPreReqAndRemovals(t *testing.T) {
|
|
|
|
// Build a list of multiple prereqs and then somes removes followed by an insert.
|
|
|
|
// We should be able to add multiple prereqs and updates.
|
|
|
|
m := new(Msg)
|
2016-02-27 23:02:32 +11:00
|
|
|
m.SetUpdate("example.org.")
|
2016-02-27 12:44:33 +11:00
|
|
|
m.Id = 1234
|
|
|
|
|
|
|
|
// Use a full set of RRs each time, so we are sure the rdata is stripped.
|
2017-11-08 21:01:19 +11:00
|
|
|
rrName1 := testRR("name_used. 3600 IN A 127.0.0.1")
|
|
|
|
rrName2 := testRR("name_not_used. 3600 IN A 127.0.0.1")
|
|
|
|
rrRemove1 := testRR("remove1. 3600 IN A 127.0.0.1")
|
|
|
|
rrRemove2 := testRR("remove2. 3600 IN A 127.0.0.1")
|
|
|
|
rrRemove3 := testRR("remove3. 3600 IN A 127.0.0.1")
|
|
|
|
rrInsert := testRR("insert. 3600 IN A 127.0.0.1")
|
|
|
|
rrRrset1 := testRR("rrset_used1. 3600 IN A 127.0.0.1")
|
|
|
|
rrRrset2 := testRR("rrset_used2. 3600 IN A 127.0.0.1")
|
|
|
|
rrRrset3 := testRR("rrset_not_used. 3600 IN A 127.0.0.1")
|
2016-02-27 12:44:33 +11:00
|
|
|
|
|
|
|
// Handle the prereqs.
|
2017-02-16 07:40:16 +11:00
|
|
|
m.NameUsed([]RR{rrName1})
|
|
|
|
m.NameNotUsed([]RR{rrName2})
|
|
|
|
m.RRsetUsed([]RR{rrRrset1})
|
|
|
|
m.Used([]RR{rrRrset2})
|
|
|
|
m.RRsetNotUsed([]RR{rrRrset3})
|
2016-02-27 12:44:33 +11:00
|
|
|
|
|
|
|
// and now the updates.
|
2017-02-16 07:40:16 +11:00
|
|
|
m.RemoveName([]RR{rrRemove1})
|
|
|
|
m.RemoveRRset([]RR{rrRemove2})
|
|
|
|
m.Remove([]RR{rrRemove3})
|
|
|
|
m.Insert([]RR{rrInsert})
|
2016-02-27 12:44:33 +11:00
|
|
|
|
2016-02-28 19:33:08 +11:00
|
|
|
// This test function isn't a Example function because we print these RR with tabs at the
|
|
|
|
// end and the Example function trim these, thus they never match.
|
|
|
|
// TODO(miek): don't print these tabs and make this into an Example function.
|
2016-02-27 12:44:33 +11:00
|
|
|
expect := `;; opcode: UPDATE, status: NOERROR, id: 1234
|
|
|
|
;; flags:; QUERY: 1, ANSWER: 5, AUTHORITY: 4, ADDITIONAL: 0
|
|
|
|
|
|
|
|
;; QUESTION SECTION:
|
2016-02-27 23:02:32 +11:00
|
|
|
;example.org. IN SOA
|
2016-02-27 12:44:33 +11:00
|
|
|
|
|
|
|
;; ANSWER SECTION:
|
2018-01-08 04:57:04 +11:00
|
|
|
name_used. 0 CLASS255 ANY
|
2016-02-27 12:44:33 +11:00
|
|
|
name_not_used. 0 NONE ANY
|
2018-01-08 04:57:04 +11:00
|
|
|
rrset_used1. 0 CLASS255 A
|
2021-07-18 17:24:05 +10:00
|
|
|
rrset_used2. 0 IN A 127.0.0.1
|
2016-02-27 12:44:33 +11:00
|
|
|
rrset_not_used. 0 NONE A
|
|
|
|
|
|
|
|
;; AUTHORITY SECTION:
|
2018-01-08 04:57:04 +11:00
|
|
|
remove1. 0 CLASS255 ANY
|
|
|
|
remove2. 0 CLASS255 A
|
2016-02-27 12:44:33 +11:00
|
|
|
remove3. 0 NONE A 127.0.0.1
|
|
|
|
insert. 3600 IN A 127.0.0.1
|
|
|
|
`
|
|
|
|
|
|
|
|
if m.String() != expect {
|
|
|
|
t.Errorf("expected msg:\n%s", expect)
|
|
|
|
t.Errorf("actual msg:\n%v", m.String())
|
|
|
|
}
|
|
|
|
}
|