Repository: miekg/dns

Issue:
Proposal: Decorate "overflow unpacking" errors with where in the unpacking the error occurred.
I'm quite willing to do this work myself but wanted to first check if it is something that might get accepted.

We're seeing `overflow unpacking uint16` errors in our system and are having trouble reproducing it locally / getting a packet capture to see what is going on. One thing that might help us pinpoint what is going on would be some better logging.

The proposal would be to decorate errors from the `unpackUint*` and related family of functions with where the error occurred. For example:

```go
	hdr.Rrtype, off, err = unpackUint16(msg, off)
	if err != nil {
		return hdr, len(msg), msg, err
	}
```
to

```go
	hdr.Rrtype, off, err = unpackUint16(msg, off)
	if err != nil {
		return hdr, len(msg), msg, fmt.Errorf("header.Rrtype: %w", err)
	}
```

Hints from issue comments:
@bkr-JNPR: @EricIO , I am also seeing the same overflow issue in this package, issue happens rarely, dns packet looks fine.
not able to find out which DNS contents getting corrupted or some other reason.

please let me know if u already know more information .@miekg: That looks useful. Needs maybe some kind of naming convention to tell where the error
originated and some tweaks to make this work for all the autogenerated code.




[ Quoting ***@***.***> in "[miekg/dns] Proposal: Decorate "ove..." ]
>I'm quite willing to do this work myself but wanted to first check if it is
>something that might get accepted first.
>
>We're seeing overflow unpacking uint16 errors in our system and are having
>trouble reproducing it locally / getting a packet capture to see what is going
>on. One thing that might help us pinpoint what is going on would be some better
>logging.
>
>The proposal would be to decorate errors from the unpackUint* and related
>family of functions with where the error occurred. For example:
>
>        hdr.Rrtype, off, err = unpackUint16(msg, off)
>        if err != nil {
>                return hdr, len(msg), msg, err
>        }
>
>to
>
>        hdr.Rrtype, off, err = unpackUint16(msg, off)
>        if err != nil {
>                return hdr, len(msg), msg, fmt.Errorf("header.Rrtype: %w", err)
>        }
>
>—
>Reply to this email directly, view it on GitHub, or unsubscribe.
>You are receiving this because you are subscribed to this thread.*Message ID:
>***@***.***>
>
/Miek

--
Miek Gieben
@EricIO: Great. I'll try and have a draft PR up by the end of the weekend.@bkr-JNPR: @miekg , as @EricIO  mentioned, it is hard to recreate the issue, It seems this happens during parsing  of DNS response records , I see packet capture during this overflow error, Wireshark says DNS packets are completely fine and contain up to 15 resource records in DNS response packet .
When wireshark says a packet is proper, how does the DNS parser say overflow? This is the confusion .@miekg: yes, this may turn up a bug or two in code, or not@bkr-JNPR: @EricIO /@miekg,
any update on the patch for this issue ?@EricIO: @bkr-JNPR Had some stuff come up so haven't had time to work on finishing it. Hopefully will soon.@bkr-JNPR: @EricIO ,
Thanks. I hope you will make the change as soon as possible, don't want to duplicate the work .@EricIO: I'm currently working on the generated code to get that in a nice format. Will be on vacation a couple days so no progress will be made until I get back.

Solution patch:
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 202ae236..4be16cd4 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -4,3 +4,7 @@ updates:
     directory: "/"
     schedule:
       interval: "monthly"
+    groups:
+      all:
+        patterns:
+          - "*"
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index c0674c78..56a62f2b 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -7,7 +7,7 @@ jobs:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        go: [ 1.22.x, 1.23.x ]
+        go: [ 1.22.x, 1.23.x, 1.24.x ]
     steps:
 
     - name: Set up Go
diff --git a/README.md b/README.md
index 8d5a2a47..54471f5c 100644
--- a/README.md
+++ b/README.md
@@ -85,7 +85,8 @@ A not-so-up-to-date-list-that-may-be-actually-current:
 * https://github.com/wintbiit/NineDNS
 * https://linuxcontainers.org/incus/
 * https://ifconfig.es
-
+* https://github.com/zmap/zdns
+* https://framagit.org/bortzmeyer/check-soa
 
 Send pull request if you want to be listed here.
 
@@ -184,6 +185,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
 * 7871 - EDNS0 Client Subnet
 * 7873 - Domain Name System (DNS) Cookies
 * 8080 - EdDSA for DNSSEC
+* 8490 - DNS Stateful Operations
 * 8499 - DNS Terminology
 * 8659 - DNS Certification Authority Authorization (CAA) Resource Record
 * 8777 - DNS Reverse IP Automatic Multicast Tunneling (AMT) Discovery
@@ -192,6 +194,9 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
 * 9460 - Service Binding and Parameter Specification via the DNS
 * 9461 - Service Binding Mapping for DNS Servers
 * 9462 - Discovery of Designated Resolvers
+* 9460 - SVCB and HTTPS Records
+* 9606 - DNS Resolver Information
+* Draft - Compact Denial of Existence in DNSSEC
 
 ## Loosely Based Upon
 
diff --git a/dnssec.go b/dnssec.go
index 1be87eae..ffdafceb 100644
--- a/dnssec.go
+++ b/dnssec.go
@@ -250,14 +250,6 @@ func (d *DS) ToCDS() *CDS {
 // zero, it is used as-is, otherwise the TTL of the RRset is used as the
 // OrigTTL.
 func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
-	if k == nil {
-		return ErrPrivKey
-	}
-	// s.Inception and s.Expiration may be 0 (rollover etc.), the rest must be set
-	if rr.KeyTag == 0 || len(rr.SignerName) == 0 || rr.Algorithm == 0 {
-		return ErrKey
-	}
-
 	h0 := rrset[0].Header()
 	rr.Hdr.Rrtype = TypeRRSIG
 	rr.Hdr.Name = h0.Name
@@ -272,6 +264,18 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
 		rr.Labels-- // wildcard, remove from label count
 	}
 
+	return rr.signAsIs(k, rrset)
+}
+
+func (rr *RRSIG) signAsIs(k crypto.Signer, rrset []RR) error {
+	if k == nil {
+		return ErrPrivKey
+	}
+	// s.Inception and s.Expiration may be 0 (rollover etc.), the rest must be set
+	if rr.KeyTag == 0 || len(rr.SignerName) == 0 || rr.Algorithm == 0 {
+		return ErrKey
+	}
+
 	sigwire := new(rrsigWireFmt)
 	sigwire.TypeCovered = rr.TypeCovered
 	sigwire.Algorithm = rr.Algorithm
@@ -370,9 +374,12 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
 	if rr.Algorithm != k.Algorithm {
 		return ErrKey
 	}
-	if !strings.EqualFold(rr.SignerName, k.Hdr.Name) {
+
+	signerName := CanonicalName(rr.SignerName)
+	if !equal(signerName, k.Hdr.Name) {
 		return ErrKey
 	}
+
 	if k.Protocol != 3 {
 		return ErrKey
 	}
@@ -384,9 +391,18 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
 	}
 
 	// IsRRset checked that we have at least one RR and that the RRs in
-	// the set have consistent type, class, and name. Also check that type and
-	// class matches the RRSIG record.
-	if h0 := rrset[0].Header(); h0.Class != rr.Hdr.Class || h0.Rrtype != rr.TypeCovered {
+	// the set have consistent type, class, and name. Also check that type,
+	// class and name matches the RRSIG record.
+	// Also checks RFC 4035 5.3.1 the number of labels in the RRset owner
+	// name MUST be greater than or equal to the value in the RRSIG RR's Labels field.
+	// RFC 4035 5.3.1 Signer's Name MUST be the name of the zone that [contains the RRset].
+	// Since we don't have SOA info, checking suffix may be the best we can do...?
+	if h0 := rrset[0].Header(); h0.Class != rr.Hdr.Class ||
+		h0.Rrtype != rr.TypeCovered ||
+		uint8(CountLabel(h0.Name)) < rr.Labels ||
+		!equal(h0.Name, rr.Hdr.Name) ||
+		!strings.HasSuffix(CanonicalName(h0.Name), signerName) {
+
 		return ErrRRset
 	}
 
@@ -400,7 +416,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
 	sigwire.Expiration = rr.Expiration
 	sigwire.Inception = rr.Inception
 	sigwire.KeyTag = rr.KeyTag
-	sigwire.SignerName = CanonicalName(rr.SignerName)
+	sigwire.SignerName = signerName
 	// Create the desired binary blob
 	signeddata := make([]byte, DefaultMsgSize)
 	n, err := packSigWire(sigwire, signeddata)
diff --git a/edns.go b/edns.go
index c1bbdaae..91793b90 100644
--- a/edns.go
+++ b/edns.go
@@ -27,6 +27,7 @@ const (
 	EDNS0LOCALSTART   = 0xFDE9  // Beginning of range reserved for local/experimental use (See RFC 6891)
 	EDNS0LOCALEND     = 0xFFFE  // End of range reserved for local/experimental use (See RFC 6891)
 	_DO               = 1 << 15 // DNSSEC OK
+	_CO               = 1 << 14 // Compact Answers OK
 )
 
 // makeDataOpt is used to unpack the EDNS0 option(s) from a message.
@@ -58,7 +59,7 @@ func makeDataOpt(code uint16) EDNS0 {
 	case EDNS0EDE:
 		return new(EDNS0_EDE)
 	case EDNS0ESU:
-		return &EDNS0_ESU{Code: EDNS0ESU}
+		return new(EDNS0_ESU)
 	default:
 		e := new(EDNS0_LOCAL)
 		e.Code = code
@@ -66,8 +67,7 @@ func makeDataOpt(code uint16) EDNS0 {
 	}
 }
 
-// OPT is the EDNS0 RR appended to messages to convey extra (meta) information.
-// See RFC 6891.
+// OPT is the EDNS0 RR appended to messages to convey extra (meta) information. See RFC 6891.
 type OPT struct {
 	Hdr    RR_Header
 	Option []EDNS0 `dns:"opt"`
@@ -76,7 +76,11 @@ type OPT struct {
 func (rr *OPT) String() string {
 	s := "\n;; OPT PSEUDOSECTION:\n; EDNS: version " + strconv.Itoa(int(rr.Version())) + "; "
 	if rr.Do() {
-		s += "flags: do; "
+		if rr.Co() {
+			s += "flags: do, co; "
+		} else {
+			s += "flags: do; "
+		}
 	} else {
 		s += "flags:; "
 	}
@@ -144,8 +148,6 @@ func (*OPT) parse(c *zlexer, origin string) *ParseError {
 
 func (rr *OPT) isDuplicate(r2 RR) bool { return false }
 
-// return the old value -> delete SetVersion?
-
 // Version returns the EDNS version used. Only zero is defined.
 func (rr *OPT) Version() uint8 {
 	return uint8(rr.Hdr.Ttl & 0x00FF0000 >> 16)
@@ -198,14 +200,34 @@ func (rr *OPT) SetDo(do ...bool) {
 	}
 }
 
-// Z returns the Z part of the OPT RR as a uint16 with only the 15 least significant bits used.
+// Co returns the value of the CO (Compact Answers OK) bit.
+func (rr *OPT) Co() bool {
+	return rr.Hdr.Ttl&_CO == _CO
+}
+
+// SetCo sets the CO (Compact Answers OK) bit.
+// If we pass an argument, set the CO bit to that value.
+// It is possible to pass 2 or more arguments, but they will be ignored.
+func (rr *OPT) SetCo(co ...bool) {
+	if len(co) == 1 {
+		if co[0] {
+			rr.Hdr.Ttl |= _CO
+		} else {
+			rr.Hdr.Ttl &^= _CO
+		}
+	} else {
+		rr.Hdr.Ttl |= _CO
+	}
+}
+
+// Z returns the Z part of the OPT RR as a uint16 with only the 14 least significant bits used.
 func (rr *OPT) Z() uint16 {
-	return uint16(rr.Hdr.Ttl & 0x7FFF)
+	return uint16(rr.Hdr.Ttl & 0x3FFF)
 }
 
-// SetZ sets the Z part of the OPT RR, note only the 15 least significant bits of z are used.
+// SetZ sets the Z part of the OPT RR, note only the 14 least significant bits of z are used.
 func (rr *OPT) SetZ(z uint16) {
-	rr.Hdr.Ttl = rr.Hdr.Ttl&^0x7FFF | uint32(z&0x7FFF)
+	rr.Hdr.Ttl = rr.Hdr.Ttl&^0x3FFF | uint32(z&0x3FFF)
 }
 
 // EDNS0 defines an EDNS0 Option. An OPT RR can have multiple options appended to it.
@@ -236,8 +258,8 @@ type EDNS0 interface {
 //	e.Nsid = "AA"
 //	o.Option = append(o.Option, e)
 type EDNS0_NSID struct {
-	Code uint16 // Always EDNS0NSID
-	Nsid string // This string needs to be hex encoded
+	Code uint16 // always EDNS0NSID
+	Nsid string // string needs to be hex encoded
 }
 
 func (e *EDNS0_NSID) pack() ([]byte, error) {
@@ -275,7 +297,7 @@ func (e *EDNS0_NSID) copy() EDNS0           { return &EDNS0_NSID{e.Code, e.Nsid}
 // When packing it will apply SourceNetmask. If you need more advanced logic,
 // patches welcome and good luck.
 type EDNS0_SUBNET struct {
-	Code          uint16 // Always EDNS0SUBNET
+	Code          uint16 // always EDNS0SUBNET
 	Family        uint16 // 1 for IP, 2 for IP6
 	SourceNetmask uint8
 	SourceScope   uint8
@@ -399,8 +421,8 @@ func (e *EDNS0_SUBNET) copy() EDNS0 {
 //
 // There is no guarantee that the Cookie string has a specific length.
 type EDNS0_COOKIE struct {
-	Code   uint16 // Always EDNS0COOKIE
-	Cookie string // Hex-encoded cookie data
+	Code   uint16 // always EDNS0COOKIE
+	Cookie string // hex encoded cookie data
 }
 
 func (e *EDNS0_COOKIE) pack() ([]byte, error) {
@@ -430,7 +452,7 @@ func (e *EDNS0_COOKIE) copy() EDNS0           { return &EDNS0_COOKIE{e.Code, e.C
 //	e.Lease = 120 // in seconds
 //	o.Option = append(o.Option, e)
 type EDNS0_UL struct {
-	Code     uint16 // Always EDNS0UL
+	Code     uint16 // always EDNS0UL
 	Lease    uint32
 	KeyLease uint32
 }
@@ -469,7 +491,7 @@ func (e *EDNS0_UL) unpack(b []byte) error {
 // EDNS0_LLQ stands for Long Lived Queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
 // Implemented for completeness, as the EDNS0 type code is assigned.
 type EDNS0_LLQ struct {
-	Code      uint16 // Always EDNS0LLQ
+	Code      uint16 // always EDNS0LLQ
 	Version   uint16
 	Opcode    uint16
 	Error     uint16
@@ -515,7 +537,7 @@ func (e *EDNS0_LLQ) copy() EDNS0 {
 
 // EDNS0_DAU implements the EDNS0 "DNSSEC Algorithm Understood" option. See RFC 6975.
 type EDNS0_DAU struct {
-	Code    uint16 // Always EDNS0DAU
+	Code    uint16 // always EDNS0DAU
 	AlgCode []uint8
 }
 
@@ -539,7 +561,7 @@ func (e *EDNS0_DAU) copy() EDNS0 { return &EDNS0_DAU{e.Code, e.AlgCode} }
 
 // EDNS0_DHU implements the EDNS0 "DS Hash Understood" option. See RFC 6975.
 type EDNS0_DHU struct {
-	Code    uint16 // Always EDNS0DHU
+	Code    uint16 // always EDNS0DHU
 	AlgCode []uint8
 }
 
@@ -563,7 +585,7 @@ func (e *EDNS0_DHU) copy() EDNS0 { return &EDNS0_DHU{e.Code, e.AlgCode} }
 
 // EDNS0_N3U implements the EDNS0 "NSEC3 Hash Understood" option. See RFC 6975.
 type EDNS0_N3U struct {
-	Code    uint16 // Always EDNS0N3U
+	Code    uint16 // always EDNS0N3U
 	AlgCode []uint8
 }
 
@@ -588,7 +610,7 @@ func (e *EDNS0_N3U) copy() EDNS0 { return &EDNS0_N3U{e.Code, e.AlgCode} }
 
 // EDNS0_EXPIRE implements the EDNS0 option as described in RFC 7314.
 type EDNS0_EXPIRE struct {
-	Code   uint16 // Always EDNS0EXPIRE
+	Code   uint16 // always EDNS0EXPIRE
 	Expire uint32
 	Empty  bool // Empty is used to signal an empty Expire option in a backwards compatible way, it's not used on the wire.
 }
@@ -668,7 +690,7 @@ func (e *EDNS0_LOCAL) unpack(b []byte) error {
 // EDNS0_TCP_KEEPALIVE is an EDNS0 option that instructs the server to keep
 // the TCP connection alive. See RFC 7828.
 type EDNS0_TCP_KEEPALIVE struct {
-	Code uint16 // Always EDNSTCPKEEPALIVE
+	Code uint16 // always EDNSTCPKEEPALIVE
 
 	// Timeout is an idle timeout value for the TCP connection, specified in
 	// units of 100 milliseconds, encoded in network byte order. If set to 0,
@@ -839,13 +861,12 @@ func (e *EDNS0_EDE) unpack(b []byte) error {
 	return nil
 }
 
-// The EDNS0_ESU option for ENUM Source-URI Extension
+// The EDNS0_ESU option for ENUM Source-URI Extension.
 type EDNS0_ESU struct {
-	Code uint16
+	Code uint16 // always EDNS0ESU
 	Uri  string
 }
 
-// Option implements the EDNS0 interface.
 func (e *EDNS0_ESU) Option() uint16        { return EDNS0ESU }
 func (e *EDNS0_ESU) String() string        { return e.Uri }
 func (e *EDNS0_ESU) copy() EDNS0           { return &EDNS0_ESU{e.Code, e.Uri} }
diff --git a/go.mod b/go.mod
index cb9c336d..ec0932a9 100644
--- a/go.mod
+++ b/go.mod
@@ -1,12 +1,14 @@
 module github.com/miekg/dns
 
-go 1.19
+go 1.23.0
+
+toolchain go1.24.2
 
 require (
-	golang.org/x/net v0.27.0
-	golang.org/x/sync v0.7.0
-	golang.org/x/sys v0.22.0
-	golang.org/x/tools v0.22.0
+	golang.org/x/net v0.40.0
+	golang.org/x/sync v0.14.0
+	golang.org/x/sys v0.33.0
+	golang.org/x/tools v0.33.0
 )
 
-require golang.org/x/mod v0.18.0 // indirect
+require golang.org/x/mod v0.24.0 // indirect
diff --git a/go.sum b/go.sum
index c835f72e..d9d371e9 100644
--- a/go.sum
+++ b/go.sum
@@ -1,10 +1,12 @@
-golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
-golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
-golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
-golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
-golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
-golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
-golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
-golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
+golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
+golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
+golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
+golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
+golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
+golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
+golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
+golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
diff --git a/listen_no_reuseport.go b/listen_no_socket_options.go
similarity index 61%
rename from listen_no_reuseport.go
rename to listen_no_socket_options.go
index 8cebb2f1..9e4010bd 100644
--- a/listen_no_reuseport.go
+++ b/listen_no_socket_options.go
@@ -3,9 +3,15 @@
 
 package dns
 
-import "net"
+import (
+	"fmt"
+	"net"
+)
 
-const supportsReusePort = false
+const (
+	supportsReusePort = false
+	supportsReuseAddr = false
+)
 
 func listenTCP(network, addr string, reuseport, reuseaddr bool) (net.Listener, error) {
 	if reuseport || reuseaddr {
@@ -15,8 +21,6 @@ func listenTCP(network, addr string, reuseport, reuseaddr bool) (net.Listener, e
 	return net.Listen(network, addr)
 }
 
-const supportsReuseAddr = false
-
 func listenUDP(network, addr string, reuseport, reuseaddr bool) (net.PacketConn, error) {
 	if reuseport || reuseaddr {
 		// TODO(tmthrgd): return an error?
@@ -24,3 +28,13 @@ func listenUDP(network, addr string, reuseport, reuseaddr bool) (net.PacketConn,
 
 	return net.ListenPacket(network, addr)
 }
+
+// this is just for test compatibility
+func checkReuseport(fd uintptr) (bool, error) {
+	return false, fmt.Errorf("not supported")
+}
+
+// this is just for test compatibility
+func checkReuseaddr(fd uintptr) (bool, error) {
+	return false, fmt.Errorf("not supported")
+}
diff --git a/listen_reuseport.go b/listen_socket_options.go
similarity index 66%
rename from listen_reuseport.go
rename to listen_socket_options.go
index 41326f20..35dfc949 100644
--- a/listen_reuseport.go
+++ b/listen_socket_options.go
@@ -39,10 +39,40 @@ func reuseaddrControl(network, address string, c syscall.RawConn) error {
 	return opErr
 }
 
+func reuseaddrandportControl(network, address string, c syscall.RawConn) error {
+	err := reuseaddrControl(network, address, c)
+	if err != nil {
+		return err
+	}
+
+	return reuseportControl(network, address, c)
+}
+
+// this is just for test compatibility
+func checkReuseport(fd uintptr) (bool, error) {
+	v, err := unix.GetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT)
+	if err != nil {
+		return false, err
+	}
+
+	return v == 1, nil
+}
+
+// this is just for test compatibility
+func checkReuseaddr(fd uintptr) (bool, error) {
+	v, err := unix.GetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR)
+	if err != nil {
+		return false, err
+	}
+
+	return v == 1, nil
+}
+
 func listenTCP(network, addr string, reuseport, reuseaddr bool) (net.Listener, error) {
 	var lc net.ListenConfig
 	switch {
 	case reuseaddr && reuseport:
+		lc.Control = reuseaddrandportControl
 	case reuseport:
 		lc.Control = reuseportControl
 	case reuseaddr:
@@ -56,6 +86,7 @@ func listenUDP(network, addr string, reuseport, reuseaddr bool) (net.PacketConn,
 	var lc net.ListenConfig
 	switch {
 	case reuseaddr && reuseport:
+		lc.Control = reuseaddrandportControl
 	case reuseport:
 		lc.Control = reuseportControl
 	case reuseaddr:
diff --git a/msg.go b/msg.go
index 5fa7f9e8..b85c1078 100644
--- a/msg.go
+++ b/msg.go
@@ -136,18 +136,19 @@ var OpcodeToString = map[int]string{
 
 // RcodeToString maps Rcodes to strings.
 var RcodeToString = map[int]string{
-	RcodeSuccess:        "NOERROR",
-	RcodeFormatError:    "FORMERR",
-	RcodeServerFailure:  "SERVFAIL",
-	RcodeNameError:      "NXDOMAIN",
-	RcodeNotImplemented: "NOTIMP",
-	RcodeRefused:        "REFUSED",
-	RcodeYXDomain:       "YXDOMAIN", // See RFC 2136
-	RcodeYXRrset:        "YXRRSET",
-	RcodeNXRrset:        "NXRRSET",
-	RcodeNotAuth:        "NOTAUTH",
-	RcodeNotZone:        "NOTZONE",
-	RcodeBadSig:         "BADSIG", // Also known as RcodeBadVers, see RFC 6891
+	RcodeSuccess:                    "NOERROR",
+	RcodeFormatError:                "FORMERR",
+	RcodeServerFailure:              "SERVFAIL",
+	RcodeNameError:                  "NXDOMAIN",
+	RcodeNotImplemented:             "NOTIMP",
+	RcodeRefused:                    "REFUSED",
+	RcodeYXDomain:                   "YXDOMAIN", // See RFC 2136
+	RcodeYXRrset:                    "YXRRSET",
+	RcodeNXRrset:                    "NXRRSET",
+	RcodeNotAuth:                    "NOTAUTH",
+	RcodeNotZone:                    "NOTZONE",
+	RcodeStatefulTypeNotImplemented: "DSOTYPENI",
+	RcodeBadSig:                     "BADSIG", // Also known as RcodeBadVers, see RFC 6891
 	//	RcodeBadVers:        "BADVERS",
 	RcodeBadKey:    "BADKEY",
 	RcodeBadTime:   "BADTIME",
@@ -871,10 +872,9 @@ func (dns *Msg) unpack(dh Header, msg []byte, off int) (err error) {
 	// TODO(miek) make this an error?
 	// use PackOpt to let people tell how detailed the error reporting should be?
 	// if off != len(msg) {
-	// 	// println("dns: extra bytes in dns packet", off, "<", len(msg))
+	//	// println("dns: extra bytes in dns packet", off, "<", len(msg))
 	// }
 	return err
-
 }
 
 // Unpack unpacks a binary message to a Msg structure.
@@ -1123,23 +1123,28 @@ func unpackQuestion(msg []byte, off int) (Question, int, error) {
 	)
 	q.Name, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return q, off, err
+		return q, off, fmt.Errorf("question.Name: %w", err)
 	}
 	if off == len(msg) {
 		return q, off, nil
 	}
 	q.Qtype, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return q, off, err
+		return q, off, fmt.Errorf("question.Qtype: %w", err)
 	}
 	if off == len(msg) {
 		return q, off, nil
 	}
 	q.Qclass, off, err = unpackUint16(msg, off)
+	if err != nil {
+		return q, off, fmt.Errorf("question.Qclass: %w", err)
+	}
+
 	if off == len(msg) {
 		return q, off, nil
 	}
-	return q, off, err
+
+	return q, off, nil
 }
 
 func (dh *Header) pack(msg []byte, off int, compression compressionMap, compress bool) (int, error) {
@@ -1177,27 +1182,27 @@ func unpackMsgHdr(msg []byte, off int) (Header, int, error) {
 	)
 	dh.Id, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return dh, off, err
+		return dh, off, fmt.Errorf("header.Id: %w", err)
 	}
 	dh.Bits, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return dh, off, err
+		return dh, off, fmt.Errorf("header.Bits: %w", err)
 	}
 	dh.Qdcount, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return dh, off, err
+		return dh, off, fmt.Errorf("header.Qdcount: %w", err)
 	}
 	dh.Ancount, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return dh, off, err
+		return dh, off, fmt.Errorf("header.Ancount: %w", err)
 	}
 	dh.Nscount, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return dh, off, err
+		return dh, off, fmt.Errorf("header.Nscount: %w", err)
 	}
 	dh.Arcount, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return dh, off, err
+		return dh, off, fmt.Errorf("header.Arcount: %w", err)
 	}
 	return dh, off, nil
 }
diff --git a/msg_generate.go b/msg_generate.go
index e3614193..b98fe9e7 100644
--- a/msg_generate.go
+++ b/msg_generate.go
@@ -24,6 +24,7 @@ var packageHdr = `
 
 package dns
 
+import "fmt"
 `
 
 // getTypeStruct will take a type and the package scope, and return the
@@ -208,10 +209,15 @@ _ = rdStart
 		for i := 1; i < st.NumFields(); i++ {
 			o := func(s string) {
 				fmt.Fprintf(b, s, st.Field(i).Name())
-				fmt.Fprint(b, `if err != nil {
-return off, err
+
+				err_name := name
+				if name != st.Field(i).Name() {
+					err_name += "." + st.Field(i).Name()
+				}
+				fmt.Fprintf(b, `if err != nil {
+return off, fmt.Errorf("%s: %%w", err)
 }
-`)
+`, err_name)
 			}
 
 			// size-* are special, because they reference a struct member we should use for the length.
diff --git a/reverse.go b/reverse.go
index 28151af8..6f5b3ea7 100644
--- a/reverse.go
+++ b/reverse.go
@@ -23,9 +23,12 @@ var StringToAlgorithm = reverseInt8(AlgorithmToString)
 // StringToHash is a map of names to hash IDs.
 var StringToHash = reverseInt8(HashToString)
 
-// StringToCertType is the reverseof CertTypeToString.
+// StringToCertType is the reverse of CertTypeToString.
 var StringToCertType = reverseInt16(CertTypeToString)
 
+// StringToStatefulType is the reverse of StatefulTypeToString.
+var StringToStatefulType = reverseInt16(StatefulTypeToString)
+
 // Reverse a map
 func reverseInt8(m map[uint8]string) map[string]uint8 {
 	n := make(map[string]uint8, len(m))
diff --git a/scan.go b/scan.go
index e26e8027..31957b2e 100644
--- a/scan.go
+++ b/scan.go
@@ -108,6 +108,8 @@ type ttlState struct {
 // origin for resolving relative domain names defaults to the DNS root (.).
 // Full zone file syntax is supported, including directives like $TTL and $ORIGIN.
 // All fields of the returned RR are set from the read data, except RR.Header().Rdlength which is set to 0.
+// Is you need a partial resource record with no rdata - for instance - for dynamic updates, see the [ANY]
+// documentation.
 func NewRR(s string) (RR, error) {
 	if len(s) > 0 && s[len(s)-1] != '\n' { // We need a closing newline
 		return ReadRR(strings.NewReader(s+"\n"), "")
@@ -1316,6 +1318,13 @@ func toAbsoluteName(name, origin string) (absolute string, ok bool) {
 		return origin, true
 	}
 
+	// this can happen when we have a comment after a RR that has a domain, '...   MX 20 ; this is wrong'.
+	// technically a newline can be in a domain name, but this is clearly an error and the newline only shows
+	// because of the scanning and the comment.
+	if name == "\n" {
+		return "", false
+	}
+
 	// require a valid domain name
 	_, ok = IsDomainName(name)
 	if !ok || name == "" {
diff --git a/scan_rr.go b/scan_rr.go
index c1a76995..ac885f66 100644
--- a/scan_rr.go
+++ b/scan_rr.go
@@ -1620,6 +1620,16 @@ func (rr *NINFO) parse(c *zlexer, o string) *ParseError {
 	return nil
 }
 
+// Uses the same format as TXT
+func (rr *RESINFO) parse(c *zlexer, o string) *ParseError {
+	s, e := endingToTxtSlice(c, "bad RESINFO Resinfo")
+	if e != nil {
+		return e
+	}
+	rr.Txt = s
+	return nil
+}
+
 func (rr *URI) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
 	i, e := strconv.ParseUint(l.token, 10, 16)
diff --git a/server.go b/server.go
index 81580d1e..839fc544 100644
--- a/server.go
+++ b/server.go
@@ -44,6 +44,8 @@ type ResponseWriter interface {
 	LocalAddr() net.Addr
 	// RemoteAddr returns the net.Addr of the client that sent the current request.
 	RemoteAddr() net.Addr
+	// Network returns the value of the Net field of the Server (e.g., "tcp", "tcp-tls").
+	Network() string
 	// WriteMsg writes a reply back to the client.
 	WriteMsg(*Msg) error
 	// Write writes a raw buffer back to the client.
@@ -77,6 +79,7 @@ type response struct {
 	udpSession     *SessionUDP    // oob data to get egress interface right
 	pcSession      net.Addr       // address to use when writing to a generic net.PacketConn
 	writer         Writer         // writer to output the raw DNS bits
+	network        string         // corresponding Server.Net value
 }
 
 // handleRefused returns a HandlerFunc that returns REFUSED for every request it gets.
@@ -226,6 +229,7 @@ type Server struct {
 	// If NotifyStartedFunc is set it is called once the server has started listening.
 	NotifyStartedFunc func()
 	// DecorateReader is optional, allows customization of the process that reads raw DNS messages.
+	// The decorated reader must not mutate the data read from the conn.
 	DecorateReader DecorateReader
 	// DecorateWriter is optional, allows customization of the process that writes raw DNS messages.
 	DecorateWriter DecorateWriter
@@ -556,7 +560,7 @@ func (srv *Server) serveUDP(l net.PacketConn) error {
 
 // Serve a new TCP connection.
 func (srv *Server) serveTCPConn(wg *sync.WaitGroup, rw net.Conn) {
-	w := &response{tsigProvider: srv.tsigProvider(), tcp: rw}
+	w := &response{tsigProvider: srv.tsigProvider(), tcp: rw, network: srv.Net}
 	if srv.DecorateWriter != nil {
 		w.writer = srv.DecorateWriter(w)
 	} else {
@@ -611,7 +615,7 @@ func (srv *Server) serveTCPConn(wg *sync.WaitGroup, rw net.Conn) {
 
 // Serve a new UDP request.
 func (srv *Server) serveUDPPacket(wg *sync.WaitGroup, m []byte, u net.PacketConn, udpSession *SessionUDP, pcSession net.Addr) {
-	w := &response{tsigProvider: srv.tsigProvider(), udp: u, udpSession: udpSession, pcSession: pcSession}
+	w := &response{tsigProvider: srv.tsigProvider(), udp: u, udpSession: udpSession, pcSession: pcSession, network: srv.Net}
 	if srv.DecorateWriter != nil {
 		w.writer = srv.DecorateWriter(w)
 	} else {
@@ -817,6 +821,9 @@ func (w *response) RemoteAddr() net.Addr {
 	}
 }
 
+// Network implements the ResponseWriter.Network method.
+func (w *response) Network() string { return w.network }
+
 // TsigStatus implements the ResponseWriter.TsigStatus method.
 func (w *response) TsigStatus() error { return w.tsigStatus }
 
diff --git a/sig0.go b/sig0.go
index 2c4b1035..057bb578 100644
--- a/sig0.go
+++ b/sig0.go
@@ -7,7 +7,6 @@ import (
 	"crypto/rsa"
 	"encoding/binary"
 	"math/big"
-	"strings"
 	"time"
 )
 
@@ -151,7 +150,7 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
 	}
 	// If key has come from the DNS name compression might
 	// have mangled the case of the name
-	if !strings.EqualFold(signername, k.Header().Name) {
+	if !equal(signername, k.Header().Name) {
 		return &Error{err: "signer name doesn't match key name"}
 	}
 	sigend := offset
diff --git a/svcb.go b/svcb.go
index 310c7d11..d1baeea9 100644
--- a/svcb.go
+++ b/svcb.go
@@ -214,11 +214,7 @@ func makeSVCBKeyValue(key SVCBKey) SVCBKeyValue {
 	}
 }
 
-// SVCB RR. See RFC xxxx (https://tools.ietf.org/html/draft-ietf-dnsop-svcb-https-08).
-//
-// NOTE: The HTTPS/SVCB RFCs are in the draft stage.
-// The API, including constants and types related to SVCBKeyValues, may
-// change in future versions in accordance with the latest drafts.
+// SVCB RR. See RFC 9460.
 type SVCB struct {
 	Hdr      RR_Header
 	Priority uint16         // If zero, Value must be empty or discarded by the user of this library
@@ -226,12 +222,8 @@ type SVCB struct {
 	Value    []SVCBKeyValue `dns:"pairs"`
 }
 
-// HTTPS RR. Everything valid for SVCB applies to HTTPS as well.
+// HTTPS RR. See RFC 9460. Everything valid for SVCB applies to HTTPS as well.
 // Except that the HTTPS record is intended for use with the HTTP and HTTPS protocols.
-//
-// NOTE: The HTTPS/SVCB RFCs are in the draft stage.
-// The API, including constants and types related to SVCBKeyValues, may
-// change in future versions in accordance with the latest drafts.
 type HTTPS struct {
 	SVCB
 }
diff --git a/types.go b/types.go
index 7a34c14c..f5067cd4 100644
--- a/types.go
+++ b/types.go
@@ -101,6 +101,7 @@ const (
 	TypeCAA        uint16 = 257
 	TypeAVC        uint16 = 258
 	TypeAMTRELAY   uint16 = 260
+	TypeRESINFO    uint16 = 261
 
 	TypeTKEY uint16 = 249
 	TypeTSIG uint16 = 250
@@ -125,33 +126,35 @@ const (
 	ClassANY    = 255
 
 	// Message Response Codes, see https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml
-	RcodeSuccess        = 0  // NoError   - No Error                          [DNS]
-	RcodeFormatError    = 1  // FormErr   - Format Error                      [DNS]
-	RcodeServerFailure  = 2  // ServFail  - Server Failure                    [DNS]
-	RcodeNameError      = 3  // NXDomain  - Non-Existent Domain               [DNS]
-	RcodeNotImplemented = 4  // NotImp    - Not Implemented                   [DNS]
-	RcodeRefused        = 5  // Refused   - Query Refused                     [DNS]
-	RcodeYXDomain       = 6  // YXDomain  - Name Exists when it should not    [DNS Update]
-	RcodeYXRrset        = 7  // YXRRSet   - RR Set Exists when it should not  [DNS Update]
-	RcodeNXRrset        = 8  // NXRRSet   - RR Set that should exist does not [DNS Update]
-	RcodeNotAuth        = 9  // NotAuth   - Server Not Authoritative for zone [DNS Update]
-	RcodeNotZone        = 10 // NotZone   - Name not contained in zone        [DNS Update/TSIG]
-	RcodeBadSig         = 16 // BADSIG    - TSIG Signature Failure            [TSIG]  https://www.rfc-editor.org/rfc/rfc6895.html#section-2.3
-	RcodeBadVers        = 16 // BADVERS   - Bad OPT Version                   [EDNS0] https://www.rfc-editor.org/rfc/rfc6895.html#section-2.3
-	RcodeBadKey         = 17 // BADKEY    - Key not recognized                [TSIG]
-	RcodeBadTime        = 18 // BADTIME   - Signature out of time window      [TSIG]
-	RcodeBadMode        = 19 // BADMODE   - Bad TKEY Mode                     [TKEY]
-	RcodeBadName        = 20 // BADNAME   - Duplicate key name                [TKEY]
-	RcodeBadAlg         = 21 // BADALG    - Algorithm not supported           [TKEY]
-	RcodeBadTrunc       = 22 // BADTRUNC  - Bad Truncation                    [TSIG]
-	RcodeBadCookie      = 23 // BADCOOKIE - Bad/missing Server Cookie         [DNS Cookies]
+	RcodeSuccess                    = 0  // NoError   - No Error                          [DNS]
+	RcodeFormatError                = 1  // FormErr   - Format Error                      [DNS]
+	RcodeServerFailure              = 2  // ServFail  - Server Failure                    [DNS]
+	RcodeNameError                  = 3  // NXDomain  - Non-Existent Domain               [DNS]
+	RcodeNotImplemented             = 4  // NotImp    - Not Implemented                   [DNS]
+	RcodeRefused                    = 5  // Refused   - Query Refused                     [DNS]
+	RcodeYXDomain                   = 6  // YXDomain  - Name Exists when it should not    [DNS Update]
+	RcodeYXRrset                    = 7  // YXRRSet   - RR Set Exists when it should not  [DNS Update]
+	RcodeNXRrset                    = 8  // NXRRSet   - RR Set that should exist does not [DNS Update]
+	RcodeNotAuth                    = 9  // NotAuth   - Server Not Authoritative for zone [DNS Update]
+	RcodeNotZone                    = 10 // NotZone   - Name not contained in zone        [DNS Update/TSIG]
+	RcodeStatefulTypeNotImplemented = 11 // DSOTypeNI - DSO-TYPE not implemented          [DNS Stateful Operations] https://www.rfc-editor.org/rfc/rfc8490.html#section-10.2
+	RcodeBadSig                     = 16 // BADSIG    - TSIG Signature Failure            [TSIG]  https://www.rfc-editor.org/rfc/rfc6895.html#section-2.3
+	RcodeBadVers                    = 16 // BADVERS   - Bad OPT Version                   [EDNS0] https://www.rfc-editor.org/rfc/rfc6895.html#section-2.3
+	RcodeBadKey                     = 17 // BADKEY    - Key not recognized                [TSIG]
+	RcodeBadTime                    = 18 // BADTIME   - Signature out of time window      [TSIG]
+	RcodeBadMode                    = 19 // BADMODE   - Bad TKEY Mode                     [TKEY]
+	RcodeBadName                    = 20 // BADNAME   - Duplicate key name                [TKEY]
+	RcodeBadAlg                     = 21 // BADALG    - Algorithm not supported           [TKEY]
+	RcodeBadTrunc                   = 22 // BADTRUNC  - Bad Truncation                    [TSIG]
+	RcodeBadCookie                  = 23 // BADCOOKIE - Bad/missing Server Cookie         [DNS Cookies]
 
 	// Message Opcodes. There is no 3.
-	OpcodeQuery  = 0
-	OpcodeIQuery = 1
-	OpcodeStatus = 2
-	OpcodeNotify = 4
-	OpcodeUpdate = 5
+	OpcodeQuery    = 0
+	OpcodeIQuery   = 1
+	OpcodeStatus   = 2
+	OpcodeNotify   = 4
+	OpcodeUpdate   = 5
+	OpcodeStateful = 6
 )
 
 // Used in ZONEMD https://tools.ietf.org/html/rfc8976
@@ -178,6 +181,19 @@ const (
 	AMTRELAYHost = IPSECGatewayHost
 )
 
+// Stateful types as defined in RFC 8490.
+const (
+	StatefulTypeKeepAlive uint16 = iota + 1
+	StatefulTypeRetryDelay
+	StatefulTypeEncryptionPadding
+)
+
+var StatefulTypeToString = map[uint16]string{
+	StatefulTypeKeepAlive:         "KeepAlive",
+	StatefulTypeRetryDelay:        "RetryDelay",
+	StatefulTypeEncryptionPadding: "EncryptionPadding",
+}
+
 // Header is the wire format for the DNS packet header.
 type Header struct {
 	Id                                 uint16
@@ -267,11 +283,20 @@ func (q *Question) String() (s string) {
 	return s
 }
 
-// ANY is a wild card record. See RFC 1035, Section 3.2.3. ANY
-// is named "*" there.
+// ANY is a wild card record. See RFC 1035, Section 3.2.3. ANY is named "*" there.
+// The ANY records can be (ab)used to create resource records without any rdata, that
+// can be used in dynamic update requests. Basic use pattern:
+//
+//	a := &ANY{RR_Header{
+//		Name:   "example.org.",
+//		Rrtype: TypeA,
+//		Class:  ClassINET,
+//	}}
+//
+// Results in an A record without rdata.
 type ANY struct {
 	Hdr RR_Header
-	// Does not have any rdata
+	// Does not have any rdata.
 }
 
 func (rr *ANY) String() string { return rr.Hdr.String() }
@@ -876,7 +901,7 @@ func (rr *LOC) String() string {
 	lon = lon % LOC_HOURS
 	s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, float64(lon)/1000, ew)
 
-	var alt = float64(rr.Altitude) / 100
+	alt := float64(rr.Altitude) / 100
 	alt -= LOC_ALTITUDEBASE
 	if rr.Altitude%100 != 0 {
 		s += fmt.Sprintf("%.2fm ", alt)
@@ -1508,6 +1533,15 @@ func (rr *ZONEMD) String() string {
 		" " + rr.Digest
 }
 
+// RESINFO RR. See RFC 9606.
+
+type RESINFO struct {
+	Hdr RR_Header
+	Txt []string `dns:"txt"`
+}
+
+func (rr *RESINFO) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
+
 // APL RR. See RFC 3123.
 type APL struct {
 	Hdr      RR_Header
diff --git a/udp.go b/udp.go
index c018ad43..d2267185 100644
--- a/udp.go
+++ b/udp.go
@@ -1,5 +1,5 @@
-//go:build !windows
-// +build !windows
+//go:build !windows && !darwin
+// +build !windows,!darwin
 
 package dns
 
diff --git a/udp_windows.go b/udp_no_control.go
similarity index 85%
rename from udp_windows.go
rename to udp_no_control.go
index a259b67e..ca3d4a63 100644
--- a/udp_windows.go
+++ b/udp_no_control.go
@@ -1,9 +1,11 @@
-//go:build windows
-// +build windows
+//go:build windows || darwin
+// +build windows darwin
 
 // TODO(tmthrgd): Remove this Windows-specific code if go.dev/issue/7175 and
 //   go.dev/issue/7174 are ever fixed.
 
+// NOTICE(stek29): darwin supports PKTINFO in sendmsg, but it unbinds sockets, see https://github.com/miekg/dns/issues/724
+
 package dns
 
 import "net"
diff --git a/update.go b/update.go
index 16f9ee85..2fef1461 100644
--- a/update.go
+++ b/update.go
@@ -2,6 +2,7 @@ package dns
 
 // NameUsed sets the RRs in the prereq section to
 // "Name is in use" RRs. RFC 2136 section 2.4.4.
+// See [ANY] on how to make RRs without rdata.
 func (u *Msg) NameUsed(rr []RR) {
 	if u.Answer == nil {
 		u.Answer = make([]RR, 0, len(rr))
@@ -41,6 +42,7 @@ func (u *Msg) Used(rr []RR) {
 
 // RRsetUsed sets the RRs in the prereq section to
 // "RRset exists (value independent -- no rdata)" RRs. RFC 2136 section 2.4.1.
+// See [ANY] on how to make RRs without rdata.
 func (u *Msg) RRsetUsed(rr []RR) {
 	if u.Answer == nil {
 		u.Answer = make([]RR, 0, len(rr))
@@ -53,6 +55,7 @@ func (u *Msg) RRsetUsed(rr []RR) {
 
 // RRsetNotUsed sets the RRs in the prereq section to
 // "RRset does not exist" RRs. RFC 2136 section 2.4.3.
+// See [ANY] on how to make RRs without rdata.
 func (u *Msg) RRsetNotUsed(rr []RR) {
 	if u.Answer == nil {
 		u.Answer = make([]RR, 0, len(rr))
@@ -64,6 +67,7 @@ func (u *Msg) RRsetNotUsed(rr []RR) {
 }
 
 // Insert creates a dynamic update packet that adds an complete RRset, see RFC 2136 section 2.5.1.
+// See [ANY] on how to make RRs without rdata.
 func (u *Msg) Insert(rr []RR) {
 	if len(u.Question) == 0 {
 		panic("dns: empty question section")
@@ -78,6 +82,7 @@ func (u *Msg) Insert(rr []RR) {
 }
 
 // RemoveRRset creates a dynamic update packet that deletes an RRset, see RFC 2136 section 2.5.2.
+// See [ANY] on how to make RRs without rdata.
 func (u *Msg) RemoveRRset(rr []RR) {
 	if u.Ns == nil {
 		u.Ns = make([]RR, 0, len(rr))
@@ -89,6 +94,7 @@ func (u *Msg) RemoveRRset(rr []RR) {
 }
 
 // RemoveName creates a dynamic update packet that deletes all RRsets of a name, see RFC 2136 section 2.5.3
+// See [ANY] on how to make RRs without rdata.
 func (u *Msg) RemoveName(rr []RR) {
 	if u.Ns == nil {
 		u.Ns = make([]RR, 0, len(rr))
@@ -99,6 +105,7 @@ func (u *Msg) RemoveName(rr []RR) {
 }
 
 // Remove creates a dynamic update packet deletes RR from a RRSset, see RFC 2136 section 2.5.4
+// See [ANY] on how to make RRs without rdata.
 func (u *Msg) Remove(rr []RR) {
 	if u.Ns == nil {
 		u.Ns = make([]RR, 0, len(rr))
diff --git a/version.go b/version.go
index 00c8629f..936dc212 100644
--- a/version.go
+++ b/version.go
@@ -3,7 +3,7 @@ package dns
 import "fmt"
 
 // Version is current version of this library.
-var Version = v{1, 1, 62}
+var Version = v{1, 1, 66}
 
 // v holds the version of this library.
 type v struct {
diff --git a/xfr.go b/xfr.go
index 5cfbb516..97a64247 100644
--- a/xfr.go
+++ b/xfr.go
@@ -251,10 +251,13 @@ func (t *Transfer) ReadMsg() (*Msg, error) {
 	if err := m.Unpack(p); err != nil {
 		return nil, err
 	}
-	if ts, tp := m.IsTsig(), t.tsigProvider(); ts != nil && tp != nil {
+
+	if tp := t.tsigProvider(); tp != nil {
 		// Need to work on the original message p, as that was used to calculate the tsig.
 		err = TsigVerifyWithProvider(p, tp, t.tsigRequestMAC, t.tsigTimersOnly)
-		t.tsigRequestMAC = ts.MAC
+		if ts := m.IsTsig(); ts != nil {
+			t.tsigRequestMAC = ts.MAC
+		}
 	}
 	return m, err
 }
diff --git a/zduplicate.go b/zduplicate.go
index 330c0539..ebd9e029 100644
--- a/zduplicate.go
+++ b/zduplicate.go
@@ -957,6 +957,23 @@ func (r1 *PX) isDuplicate(_r2 RR) bool {
 	return true
 }
 
+func (r1 *RESINFO) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*RESINFO)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if len(r1.Txt) != len(r2.Txt) {
+		return false
+	}
+	for i := 0; i < len(r1.Txt); i++ {
+		if r1.Txt[i] != r2.Txt[i] {
+			return false
+		}
+	}
+	return true
+}
+
 func (r1 *RFC3597) isDuplicate(_r2 RR) bool {
 	r2, ok := _r2.(*RFC3597)
 	if !ok {
diff --git a/zmsg.go b/zmsg.go
index 5a6cf4c6..8143ddc1 100644
--- a/zmsg.go
+++ b/zmsg.go
@@ -2,6 +2,8 @@
 
 package dns
 
+import "fmt"
+
 // pack*() functions
 
 func (rr *A) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
@@ -762,6 +764,14 @@ func (rr *PX) pack(msg []byte, off int, compression compressionMap, compress boo
 	return off, nil
 }
 
+func (rr *RESINFO) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packStringTxt(rr.Txt, msg, off)
+	if err != nil {
+		return off, err
+	}
+	return off, nil
+}
+
 func (rr *RFC3597) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packStringHex(rr.Rdata, msg, off)
 	if err != nil {
@@ -1214,7 +1224,7 @@ func (rr *A) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.A, off, err = unpackDataA(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("A: %w", err)
 	}
 	return off, nil
 }
@@ -1225,7 +1235,7 @@ func (rr *AAAA) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.AAAA, off, err = unpackDataAAAA(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("AAAA: %w", err)
 	}
 	return off, nil
 }
@@ -1236,14 +1246,14 @@ func (rr *AFSDB) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Subtype, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("AFSDB.Subtype: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Hostname, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("AFSDB.Hostname: %w", err)
 	}
 	return off, nil
 }
@@ -1254,14 +1264,14 @@ func (rr *AMTRELAY) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Precedence, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("AMTRELAY.Precedence: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.GatewayType, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("AMTRELAY.GatewayType: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
@@ -1271,7 +1281,7 @@ func (rr *AMTRELAY) unpack(msg []byte, off int) (off1 int, err error) {
 	}
 	rr.GatewayAddr, rr.GatewayHost, off, err = unpackIPSECGateway(msg, off, rr.GatewayType)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("AMTRELAY.GatewayHost: %w", err)
 	}
 	return off, nil
 }
@@ -1289,7 +1299,7 @@ func (rr *APL) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Prefixes, off, err = unpackDataApl(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("APL.Prefixes: %w", err)
 	}
 	return off, nil
 }
@@ -1300,7 +1310,7 @@ func (rr *AVC) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Txt, off, err = unpackStringTxt(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("AVC.Txt: %w", err)
 	}
 	return off, nil
 }
@@ -1311,21 +1321,21 @@ func (rr *CAA) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Flag, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("CAA.Flag: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Tag, off, err = unpackString(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("CAA.Tag: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Value, off, err = unpackStringOctet(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("CAA.Value: %w", err)
 	}
 	return off, nil
 }
@@ -1336,28 +1346,28 @@ func (rr *CDNSKEY) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Flags, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("CDNSKEY.Flags: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Protocol, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("CDNSKEY.Protocol: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("CDNSKEY.Algorithm: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.PublicKey, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("CDNSKEY.PublicKey: %w", err)
 	}
 	return off, nil
 }
@@ -1368,28 +1378,28 @@ func (rr *CDS) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.KeyTag, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("CDS.KeyTag: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("CDS.Algorithm: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.DigestType, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("CDS.DigestType: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Digest, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("CDS.Digest: %w", err)
 	}
 	return off, nil
 }
@@ -1400,28 +1410,28 @@ func (rr *CERT) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Type, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("CERT.Type: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.KeyTag, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("CERT.KeyTag: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("CERT.Algorithm: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Certificate, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("CERT.Certificate: %w", err)
 	}
 	return off, nil
 }
@@ -1432,7 +1442,7 @@ func (rr *CNAME) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Target, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("CNAME.Target: %w", err)
 	}
 	return off, nil
 }
@@ -1443,21 +1453,21 @@ func (rr *CSYNC) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Serial, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("CSYNC.Serial: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Flags, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("CSYNC.Flags: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.TypeBitMap, off, err = unpackDataNsec(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("CSYNC.TypeBitMap: %w", err)
 	}
 	return off, nil
 }
@@ -1468,7 +1478,7 @@ func (rr *DHCID) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Digest, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("DHCID.Digest: %w", err)
 	}
 	return off, nil
 }
@@ -1479,28 +1489,28 @@ func (rr *DLV) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.KeyTag, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("DLV.KeyTag: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("DLV.Algorithm: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.DigestType, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("DLV.DigestType: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Digest, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("DLV.Digest: %w", err)
 	}
 	return off, nil
 }
@@ -1511,7 +1521,7 @@ func (rr *DNAME) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Target, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("DNAME.Target: %w", err)
 	}
 	return off, nil
 }
@@ -1522,28 +1532,28 @@ func (rr *DNSKEY) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Flags, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("DNSKEY.Flags: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Protocol, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("DNSKEY.Protocol: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("DNSKEY.Algorithm: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.PublicKey, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("DNSKEY.PublicKey: %w", err)
 	}
 	return off, nil
 }
@@ -1554,28 +1564,28 @@ func (rr *DS) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.KeyTag, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("DS.KeyTag: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("DS.Algorithm: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.DigestType, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("DS.DigestType: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Digest, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("DS.Digest: %w", err)
 	}
 	return off, nil
 }
@@ -1586,7 +1596,7 @@ func (rr *EID) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Endpoint, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("EID.Endpoint: %w", err)
 	}
 	return off, nil
 }
@@ -1597,7 +1607,7 @@ func (rr *EUI48) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Address, off, err = unpackUint48(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("EUI48.Address: %w", err)
 	}
 	return off, nil
 }
@@ -1608,7 +1618,7 @@ func (rr *EUI64) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Address, off, err = unpackUint64(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("EUI64.Address: %w", err)
 	}
 	return off, nil
 }
@@ -1619,7 +1629,7 @@ func (rr *GID) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Gid, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("GID.Gid: %w", err)
 	}
 	return off, nil
 }
@@ -1630,21 +1640,21 @@ func (rr *GPOS) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Longitude, off, err = unpackString(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("GPOS.Longitude: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Latitude, off, err = unpackString(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("GPOS.Latitude: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Altitude, off, err = unpackString(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("GPOS.Altitude: %w", err)
 	}
 	return off, nil
 }
@@ -1655,14 +1665,14 @@ func (rr *HINFO) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Cpu, off, err = unpackString(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("HINFO.Cpu: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Os, off, err = unpackString(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("HINFO.Os: %w", err)
 	}
 	return off, nil
 }
@@ -1673,21 +1683,21 @@ func (rr *HIP) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.HitLength, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("HIP.HitLength: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.PublicKeyAlgorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("HIP.PublicKeyAlgorithm: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.PublicKeyLength, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("HIP.PublicKeyLength: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
@@ -1702,7 +1712,7 @@ func (rr *HIP) unpack(msg []byte, off int) (off1 int, err error) {
 	}
 	rr.RendezvousServers, off, err = unpackDataDomainNames(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("HIP.RendezvousServers: %w", err)
 	}
 	return off, nil
 }
@@ -1713,21 +1723,21 @@ func (rr *HTTPS) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Priority, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("HTTPS.Priority: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Target, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("HTTPS.Target: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Value, off, err = unpackDataSVCB(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("HTTPS.Value: %w", err)
 	}
 	return off, nil
 }
@@ -1738,21 +1748,21 @@ func (rr *IPSECKEY) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Precedence, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("IPSECKEY.Precedence: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.GatewayType, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("IPSECKEY.GatewayType: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("IPSECKEY.Algorithm: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
@@ -1762,14 +1772,14 @@ func (rr *IPSECKEY) unpack(msg []byte, off int) (off1 int, err error) {
 	}
 	rr.GatewayAddr, rr.GatewayHost, off, err = unpackIPSECGateway(msg, off, rr.GatewayType)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("IPSECKEY.GatewayHost: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.PublicKey, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("IPSECKEY.PublicKey: %w", err)
 	}
 	return off, nil
 }
@@ -1780,14 +1790,14 @@ func (rr *ISDN) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Address, off, err = unpackString(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("ISDN.Address: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.SubAddress, off, err = unpackString(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("ISDN.SubAddress: %w", err)
 	}
 	return off, nil
 }
@@ -1798,28 +1808,28 @@ func (rr *KEY) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Flags, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("KEY.Flags: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Protocol, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("KEY.Protocol: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("KEY.Algorithm: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.PublicKey, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("KEY.PublicKey: %w", err)
 	}
 	return off, nil
 }
@@ -1830,14 +1840,14 @@ func (rr *KX) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Preference, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("KX.Preference: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Exchanger, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("KX.Exchanger: %w", err)
 	}
 	return off, nil
 }
@@ -1848,14 +1858,14 @@ func (rr *L32) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Preference, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("L32.Preference: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Locator32, off, err = unpackDataA(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("L32.Locator32: %w", err)
 	}
 	return off, nil
 }
@@ -1866,14 +1876,14 @@ func (rr *L64) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Preference, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("L64.Preference: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Locator64, off, err = unpackUint64(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("L64.Locator64: %w", err)
 	}
 	return off, nil
 }
@@ -1884,49 +1894,49 @@ func (rr *LOC) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Version, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("LOC.Version: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Size, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("LOC.Size: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.HorizPre, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("LOC.HorizPre: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.VertPre, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("LOC.VertPre: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Latitude, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("LOC.Latitude: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Longitude, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("LOC.Longitude: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Altitude, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("LOC.Altitude: %w", err)
 	}
 	return off, nil
 }
@@ -1937,14 +1947,14 @@ func (rr *LP) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Preference, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("LP.Preference: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Fqdn, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("LP.Fqdn: %w", err)
 	}
 	return off, nil
 }
@@ -1955,7 +1965,7 @@ func (rr *MB) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Mb, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("MB.Mb: %w", err)
 	}
 	return off, nil
 }
@@ -1966,7 +1976,7 @@ func (rr *MD) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Md, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("MD.Md: %w", err)
 	}
 	return off, nil
 }
@@ -1977,7 +1987,7 @@ func (rr *MF) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Mf, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("MF.Mf: %w", err)
 	}
 	return off, nil
 }
@@ -1988,7 +1998,7 @@ func (rr *MG) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Mg, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("MG.Mg: %w", err)
 	}
 	return off, nil
 }
@@ -1999,14 +2009,14 @@ func (rr *MINFO) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Rmail, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("MINFO.Rmail: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Email, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("MINFO.Email: %w", err)
 	}
 	return off, nil
 }
@@ -2017,7 +2027,7 @@ func (rr *MR) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Mr, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("MR.Mr: %w", err)
 	}
 	return off, nil
 }
@@ -2028,14 +2038,14 @@ func (rr *MX) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Preference, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("MX.Preference: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Mx, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("MX.Mx: %w", err)
 	}
 	return off, nil
 }
@@ -2046,42 +2056,42 @@ func (rr *NAPTR) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Order, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NAPTR.Order: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Preference, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NAPTR.Preference: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Flags, off, err = unpackString(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NAPTR.Flags: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Service, off, err = unpackString(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NAPTR.Service: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Regexp, off, err = unpackString(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NAPTR.Regexp: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Replacement, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NAPTR.Replacement: %w", err)
 	}
 	return off, nil
 }
@@ -2092,14 +2102,14 @@ func (rr *NID) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Preference, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NID.Preference: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.NodeID, off, err = unpackUint64(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NID.NodeID: %w", err)
 	}
 	return off, nil
 }
@@ -2110,7 +2120,7 @@ func (rr *NIMLOC) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Locator, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NIMLOC.Locator: %w", err)
 	}
 	return off, nil
 }
@@ -2121,7 +2131,7 @@ func (rr *NINFO) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.ZSData, off, err = unpackStringTxt(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NINFO.ZSData: %w", err)
 	}
 	return off, nil
 }
@@ -2132,7 +2142,7 @@ func (rr *NS) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Ns, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NS.Ns: %w", err)
 	}
 	return off, nil
 }
@@ -2143,7 +2153,7 @@ func (rr *NSAPPTR) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Ptr, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NSAPPTR.Ptr: %w", err)
 	}
 	return off, nil
 }
@@ -2154,14 +2164,14 @@ func (rr *NSEC) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.NextDomain, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NSEC.NextDomain: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.TypeBitMap, off, err = unpackDataNsec(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NSEC.TypeBitMap: %w", err)
 	}
 	return off, nil
 }
@@ -2172,28 +2182,28 @@ func (rr *NSEC3) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Hash, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NSEC3.Hash: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Flags, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NSEC3.Flags: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Iterations, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NSEC3.Iterations: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.SaltLength, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NSEC3.SaltLength: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
@@ -2204,7 +2214,7 @@ func (rr *NSEC3) unpack(msg []byte, off int) (off1 int, err error) {
 	}
 	rr.HashLength, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NSEC3.HashLength: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
@@ -2215,7 +2225,7 @@ func (rr *NSEC3) unpack(msg []byte, off int) (off1 int, err error) {
 	}
 	rr.TypeBitMap, off, err = unpackDataNsec(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NSEC3.TypeBitMap: %w", err)
 	}
 	return off, nil
 }
@@ -2226,28 +2236,28 @@ func (rr *NSEC3PARAM) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Hash, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NSEC3PARAM.Hash: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Flags, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NSEC3PARAM.Flags: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Iterations, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NSEC3PARAM.Iterations: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.SaltLength, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NSEC3PARAM.SaltLength: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
@@ -2265,7 +2275,7 @@ func (rr *NULL) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Data, off, err = unpackStringAny(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NULL.Data: %w", err)
 	}
 	return off, nil
 }
@@ -2283,14 +2293,14 @@ func (rr *NXT) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.NextDomain, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NXT.NextDomain: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.TypeBitMap, off, err = unpackDataNsec(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("NXT.TypeBitMap: %w", err)
 	}
 	return off, nil
 }
@@ -2301,7 +2311,7 @@ func (rr *OPENPGPKEY) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.PublicKey, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("OPENPGPKEY.PublicKey: %w", err)
 	}
 	return off, nil
 }
@@ -2312,7 +2322,7 @@ func (rr *OPT) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Option, off, err = unpackDataOpt(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("OPT.Option: %w", err)
 	}
 	return off, nil
 }
@@ -2323,7 +2333,7 @@ func (rr *PTR) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Ptr, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("PTR.Ptr: %w", err)
 	}
 	return off, nil
 }
@@ -2334,19 +2344,30 @@ func (rr *PX) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Preference, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("PX.Preference: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Map822, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("PX.Map822: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Mapx400, off, err = UnpackDomainName(msg, off)
+	if err != nil {
+		return off, fmt.Errorf("PX.Mapx400: %w", err)
+	}
+	return off, nil
+}
+
+func (rr *RESINFO) unpack(msg []byte, off int) (off1 int, err error) {
+	rdStart := off
+	_ = rdStart
+
+	rr.Txt, off, err = unpackStringTxt(msg, off)
 	if err != nil {
 		return off, err
 	}
@@ -2359,7 +2380,7 @@ func (rr *RFC3597) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Rdata, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("RFC3597.Rdata: %w", err)
 	}
 	return off, nil
 }
@@ -2370,28 +2391,28 @@ func (rr *RKEY) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Flags, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("RKEY.Flags: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Protocol, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("RKEY.Protocol: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("RKEY.Algorithm: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.PublicKey, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("RKEY.PublicKey: %w", err)
 	}
 	return off, nil
 }
@@ -2402,14 +2423,14 @@ func (rr *RP) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Mbox, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("RP.Mbox: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Txt, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("RP.Txt: %w", err)
 	}
 	return off, nil
 }
@@ -2420,63 +2441,63 @@ func (rr *RRSIG) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.TypeCovered, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("RRSIG.TypeCovered: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("RRSIG.Algorithm: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Labels, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("RRSIG.Labels: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.OrigTtl, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("RRSIG.OrigTtl: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Expiration, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("RRSIG.Expiration: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Inception, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("RRSIG.Inception: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.KeyTag, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("RRSIG.KeyTag: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.SignerName, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("RRSIG.SignerName: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Signature, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("RRSIG.Signature: %w", err)
 	}
 	return off, nil
 }
@@ -2487,14 +2508,14 @@ func (rr *RT) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Preference, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("RT.Preference: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Host, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("RT.Host: %w", err)
 	}
 	return off, nil
 }
@@ -2505,63 +2526,63 @@ func (rr *SIG) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.TypeCovered, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SIG.TypeCovered: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SIG.Algorithm: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Labels, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SIG.Labels: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.OrigTtl, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SIG.OrigTtl: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Expiration, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SIG.Expiration: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Inception, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SIG.Inception: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.KeyTag, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SIG.KeyTag: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.SignerName, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SIG.SignerName: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Signature, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SIG.Signature: %w", err)
 	}
 	return off, nil
 }
@@ -2572,28 +2593,28 @@ func (rr *SMIMEA) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Usage, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SMIMEA.Usage: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Selector, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SMIMEA.Selector: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.MatchingType, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SMIMEA.MatchingType: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Certificate, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SMIMEA.Certificate: %w", err)
 	}
 	return off, nil
 }
@@ -2604,49 +2625,49 @@ func (rr *SOA) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Ns, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SOA.Ns: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Mbox, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SOA.Mbox: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Serial, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SOA.Serial: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Refresh, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SOA.Refresh: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Retry, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SOA.Retry: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Expire, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SOA.Expire: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Minttl, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SOA.Minttl: %w", err)
 	}
 	return off, nil
 }
