An update msg can have multiple, different prerequests and also multiple,
dfferent remove and inserts. The old code did a reset of the ANSWER and AUTHORITY section each time a rrset was added. Made a slight optimalisation that the first time an rrset is added, we take it length as the initial size. Helps for the one-time add cases. Added test to prevent regressions.
This commit is contained in:
parent
f89e57ed50
commit
13a6137d79
88
update.go
88
update.go
|
@ -3,18 +3,22 @@ package dns
|
|||
// NameUsed sets the RRs in the prereq section to
|
||||
// "Name is in use" RRs. RFC 2136 section 2.4.4.
|
||||
func (u *Msg) NameUsed(rr []RR) {
|
||||
u.Answer = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Answer[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}}
|
||||
if u.Answer == nil {
|
||||
u.Answer = make([]RR, 0, len(rr))
|
||||
}
|
||||
for _, r := range rr {
|
||||
u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}})
|
||||
}
|
||||
}
|
||||
|
||||
// NameNotUsed sets the RRs in the prereq section to
|
||||
// "Name is in not use" RRs. RFC 2136 section 2.4.5.
|
||||
func (u *Msg) NameNotUsed(rr []RR) {
|
||||
u.Answer = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Answer[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassNONE}}
|
||||
if u.Answer == nil {
|
||||
u.Answer = make([]RR, 0, len(rr))
|
||||
}
|
||||
for _, r := range rr {
|
||||
u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassNONE}})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,34 +28,34 @@ func (u *Msg) Used(rr []RR) {
|
|||
if len(u.Question) == 0 {
|
||||
panic("dns: empty question section")
|
||||
}
|
||||
u.Answer = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Answer[i] = r
|
||||
u.Answer[i].Header().Class = u.Question[0].Qclass
|
||||
if u.Answer == nil {
|
||||
u.Answer = make([]RR, 0, len(rr))
|
||||
}
|
||||
for _, r := range rr {
|
||||
r.Header().Class = u.Question[0].Qclass
|
||||
u.Answer = append(u.Answer, r)
|
||||
}
|
||||
}
|
||||
|
||||
// RRsetUsed sets the RRs in the prereq section to
|
||||
// "RRset exists (value independent -- no rdata)" RRs. RFC 2136 section 2.4.1.
|
||||
func (u *Msg) RRsetUsed(rr []RR) {
|
||||
u.Answer = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Answer[i] = r
|
||||
u.Answer[i].Header().Class = ClassANY
|
||||
u.Answer[i].Header().Ttl = 0
|
||||
u.Answer[i].Header().Rdlength = 0
|
||||
if u.Answer == nil {
|
||||
u.Answer = make([]RR, 0, len(rr))
|
||||
}
|
||||
for _, r := range rr {
|
||||
u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassANY}})
|
||||
}
|
||||
}
|
||||
|
||||
// RRsetNotUsed sets the RRs in the prereq section to
|
||||
// "RRset does not exist" RRs. RFC 2136 section 2.4.3.
|
||||
func (u *Msg) RRsetNotUsed(rr []RR) {
|
||||
u.Answer = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Answer[i] = r
|
||||
u.Answer[i].Header().Class = ClassNONE
|
||||
u.Answer[i].Header().Rdlength = 0
|
||||
u.Answer[i].Header().Ttl = 0
|
||||
if u.Answer == nil {
|
||||
u.Answer = make([]RR, 0, len(rr))
|
||||
}
|
||||
for _, r := range rr {
|
||||
u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassNONE}})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,35 +64,43 @@ func (u *Msg) Insert(rr []RR) {
|
|||
if len(u.Question) == 0 {
|
||||
panic("dns: empty question section")
|
||||
}
|
||||
u.Ns = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Ns[i] = r
|
||||
u.Ns[i].Header().Class = u.Question[0].Qclass
|
||||
if u.Ns == nil {
|
||||
u.Ns = make([]RR, 0, len(rr))
|
||||
}
|
||||
for _, r := range rr {
|
||||
r.Header().Class = u.Question[0].Qclass
|
||||
u.Ns = append(u.Ns, r)
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveRRset creates a dynamic update packet that deletes an RRset, see RFC 2136 section 2.5.2.
|
||||
func (u *Msg) RemoveRRset(rr []RR) {
|
||||
u.Ns = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Ns[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassANY}}
|
||||
if u.Ns == nil {
|
||||
u.Ns = make([]RR, 0, len(rr))
|
||||
}
|
||||
for _, r := range rr {
|
||||
u.Ns = append(u.Ns, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassANY}})
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveName creates a dynamic update packet that deletes all RRsets of a name, see RFC 2136 section 2.5.3
|
||||
func (u *Msg) RemoveName(rr []RR) {
|
||||
u.Ns = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Ns[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}}
|
||||
if u.Ns == nil {
|
||||
u.Ns = make([]RR, 0, len(rr))
|
||||
}
|
||||
for _, r := range rr {
|
||||
u.Ns = append(u.Ns, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}})
|
||||
}
|
||||
}
|
||||
|
||||
// Remove creates a dynamic update packet deletes RR from the RRSset, see RFC 2136 section 2.5.4
|
||||
// Remove creates a dynamic update packet deletes RR from a RRSset, see RFC 2136 section 2.5.4
|
||||
func (u *Msg) Remove(rr []RR) {
|
||||
u.Ns = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Ns[i] = r
|
||||
u.Ns[i].Header().Class = ClassNONE
|
||||
u.Ns[i].Header().Ttl = 0
|
||||
if u.Ns == nil {
|
||||
u.Ns = make([]RR, 0, len(rr))
|
||||
}
|
||||
for _, r := range rr {
|
||||
r.Header().Class = ClassNONE
|
||||
r.Header().Ttl = 0
|
||||
u.Ns = append(u.Ns, r)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
)
|
||||
|
||||
func TestDynamicUpdateParsing(t *testing.T) {
|
||||
// This does nothing with dynamic updates, move elsewhere?
|
||||
prefix := "example.com. IN "
|
||||
for _, typ := range TypeToString {
|
||||
if typ == "OPT" || typ == "AXFR" || typ == "IXFR" || typ == "ANY" || typ == "TKEY" ||
|
||||
|
@ -83,3 +84,60 @@ func TestRemoveRRset(t *testing.T) {
|
|||
t.Errorf("actual msg:\n%v", tmp)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
m.SetUpdate("some_zone.")
|
||||
m.Id = 1234
|
||||
|
||||
// Use a full set of RRs each time, so we are sure the rdata is stripped.
|
||||
rr_name1, _ := NewRR("name_used. 3600 IN A 127.0.0.1")
|
||||
rr_name2, _ := NewRR("name_not_used. 3600 IN A 127.0.0.1")
|
||||
rr_remove1, _ := NewRR("remove1. 3600 IN A 127.0.0.1")
|
||||
rr_remove2, _ := NewRR("remove2. 3600 IN A 127.0.0.1")
|
||||
rr_remove3, _ := NewRR("remove3. 3600 IN A 127.0.0.1")
|
||||
rr_insert, _ := NewRR("insert. 3600 IN A 127.0.0.1")
|
||||
rr_rrset1, _ := NewRR("rrset_used1. 3600 IN A 127.0.0.1")
|
||||
rr_rrset2, _ := NewRR("rrset_used2. 3600 IN A 127.0.0.1")
|
||||
rr_rrset3, _ := NewRR("rrset_not_used. 3600 IN A 127.0.0.1")
|
||||
|
||||
// Handle the prereqs.
|
||||
m.NameUsed([]RR{rr_name1})
|
||||
m.NameNotUsed([]RR{rr_name2})
|
||||
m.RRsetUsed([]RR{rr_rrset1})
|
||||
m.Used([]RR{rr_rrset2})
|
||||
m.RRsetNotUsed([]RR{rr_rrset3})
|
||||
|
||||
// and now the updates.
|
||||
m.RemoveName([]RR{rr_remove1})
|
||||
m.RemoveRRset([]RR{rr_remove2})
|
||||
m.Remove([]RR{rr_remove3})
|
||||
m.Insert([]RR{rr_insert})
|
||||
|
||||
expect := `;; opcode: UPDATE, status: NOERROR, id: 1234
|
||||
;; flags:; QUERY: 1, ANSWER: 5, AUTHORITY: 4, ADDITIONAL: 0
|
||||
|
||||
;; QUESTION SECTION:
|
||||
;some_zone. IN SOA
|
||||
|
||||
;; ANSWER SECTION:
|
||||
name_used. 0 ANY ANY
|
||||
name_not_used. 0 NONE ANY
|
||||
rrset_used1. 0 ANY A
|
||||
rrset_used2. 3600 IN A 127.0.0.1
|
||||
rrset_not_used. 0 NONE A
|
||||
|
||||
;; AUTHORITY SECTION:
|
||||
remove1. 0 ANY ANY
|
||||
remove2. 0 ANY A
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue