diff --git a/dns_test.go b/dns_test.go index bf7bace8..8b795959 100644 --- a/dns_test.go +++ b/dns_test.go @@ -255,9 +255,14 @@ func TestNoRdataPack(t *testing.T) { } // TODO(miek): fix dns buffer too small errors this throws -func testNoRdataUnpack(t *testing.T) { +func TestNoRdataUnpack(t *testing.T) { data := make([]byte, 1024) for typ, fn := range rr_mk { + if typ == TypeSOA || typ == TypeTSIG || typ == TypeWKS { + // SOA, TSIG will not be seen in dyn. updates? + // WKS is an bug, but...deprecated record. + continue + } r := fn() *r.Header() = RR_Header{Name: "miek.nl.", Rrtype: typ, Class: ClassINET, Ttl: 3600} off, e := PackRR(r, data, 0, nil, false) diff --git a/msg.go b/msg.go index b84d30b9..d5ccd821 100644 --- a/msg.go +++ b/msg.go @@ -482,6 +482,9 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str off++ } case `dns:"wks"`: + if off == lenmsg { + break // dyn. updates + } if val.Field(i).Len() == 0 { break } @@ -684,6 +687,8 @@ func packStructCompress(any interface{}, msg []byte, off int, compression map[st return off, err } +// TODO(mg): Fix use of rdlength here + // Unpack a reflect.StructValue from msg. // Same restrictions as packStructValue. func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err error) { @@ -713,6 +718,9 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er txt := make([]string, 0) rdlength := off + int(val.FieldByName("Hdr").FieldByName("Rdlength").Uint()) Txts: + if off == lenmsg { // dyn. updates, no rdata is OK + break + } l := int(msg[off]) if off+l+1 > lenmsg { return lenmsg, &Error{err: "overflow unpacking txt"} @@ -788,12 +796,18 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er } fv.Set(reflect.ValueOf(edns)) case `dns:"a"`: + if off == lenmsg { + break // dyn. update + } if off+net.IPv4len > lenmsg { return lenmsg, &Error{err: "overflow unpacking a"} } fv.Set(reflect.ValueOf(net.IPv4(msg[off], msg[off+1], msg[off+2], msg[off+3]))) off += net.IPv4len case `dns:"aaaa"`: + if off == lenmsg { + break + } if off+net.IPv6len > lenmsg { return lenmsg, &Error{err: "overflow unpacking aaaa"} } @@ -839,10 +853,12 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er } fv.Set(reflect.ValueOf(serv)) case `dns:"nsec"`: // NSEC/NSEC3 + if off == lenmsg { + break + } // Rest of the record is the type bitmap rdlength := int(val.FieldByName("Hdr").FieldByName("Rdlength").Uint()) endrr := rdstart + rdlength - if off+2 > lenmsg { return lenmsg, &Error{err: "overflow unpacking nsecx"} } @@ -906,12 +922,18 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er rdstart = off } case reflect.Uint8: + if off == lenmsg { + break + } if off+1 > lenmsg { return lenmsg, &Error{err: "overflow unpacking uint8"} } fv.SetUint(uint64(uint8(msg[off]))) off++ case reflect.Uint16: + if off == lenmsg { + break + } var i uint16 if off+2 > lenmsg { return lenmsg, &Error{err: "overflow unpacking uint16"} @@ -919,6 +941,9 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er i, off = unpackUint16(msg, off) fv.SetUint(uint64(i)) case reflect.Uint32: + if off == lenmsg { + break + } if off+4 > lenmsg { return lenmsg, &Error{err: "overflow unpacking uint32"} } @@ -944,6 +969,9 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er } case reflect.String: var s string + if off == lenmsg { + break + } switch val.Type().Field(i).Tag { default: return lenmsg, &Error{"bad tag unpacking string: " + val.Type().Field(i).Tag.Get("dns")} @@ -968,6 +996,10 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er case `dns:"cdomain-name"`: fallthrough case `dns:"domain-name"`: + if off == lenmsg { + // zero rdata foo, OK for dyn. updates + break + } s, off, err = UnpackDomainName(msg, off) if err != nil { return lenmsg, err diff --git a/types.go b/types.go index 72a7bb91..2ddbc77c 100644 --- a/types.go +++ b/types.go @@ -1271,8 +1271,11 @@ type WKS struct { func (rr *WKS) Header() *RR_Header { return &rr.Hdr } func (rr *WKS) copy() RR { return &WKS{*rr.Hdr.copyHeader(), rr.Address, rr.Protocol, rr.BitMap} } -func (rr *WKS) String() string { - s := rr.Hdr.String() + rr.Address.String() +func (rr *WKS) String() (s string) { + s = rr.Hdr.String() + if rr.Address != nil { + s += rr.Address.String() + } for i := 0; i < len(rr.BitMap); i++ { // should lookup the port s += " " + strconv.Itoa(int(rr.BitMap[i])) @@ -1314,6 +1317,9 @@ func (rr *L32) Header() *RR_Header { return &rr.Hdr } func (rr *L32) copy() RR { return &L32{*rr.Hdr.copyHeader(), rr.Preference, rr.Locator32} } func (rr *L32) String() string { + if rr.Locator32 == nil { + return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + } return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + rr.Locator32.String() }