@@ -2657,7 +2678,7 @@ func (rr *SPF) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Txt, off, err = unpackStringTxt(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SPF.Txt: %w", err)
 	}
 	return off, nil
 }
@@ -2668,28 +2689,28 @@ func (rr *SRV) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Priority, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SRV.Priority: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Weight, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SRV.Weight: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Port, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SRV.Port: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Target, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SRV.Target: %w", err)
 	}
 	return off, nil
 }
@@ -2700,21 +2721,21 @@ func (rr *SSHFP) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SSHFP.Algorithm: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Type, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SSHFP.Type: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.FingerPrint, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SSHFP.FingerPrint: %w", err)
 	}
 	return off, nil
 }
@@ -2725,21 +2746,21 @@ func (rr *SVCB) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Priority, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SVCB.Priority: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Target, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SVCB.Target: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Value, off, err = unpackDataSVCB(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("SVCB.Value: %w", err)
 	}
 	return off, nil
 }
@@ -2750,28 +2771,28 @@ func (rr *TA) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.KeyTag, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TA.KeyTag: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TA.Algorithm: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.DigestType, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TA.DigestType: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Digest, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TA.Digest: %w", err)
 	}
 	return off, nil
 }
@@ -2782,14 +2803,14 @@ func (rr *TALINK) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.PreviousName, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TALINK.PreviousName: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.NextName, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TALINK.NextName: %w", err)
 	}
 	return off, nil
 }
@@ -2800,42 +2821,42 @@ func (rr *TKEY) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Algorithm, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TKEY.Algorithm: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Inception, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TKEY.Inception: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Expiration, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TKEY.Expiration: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Mode, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TKEY.Mode: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Error, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TKEY.Error: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.KeySize, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TKEY.KeySize: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
@@ -2846,7 +2867,7 @@ func (rr *TKEY) unpack(msg []byte, off int) (off1 int, err error) {
 	}
 	rr.OtherLen, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TKEY.OtherLen: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
@@ -2864,28 +2885,28 @@ func (rr *TLSA) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Usage, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TLSA.Usage: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Selector, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TLSA.Selector: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.MatchingType, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TLSA.MatchingType: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Certificate, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TLSA.Certificate: %w", err)
 	}
 	return off, nil
 }
@@ -2896,28 +2917,28 @@ func (rr *TSIG) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Algorithm, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TSIG.Algorithm: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.TimeSigned, off, err = unpackUint48(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TSIG.TimeSigned: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Fudge, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TSIG.Fudge: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.MACSize, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TSIG.MACSize: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
@@ -2928,21 +2949,21 @@ func (rr *TSIG) unpack(msg []byte, off int) (off1 int, err error) {
 	}
 	rr.OrigId, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TSIG.OrigId: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Error, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TSIG.Error: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.OtherLen, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TSIG.OtherLen: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
@@ -2960,7 +2981,7 @@ func (rr *TXT) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Txt, off, err = unpackStringTxt(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("TXT.Txt: %w", err)
 	}
 	return off, nil
 }
@@ -2971,7 +2992,7 @@ func (rr *UID) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Uid, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("UID.Uid: %w", err)
 	}
 	return off, nil
 }
@@ -2982,7 +3003,7 @@ func (rr *UINFO) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Uinfo, off, err = unpackString(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("UINFO.Uinfo: %w", err)
 	}
 	return off, nil
 }
@@ -2993,21 +3014,21 @@ func (rr *URI) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Priority, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("URI.Priority: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Weight, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("URI.Weight: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Target, off, err = unpackStringOctet(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("URI.Target: %w", err)
 	}
 	return off, nil
 }
@@ -3018,7 +3039,7 @@ func (rr *X25) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.PSDNAddress, off, err = unpackString(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("X25.PSDNAddress: %w", err)
 	}
 	return off, nil
 }
@@ -3029,28 +3050,28 @@ func (rr *ZONEMD) unpack(msg []byte, off int) (off1 int, err error) {
 
 	rr.Serial, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("ZONEMD.Serial: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Scheme, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("ZONEMD.Scheme: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Hash, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("ZONEMD.Hash: %w", err)
 	}
 	if off == len(msg) {
 		return off, nil
 	}
 	rr.Digest, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return off, err
+		return off, fmt.Errorf("ZONEMD.Digest: %w", err)
 	}
 	return off, nil
 }
diff --git a/ztypes.go b/ztypes.go
index 11f13ecf..cea79ae7 100644
--- a/ztypes.go
+++ b/ztypes.go
@@ -66,6 +66,7 @@ var TypeToRR = map[uint16]func() RR{
 	TypeOPT:        func() RR { return new(OPT) },
 	TypePTR:        func() RR { return new(PTR) },
 	TypePX:         func() RR { return new(PX) },
+	TypeRESINFO:    func() RR { return new(RESINFO) },
 	TypeRKEY:       func() RR { return new(RKEY) },
 	TypeRP:         func() RR { return new(RP) },
 	TypeRRSIG:      func() RR { return new(RRSIG) },
@@ -154,6 +155,7 @@ var TypeToString = map[uint16]string{
 	TypeOPT:        "OPT",
 	TypePTR:        "PTR",
 	TypePX:         "PX",
+	TypeRESINFO:    "RESINFO",
 	TypeRKEY:       "RKEY",
 	TypeRP:         "RP",
 	TypeRRSIG:      "RRSIG",
@@ -238,6 +240,7 @@ func (rr *OPENPGPKEY) Header() *RR_Header { return &rr.Hdr }
 func (rr *OPT) Header() *RR_Header        { return &rr.Hdr }
 func (rr *PTR) Header() *RR_Header        { return &rr.Hdr }
 func (rr *PX) Header() *RR_Header         { return &rr.Hdr }
+func (rr *RESINFO) Header() *RR_Header    { return &rr.Hdr }
 func (rr *RFC3597) Header() *RR_Header    { return &rr.Hdr }
 func (rr *RKEY) Header() *RR_Header       { return &rr.Hdr }
 func (rr *RP) Header() *RR_Header         { return &rr.Hdr }
@@ -622,6 +625,14 @@ func (rr *PX) len(off int, compression map[string]struct{}) int {
 	return l
 }
 
+func (rr *RESINFO) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	for _, x := range rr.Txt {
+		l += len(x) + 1
+	}
+	return l
+}
+
 func (rr *RFC3597) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l += len(rr.Rdata) / 2
@@ -1148,6 +1159,10 @@ func (rr *PX) copy() RR {
 	}
 }
 
+func (rr *RESINFO) copy() RR {
+	return &RESINFO{rr.Hdr, cloneSlice(rr.Txt)}
+}
+
 func (rr *RFC3597) copy() RR {
 	return &RFC3597{rr.Hdr, rr.Rdata}
 }



Test patch:
diff --git a/dnssec_test.go b/dnssec_test.go
index 1511278c..4f04e85f 100644
--- a/dnssec_test.go
+++ b/dnssec_test.go
@@ -155,6 +155,117 @@ func TestSignVerify(t *testing.T) {
 	}
 }
 
+// Test if RRSIG.Verify() conforms to RFC 4035 Section 5.3.1
+func TestShouldNotVerifyInvalidSig(t *testing.T) {
+	// The RRSIG RR and the RRset MUST have the same owner name
+	rrNameMismatch := getSoa()
+	rrNameMismatch.Hdr.Name = "example.com."
+
+	// ... and the same class
+	rrClassMismatch := getSoa()
+	rrClassMismatch.Hdr.Class = ClassCHAOS
+
+	// The RRSIG RR's Type Covered field MUST equal the RRset's type.
+	rrTypeMismatch := getSoa()
+	rrTypeMismatch.Hdr.Rrtype = TypeA
+
+	// The number of labels in the RRset owner name MUST be greater than
+	// or equal to the value in the RRSIG RR's Labels field.
+	rrLabelLessThan := getSoa()
+	rrLabelLessThan.Hdr.Name = "nl."
+
+	// Time checks are done in ValidityPeriod
+
+	// With this key
+	key := new(DNSKEY)
+	key.Hdr.Rrtype = TypeDNSKEY
+	key.Hdr.Name = "miek.nl."
+	key.Hdr.Class = ClassINET
+	key.Hdr.Ttl = 14400
+	key.Flags = 256
+	key.Protocol = 3
+	key.Algorithm = RSASHA256
+	privkey, _ := key.Generate(512)
+
+	normalSoa := getSoa()
+
+	// Fill in the normal values of the Sig, before signing
+	sig := new(RRSIG)
+	sig.Hdr = RR_Header{"miek.nl.", TypeRRSIG, ClassINET, 14400, 0}
+	sig.TypeCovered = TypeSOA
+	sig.Labels = uint8(CountLabel(normalSoa.Hdr.Name))
+	sig.OrigTtl = normalSoa.Hdr.Ttl
+	sig.Expiration = 1296534305 // date -u '+%s' -d"2011-02-01 04:25:05"
+	sig.Inception = 1293942305  // date -u '+%s' -d"2011-01-02 04:25:05"
+	sig.KeyTag = key.KeyTag()   // Get the keyfrom the Key
+	sig.SignerName = key.Hdr.Name
+	sig.Algorithm = RSASHA256
+
+	for i, rr := range []RR{rrNameMismatch, rrClassMismatch, rrTypeMismatch, rrLabelLessThan} {
+		if i != 0 { // Just for the rrNameMismatch case, we need the name to mismatch
+			sig := sig.copy().(*RRSIG)
+			sig.SignerName = rr.Header().Name
+			sig.Hdr.Name = rr.Header().Name
+			key := key.copy().(*DNSKEY)
+			key.Hdr.Name = rr.Header().Name
+		}
+
+		if err := sig.signAsIs(privkey.(*rsa.PrivateKey), []RR{rr}); err != nil {
+			t.Error("failure to sign the record:", err)
+			continue
+		}
+
+		if err := sig.Verify(key, []RR{rr}); err == nil {
+			t.Error("should not validate: ", rr)
+			continue
+		} else {
+			t.Logf("expected failure: %v for RR name %s, class %d, type %d, rrsig labels %d", err, rr.Header().Name, rr.Header().Class, rr.Header().Rrtype, CountLabel(rr.Header().Name))
+		}
+	}
+
+	// The RRSIG RR's Signer's Name field MUST be the name of the zone that contains the RRset.
+	// The RRSIG RR's Signer's Name, Algorithm, and Key Tag fields MUST match the owner name,
+	// algorithm, and key tag for some DNSKEY RR in the zone's apex DNSKEY RRset.
+	sigMismatchName := sig.copy().(*RRSIG)
+	sigMismatchName.SignerName = "example.com."
+	soaMismatchName := getSoa()
+	soaMismatchName.Hdr.Name = "example.com."
+	keyMismatchName := key.copy().(*DNSKEY)
+	keyMismatchName.Hdr.Name = "example.com."
+	if err := sigMismatchName.signAsIs(privkey.(*rsa.PrivateKey), []RR{soaMismatchName}); err != nil {
+		t.Error("failure to sign the record:", err)
+	} else if err := sigMismatchName.Verify(keyMismatchName, []RR{soaMismatchName}); err == nil {
+		t.Error("should not validate: ", soaMismatchName, ", RRSIG's signer's name does not match the owner name")
+	} else {
+		t.Logf("expected failure: %v for signer %s and owner %s", err, sigMismatchName.SignerName, sigMismatchName.Hdr.Name)
+	}
+
+	sigMismatchAlgo := sig.copy().(*RRSIG)
+	sigMismatchAlgo.Algorithm = RSASHA1
+	sigMismatchKeyTag := sig.copy().(*RRSIG)
+	sigMismatchKeyTag.KeyTag = 12345
+	for _, sigMismatch := range []*RRSIG{sigMismatchAlgo, sigMismatchKeyTag} {
+		if err := sigMismatch.Sign(privkey.(*rsa.PrivateKey), []RR{normalSoa}); err != nil {
+			t.Error("failure to sign the record:", err)
+		} else if err := sigMismatch.Verify(key, []RR{normalSoa}); err == nil {
+			t.Error("should not validate: ", normalSoa)
+		} else {
+			t.Logf("expected failure: %v for signer %s algo %d keytag %d", err, sigMismatch.SignerName, sigMismatch.Algorithm, sigMismatch.KeyTag)
+		}
+	}
+
+	// The matching DNSKEY RR MUST have the Zone Flag bit (DNSKEY RDATA Flag bit 7) set.
+	keyZoneBitWrong := key.copy().(*DNSKEY)
+	keyZoneBitWrong.Flags = key.Flags &^ ZONE
+	if err := sig.Sign(privkey.(*rsa.PrivateKey), []RR{normalSoa}); err != nil {
+		t.Error("failure to sign the record:", err)
+	} else if err := sig.Verify(keyZoneBitWrong, []RR{normalSoa}); err == nil {
+		t.Error("should not validate: ", normalSoa)
+	} else {
+		t.Logf("expected failure: %v for key flags %d", err, keyZoneBitWrong.Flags)
+	}
+}
+
 func Test65534(t *testing.T) {
 	t6 := new(RFC3597)
 	t6.Hdr = RR_Header{"miek.nl.", 65534, ClassINET, 14400, 0}
diff --git a/edns_test.go b/edns_test.go
index b7c15f7e..b9853dd2 100644
--- a/edns_test.go
+++ b/edns_test.go
@@ -56,6 +56,39 @@ func TestOPTTtl(t *testing.T) {
 		t.Errorf("DO bit should be non-zero")
 	}
 
+	// CO (Compact ANswers OK) flag tests follow the same pattern as DO tests
+	// verify that invoking SetCo() sets CO=1
+	e.SetCo()
+	if !e.Co() {
+		t.Errorf("CO bit should be non-zero")
+	}
+
+	// verify that using SetCo(true) works when CO=1
+	e.SetCo(true)
+	if !e.Co() {
+		t.Errorf("CO bit should still be non-zero")
+	}
+	// verify that we can use SetCo(false) to set CO=0
+	e.SetCo(false)
+	if e.Co() {
+		t.Errorf("CO bit should be zero")
+	}
+	// verify that if we call SetCo(false) when CO=0 that it is unchanged
+	e.SetCo(false)
+	if e.Co() {
+		t.Errorf("CO bit should still be zero")
+	}
+	// verify that using SetCo(true) works for CO=0
+	e.SetCo(true)
+	if !e.Co() {
+		t.Errorf("CO bit should be non-zero")
+	}
+	// verify that using SetCo() works for CO=1
+	e.SetCo()
+	if !e.Co() {
+		t.Errorf("CO bit should be non-zero")
+	}
+
 	if e.Version() != 0 {
 		t.Errorf("version should be non-zero")
 	}
@@ -141,6 +174,7 @@ func TestZ(t *testing.T) {
 	e.Hdr.Rrtype = TypeOPT
 	e.SetVersion(8)
 	e.SetDo()
+	e.SetCo()
 	if e.Z() != 0 {
 		t.Errorf("expected Z of 0, got %d", e.Z())
 	}
@@ -149,8 +183,8 @@ func TestZ(t *testing.T) {
 		t.Errorf("expected Z of 5, got %d", e.Z())
 	}
 	e.SetZ(0xFFFF)
-	if e.Z() != 0x7FFF {
-		t.Errorf("expected Z of 0x7FFFF, got %d", e.Z())
+	if e.Z() != 0x3FFF {
+		t.Errorf("expected Z of 0x3FFFF, got %d", e.Z())
 	}
 	if e.Version() != 8 {
 		t.Errorf("expected version to still be 8, got %d", e.Version())
diff --git a/scan_test.go b/scan_test.go
index c4f7e7f4..e46b3684 100644
--- a/scan_test.go
+++ b/scan_test.go
@@ -226,6 +226,22 @@ func TestZoneParserAddressAAAA(t *testing.T) {
 	}
 }
 
+func TestZoneParserTargetBad(t *testing.T) {
+	records := []string{
+		"bad.example.org. CNAME ; bad cname",
+		"bad.example.org. HTTPS 10 ; bad https",
+		"bad.example.org. MX 10 ; bad mx",
+		"bad.example.org. SRV 1 0 80 ; bad srv",
+	}
+
+	for _, record := range records {
+		const expect = "bad "
+		if got, err := NewRR(record); err == nil || !strings.Contains(err.Error(), expect) {
+			t.Errorf("NewRR(%v) = %v, want err to contain %q", record, got, expect)
+		}
+	}
+}
+
 func TestZoneParserAddressBad(t *testing.T) {
 	records := []string{
 		"1.bad.example.org. 600 IN A ::1",
diff --git a/server_test.go b/server_test.go
index 4fc2af32..a9e2339b 100644
--- a/server_test.go
+++ b/server_test.go
@@ -996,6 +996,101 @@ func TestServerStartStopRace(t *testing.T) {
 	wg.Wait()
 }
 
+func TestSocketOptions(t *testing.T) {
+	if !supportsReuseAddr || !supportsReusePort {
+		t.Skip("reuseaddr or reuseport is not supported")
+	}
+
+	testSocketOptions := func(t *testing.T, reuseAddr bool, reusePort bool) {
+		wait := make(chan struct{})
+
+		srv := &Server{
+			Net:       "udp",
+			Addr:      ":0",
+			ReuseAddr: reuseAddr,
+			ReusePort: reusePort,
+		}
+
+		srv.NotifyStartedFunc = func() {
+			defer close(wait)
+
+			conn, ok := srv.PacketConn.(*net.UDPConn)
+			if !ok {
+				t.Errorf("unexpected conn type: %T", srv.PacketConn)
+				return
+			}
+
+			syscallConn, err := conn.SyscallConn()
+			if err != nil {
+				t.Errorf("cannot cast UDP conn to syscall conn: %v", err)
+				return
+
+			}
+
+			err = syscallConn.Control(func(fd uintptr) {
+				actualReusePort, err := checkReuseport(fd)
+				if err != nil {
+					t.Errorf("cannot get SO_REUSEPORT socket option: %v", err)
+					return
+				}
+
+				if actualReusePort != reusePort {
+					t.Errorf("SO_REUSEPORT is %v instead of %v", actualReusePort, reusePort)
+				}
+
+				actualReuseAddr, err := checkReuseaddr(fd)
+				if err != nil {
+					t.Errorf("cannot get SO_REUSEADDR socket option: %v", err)
+					return
+				}
+
+				if actualReuseAddr != reuseAddr {
+					t.Errorf("SO_REUSEADDR is %v instead of %v", actualReuseAddr, reusePort)
+				}
+			})
+			if err != nil {
+				t.Errorf("cannot check socket options: %v", err)
+			}
+		}
+
+		fin := make(chan error, 1)
+		go func() {
+			fin <- srv.ListenAndServe()
+		}()
+
+		select {
+		case <-wait:
+			err := srv.Shutdown()
+			if err != nil {
+				t.Fatalf("cannot shutdown server: %v", err)
+			}
+
+			err = <-fin
+			if err != nil {
+				t.Fatalf("listen adn serve: %v", err)
+			}
+		case err := <-fin:
+			t.Fatalf("listen adn serve: %v", err)
+		}
+	}
+
+	t.Run("no socket options", func(t *testing.T) {
+		testSocketOptions(t, false, false)
+	})
+
+	t.Run("SO_REUSEPORT", func(t *testing.T) {
+		testSocketOptions(t, false, true)
+	})
+
+	t.Run("SO_REUSEADDR", func(t *testing.T) {
+		testSocketOptions(t, true, false)
+	})
+
+	t.Run("SO_REUSEADDR and SO_REUSEPORT", func(t *testing.T) {
+		testSocketOptions(t, true, true)
+	})
+}
+
 func TestServerReuseport(t *testing.T) {
 	if !supportsReusePort {
 		t.Skip("reuseport is not supported")
@@ -1329,7 +1424,6 @@ func TestResponseWriteSinglePacket(t *testing.T) {
 	m.SetQuestion("miek.nl.", TypeTXT)
 	m.Response = true
 	err := rw.WriteMsg(m)
-
 	if err != nil {
 		t.Fatalf("failed to write: %v", err)
 	}
diff --git a/xfr_test.go b/xfr_test.go
index 04801a2e..c580ceef 100644
--- a/xfr_test.go
+++ b/xfr_test.go
@@ -2,6 +2,7 @@ package dns
 
 import (
 	"crypto/tls"
+	"errors"
 	"testing"
 	"time"
 )
@@ -221,6 +222,29 @@ func axfrTestingSuiteWithCustomTsig(t *testing.T, addrstr string, provider TsigP
 	}
 }
 
+func axfrTestingSuiteWithMsgNotSigned(t *testing.T, addrstr string, provider TsigProvider) {
+	tr := new(Transfer)
+	m := new(Msg)
+	var err error
+	tr.Conn, err = Dial("tcp", addrstr)
+	if err != nil {
+		t.Fatal("failed to dial", err)
+	}
+	tr.TsigProvider = provider
+	m.SetAxfr("miek.nl.")
+
+	c, err := tr.In(m, addrstr)
+	if err != nil {
+		t.Fatal("failed to zone transfer in", err)
+	}
+
+	for msg := range c {
+		if !errors.Is(msg.Error, ErrNoSig) {
+			t.Fatal("expecting ErrNoSig error")
+		}
+	}
+}
+
 func TestCustomTsigProvider(t *testing.T) {
 	HandleFunc("miek.nl.", SingleEnvelopeXfrServer)
 	defer HandleRemove("miek.nl.")
@@ -235,3 +259,16 @@ func TestCustomTsigProvider(t *testing.T) {
 
 	axfrTestingSuiteWithCustomTsig(t, addrstr, tsigSecretProvider(tsigSecret))
 }
+
+func TestTSIGNotSigned(t *testing.T) {
+	HandleFunc("miek.nl.", SingleEnvelopeXfrServer)
+	defer HandleRemove("miek.nl.")
+
+	s, addrstr, _, err := RunLocalTCPServer(":0")
+	if err != nil {
+		t.Fatalf("unable to run test server: %s", err)
+	}
+	defer s.Shutdown()
+
+	axfrTestingSuiteWithMsgNotSigned(t, addrstr, tsigSecretProvider(tsigSecret))
+}