Преглед на файлове

vendor: github.com/miekg/dns v1.1.57

full diff: https://github.com/github.com/miekg/dns/compare/v1.1.43...v1.1.57

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Paweł Gronowski преди 1 година
родител
ревизия
9f4e824a6e
променени са 38 файла, в които са добавени 1831 реда и са изтрити 790 реда
  1. 1 1
      vendor.mod
  2. 2 3
      vendor.sum
  3. 24 25
      vendor/github.com/miekg/dns/LICENSE
  4. 11 0
      vendor/github.com/miekg/dns/README.md
  5. 1 4
      vendor/github.com/miekg/dns/acceptfunc.go
  6. 83 69
      vendor/github.com/miekg/dns/client.go
  7. 1 1
      vendor/github.com/miekg/dns/clientconfig.go
  8. 34 25
      vendor/github.com/miekg/dns/defaults.go
  9. 21 41
      vendor/github.com/miekg/dns/dnssec.go
  10. 2 1
      vendor/github.com/miekg/dns/dnssec_keyscan.go
  11. 44 44
      vendor/github.com/miekg/dns/doc.go
  12. 88 65
      vendor/github.com/miekg/dns/edns.go
  13. 1 0
      vendor/github.com/miekg/dns/fuzz.go
  14. 17 16
      vendor/github.com/miekg/dns/generate.go
  15. 31 0
      vendor/github.com/miekg/dns/hash.go
  16. 1 1
      vendor/github.com/miekg/dns/labels.go
  17. 8 5
      vendor/github.com/miekg/dns/listen_no_reuseport.go
  18. 27 5
      vendor/github.com/miekg/dns/listen_reuseport.go
  19. 73 52
      vendor/github.com/miekg/dns/msg.go
  20. 74 44
      vendor/github.com/miekg/dns/msg_helpers.go
  21. 26 39
      vendor/github.com/miekg/dns/scan.go
  22. 126 8
      vendor/github.com/miekg/dns/scan_rr.go
  23. 34 22
      vendor/github.com/miekg/dns/server.go
  24. 25 28
      vendor/github.com/miekg/dns/sig0.go
  25. 0 61
      vendor/github.com/miekg/dns/singleinflight.go
  26. 298 118
      vendor/github.com/miekg/dns/svcb.go
  27. 10 0
      vendor/github.com/miekg/dns/tools.go
  28. 46 19
      vendor/github.com/miekg/dns/tsig.go
  29. 109 20
      vendor/github.com/miekg/dns/types.go
  30. 1 0
      vendor/github.com/miekg/dns/udp.go
  31. 4 4
      vendor/github.com/miekg/dns/udp_windows.go
  32. 3 1
      vendor/github.com/miekg/dns/update.go
  33. 1 1
      vendor/github.com/miekg/dns/version.go
  34. 30 16
      vendor/github.com/miekg/dns/xfr.go
  35. 58 0
      vendor/github.com/miekg/dns/zduplicate.go
  36. 110 0
      vendor/github.com/miekg/dns/zmsg.go
  37. 404 49
      vendor/github.com/miekg/dns/ztypes.go
  38. 2 2
      vendor/modules.txt

+ 1 - 1
vendor.mod

@@ -57,7 +57,7 @@ require (
 	github.com/hashicorp/serf v0.8.5
 	github.com/hashicorp/serf v0.8.5
 	github.com/ishidawataru/sctp v0.0.0-20230406120618-7ff4192f6ff2
 	github.com/ishidawataru/sctp v0.0.0-20230406120618-7ff4192f6ff2
 	github.com/klauspost/compress v1.17.4
 	github.com/klauspost/compress v1.17.4
-	github.com/miekg/dns v1.1.43
+	github.com/miekg/dns v1.1.57
 	github.com/mistifyio/go-zfs/v3 v3.0.1
 	github.com/mistifyio/go-zfs/v3 v3.0.1
 	github.com/mitchellh/copystructure v1.2.0
 	github.com/mitchellh/copystructure v1.2.0
 	github.com/moby/buildkit v0.13.0-rc3
 	github.com/moby/buildkit v0.13.0-rc3

+ 2 - 3
vendor.sum

@@ -458,8 +458,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zk
 github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
 github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
 github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
 github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
-github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
-github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
+github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM=
+github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk=
 github.com/mistifyio/go-zfs/v3 v3.0.1 h1:YaoXgBePoMA12+S1u/ddkv+QqxcfiZK4prI6HPnkFiU=
 github.com/mistifyio/go-zfs/v3 v3.0.1 h1:YaoXgBePoMA12+S1u/ddkv+QqxcfiZK4prI6HPnkFiU=
 github.com/mistifyio/go-zfs/v3 v3.0.1/go.mod h1:CzVgeB0RvF2EGzQnytKVvVSDwmKJXxkOTUGbNrTja/k=
 github.com/mistifyio/go-zfs/v3 v3.0.1/go.mod h1:CzVgeB0RvF2EGzQnytKVvVSDwmKJXxkOTUGbNrTja/k=
 github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
 github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
@@ -918,7 +918,6 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

+ 24 - 25
vendor/github.com/miekg/dns/LICENSE

@@ -1,30 +1,29 @@
-Copyright (c) 2009 The Go Authors. All rights reserved.
+BSD 3-Clause License
+
+Copyright (c) 2009, The Go Authors. Extensions copyright (c) 2011, Miek Gieben. 
+All rights reserved.
 
 
 Redistribution and use in source and binary forms, with or without
 Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
+modification, are permitted provided that the following conditions are met:
 
 
-   * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-   * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
-   * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
 
 
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
 
 
-As this is fork of the official Go code the same license applies.
-Extensions of the original work are copyright (c) 2011 Miek Gieben
+3. Neither the name of the copyright holder nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 11 - 0
vendor/github.com/miekg/dns/README.md

@@ -73,6 +73,15 @@ A not-so-up-to-date-list-that-may-be-actually-current:
 * https://github.com/bodgit/tsig
 * https://github.com/bodgit/tsig
 * https://github.com/v2fly/v2ray-core (test only)
 * https://github.com/v2fly/v2ray-core (test only)
 * https://kuma.io/
 * https://kuma.io/
+* https://www.misaka.io/services/dns
+* https://ping.sx/dig
+* https://fleetdeck.io/
+* https://github.com/markdingo/autoreverse
+* https://github.com/slackhq/nebula
+* https://addr.tools/
+* https://dnscheck.tools/
+* https://github.com/egbakou/domainverifier
+* https://github.com/semihalev/sdns
 
 
 
 
 Send pull request if you want to be listed here.
 Send pull request if you want to be listed here.
@@ -136,6 +145,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
 * 340{1,2,3} - NAPTR record
 * 340{1,2,3} - NAPTR record
 * 3445 - Limiting the scope of (DNS)KEY
 * 3445 - Limiting the scope of (DNS)KEY
 * 3597 - Unknown RRs
 * 3597 - Unknown RRs
+* 4025 - A Method for Storing IPsec Keying Material in DNS
 * 403{3,4,5} - DNSSEC + validation functions
 * 403{3,4,5} - DNSSEC + validation functions
 * 4255 - SSHFP record
 * 4255 - SSHFP record
 * 4343 - Case insensitivity
 * 4343 - Case insensitivity
@@ -171,6 +181,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
 * 8080 - EdDSA for DNSSEC
 * 8080 - EdDSA for DNSSEC
 * 8499 - DNS Terminology
 * 8499 - DNS Terminology
 * 8659 - DNS Certification Authority Authorization (CAA) Resource Record
 * 8659 - DNS Certification Authority Authorization (CAA) Resource Record
+* 8777 - DNS Reverse IP Automatic Multicast Tunneling (AMT) Discovery
 * 8914 - Extended DNS Errors
 * 8914 - Extended DNS Errors
 * 8976 - Message Digest for DNS Zones (ZONEMD RR)
 * 8976 - Message Digest for DNS Zones (ZONEMD RR)
 
 

+ 1 - 4
vendor/github.com/miekg/dns/acceptfunc.go

@@ -10,16 +10,13 @@ type MsgAcceptFunc func(dh Header) MsgAcceptAction
 //
 //
 // * opcode isn't OpcodeQuery or OpcodeNotify
 // * opcode isn't OpcodeQuery or OpcodeNotify
 //
 //
-// * Zero bit isn't zero
-//
-// * has more than 1 question in the question section
+// * does not have exactly 1 question in the question section
 //
 //
 // * has more than 1 RR in the Answer section
 // * has more than 1 RR in the Answer section
 //
 //
 // * has more than 0 RRs in the Authority section
 // * has more than 0 RRs in the Authority section
 //
 //
 // * has more than 2 RRs in the Additional section
 // * has more than 2 RRs in the Additional section
-//
 var DefaultMsgAcceptFunc MsgAcceptFunc = defaultMsgAcceptFunc
 var DefaultMsgAcceptFunc MsgAcceptFunc = defaultMsgAcceptFunc
 
 
 // MsgAcceptAction represents the action to be taken.
 // MsgAcceptAction represents the action to be taken.

+ 83 - 69
vendor/github.com/miekg/dns/client.go

@@ -6,7 +6,6 @@ import (
 	"context"
 	"context"
 	"crypto/tls"
 	"crypto/tls"
 	"encoding/binary"
 	"encoding/binary"
-	"fmt"
 	"io"
 	"io"
 	"net"
 	"net"
 	"strings"
 	"strings"
@@ -18,6 +17,18 @@ const (
 	tcpIdleTimeout time.Duration = 8 * time.Second
 	tcpIdleTimeout time.Duration = 8 * time.Second
 )
 )
 
 
+func isPacketConn(c net.Conn) bool {
+	if _, ok := c.(net.PacketConn); !ok {
+		return false
+	}
+
+	if ua, ok := c.LocalAddr().(*net.UnixAddr); ok {
+		return ua.Net == "unixgram" || ua.Net == "unixpacket"
+	}
+
+	return true
+}
+
 // A Conn represents a connection to a DNS server.
 // A Conn represents a connection to a DNS server.
 type Conn struct {
 type Conn struct {
 	net.Conn                         // a net.Conn holding the connection
 	net.Conn                         // a net.Conn holding the connection
@@ -27,6 +38,14 @@ type Conn struct {
 	tsigRequestMAC string
 	tsigRequestMAC string
 }
 }
 
 
+func (co *Conn) tsigProvider() TsigProvider {
+	if co.TsigProvider != nil {
+		return co.TsigProvider
+	}
+	// tsigSecretProvider will return ErrSecret if co.TsigSecret is nil.
+	return tsigSecretProvider(co.TsigSecret)
+}
+
 // A Client defines parameters for a DNS client.
 // A Client defines parameters for a DNS client.
 type Client struct {
 type Client struct {
 	Net       string      // if "tcp" or "tcp-tls" (DNS over TLS) a TCP query will be initiated, otherwise an UDP one (default is "" for UDP)
 	Net       string      // if "tcp" or "tcp-tls" (DNS over TLS) a TCP query will be initiated, otherwise an UDP one (default is "" for UDP)
@@ -36,14 +55,20 @@ type Client struct {
 	// Timeout is a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout,
 	// Timeout is a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout,
 	// WriteTimeout when non-zero. Can be overridden with net.Dialer.Timeout (see Client.ExchangeWithDialer and
 	// WriteTimeout when non-zero. Can be overridden with net.Dialer.Timeout (see Client.ExchangeWithDialer and
 	// Client.Dialer) or context.Context.Deadline (see ExchangeContext)
 	// Client.Dialer) or context.Context.Deadline (see ExchangeContext)
-	Timeout        time.Duration
-	DialTimeout    time.Duration     // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero
-	ReadTimeout    time.Duration     // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
-	WriteTimeout   time.Duration     // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
-	TsigSecret     map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
-	TsigProvider   TsigProvider      // An implementation of the TsigProvider interface. If defined it replaces TsigSecret and is used for all TSIG operations.
-	SingleInflight bool              // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass
-	group          singleflight
+	Timeout      time.Duration
+	DialTimeout  time.Duration     // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero
+	ReadTimeout  time.Duration     // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
+	WriteTimeout time.Duration     // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
+	TsigSecret   map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
+	TsigProvider TsigProvider      // An implementation of the TsigProvider interface. If defined it replaces TsigSecret and is used for all TSIG operations.
+
+	// SingleInflight previously serialised multiple concurrent queries for the
+	// same Qname, Qtype and Qclass to ensure only one would be in flight at a
+	// time.
+	//
+	// Deprecated: This is a no-op. Callers should implement their own in flight
+	// query caching if needed. See github.com/miekg/dns/issues/1449.
+	SingleInflight bool
 }
 }
 
 
 // Exchange performs a synchronous UDP query. It sends the message m to the address
 // Exchange performs a synchronous UDP query. It sends the message m to the address
@@ -82,6 +107,11 @@ func (c *Client) writeTimeout() time.Duration {
 
 
 // Dial connects to the address on the named network.
 // Dial connects to the address on the named network.
 func (c *Client) Dial(address string) (conn *Conn, err error) {
 func (c *Client) Dial(address string) (conn *Conn, err error) {
+	return c.DialContext(context.Background(), address)
+}
+
+// DialContext connects to the address on the named network, with a context.Context.
+func (c *Client) DialContext(ctx context.Context, address string) (conn *Conn, err error) {
 	// create a new dialer with the appropriate timeout
 	// create a new dialer with the appropriate timeout
 	var d net.Dialer
 	var d net.Dialer
 	if c.Dialer == nil {
 	if c.Dialer == nil {
@@ -101,9 +131,13 @@ func (c *Client) Dial(address string) (conn *Conn, err error) {
 	if useTLS {
 	if useTLS {
 		network = strings.TrimSuffix(network, "-tls")
 		network = strings.TrimSuffix(network, "-tls")
 
 
-		conn.Conn, err = tls.DialWithDialer(&d, network, address, c.TLSConfig)
+		tlsDialer := tls.Dialer{
+			NetDialer: &d,
+			Config:    c.TLSConfig,
+		}
+		conn.Conn, err = tlsDialer.DialContext(ctx, network, address)
 	} else {
 	} else {
-		conn.Conn, err = d.Dial(network, address)
+		conn.Conn, err = d.DialContext(ctx, network, address)
 	}
 	}
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
@@ -139,34 +173,23 @@ func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, er
 // ExchangeWithConn has the same behavior as Exchange, just with a predetermined connection
 // ExchangeWithConn has the same behavior as Exchange, just with a predetermined connection
 // that will be used instead of creating a new one.
 // that will be used instead of creating a new one.
 // Usage pattern with a *dns.Client:
 // Usage pattern with a *dns.Client:
+//
 //	c := new(dns.Client)
 //	c := new(dns.Client)
 //	// connection management logic goes here
 //	// connection management logic goes here
 //
 //
 //	conn := c.Dial(address)
 //	conn := c.Dial(address)
 //	in, rtt, err := c.ExchangeWithConn(message, conn)
 //	in, rtt, err := c.ExchangeWithConn(message, conn)
 //
 //
-//  This allows users of the library to implement their own connection management,
-//  as opposed to Exchange, which will always use new connections and incur the added overhead
-//  that entails when using "tcp" and especially "tcp-tls" clients.
+// This allows users of the library to implement their own connection management,
+// as opposed to Exchange, which will always use new connections and incur the added overhead
+// that entails when using "tcp" and especially "tcp-tls" clients.
 func (c *Client) ExchangeWithConn(m *Msg, conn *Conn) (r *Msg, rtt time.Duration, err error) {
 func (c *Client) ExchangeWithConn(m *Msg, conn *Conn) (r *Msg, rtt time.Duration, err error) {
-	if !c.SingleInflight {
-		return c.exchange(m, conn)
-	}
-
-	q := m.Question[0]
-	key := fmt.Sprintf("%s:%d:%d", q.Name, q.Qtype, q.Qclass)
-	r, rtt, err, shared := c.group.Do(key, func() (*Msg, time.Duration, error) {
-		return c.exchange(m, conn)
-	})
-	if r != nil && shared {
-		r = r.Copy()
-	}
-
-	return r, rtt, err
+	return c.ExchangeWithConnContext(context.Background(), m, conn)
 }
 }
 
 
-func (c *Client) exchange(m *Msg, co *Conn) (r *Msg, rtt time.Duration, err error) {
-
+// ExchangeWithConnContext has the same behaviour as ExchangeWithConn and
+// additionally obeys deadlines from the passed Context.
+func (c *Client) ExchangeWithConnContext(ctx context.Context, m *Msg, co *Conn) (r *Msg, rtt time.Duration, err error) {
 	opt := m.IsEdns0()
 	opt := m.IsEdns0()
 	// If EDNS0 is used use that for size.
 	// If EDNS0 is used use that for size.
 	if opt != nil && opt.UDPSize() >= MinMsgSize {
 	if opt != nil && opt.UDPSize() >= MinMsgSize {
@@ -177,16 +200,28 @@ func (c *Client) exchange(m *Msg, co *Conn) (r *Msg, rtt time.Duration, err erro
 		co.UDPSize = c.UDPSize
 		co.UDPSize = c.UDPSize
 	}
 	}
 
 
-	co.TsigSecret, co.TsigProvider = c.TsigSecret, c.TsigProvider
-	t := time.Now()
 	// write with the appropriate write timeout
 	// write with the appropriate write timeout
-	co.SetWriteDeadline(t.Add(c.getTimeoutForRequest(c.writeTimeout())))
+	t := time.Now()
+	writeDeadline := t.Add(c.getTimeoutForRequest(c.writeTimeout()))
+	readDeadline := t.Add(c.getTimeoutForRequest(c.readTimeout()))
+	if deadline, ok := ctx.Deadline(); ok {
+		if deadline.Before(writeDeadline) {
+			writeDeadline = deadline
+		}
+		if deadline.Before(readDeadline) {
+			readDeadline = deadline
+		}
+	}
+	co.SetWriteDeadline(writeDeadline)
+	co.SetReadDeadline(readDeadline)
+
+	co.TsigSecret, co.TsigProvider = c.TsigSecret, c.TsigProvider
+
 	if err = co.WriteMsg(m); err != nil {
 	if err = co.WriteMsg(m); err != nil {
 		return nil, 0, err
 		return nil, 0, err
 	}
 	}
 
 
-	co.SetReadDeadline(time.Now().Add(c.getTimeoutForRequest(c.readTimeout())))
-	if _, ok := co.Conn.(net.PacketConn); ok {
+	if isPacketConn(co.Conn) {
 		for {
 		for {
 			r, err = co.ReadMsg()
 			r, err = co.ReadMsg()
 			// Ignore replies with mismatched IDs because they might be
 			// Ignore replies with mismatched IDs because they might be
@@ -224,15 +259,8 @@ func (co *Conn) ReadMsg() (*Msg, error) {
 		return m, err
 		return m, err
 	}
 	}
 	if t := m.IsTsig(); t != nil {
 	if t := m.IsTsig(); t != nil {
-		if co.TsigProvider != nil {
-			err = tsigVerifyProvider(p, co.TsigProvider, co.tsigRequestMAC, false)
-		} else {
-			if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
-				return m, ErrSecret
-			}
-			// Need to work on the original message p, as that was used to calculate the tsig.
-			err = TsigVerify(p, co.TsigSecret[t.Hdr.Name], co.tsigRequestMAC, false)
-		}
+		// Need to work on the original message p, as that was used to calculate the tsig.
+		err = TsigVerifyWithProvider(p, co.tsigProvider(), co.tsigRequestMAC, false)
 	}
 	}
 	return m, err
 	return m, err
 }
 }
@@ -247,7 +275,7 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
 		err error
 		err error
 	)
 	)
 
 
-	if _, ok := co.Conn.(net.PacketConn); ok {
+	if isPacketConn(co.Conn) {
 		if co.UDPSize > MinMsgSize {
 		if co.UDPSize > MinMsgSize {
 			p = make([]byte, co.UDPSize)
 			p = make([]byte, co.UDPSize)
 		} else {
 		} else {
@@ -287,7 +315,7 @@ func (co *Conn) Read(p []byte) (n int, err error) {
 		return 0, ErrConnEmpty
 		return 0, ErrConnEmpty
 	}
 	}
 
 
-	if _, ok := co.Conn.(net.PacketConn); ok {
+	if isPacketConn(co.Conn) {
 		// UDP connection
 		// UDP connection
 		return co.Conn.Read(p)
 		return co.Conn.Read(p)
 	}
 	}
@@ -309,17 +337,8 @@ func (co *Conn) Read(p []byte) (n int, err error) {
 func (co *Conn) WriteMsg(m *Msg) (err error) {
 func (co *Conn) WriteMsg(m *Msg) (err error) {
 	var out []byte
 	var out []byte
 	if t := m.IsTsig(); t != nil {
 	if t := m.IsTsig(); t != nil {
-		mac := ""
-		if co.TsigProvider != nil {
-			out, mac, err = tsigGenerateProvider(m, co.TsigProvider, co.tsigRequestMAC, false)
-		} else {
-			if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
-				return ErrSecret
-			}
-			out, mac, err = TsigGenerate(m, co.TsigSecret[t.Hdr.Name], co.tsigRequestMAC, false)
-		}
-		// Set for the next read, although only used in zone transfers
-		co.tsigRequestMAC = mac
+		// Set tsigRequestMAC for the next read, although only used in zone transfers.
+		out, co.tsigRequestMAC, err = TsigGenerateWithProvider(m, co.tsigProvider(), co.tsigRequestMAC, false)
 	} else {
 	} else {
 		out, err = m.Pack()
 		out, err = m.Pack()
 	}
 	}
@@ -336,7 +355,7 @@ func (co *Conn) Write(p []byte) (int, error) {
 		return 0, &Error{err: "message too large"}
 		return 0, &Error{err: "message too large"}
 	}
 	}
 
 
-	if _, ok := co.Conn.(net.PacketConn); ok {
+	if isPacketConn(co.Conn) {
 		return co.Conn.Write(p)
 		return co.Conn.Write(p)
 	}
 	}
 
 
@@ -392,7 +411,6 @@ func ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, err error)
 //	co.WriteMsg(m)
 //	co.WriteMsg(m)
 //	in, _  := co.ReadMsg()
 //	in, _  := co.ReadMsg()
 //	co.Close()
 //	co.Close()
-//
 func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
 func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
 	println("dns: ExchangeConn: this function is deprecated")
 	println("dns: ExchangeConn: this function is deprecated")
 	co := new(Conn)
 	co := new(Conn)
@@ -435,15 +453,11 @@ func DialTimeoutWithTLS(network, address string, tlsConfig *tls.Config, timeout
 // context, if present. If there is both a context deadline and a configured
 // context, if present. If there is both a context deadline and a configured
 // timeout on the client, the earliest of the two takes effect.
 // timeout on the client, the earliest of the two takes effect.
 func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
 func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
-	var timeout time.Duration
-	if deadline, ok := ctx.Deadline(); !ok {
-		timeout = 0
-	} else {
-		timeout = time.Until(deadline)
+	conn, err := c.DialContext(ctx, a)
+	if err != nil {
+		return nil, 0, err
 	}
 	}
-	// not passing the context to the underlying calls, as the API does not support
-	// context. For timeouts you should set up Client.Dialer and call Client.Exchange.
-	// TODO(tmthrgd,miekg): this is a race condition.
-	c.Dialer = &net.Dialer{Timeout: timeout}
-	return c.Exchange(m, a)
+	defer conn.Close()
+
+	return c.ExchangeWithConnContext(ctx, m, conn)
 }
 }

+ 1 - 1
vendor/github.com/miekg/dns/clientconfig.go

@@ -68,7 +68,7 @@ func ClientConfigFromReader(resolvconf io.Reader) (*ClientConfig, error) {
 			}
 			}
 
 
 		case "search": // set search path to given servers
 		case "search": // set search path to given servers
-			c.Search = append([]string(nil), f[1:]...)
+			c.Search = cloneSlice(f[1:])
 
 
 		case "options": // magic options
 		case "options": // magic options
 			for _, s := range f[1:] {
 			for _, s := range f[1:] {

+ 34 - 25
vendor/github.com/miekg/dns/defaults.go

@@ -22,8 +22,7 @@ func (dns *Msg) SetReply(request *Msg) *Msg {
 	}
 	}
 	dns.Rcode = RcodeSuccess
 	dns.Rcode = RcodeSuccess
 	if len(request.Question) > 0 {
 	if len(request.Question) > 0 {
-		dns.Question = make([]Question, 1)
-		dns.Question[0] = request.Question[0]
+		dns.Question = []Question{request.Question[0]}
 	}
 	}
 	return dns
 	return dns
 }
 }
@@ -208,7 +207,7 @@ func IsDomainName(s string) (labels int, ok bool) {
 			}
 			}
 
 
 			// check for \DDD
 			// check for \DDD
-			if i+3 < len(s) && isDigit(s[i+1]) && isDigit(s[i+2]) && isDigit(s[i+3]) {
+			if isDDD(s[i+1:]) {
 				i += 3
 				i += 3
 				begin += 3
 				begin += 3
 			} else {
 			} else {
@@ -218,6 +217,11 @@ func IsDomainName(s string) (labels int, ok bool) {
 
 
 			wasDot = false
 			wasDot = false
 		case '.':
 		case '.':
+			if i == 0 && len(s) > 1 {
+				// leading dots are not legal except for the root zone
+				return labels, false
+			}
+
 			if wasDot {
 			if wasDot {
 				// two dots back to back is not legal
 				// two dots back to back is not legal
 				return labels, false
 				return labels, false
@@ -267,40 +271,39 @@ func IsMsg(buf []byte) error {
 
 
 // IsFqdn checks if a domain name is fully qualified.
 // IsFqdn checks if a domain name is fully qualified.
 func IsFqdn(s string) bool {
 func IsFqdn(s string) bool {
-	s2 := strings.TrimSuffix(s, ".")
-	if s == s2 {
+	// Check for (and remove) a trailing dot, returning if there isn't one.
+	if s == "" || s[len(s)-1] != '.' {
 		return false
 		return false
 	}
 	}
+	s = s[:len(s)-1]
+
+	// If we don't have an escape sequence before the final dot, we know it's
+	// fully qualified and can return here.
+	if s == "" || s[len(s)-1] != '\\' {
+		return true
+	}
 
 
-	i := strings.LastIndexFunc(s2, func(r rune) bool {
+	// Otherwise we have to check if the dot is escaped or not by checking if
+	// there are an odd or even number of escape sequences before the dot.
+	i := strings.LastIndexFunc(s, func(r rune) bool {
 		return r != '\\'
 		return r != '\\'
 	})
 	})
-
-	// Test whether we have an even number of escape sequences before
-	// the dot or none.
-	return (len(s2)-i)%2 != 0
+	return (len(s)-i)%2 != 0
 }
 }
 
 
-// IsRRset checks if a set of RRs is a valid RRset as defined by RFC 2181.
-// This means the RRs need to have the same type, name, and class. Returns true
-// if the RR set is valid, otherwise false.
+// IsRRset reports whether a set of RRs is a valid RRset as defined by RFC 2181.
+// This means the RRs need to have the same type, name, and class.
 func IsRRset(rrset []RR) bool {
 func IsRRset(rrset []RR) bool {
 	if len(rrset) == 0 {
 	if len(rrset) == 0 {
 		return false
 		return false
 	}
 	}
-	if len(rrset) == 1 {
-		return true
-	}
-	rrHeader := rrset[0].Header()
-	rrType := rrHeader.Rrtype
-	rrClass := rrHeader.Class
-	rrName := rrHeader.Name
 
 
+	baseH := rrset[0].Header()
 	for _, rr := range rrset[1:] {
 	for _, rr := range rrset[1:] {
-		curRRHeader := rr.Header()
-		if curRRHeader.Rrtype != rrType || curRRHeader.Class != rrClass || curRRHeader.Name != rrName {
+		curH := rr.Header()
+		if curH.Rrtype != baseH.Rrtype || curH.Class != baseH.Class || curH.Name != baseH.Name {
 			// Mismatch between the records, so this is not a valid rrset for
 			// Mismatch between the records, so this is not a valid rrset for
-			//signing/verifying
+			// signing/verifying
 			return false
 			return false
 		}
 		}
 	}
 	}
@@ -318,9 +321,15 @@ func Fqdn(s string) string {
 }
 }
 
 
 // CanonicalName returns the domain name in canonical form. A name in canonical
 // CanonicalName returns the domain name in canonical form. A name in canonical
-// form is lowercase and fully qualified. See Section 6.2 in RFC 4034.
+// form is lowercase and fully qualified. Only US-ASCII letters are affected. See
+// Section 6.2 in RFC 4034.
 func CanonicalName(s string) string {
 func CanonicalName(s string) string {
-	return strings.ToLower(Fqdn(s))
+	return strings.Map(func(r rune) rune {
+		if r >= 'A' && r <= 'Z' {
+			r += 'a' - 'A'
+		}
+		return r
+	}, Fqdn(s))
 }
 }
 
 
 // Copied from the official Go code.
 // Copied from the official Go code.

+ 21 - 41
vendor/github.com/miekg/dns/dnssec.go

@@ -65,6 +65,9 @@ var AlgorithmToString = map[uint8]string{
 }
 }
 
 
 // AlgorithmToHash is a map of algorithm crypto hash IDs to crypto.Hash's.
 // AlgorithmToHash is a map of algorithm crypto hash IDs to crypto.Hash's.
+// For newer algorithm that do their own hashing (i.e. ED25519) the returned value
+// is 0, implying no (external) hashing should occur. The non-exported identityHash is then
+// used.
 var AlgorithmToHash = map[uint8]crypto.Hash{
 var AlgorithmToHash = map[uint8]crypto.Hash{
 	RSAMD5:           crypto.MD5, // Deprecated in RFC 6725
 	RSAMD5:           crypto.MD5, // Deprecated in RFC 6725
 	DSA:              crypto.SHA1,
 	DSA:              crypto.SHA1,
@@ -74,7 +77,7 @@ var AlgorithmToHash = map[uint8]crypto.Hash{
 	ECDSAP256SHA256:  crypto.SHA256,
 	ECDSAP256SHA256:  crypto.SHA256,
 	ECDSAP384SHA384:  crypto.SHA384,
 	ECDSAP384SHA384:  crypto.SHA384,
 	RSASHA512:        crypto.SHA512,
 	RSASHA512:        crypto.SHA512,
-	ED25519:          crypto.Hash(0),
+	ED25519:          0,
 }
 }
 
 
 // DNSSEC hashing algorithm codes.
 // DNSSEC hashing algorithm codes.
@@ -125,10 +128,6 @@ type dnskeyWireFmt struct {
 	/* Nothing is left out */
 	/* Nothing is left out */
 }
 }
 
 
-func divRoundUp(a, b int) int {
-	return (a + b - 1) / b
-}
-
 // KeyTag calculates the keytag (or key-id) of the DNSKEY.
 // KeyTag calculates the keytag (or key-id) of the DNSKEY.
 func (k *DNSKEY) KeyTag() uint16 {
 func (k *DNSKEY) KeyTag() uint16 {
 	if k == nil {
 	if k == nil {
@@ -137,12 +136,12 @@ func (k *DNSKEY) KeyTag() uint16 {
 	var keytag int
 	var keytag int
 	switch k.Algorithm {
 	switch k.Algorithm {
 	case RSAMD5:
 	case RSAMD5:
-		// Look at the bottom two bytes of the modules, which the last
-		// item in the pubkey.
 		// This algorithm has been deprecated, but keep this key-tag calculation.
 		// This algorithm has been deprecated, but keep this key-tag calculation.
+		// Look at the bottom two bytes of the modules, which the last item in the pubkey.
+		// See https://www.rfc-editor.org/errata/eid193 .
 		modulus, _ := fromBase64([]byte(k.PublicKey))
 		modulus, _ := fromBase64([]byte(k.PublicKey))
 		if len(modulus) > 1 {
 		if len(modulus) > 1 {
-			x := binary.BigEndian.Uint16(modulus[len(modulus)-2:])
+			x := binary.BigEndian.Uint16(modulus[len(modulus)-3:])
 			keytag = int(x)
 			keytag = int(x)
 		}
 		}
 	default:
 	default:
@@ -296,35 +295,20 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
 		return err
 		return err
 	}
 	}
 
 
-	hash, ok := AlgorithmToHash[rr.Algorithm]
-	if !ok {
-		return ErrAlg
+	h, cryptohash, err := hashFromAlgorithm(rr.Algorithm)
+	if err != nil {
+		return err
 	}
 	}
 
 
 	switch rr.Algorithm {
 	switch rr.Algorithm {
-	case ED25519:
-		// ed25519 signs the raw message and performs hashing internally.
-		// All other supported signature schemes operate over the pre-hashed
-		// message, and thus ed25519 must be handled separately here.
-		//
-		// The raw message is passed directly into sign and crypto.Hash(0) is
-		// used to signal to the crypto.Signer that the data has not been hashed.
-		signature, err := sign(k, append(signdata, wire...), crypto.Hash(0), rr.Algorithm)
-		if err != nil {
-			return err
-		}
-
-		rr.Signature = toBase64(signature)
-		return nil
 	case RSAMD5, DSA, DSANSEC3SHA1:
 	case RSAMD5, DSA, DSANSEC3SHA1:
 		// See RFC 6944.
 		// See RFC 6944.
 		return ErrAlg
 		return ErrAlg
 	default:
 	default:
-		h := hash.New()
 		h.Write(signdata)
 		h.Write(signdata)
 		h.Write(wire)
 		h.Write(wire)
 
 
-		signature, err := sign(k, h.Sum(nil), hash, rr.Algorithm)
+		signature, err := sign(k, h.Sum(nil), cryptohash, rr.Algorithm)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
@@ -341,7 +325,7 @@ func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte,
 	}
 	}
 
 
 	switch alg {
 	switch alg {
-	case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512:
+	case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512, ED25519:
 		return signature, nil
 		return signature, nil
 	case ECDSAP256SHA256, ECDSAP384SHA384:
 	case ECDSAP256SHA256, ECDSAP384SHA384:
 		ecdsaSignature := &struct {
 		ecdsaSignature := &struct {
@@ -362,8 +346,6 @@ func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte,
 		signature := intToBytes(ecdsaSignature.R, intlen)
 		signature := intToBytes(ecdsaSignature.R, intlen)
 		signature = append(signature, intToBytes(ecdsaSignature.S, intlen)...)
 		signature = append(signature, intToBytes(ecdsaSignature.S, intlen)...)
 		return signature, nil
 		return signature, nil
-	case ED25519:
-		return signature, nil
 	default:
 	default:
 		return nil, ErrAlg
 		return nil, ErrAlg
 	}
 	}
@@ -431,15 +413,15 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
 		return err
 		return err
 	}
 	}
 
 
-	sigbuf := rr.sigBuf()           // Get the binary signature data
-	if rr.Algorithm == PRIVATEDNS { // PRIVATEOID
-		// TODO(miek)
-		// remove the domain name and assume its ours?
-	}
+	sigbuf := rr.sigBuf() // Get the binary signature data
+	// TODO(miek)
+	// remove the domain name and assume its ours?
+	// if rr.Algorithm == PRIVATEDNS { // PRIVATEOID
+	// }
 
 
-	hash, ok := AlgorithmToHash[rr.Algorithm]
-	if !ok {
-		return ErrAlg
+	h, cryptohash, err := hashFromAlgorithm(rr.Algorithm)
+	if err != nil {
+		return err
 	}
 	}
 
 
 	switch rr.Algorithm {
 	switch rr.Algorithm {
@@ -450,10 +432,9 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
 			return ErrKey
 			return ErrKey
 		}
 		}
 
 
-		h := hash.New()
 		h.Write(signeddata)
 		h.Write(signeddata)
 		h.Write(wire)
 		h.Write(wire)
-		return rsa.VerifyPKCS1v15(pubkey, hash, h.Sum(nil), sigbuf)
+		return rsa.VerifyPKCS1v15(pubkey, cryptohash, h.Sum(nil), sigbuf)
 
 
 	case ECDSAP256SHA256, ECDSAP384SHA384:
 	case ECDSAP256SHA256, ECDSAP384SHA384:
 		pubkey := k.publicKeyECDSA()
 		pubkey := k.publicKeyECDSA()
@@ -465,7 +446,6 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
 		r := new(big.Int).SetBytes(sigbuf[:len(sigbuf)/2])
 		r := new(big.Int).SetBytes(sigbuf[:len(sigbuf)/2])
 		s := new(big.Int).SetBytes(sigbuf[len(sigbuf)/2:])
 		s := new(big.Int).SetBytes(sigbuf[len(sigbuf)/2:])
 
 
-		h := hash.New()
 		h.Write(signeddata)
 		h.Write(signeddata)
 		h.Write(wire)
 		h.Write(wire)
 		if ecdsa.Verify(pubkey, h.Sum(nil), r, s) {
 		if ecdsa.Verify(pubkey, h.Sum(nil), r, s) {

+ 2 - 1
vendor/github.com/miekg/dns/dnssec_keyscan.go

@@ -37,7 +37,8 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, er
 		return nil, ErrPrivKey
 		return nil, ErrPrivKey
 	}
 	}
 	// TODO(mg): check if the pubkey matches the private key
 	// TODO(mg): check if the pubkey matches the private key
-	algo, err := strconv.ParseUint(strings.SplitN(m["algorithm"], " ", 2)[0], 10, 8)
+	algoStr, _, _ := strings.Cut(m["algorithm"], " ")
+	algo, err := strconv.ParseUint(algoStr, 10, 8)
 	if err != nil {
 	if err != nil {
 		return nil, ErrPrivKey
 		return nil, ErrPrivKey
 	}
 	}

+ 44 - 44
vendor/github.com/miekg/dns/doc.go

@@ -13,28 +13,28 @@ names in a message will result in a packing failure.
 Resource records are native types. They are not stored in wire format. Basic
 Resource records are native types. They are not stored in wire format. Basic
 usage pattern for creating a new resource record:
 usage pattern for creating a new resource record:
 
 
-     r := new(dns.MX)
-     r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX, Class: dns.ClassINET, Ttl: 3600}
-     r.Preference = 10
-     r.Mx = "mx.miek.nl."
+	r := new(dns.MX)
+	r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX, Class: dns.ClassINET, Ttl: 3600}
+	r.Preference = 10
+	r.Mx = "mx.miek.nl."
 
 
 Or directly from a string:
 Or directly from a string:
 
 
-     mx, err := dns.NewRR("miek.nl. 3600 IN MX 10 mx.miek.nl.")
+	mx, err := dns.NewRR("miek.nl. 3600 IN MX 10 mx.miek.nl.")
 
 
 Or when the default origin (.) and TTL (3600) and class (IN) suit you:
 Or when the default origin (.) and TTL (3600) and class (IN) suit you:
 
 
-     mx, err := dns.NewRR("miek.nl MX 10 mx.miek.nl")
+	mx, err := dns.NewRR("miek.nl MX 10 mx.miek.nl")
 
 
 Or even:
 Or even:
 
 
-     mx, err := dns.NewRR("$ORIGIN nl.\nmiek 1H IN MX 10 mx.miek")
+	mx, err := dns.NewRR("$ORIGIN nl.\nmiek 1H IN MX 10 mx.miek")
 
 
 In the DNS messages are exchanged, these messages contain resource records
 In the DNS messages are exchanged, these messages contain resource records
 (sets). Use pattern for creating a message:
 (sets). Use pattern for creating a message:
 
 
-     m := new(dns.Msg)
-     m.SetQuestion("miek.nl.", dns.TypeMX)
+	m := new(dns.Msg)
+	m.SetQuestion("miek.nl.", dns.TypeMX)
 
 
 Or when not certain if the domain name is fully qualified:
 Or when not certain if the domain name is fully qualified:
 
 
@@ -45,17 +45,17 @@ records for the miek.nl. zone.
 
 
 The following is slightly more verbose, but more flexible:
 The following is slightly more verbose, but more flexible:
 
 
-     m1 := new(dns.Msg)
-     m1.Id = dns.Id()
-     m1.RecursionDesired = true
-     m1.Question = make([]dns.Question, 1)
-     m1.Question[0] = dns.Question{"miek.nl.", dns.TypeMX, dns.ClassINET}
+	m1 := new(dns.Msg)
+	m1.Id = dns.Id()
+	m1.RecursionDesired = true
+	m1.Question = make([]dns.Question, 1)
+	m1.Question[0] = dns.Question{"miek.nl.", dns.TypeMX, dns.ClassINET}
 
 
 After creating a message it can be sent. Basic use pattern for synchronous
 After creating a message it can be sent. Basic use pattern for synchronous
 querying the DNS at a server configured on 127.0.0.1 and port 53:
 querying the DNS at a server configured on 127.0.0.1 and port 53:
 
 
-     c := new(dns.Client)
-     in, rtt, err := c.Exchange(m1, "127.0.0.1:53")
+	c := new(dns.Client)
+	in, rtt, err := c.Exchange(m1, "127.0.0.1:53")
 
 
 Suppressing multiple outstanding queries (with the same question, type and
 Suppressing multiple outstanding queries (with the same question, type and
 class) is as easy as setting:
 class) is as easy as setting:
@@ -72,7 +72,7 @@ and port to use for the connection:
 		Port: 12345,
 		Port: 12345,
 		Zone: "",
 		Zone: "",
 	}
 	}
-	c.Dialer := &net.Dialer{
+	c.Dialer = &net.Dialer{
 		Timeout: 200 * time.Millisecond,
 		Timeout: 200 * time.Millisecond,
 		LocalAddr: &laddr,
 		LocalAddr: &laddr,
 	}
 	}
@@ -96,7 +96,7 @@ the Answer section:
 		// do something with t.Txt
 		// do something with t.Txt
 	}
 	}
 
 
-Domain Name and TXT Character String Representations
+# Domain Name and TXT Character String Representations
 
 
 Both domain names and TXT character strings are converted to presentation form
 Both domain names and TXT character strings are converted to presentation form
 both when unpacked and when converted to strings.
 both when unpacked and when converted to strings.
@@ -108,7 +108,7 @@ be escaped. Bytes below 32 and above 127 will be converted to \DDD form.
 For domain names, in addition to the above rules brackets, periods, spaces,
 For domain names, in addition to the above rules brackets, periods, spaces,
 semicolons and the at symbol are escaped.
 semicolons and the at symbol are escaped.
 
 
-DNSSEC
+# DNSSEC
 
 
 DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It uses
 DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It uses
 public key cryptography to sign resource records. The public keys are stored in
 public key cryptography to sign resource records. The public keys are stored in
@@ -117,12 +117,12 @@ DNSKEY records and the signatures in RRSIG records.
 Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK)
 Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK)
 bit to a request.
 bit to a request.
 
 
-     m := new(dns.Msg)
-     m.SetEdns0(4096, true)
+	m := new(dns.Msg)
+	m.SetEdns0(4096, true)
 
 
 Signature generation, signature verification and key generation are all supported.
 Signature generation, signature verification and key generation are all supported.
 
 
-DYNAMIC UPDATES
+# DYNAMIC UPDATES
 
 
 Dynamic updates reuses the DNS message format, but renames three of the
 Dynamic updates reuses the DNS message format, but renames three of the
 sections. Question is Zone, Answer is Prerequisite, Authority is Update, only
 sections. Question is Zone, Answer is Prerequisite, Authority is Update, only
@@ -133,30 +133,30 @@ certain resource records or names in a zone to specify if resource records
 should be added or removed. The table from RFC 2136 supplemented with the Go
 should be added or removed. The table from RFC 2136 supplemented with the Go
 DNS function shows which functions exist to specify the prerequisites.
 DNS function shows which functions exist to specify the prerequisites.
 
 
- 3.2.4 - Table Of Metavalues Used In Prerequisite Section
+	3.2.4 - Table Of Metavalues Used In Prerequisite Section
 
 
-  CLASS    TYPE     RDATA    Meaning                    Function
-  --------------------------------------------------------------
-  ANY      ANY      empty    Name is in use             dns.NameUsed
-  ANY      rrset    empty    RRset exists (value indep) dns.RRsetUsed
-  NONE     ANY      empty    Name is not in use         dns.NameNotUsed
-  NONE     rrset    empty    RRset does not exist       dns.RRsetNotUsed
-  zone     rrset    rr       RRset exists (value dep)   dns.Used
+	 CLASS    TYPE     RDATA    Meaning                    Function
+	 --------------------------------------------------------------
+	 ANY      ANY      empty    Name is in use             dns.NameUsed
+	 ANY      rrset    empty    RRset exists (value indep) dns.RRsetUsed
+	 NONE     ANY      empty    Name is not in use         dns.NameNotUsed
+	 NONE     rrset    empty    RRset does not exist       dns.RRsetNotUsed
+	 zone     rrset    rr       RRset exists (value dep)   dns.Used
 
 
 The prerequisite section can also be left empty. If you have decided on the
 The prerequisite section can also be left empty. If you have decided on the
 prerequisites you can tell what RRs should be added or deleted. The next table
 prerequisites you can tell what RRs should be added or deleted. The next table
 shows the options you have and what functions to call.
 shows the options you have and what functions to call.
 
 
- 3.4.2.6 - Table Of Metavalues Used In Update Section
+	3.4.2.6 - Table Of Metavalues Used In Update Section
 
 
-  CLASS    TYPE     RDATA    Meaning                     Function
-  ---------------------------------------------------------------
-  ANY      ANY      empty    Delete all RRsets from name dns.RemoveName
-  ANY      rrset    empty    Delete an RRset             dns.RemoveRRset
-  NONE     rrset    rr       Delete an RR from RRset     dns.Remove
-  zone     rrset    rr       Add to an RRset             dns.Insert
+	 CLASS    TYPE     RDATA    Meaning                     Function
+	 ---------------------------------------------------------------
+	 ANY      ANY      empty    Delete all RRsets from name dns.RemoveName
+	 ANY      rrset    empty    Delete an RRset             dns.RemoveRRset
+	 NONE     rrset    rr       Delete an RR from RRset     dns.Remove
+	 zone     rrset    rr       Add to an RRset             dns.Insert
 
 
-TRANSACTION SIGNATURE
+# TRANSACTION SIGNATURE
 
 
 An TSIG or transaction signature adds a HMAC TSIG record to each message sent.
 An TSIG or transaction signature adds a HMAC TSIG record to each message sent.
 The supported algorithms include: HmacSHA1, HmacSHA256 and HmacSHA512.
 The supported algorithms include: HmacSHA1, HmacSHA256 and HmacSHA512.
@@ -239,7 +239,7 @@ Basic use pattern validating and replying to a message that has TSIG set.
 		w.WriteMsg(m)
 		w.WriteMsg(m)
 	}
 	}
 
 
-PRIVATE RRS
+# PRIVATE RRS
 
 
 RFC 6895 sets aside a range of type codes for private use. This range is 65,280
 RFC 6895 sets aside a range of type codes for private use. This range is 65,280
 - 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these
 - 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these
@@ -248,10 +248,10 @@ can be used, before requesting an official type code from IANA.
 See https://miek.nl/2014/september/21/idn-and-private-rr-in-go-dns/ for more
 See https://miek.nl/2014/september/21/idn-and-private-rr-in-go-dns/ for more
 information.
 information.
 
 
-EDNS0
+# EDNS0
 
 
 EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated by
 EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated by
-RFC 6891. It defines an new RR type, the OPT RR, which is then completely
+RFC 6891. It defines a new RR type, the OPT RR, which is then completely
 abused.
 abused.
 
 
 Basic use pattern for creating an (empty) OPT RR:
 Basic use pattern for creating an (empty) OPT RR:
@@ -279,9 +279,9 @@ SIG(0)
 
 
 From RFC 2931:
 From RFC 2931:
 
 
-    SIG(0) provides protection for DNS transactions and requests ....
-    ... protection for glue records, DNS requests, protection for message headers
-    on requests and responses, and protection of the overall integrity of a response.
+	SIG(0) provides protection for DNS transactions and requests ....
+	... protection for glue records, DNS requests, protection for message headers
+	on requests and responses, and protection of the overall integrity of a response.
 
 
 It works like TSIG, except that SIG(0) uses public key cryptography, instead of
 It works like TSIG, except that SIG(0) uses public key cryptography, instead of
 the shared secret approach in TSIG. Supported algorithms: ECDSAP256SHA256,
 the shared secret approach in TSIG. Supported algorithms: ECDSAP256SHA256,

+ 88 - 65
vendor/github.com/miekg/dns/edns.go

@@ -14,6 +14,7 @@ const (
 	EDNS0LLQ          = 0x1     // long lived queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
 	EDNS0LLQ          = 0x1     // long lived queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
 	EDNS0UL           = 0x2     // update lease draft: http://files.dns-sd.org/draft-sekar-dns-ul.txt
 	EDNS0UL           = 0x2     // update lease draft: http://files.dns-sd.org/draft-sekar-dns-ul.txt
 	EDNS0NSID         = 0x3     // nsid (See RFC 5001)
 	EDNS0NSID         = 0x3     // nsid (See RFC 5001)
+	EDNS0ESU          = 0x4     // ENUM Source-URI draft: https://datatracker.ietf.org/doc/html/draft-kaplan-enum-source-uri-00
 	EDNS0DAU          = 0x5     // DNSSEC Algorithm Understood
 	EDNS0DAU          = 0x5     // DNSSEC Algorithm Understood
 	EDNS0DHU          = 0x6     // DS Hash Understood
 	EDNS0DHU          = 0x6     // DS Hash Understood
 	EDNS0N3U          = 0x7     // NSEC3 Hash Understood
 	EDNS0N3U          = 0x7     // NSEC3 Hash Understood
@@ -56,6 +57,8 @@ func makeDataOpt(code uint16) EDNS0 {
 		return new(EDNS0_PADDING)
 		return new(EDNS0_PADDING)
 	case EDNS0EDE:
 	case EDNS0EDE:
 		return new(EDNS0_EDE)
 		return new(EDNS0_EDE)
+	case EDNS0ESU:
+		return &EDNS0_ESU{Code: EDNS0ESU}
 	default:
 	default:
 		e := new(EDNS0_LOCAL)
 		e := new(EDNS0_LOCAL)
 		e.Code = code
 		e.Code = code
@@ -75,7 +78,10 @@ func (rr *OPT) String() string {
 	if rr.Do() {
 	if rr.Do() {
 		s += "flags: do; "
 		s += "flags: do; "
 	} else {
 	} else {
-		s += "flags: ; "
+		s += "flags:; "
+	}
+	if rr.Hdr.Ttl&0x7FFF != 0 {
+		s += fmt.Sprintf("MBZ: 0x%04x, ", rr.Hdr.Ttl&0x7FFF)
 	}
 	}
 	s += "udp: " + strconv.Itoa(int(rr.UDPSize()))
 	s += "udp: " + strconv.Itoa(int(rr.UDPSize()))
 
 
@@ -95,6 +101,10 @@ func (rr *OPT) String() string {
 			s += "\n; SUBNET: " + o.String()
 			s += "\n; SUBNET: " + o.String()
 		case *EDNS0_COOKIE:
 		case *EDNS0_COOKIE:
 			s += "\n; COOKIE: " + o.String()
 			s += "\n; COOKIE: " + o.String()
+		case *EDNS0_EXPIRE:
+			s += "\n; EXPIRE: " + o.String()
+		case *EDNS0_TCP_KEEPALIVE:
+			s += "\n; KEEPALIVE: " + o.String()
 		case *EDNS0_UL:
 		case *EDNS0_UL:
 			s += "\n; UPDATE LEASE: " + o.String()
 			s += "\n; UPDATE LEASE: " + o.String()
 		case *EDNS0_LLQ:
 		case *EDNS0_LLQ:
@@ -111,6 +121,8 @@ func (rr *OPT) String() string {
 			s += "\n; PADDING: " + o.String()
 			s += "\n; PADDING: " + o.String()
 		case *EDNS0_EDE:
 		case *EDNS0_EDE:
 			s += "\n; EDE: " + o.String()
 			s += "\n; EDE: " + o.String()
+		case *EDNS0_ESU:
+			s += "\n; ESU: " + o.String()
 		}
 		}
 	}
 	}
 	return s
 	return s
@@ -173,7 +185,7 @@ func (rr *OPT) Do() bool {
 
 
 // SetDo sets the DO (DNSSEC OK) bit.
 // SetDo sets the DO (DNSSEC OK) bit.
 // If we pass an argument, set the DO bit to that value.
 // If we pass an argument, set the DO bit to that value.
-// It is possible to pass 2 or more arguments. Any arguments after the 1st is silently ignored.
+// It is possible to pass 2 or more arguments, but they will be ignored.
 func (rr *OPT) SetDo(do ...bool) {
 func (rr *OPT) SetDo(do ...bool) {
 	if len(do) == 1 {
 	if len(do) == 1 {
 		if do[0] {
 		if do[0] {
@@ -251,7 +263,7 @@ func (e *EDNS0_NSID) copy() EDNS0           { return &EDNS0_NSID{e.Code, e.Nsid}
 //	o.Hdr.Name = "."
 //	o.Hdr.Name = "."
 //	o.Hdr.Rrtype = dns.TypeOPT
 //	o.Hdr.Rrtype = dns.TypeOPT
 //	e := new(dns.EDNS0_SUBNET)
 //	e := new(dns.EDNS0_SUBNET)
-//	e.Code = dns.EDNS0SUBNET
+//	e.Code = dns.EDNS0SUBNET // by default this is filled in through unpacking OPT packets (unpackDataOpt)
 //	e.Family = 1	// 1 for IPv4 source address, 2 for IPv6
 //	e.Family = 1	// 1 for IPv4 source address, 2 for IPv6
 //	e.SourceNetmask = 32	// 32 for IPV4, 128 for IPv6
 //	e.SourceNetmask = 32	// 32 for IPV4, 128 for IPv6
 //	e.SourceScope = 0
 //	e.SourceScope = 0
@@ -496,6 +508,7 @@ func (e *EDNS0_LLQ) String() string {
 		" " + strconv.FormatUint(uint64(e.LeaseLife), 10)
 		" " + strconv.FormatUint(uint64(e.LeaseLife), 10)
 	return s
 	return s
 }
 }
+
 func (e *EDNS0_LLQ) copy() EDNS0 {
 func (e *EDNS0_LLQ) copy() EDNS0 {
 	return &EDNS0_LLQ{e.Code, e.Version, e.Opcode, e.Error, e.Id, e.LeaseLife}
 	return &EDNS0_LLQ{e.Code, e.Version, e.Opcode, e.Error, e.Id, e.LeaseLife}
 }
 }
@@ -508,8 +521,8 @@ type EDNS0_DAU struct {
 
 
 // Option implements the EDNS0 interface.
 // Option implements the EDNS0 interface.
 func (e *EDNS0_DAU) Option() uint16        { return EDNS0DAU }
 func (e *EDNS0_DAU) Option() uint16        { return EDNS0DAU }
-func (e *EDNS0_DAU) pack() ([]byte, error) { return e.AlgCode, nil }
-func (e *EDNS0_DAU) unpack(b []byte) error { e.AlgCode = b; return nil }
+func (e *EDNS0_DAU) pack() ([]byte, error) { return cloneSlice(e.AlgCode), nil }
+func (e *EDNS0_DAU) unpack(b []byte) error { e.AlgCode = cloneSlice(b); return nil }
 
 
 func (e *EDNS0_DAU) String() string {
 func (e *EDNS0_DAU) String() string {
 	s := ""
 	s := ""
@@ -532,8 +545,8 @@ type EDNS0_DHU struct {
 
 
 // Option implements the EDNS0 interface.
 // Option implements the EDNS0 interface.
 func (e *EDNS0_DHU) Option() uint16        { return EDNS0DHU }
 func (e *EDNS0_DHU) Option() uint16        { return EDNS0DHU }
-func (e *EDNS0_DHU) pack() ([]byte, error) { return e.AlgCode, nil }
-func (e *EDNS0_DHU) unpack(b []byte) error { e.AlgCode = b; return nil }
+func (e *EDNS0_DHU) pack() ([]byte, error) { return cloneSlice(e.AlgCode), nil }
+func (e *EDNS0_DHU) unpack(b []byte) error { e.AlgCode = cloneSlice(b); return nil }
 
 
 func (e *EDNS0_DHU) String() string {
 func (e *EDNS0_DHU) String() string {
 	s := ""
 	s := ""
@@ -556,8 +569,8 @@ type EDNS0_N3U struct {
 
 
 // Option implements the EDNS0 interface.
 // Option implements the EDNS0 interface.
 func (e *EDNS0_N3U) Option() uint16        { return EDNS0N3U }
 func (e *EDNS0_N3U) Option() uint16        { return EDNS0N3U }
-func (e *EDNS0_N3U) pack() ([]byte, error) { return e.AlgCode, nil }
-func (e *EDNS0_N3U) unpack(b []byte) error { e.AlgCode = b; return nil }
+func (e *EDNS0_N3U) pack() ([]byte, error) { return cloneSlice(e.AlgCode), nil }
+func (e *EDNS0_N3U) unpack(b []byte) error { e.AlgCode = cloneSlice(b); return nil }
 
 
 func (e *EDNS0_N3U) String() string {
 func (e *EDNS0_N3U) String() string {
 	// Re-use the hash map
 	// Re-use the hash map
@@ -577,14 +590,17 @@ func (e *EDNS0_N3U) copy() EDNS0 { return &EDNS0_N3U{e.Code, e.AlgCode} }
 type EDNS0_EXPIRE struct {
 type EDNS0_EXPIRE struct {
 	Code   uint16 // Always EDNS0EXPIRE
 	Code   uint16 // Always EDNS0EXPIRE
 	Expire uint32
 	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.
 }
 }
 
 
 // Option implements the EDNS0 interface.
 // Option implements the EDNS0 interface.
 func (e *EDNS0_EXPIRE) Option() uint16 { return EDNS0EXPIRE }
 func (e *EDNS0_EXPIRE) Option() uint16 { return EDNS0EXPIRE }
-func (e *EDNS0_EXPIRE) String() string { return strconv.FormatUint(uint64(e.Expire), 10) }
-func (e *EDNS0_EXPIRE) copy() EDNS0    { return &EDNS0_EXPIRE{e.Code, e.Expire} }
+func (e *EDNS0_EXPIRE) copy() EDNS0    { return &EDNS0_EXPIRE{e.Code, e.Expire, e.Empty} }
 
 
 func (e *EDNS0_EXPIRE) pack() ([]byte, error) {
 func (e *EDNS0_EXPIRE) pack() ([]byte, error) {
+	if e.Empty {
+		return []byte{}, nil
+	}
 	b := make([]byte, 4)
 	b := make([]byte, 4)
 	binary.BigEndian.PutUint32(b, e.Expire)
 	binary.BigEndian.PutUint32(b, e.Expire)
 	return b, nil
 	return b, nil
@@ -593,15 +609,24 @@ func (e *EDNS0_EXPIRE) pack() ([]byte, error) {
 func (e *EDNS0_EXPIRE) unpack(b []byte) error {
 func (e *EDNS0_EXPIRE) unpack(b []byte) error {
 	if len(b) == 0 {
 	if len(b) == 0 {
 		// zero-length EXPIRE query, see RFC 7314 Section 2
 		// zero-length EXPIRE query, see RFC 7314 Section 2
+		e.Empty = true
 		return nil
 		return nil
 	}
 	}
 	if len(b) < 4 {
 	if len(b) < 4 {
 		return ErrBuf
 		return ErrBuf
 	}
 	}
 	e.Expire = binary.BigEndian.Uint32(b)
 	e.Expire = binary.BigEndian.Uint32(b)
+	e.Empty = false
 	return nil
 	return nil
 }
 }
 
 
+func (e *EDNS0_EXPIRE) String() (s string) {
+	if e.Empty {
+		return ""
+	}
+	return strconv.FormatUint(uint64(e.Expire), 10)
+}
+
 // The EDNS0_LOCAL option is used for local/experimental purposes. The option
 // The EDNS0_LOCAL option is used for local/experimental purposes. The option
 // code is recommended to be within the range [EDNS0LOCALSTART, EDNS0LOCALEND]
 // code is recommended to be within the range [EDNS0LOCALSTART, EDNS0LOCALEND]
 // (RFC6891), although any unassigned code can actually be used.  The content of
 // (RFC6891), although any unassigned code can actually be used.  The content of
@@ -622,87 +647,73 @@ type EDNS0_LOCAL struct {
 
 
 // Option implements the EDNS0 interface.
 // Option implements the EDNS0 interface.
 func (e *EDNS0_LOCAL) Option() uint16 { return e.Code }
 func (e *EDNS0_LOCAL) Option() uint16 { return e.Code }
+
 func (e *EDNS0_LOCAL) String() string {
 func (e *EDNS0_LOCAL) String() string {
 	return strconv.FormatInt(int64(e.Code), 10) + ":0x" + hex.EncodeToString(e.Data)
 	return strconv.FormatInt(int64(e.Code), 10) + ":0x" + hex.EncodeToString(e.Data)
 }
 }
+
 func (e *EDNS0_LOCAL) copy() EDNS0 {
 func (e *EDNS0_LOCAL) copy() EDNS0 {
-	b := make([]byte, len(e.Data))
-	copy(b, e.Data)
-	return &EDNS0_LOCAL{e.Code, b}
+	return &EDNS0_LOCAL{e.Code, cloneSlice(e.Data)}
 }
 }
 
 
 func (e *EDNS0_LOCAL) pack() ([]byte, error) {
 func (e *EDNS0_LOCAL) pack() ([]byte, error) {
-	b := make([]byte, len(e.Data))
-	copied := copy(b, e.Data)
-	if copied != len(e.Data) {
-		return nil, ErrBuf
-	}
-	return b, nil
+	return cloneSlice(e.Data), nil
 }
 }
 
 
 func (e *EDNS0_LOCAL) unpack(b []byte) error {
 func (e *EDNS0_LOCAL) unpack(b []byte) error {
-	e.Data = make([]byte, len(b))
-	copied := copy(e.Data, b)
-	if copied != len(b) {
-		return ErrBuf
-	}
+	e.Data = cloneSlice(b)
 	return nil
 	return nil
 }
 }
 
 
 // EDNS0_TCP_KEEPALIVE is an EDNS0 option that instructs the server to keep
 // EDNS0_TCP_KEEPALIVE is an EDNS0 option that instructs the server to keep
 // the TCP connection alive. See RFC 7828.
 // the TCP connection alive. See RFC 7828.
 type EDNS0_TCP_KEEPALIVE struct {
 type EDNS0_TCP_KEEPALIVE struct {
-	Code    uint16 // Always EDNSTCPKEEPALIVE
-	Length  uint16 // the value 0 if the TIMEOUT is omitted, the value 2 if it is present;
-	Timeout uint16 // an idle timeout value for the TCP connection, specified in units of 100 milliseconds, encoded in network byte order.
+	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,
+	// pack will return a nil slice.
+	Timeout uint16
+
+	// Length is the option's length.
+	// Deprecated: this field is deprecated and is always equal to 0.
+	Length uint16
 }
 }
 
 
 // Option implements the EDNS0 interface.
 // Option implements the EDNS0 interface.
 func (e *EDNS0_TCP_KEEPALIVE) Option() uint16 { return EDNS0TCPKEEPALIVE }
 func (e *EDNS0_TCP_KEEPALIVE) Option() uint16 { return EDNS0TCPKEEPALIVE }
 
 
 func (e *EDNS0_TCP_KEEPALIVE) pack() ([]byte, error) {
 func (e *EDNS0_TCP_KEEPALIVE) pack() ([]byte, error) {
-	if e.Timeout != 0 && e.Length != 2 {
-		return nil, errors.New("dns: timeout specified but length is not 2")
-	}
-	if e.Timeout == 0 && e.Length != 0 {
-		return nil, errors.New("dns: timeout not specified but length is not 0")
+	if e.Timeout > 0 {
+		b := make([]byte, 2)
+		binary.BigEndian.PutUint16(b, e.Timeout)
+		return b, nil
 	}
 	}
-	b := make([]byte, 4+e.Length)
-	binary.BigEndian.PutUint16(b[0:], e.Code)
-	binary.BigEndian.PutUint16(b[2:], e.Length)
-	if e.Length == 2 {
-		binary.BigEndian.PutUint16(b[4:], e.Timeout)
-	}
-	return b, nil
+	return nil, nil
 }
 }
 
 
 func (e *EDNS0_TCP_KEEPALIVE) unpack(b []byte) error {
 func (e *EDNS0_TCP_KEEPALIVE) unpack(b []byte) error {
-	if len(b) < 4 {
-		return ErrBuf
-	}
-	e.Length = binary.BigEndian.Uint16(b[2:4])
-	if e.Length != 0 && e.Length != 2 {
-		return errors.New("dns: length mismatch, want 0/2 but got " + strconv.FormatUint(uint64(e.Length), 10))
-	}
-	if e.Length == 2 {
-		if len(b) < 6 {
-			return ErrBuf
-		}
-		e.Timeout = binary.BigEndian.Uint16(b[4:6])
+	switch len(b) {
+	case 0:
+	case 2:
+		e.Timeout = binary.BigEndian.Uint16(b)
+	default:
+		return fmt.Errorf("dns: length mismatch, want 0/2 but got %d", len(b))
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (e *EDNS0_TCP_KEEPALIVE) String() (s string) {
-	s = "use tcp keep-alive"
-	if e.Length == 0 {
+func (e *EDNS0_TCP_KEEPALIVE) String() string {
+	s := "use tcp keep-alive"
+	if e.Timeout == 0 {
 		s += ", timeout omitted"
 		s += ", timeout omitted"
 	} else {
 	} else {
 		s += fmt.Sprintf(", timeout %dms", e.Timeout*100)
 		s += fmt.Sprintf(", timeout %dms", e.Timeout*100)
 	}
 	}
-	return
+	return s
 }
 }
-func (e *EDNS0_TCP_KEEPALIVE) copy() EDNS0 { return &EDNS0_TCP_KEEPALIVE{e.Code, e.Length, e.Timeout} }
+
+func (e *EDNS0_TCP_KEEPALIVE) copy() EDNS0 { return &EDNS0_TCP_KEEPALIVE{e.Code, e.Timeout, e.Length} }
 
 
 // EDNS0_PADDING option is used to add padding to a request/response. The default
 // EDNS0_PADDING option is used to add padding to a request/response. The default
 // value of padding SHOULD be 0x0 but other values MAY be used, for instance if
 // value of padding SHOULD be 0x0 but other values MAY be used, for instance if
@@ -713,14 +724,10 @@ type EDNS0_PADDING struct {
 
 
 // Option implements the EDNS0 interface.
 // Option implements the EDNS0 interface.
 func (e *EDNS0_PADDING) Option() uint16        { return EDNS0PADDING }
 func (e *EDNS0_PADDING) Option() uint16        { return EDNS0PADDING }
-func (e *EDNS0_PADDING) pack() ([]byte, error) { return e.Padding, nil }
-func (e *EDNS0_PADDING) unpack(b []byte) error { e.Padding = b; return nil }
+func (e *EDNS0_PADDING) pack() ([]byte, error) { return cloneSlice(e.Padding), nil }
+func (e *EDNS0_PADDING) unpack(b []byte) error { e.Padding = cloneSlice(b); return nil }
 func (e *EDNS0_PADDING) String() string        { return fmt.Sprintf("%0X", e.Padding) }
 func (e *EDNS0_PADDING) String() string        { return fmt.Sprintf("%0X", e.Padding) }
-func (e *EDNS0_PADDING) copy() EDNS0 {
-	b := make([]byte, len(e.Padding))
-	copy(b, e.Padding)
-	return &EDNS0_PADDING{b}
-}
+func (e *EDNS0_PADDING) copy() EDNS0           { return &EDNS0_PADDING{cloneSlice(e.Padding)} }
 
 
 // Extended DNS Error Codes (RFC 8914).
 // Extended DNS Error Codes (RFC 8914).
 const (
 const (
@@ -807,7 +814,7 @@ func (e *EDNS0_EDE) String() string {
 func (e *EDNS0_EDE) pack() ([]byte, error) {
 func (e *EDNS0_EDE) pack() ([]byte, error) {
 	b := make([]byte, 2+len(e.ExtraText))
 	b := make([]byte, 2+len(e.ExtraText))
 	binary.BigEndian.PutUint16(b[0:], e.InfoCode)
 	binary.BigEndian.PutUint16(b[0:], e.InfoCode)
-	copy(b[2:], []byte(e.ExtraText))
+	copy(b[2:], e.ExtraText)
 	return b, nil
 	return b, nil
 }
 }
 
 
@@ -819,3 +826,19 @@ func (e *EDNS0_EDE) unpack(b []byte) error {
 	e.ExtraText = string(b[2:])
 	e.ExtraText = string(b[2:])
 	return nil
 	return nil
 }
 }
+
+// The EDNS0_ESU option for ENUM Source-URI Extension
+type EDNS0_ESU struct {
+	Code uint16
+	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} }
+func (e *EDNS0_ESU) pack() ([]byte, error) { return []byte(e.Uri), nil }
+func (e *EDNS0_ESU) unpack(b []byte) error {
+	e.Uri = string(b)
+	return nil
+}

+ 1 - 0
vendor/github.com/miekg/dns/fuzz.go

@@ -1,3 +1,4 @@
+//go:build fuzz
 // +build fuzz
 // +build fuzz
 
 
 package dns
 package dns

+ 17 - 16
vendor/github.com/miekg/dns/generate.go

@@ -35,17 +35,17 @@ func (zp *ZoneParser) generate(l lex) (RR, bool) {
 		token = token[:i]
 		token = token[:i]
 	}
 	}
 
 
-	sx := strings.SplitN(token, "-", 2)
-	if len(sx) != 2 {
+	startStr, endStr, ok := strings.Cut(token, "-")
+	if !ok {
 		return zp.setParseError("bad start-stop in $GENERATE range", l)
 		return zp.setParseError("bad start-stop in $GENERATE range", l)
 	}
 	}
 
 
-	start, err := strconv.ParseInt(sx[0], 10, 64)
+	start, err := strconv.ParseInt(startStr, 10, 64)
 	if err != nil {
 	if err != nil {
 		return zp.setParseError("bad start in $GENERATE range", l)
 		return zp.setParseError("bad start in $GENERATE range", l)
 	}
 	}
 
 
-	end, err := strconv.ParseInt(sx[1], 10, 64)
+	end, err := strconv.ParseInt(endStr, 10, 64)
 	if err != nil {
 	if err != nil {
 		return zp.setParseError("bad stop in $GENERATE range", l)
 		return zp.setParseError("bad stop in $GENERATE range", l)
 	}
 	}
@@ -54,7 +54,7 @@ func (zp *ZoneParser) generate(l lex) (RR, bool) {
 	}
 	}
 
 
 	// _BLANK
 	// _BLANK
-	l, ok := zp.c.Next()
+	l, ok = zp.c.Next()
 	if !ok || l.value != zBlank {
 	if !ok || l.value != zBlank {
 		return zp.setParseError("garbage after $GENERATE range", l)
 		return zp.setParseError("garbage after $GENERATE range", l)
 	}
 	}
@@ -211,15 +211,16 @@ func (r *generateReader) ReadByte() (byte, error) {
 func modToPrintf(s string) (string, int64, string) {
 func modToPrintf(s string) (string, int64, string) {
 	// Modifier is { offset [ ,width [ ,base ] ] } - provide default
 	// Modifier is { offset [ ,width [ ,base ] ] } - provide default
 	// values for optional width and type, if necessary.
 	// values for optional width and type, if necessary.
-	var offStr, widthStr, base string
-	switch xs := strings.Split(s, ","); len(xs) {
-	case 1:
-		offStr, widthStr, base = xs[0], "0", "d"
-	case 2:
-		offStr, widthStr, base = xs[0], xs[1], "d"
-	case 3:
-		offStr, widthStr, base = xs[0], xs[1], xs[2]
-	default:
+	offStr, s, ok0 := strings.Cut(s, ",")
+	widthStr, s, ok1 := strings.Cut(s, ",")
+	base, _, ok2 := strings.Cut(s, ",")
+	if !ok0 {
+		widthStr = "0"
+	}
+	if !ok1 {
+		base = "d"
+	}
+	if ok2 {
 		return "", 0, "bad modifier in $GENERATE"
 		return "", 0, "bad modifier in $GENERATE"
 	}
 	}
 
 
@@ -234,8 +235,8 @@ func modToPrintf(s string) (string, int64, string) {
 		return "", 0, "bad offset in $GENERATE"
 		return "", 0, "bad offset in $GENERATE"
 	}
 	}
 
 
-	width, err := strconv.ParseInt(widthStr, 10, 64)
-	if err != nil || width < 0 || width > 255 {
+	width, err := strconv.ParseUint(widthStr, 10, 8)
+	if err != nil {
 		return "", 0, "bad width in $GENERATE"
 		return "", 0, "bad width in $GENERATE"
 	}
 	}
 
 

+ 31 - 0
vendor/github.com/miekg/dns/hash.go

@@ -0,0 +1,31 @@
+package dns
+
+import (
+	"bytes"
+	"crypto"
+	"hash"
+)
+
+// identityHash will not hash, it only buffers the data written into it and returns it as-is.
+type identityHash struct {
+	b *bytes.Buffer
+}
+
+// Implement the hash.Hash interface.
+
+func (i identityHash) Write(b []byte) (int, error) { return i.b.Write(b) }
+func (i identityHash) Size() int                   { return i.b.Len() }
+func (i identityHash) BlockSize() int              { return 1024 }
+func (i identityHash) Reset()                      { i.b.Reset() }
+func (i identityHash) Sum(b []byte) []byte         { return append(b, i.b.Bytes()...) }
+
+func hashFromAlgorithm(alg uint8) (hash.Hash, crypto.Hash, error) {
+	hashnumber, ok := AlgorithmToHash[alg]
+	if !ok {
+		return nil, 0, ErrAlg
+	}
+	if hashnumber == 0 {
+		return identityHash{b: &bytes.Buffer{}}, hashnumber, nil
+	}
+	return hashnumber.New(), hashnumber, nil
+}

+ 1 - 1
vendor/github.com/miekg/dns/labels.go

@@ -122,7 +122,7 @@ func Split(s string) []int {
 }
 }
 
 
 // NextLabel returns the index of the start of the next label in the
 // NextLabel returns the index of the start of the next label in the
-// string s starting at offset.
+// string s starting at offset. A negative offset will cause a panic.
 // The bool end is true when the end of the string has been reached.
 // The bool end is true when the end of the string has been reached.
 // Also see PrevLabel.
 // Also see PrevLabel.
 func NextLabel(s string, offset int) (i int, end bool) {
 func NextLabel(s string, offset int) (i int, end bool) {

+ 8 - 5
vendor/github.com/miekg/dns/listen_no_reuseport.go

@@ -1,4 +1,5 @@
-// +build !go1.11 !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd
+//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd
+// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd
 
 
 package dns
 package dns
 
 
@@ -6,16 +7,18 @@ import "net"
 
 
 const supportsReusePort = false
 const supportsReusePort = false
 
 
-func listenTCP(network, addr string, reuseport bool) (net.Listener, error) {
-	if reuseport {
+func listenTCP(network, addr string, reuseport, reuseaddr bool) (net.Listener, error) {
+	if reuseport || reuseaddr {
 		// TODO(tmthrgd): return an error?
 		// TODO(tmthrgd): return an error?
 	}
 	}
 
 
 	return net.Listen(network, addr)
 	return net.Listen(network, addr)
 }
 }
 
 
-func listenUDP(network, addr string, reuseport bool) (net.PacketConn, error) {
-	if reuseport {
+const supportsReuseAddr = false
+
+func listenUDP(network, addr string, reuseport, reuseaddr bool) (net.PacketConn, error) {
+	if reuseport || reuseaddr {
 		// TODO(tmthrgd): return an error?
 		// TODO(tmthrgd): return an error?
 	}
 	}
 
 

+ 27 - 5
vendor/github.com/miekg/dns/listen_reuseport.go

@@ -1,4 +1,4 @@
-// +build go1.11
+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd
 // +build aix darwin dragonfly freebsd linux netbsd openbsd
 // +build aix darwin dragonfly freebsd linux netbsd openbsd
 
 
 package dns
 package dns
@@ -25,19 +25,41 @@ func reuseportControl(network, address string, c syscall.RawConn) error {
 	return opErr
 	return opErr
 }
 }
 
 
-func listenTCP(network, addr string, reuseport bool) (net.Listener, error) {
+const supportsReuseAddr = true
+
+func reuseaddrControl(network, address string, c syscall.RawConn) error {
+	var opErr error
+	err := c.Control(func(fd uintptr) {
+		opErr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1)
+	})
+	if err != nil {
+		return err
+	}
+
+	return opErr
+}
+
+func listenTCP(network, addr string, reuseport, reuseaddr bool) (net.Listener, error) {
 	var lc net.ListenConfig
 	var lc net.ListenConfig
-	if reuseport {
+	switch {
+	case reuseaddr && reuseport:
+	case reuseport:
 		lc.Control = reuseportControl
 		lc.Control = reuseportControl
+	case reuseaddr:
+		lc.Control = reuseaddrControl
 	}
 	}
 
 
 	return lc.Listen(context.Background(), network, addr)
 	return lc.Listen(context.Background(), network, addr)
 }
 }
 
 
-func listenUDP(network, addr string, reuseport bool) (net.PacketConn, error) {
+func listenUDP(network, addr string, reuseport, reuseaddr bool) (net.PacketConn, error) {
 	var lc net.ListenConfig
 	var lc net.ListenConfig
-	if reuseport {
+	switch {
+	case reuseaddr && reuseport:
+	case reuseport:
 		lc.Control = reuseportControl
 		lc.Control = reuseportControl
+	case reuseaddr:
+		lc.Control = reuseaddrControl
 	}
 	}
 
 
 	return lc.ListenPacket(context.Background(), network, addr)
 	return lc.ListenPacket(context.Background(), network, addr)

+ 73 - 52
vendor/github.com/miekg/dns/msg.go

@@ -252,7 +252,7 @@ loop:
 			}
 			}
 
 
 			// check for \DDD
 			// check for \DDD
-			if i+3 < ls && isDigit(bs[i+1]) && isDigit(bs[i+2]) && isDigit(bs[i+3]) {
+			if isDDD(bs[i+1:]) {
 				bs[i] = dddToByte(bs[i+1:])
 				bs[i] = dddToByte(bs[i+1:])
 				copy(bs[i+1:ls-3], bs[i+4:])
 				copy(bs[i+1:ls-3], bs[i+4:])
 				ls -= 3
 				ls -= 3
@@ -265,6 +265,11 @@ loop:
 
 
 			wasDot = false
 			wasDot = false
 		case '.':
 		case '.':
+			if i == 0 && len(s) > 1 {
+				// leading dots are not legal except for the root zone
+				return len(msg), ErrRdata
+			}
+
 			if wasDot {
 			if wasDot {
 				// two dots back to back is not legal
 				// two dots back to back is not legal
 				return len(msg), ErrRdata
 				return len(msg), ErrRdata
@@ -443,7 +448,7 @@ Loop:
 	return string(s), off1, nil
 	return string(s), off1, nil
 }
 }
 
 
-func packTxt(txt []string, msg []byte, offset int, tmp []byte) (int, error) {
+func packTxt(txt []string, msg []byte, offset int) (int, error) {
 	if len(txt) == 0 {
 	if len(txt) == 0 {
 		if offset >= len(msg) {
 		if offset >= len(msg) {
 			return offset, ErrBuf
 			return offset, ErrBuf
@@ -453,10 +458,7 @@ func packTxt(txt []string, msg []byte, offset int, tmp []byte) (int, error) {
 	}
 	}
 	var err error
 	var err error
 	for _, s := range txt {
 	for _, s := range txt {
-		if len(s) > len(tmp) {
-			return offset, ErrBuf
-		}
-		offset, err = packTxtString(s, msg, offset, tmp)
+		offset, err = packTxtString(s, msg, offset)
 		if err != nil {
 		if err != nil {
 			return offset, err
 			return offset, err
 		}
 		}
@@ -464,32 +466,30 @@ func packTxt(txt []string, msg []byte, offset int, tmp []byte) (int, error) {
 	return offset, nil
 	return offset, nil
 }
 }
 
 
-func packTxtString(s string, msg []byte, offset int, tmp []byte) (int, error) {
+func packTxtString(s string, msg []byte, offset int) (int, error) {
 	lenByteOffset := offset
 	lenByteOffset := offset
-	if offset >= len(msg) || len(s) > len(tmp) {
+	if offset >= len(msg) || len(s) > 256*4+1 /* If all \DDD */ {
 		return offset, ErrBuf
 		return offset, ErrBuf
 	}
 	}
 	offset++
 	offset++
-	bs := tmp[:len(s)]
-	copy(bs, s)
-	for i := 0; i < len(bs); i++ {
+	for i := 0; i < len(s); i++ {
 		if len(msg) <= offset {
 		if len(msg) <= offset {
 			return offset, ErrBuf
 			return offset, ErrBuf
 		}
 		}
-		if bs[i] == '\\' {
+		if s[i] == '\\' {
 			i++
 			i++
-			if i == len(bs) {
+			if i == len(s) {
 				break
 				break
 			}
 			}
 			// check for \DDD
 			// check for \DDD
-			if i+2 < len(bs) && isDigit(bs[i]) && isDigit(bs[i+1]) && isDigit(bs[i+2]) {
-				msg[offset] = dddToByte(bs[i:])
+			if isDDD(s[i:]) {
+				msg[offset] = dddToByte(s[i:])
 				i += 2
 				i += 2
 			} else {
 			} else {
-				msg[offset] = bs[i]
+				msg[offset] = s[i]
 			}
 			}
 		} else {
 		} else {
-			msg[offset] = bs[i]
+			msg[offset] = s[i]
 		}
 		}
 		offset++
 		offset++
 	}
 	}
@@ -501,30 +501,28 @@ func packTxtString(s string, msg []byte, offset int, tmp []byte) (int, error) {
 	return offset, nil
 	return offset, nil
 }
 }
 
 
-func packOctetString(s string, msg []byte, offset int, tmp []byte) (int, error) {
-	if offset >= len(msg) || len(s) > len(tmp) {
+func packOctetString(s string, msg []byte, offset int) (int, error) {
+	if offset >= len(msg) || len(s) > 256*4+1 {
 		return offset, ErrBuf
 		return offset, ErrBuf
 	}
 	}
-	bs := tmp[:len(s)]
-	copy(bs, s)
-	for i := 0; i < len(bs); i++ {
+	for i := 0; i < len(s); i++ {
 		if len(msg) <= offset {
 		if len(msg) <= offset {
 			return offset, ErrBuf
 			return offset, ErrBuf
 		}
 		}
-		if bs[i] == '\\' {
+		if s[i] == '\\' {
 			i++
 			i++
-			if i == len(bs) {
+			if i == len(s) {
 				break
 				break
 			}
 			}
 			// check for \DDD
 			// check for \DDD
-			if i+2 < len(bs) && isDigit(bs[i]) && isDigit(bs[i+1]) && isDigit(bs[i+2]) {
-				msg[offset] = dddToByte(bs[i:])
+			if isDDD(s[i:]) {
+				msg[offset] = dddToByte(s[i:])
 				i += 2
 				i += 2
 			} else {
 			} else {
-				msg[offset] = bs[i]
+				msg[offset] = s[i]
 			}
 			}
 		} else {
 		} else {
-			msg[offset] = bs[i]
+			msg[offset] = s[i]
 		}
 		}
 		offset++
 		offset++
 	}
 	}
@@ -546,12 +544,11 @@ func unpackTxt(msg []byte, off0 int) (ss []string, off int, err error) {
 // Helpers for dealing with escaped bytes
 // Helpers for dealing with escaped bytes
 func isDigit(b byte) bool { return b >= '0' && b <= '9' }
 func isDigit(b byte) bool { return b >= '0' && b <= '9' }
 
 
-func dddToByte(s []byte) byte {
-	_ = s[2] // bounds check hint to compiler; see golang.org/issue/14808
-	return byte((s[0]-'0')*100 + (s[1]-'0')*10 + (s[2] - '0'))
+func isDDD[T ~[]byte | ~string](s T) bool {
+	return len(s) >= 3 && isDigit(s[0]) && isDigit(s[1]) && isDigit(s[2])
 }
 }
 
 
-func dddStringToByte(s string) byte {
+func dddToByte[T ~[]byte | ~string](s T) byte {
 	_ = s[2] // bounds check hint to compiler; see golang.org/issue/14808
 	_ = s[2] // bounds check hint to compiler; see golang.org/issue/14808
 	return byte((s[0]-'0')*100 + (s[1]-'0')*10 + (s[2] - '0'))
 	return byte((s[0]-'0')*100 + (s[1]-'0')*10 + (s[2] - '0'))
 }
 }
@@ -675,9 +672,9 @@ func unpackRRslice(l int, msg []byte, off int) (dst1 []RR, off1 int, err error)
 
 
 // Convert a MsgHdr to a string, with dig-like headers:
 // Convert a MsgHdr to a string, with dig-like headers:
 //
 //
-//;; opcode: QUERY, status: NOERROR, id: 48404
+// ;; opcode: QUERY, status: NOERROR, id: 48404
 //
 //
-//;; flags: qr aa rd ra;
+// ;; flags: qr aa rd ra;
 func (h *MsgHdr) String() string {
 func (h *MsgHdr) String() string {
 	if h == nil {
 	if h == nil {
 		return "<nil> MsgHdr"
 		return "<nil> MsgHdr"
@@ -861,7 +858,7 @@ func (dns *Msg) unpack(dh Header, msg []byte, off int) (err error) {
 	// The header counts might have been wrong so we need to update it
 	// The header counts might have been wrong so we need to update it
 	dh.Nscount = uint16(len(dns.Ns))
 	dh.Nscount = uint16(len(dns.Ns))
 	if err == nil {
 	if err == nil {
-		dns.Extra, off, err = unpackRRslice(int(dh.Arcount), msg, off)
+		dns.Extra, _, err = unpackRRslice(int(dh.Arcount), msg, off)
 	}
 	}
 	// The header counts might have been wrong so we need to update it
 	// The header counts might have been wrong so we need to update it
 	dh.Arcount = uint16(len(dns.Extra))
 	dh.Arcount = uint16(len(dns.Extra))
@@ -871,11 +868,11 @@ func (dns *Msg) unpack(dh Header, msg []byte, off int) (err error) {
 		dns.Rcode |= opt.ExtendedRcode()
 		dns.Rcode |= opt.ExtendedRcode()
 	}
 	}
 
 
-	if off != len(msg) {
-		// TODO(miek) make this an error?
-		// use PackOpt to let people tell how detailed the error reporting should be?
-		// println("dns: extra bytes in dns packet", off, "<", len(msg))
-	}
+	// 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))
+	// }
 	return err
 	return err
 
 
 }
 }
@@ -897,18 +894,38 @@ func (dns *Msg) String() string {
 		return "<nil> MsgHdr"
 		return "<nil> MsgHdr"
 	}
 	}
 	s := dns.MsgHdr.String() + " "
 	s := dns.MsgHdr.String() + " "
-	s += "QUERY: " + strconv.Itoa(len(dns.Question)) + ", "
-	s += "ANSWER: " + strconv.Itoa(len(dns.Answer)) + ", "
-	s += "AUTHORITY: " + strconv.Itoa(len(dns.Ns)) + ", "
-	s += "ADDITIONAL: " + strconv.Itoa(len(dns.Extra)) + "\n"
+	if dns.MsgHdr.Opcode == OpcodeUpdate {
+		s += "ZONE: " + strconv.Itoa(len(dns.Question)) + ", "
+		s += "PREREQ: " + strconv.Itoa(len(dns.Answer)) + ", "
+		s += "UPDATE: " + strconv.Itoa(len(dns.Ns)) + ", "
+		s += "ADDITIONAL: " + strconv.Itoa(len(dns.Extra)) + "\n"
+	} else {
+		s += "QUERY: " + strconv.Itoa(len(dns.Question)) + ", "
+		s += "ANSWER: " + strconv.Itoa(len(dns.Answer)) + ", "
+		s += "AUTHORITY: " + strconv.Itoa(len(dns.Ns)) + ", "
+		s += "ADDITIONAL: " + strconv.Itoa(len(dns.Extra)) + "\n"
+	}
+	opt := dns.IsEdns0()
+	if opt != nil {
+		// OPT PSEUDOSECTION
+		s += opt.String() + "\n"
+	}
 	if len(dns.Question) > 0 {
 	if len(dns.Question) > 0 {
-		s += "\n;; QUESTION SECTION:\n"
+		if dns.MsgHdr.Opcode == OpcodeUpdate {
+			s += "\n;; ZONE SECTION:\n"
+		} else {
+			s += "\n;; QUESTION SECTION:\n"
+		}
 		for _, r := range dns.Question {
 		for _, r := range dns.Question {
 			s += r.String() + "\n"
 			s += r.String() + "\n"
 		}
 		}
 	}
 	}
 	if len(dns.Answer) > 0 {
 	if len(dns.Answer) > 0 {
-		s += "\n;; ANSWER SECTION:\n"
+		if dns.MsgHdr.Opcode == OpcodeUpdate {
+			s += "\n;; PREREQUISITE SECTION:\n"
+		} else {
+			s += "\n;; ANSWER SECTION:\n"
+		}
 		for _, r := range dns.Answer {
 		for _, r := range dns.Answer {
 			if r != nil {
 			if r != nil {
 				s += r.String() + "\n"
 				s += r.String() + "\n"
@@ -916,17 +933,21 @@ func (dns *Msg) String() string {
 		}
 		}
 	}
 	}
 	if len(dns.Ns) > 0 {
 	if len(dns.Ns) > 0 {
-		s += "\n;; AUTHORITY SECTION:\n"
+		if dns.MsgHdr.Opcode == OpcodeUpdate {
+			s += "\n;; UPDATE SECTION:\n"
+		} else {
+			s += "\n;; AUTHORITY SECTION:\n"
+		}
 		for _, r := range dns.Ns {
 		for _, r := range dns.Ns {
 			if r != nil {
 			if r != nil {
 				s += r.String() + "\n"
 				s += r.String() + "\n"
 			}
 			}
 		}
 		}
 	}
 	}
-	if len(dns.Extra) > 0 {
+	if len(dns.Extra) > 0 && (opt == nil || len(dns.Extra) > 1) {
 		s += "\n;; ADDITIONAL SECTION:\n"
 		s += "\n;; ADDITIONAL SECTION:\n"
 		for _, r := range dns.Extra {
 		for _, r := range dns.Extra {
-			if r != nil {
+			if r != nil && r.Header().Rrtype != TypeOPT {
 				s += r.String() + "\n"
 				s += r.String() + "\n"
 			}
 			}
 		}
 		}
@@ -1014,7 +1035,7 @@ func escapedNameLen(s string) int {
 			continue
 			continue
 		}
 		}
 
 
-		if i+3 < len(s) && isDigit(s[i+1]) && isDigit(s[i+2]) && isDigit(s[i+3]) {
+		if isDDD(s[i+1:]) {
 			nameLen -= 3
 			nameLen -= 3
 			i += 3
 			i += 3
 		} else {
 		} else {
@@ -1055,8 +1076,8 @@ func (dns *Msg) CopyTo(r1 *Msg) *Msg {
 	r1.Compress = dns.Compress
 	r1.Compress = dns.Compress
 
 
 	if len(dns.Question) > 0 {
 	if len(dns.Question) > 0 {
-		r1.Question = make([]Question, len(dns.Question))
-		copy(r1.Question, dns.Question) // TODO(miek): Question is an immutable value, ok to do a shallow-copy
+		// TODO(miek): Question is an immutable value, ok to do a shallow-copy
+		r1.Question = cloneSlice(dns.Question)
 	}
 	}
 
 
 	rrArr := make([]RR, len(dns.Answer)+len(dns.Ns)+len(dns.Extra))
 	rrArr := make([]RR, len(dns.Answer)+len(dns.Ns)+len(dns.Extra))

+ 74 - 44
vendor/github.com/miekg/dns/msg_helpers.go

@@ -20,9 +20,7 @@ func unpackDataA(msg []byte, off int) (net.IP, int, error) {
 	if off+net.IPv4len > len(msg) {
 	if off+net.IPv4len > len(msg) {
 		return nil, len(msg), &Error{err: "overflow unpacking a"}
 		return nil, len(msg), &Error{err: "overflow unpacking a"}
 	}
 	}
-	a := append(make(net.IP, 0, net.IPv4len), msg[off:off+net.IPv4len]...)
-	off += net.IPv4len
-	return a, off, nil
+	return cloneSlice(msg[off : off+net.IPv4len]), off + net.IPv4len, nil
 }
 }
 
 
 func packDataA(a net.IP, msg []byte, off int) (int, error) {
 func packDataA(a net.IP, msg []byte, off int) (int, error) {
@@ -47,9 +45,7 @@ func unpackDataAAAA(msg []byte, off int) (net.IP, int, error) {
 	if off+net.IPv6len > len(msg) {
 	if off+net.IPv6len > len(msg) {
 		return nil, len(msg), &Error{err: "overflow unpacking aaaa"}
 		return nil, len(msg), &Error{err: "overflow unpacking aaaa"}
 	}
 	}
-	aaaa := append(make(net.IP, 0, net.IPv6len), msg[off:off+net.IPv6len]...)
-	off += net.IPv6len
-	return aaaa, off, nil
+	return cloneSlice(msg[off : off+net.IPv6len]), off + net.IPv6len, nil
 }
 }
 
 
 func packDataAAAA(aaaa net.IP, msg []byte, off int) (int, error) {
 func packDataAAAA(aaaa net.IP, msg []byte, off int) (int, error) {
@@ -299,8 +295,7 @@ func unpackString(msg []byte, off int) (string, int, error) {
 }
 }
 
 
 func packString(s string, msg []byte, off int) (int, error) {
 func packString(s string, msg []byte, off int) (int, error) {
-	txtTmp := make([]byte, 256*4+1)
-	off, err := packTxtString(s, msg, off, txtTmp)
+	off, err := packTxtString(s, msg, off)
 	if err != nil {
 	if err != nil {
 		return len(msg), err
 		return len(msg), err
 	}
 	}
@@ -402,8 +397,7 @@ func unpackStringTxt(msg []byte, off int) ([]string, int, error) {
 }
 }
 
 
 func packStringTxt(s []string, msg []byte, off int) (int, error) {
 func packStringTxt(s []string, msg []byte, off int) (int, error) {
-	txtTmp := make([]byte, 256*4+1) // If the whole string consists out of \DDD we need this many.
-	off, err := packTxt(s, msg, off, txtTmp)
+	off, err := packTxt(s, msg, off)
 	if err != nil {
 	if err != nil {
 		return len(msg), err
 		return len(msg), err
 	}
 	}
@@ -412,29 +406,24 @@ func packStringTxt(s []string, msg []byte, off int) (int, error) {
 
 
 func unpackDataOpt(msg []byte, off int) ([]EDNS0, int, error) {
 func unpackDataOpt(msg []byte, off int) ([]EDNS0, int, error) {
 	var edns []EDNS0
 	var edns []EDNS0
-Option:
-	var code uint16
-	if off+4 > len(msg) {
-		return nil, len(msg), &Error{err: "overflow unpacking opt"}
-	}
-	code = binary.BigEndian.Uint16(msg[off:])
-	off += 2
-	optlen := binary.BigEndian.Uint16(msg[off:])
-	off += 2
-	if off+int(optlen) > len(msg) {
-		return nil, len(msg), &Error{err: "overflow unpacking opt"}
-	}
-	e := makeDataOpt(code)
-	if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
-		return nil, len(msg), err
-	}
-	edns = append(edns, e)
-	off += int(optlen)
-
-	if off < len(msg) {
-		goto Option
+	for off < len(msg) {
+		if off+4 > len(msg) {
+			return nil, len(msg), &Error{err: "overflow unpacking opt"}
+		}
+		code := binary.BigEndian.Uint16(msg[off:])
+		off += 2
+		optlen := binary.BigEndian.Uint16(msg[off:])
+		off += 2
+		if off+int(optlen) > len(msg) {
+			return nil, len(msg), &Error{err: "overflow unpacking opt"}
+		}
+		opt := makeDataOpt(code)
+		if err := opt.unpack(msg[off : off+int(optlen)]); err != nil {
+			return nil, len(msg), err
+		}
+		edns = append(edns, opt)
+		off += int(optlen)
 	}
 	}
-
 	return edns, off, nil
 	return edns, off, nil
 }
 }
 
 
@@ -463,8 +452,7 @@ func unpackStringOctet(msg []byte, off int) (string, int, error) {
 }
 }
 
 
 func packStringOctet(s string, msg []byte, off int) (int, error) {
 func packStringOctet(s string, msg []byte, off int) (int, error) {
-	txtTmp := make([]byte, 256*4+1)
-	off, err := packOctetString(s, msg, off, txtTmp)
+	off, err := packOctetString(s, msg, off)
 	if err != nil {
 	if err != nil {
 		return len(msg), err
 		return len(msg), err
 	}
 	}
@@ -476,7 +464,7 @@ func unpackDataNsec(msg []byte, off int) ([]uint16, int, error) {
 	length, window, lastwindow := 0, 0, -1
 	length, window, lastwindow := 0, 0, -1
 	for off < len(msg) {
 	for off < len(msg) {
 		if off+2 > len(msg) {
 		if off+2 > len(msg) {
-			return nsec, len(msg), &Error{err: "overflow unpacking nsecx"}
+			return nsec, len(msg), &Error{err: "overflow unpacking NSEC(3)"}
 		}
 		}
 		window = int(msg[off])
 		window = int(msg[off])
 		length = int(msg[off+1])
 		length = int(msg[off+1])
@@ -484,17 +472,17 @@ func unpackDataNsec(msg []byte, off int) ([]uint16, int, error) {
 		if window <= lastwindow {
 		if window <= lastwindow {
 			// RFC 4034: Blocks are present in the NSEC RR RDATA in
 			// RFC 4034: Blocks are present in the NSEC RR RDATA in
 			// increasing numerical order.
 			// increasing numerical order.
-			return nsec, len(msg), &Error{err: "out of order NSEC block"}
+			return nsec, len(msg), &Error{err: "out of order NSEC(3) block in type bitmap"}
 		}
 		}
 		if length == 0 {
 		if length == 0 {
 			// RFC 4034: Blocks with no types present MUST NOT be included.
 			// RFC 4034: Blocks with no types present MUST NOT be included.
-			return nsec, len(msg), &Error{err: "empty NSEC block"}
+			return nsec, len(msg), &Error{err: "empty NSEC(3) block in type bitmap"}
 		}
 		}
 		if length > 32 {
 		if length > 32 {
-			return nsec, len(msg), &Error{err: "NSEC block too long"}
+			return nsec, len(msg), &Error{err: "NSEC(3) block too long in type bitmap"}
 		}
 		}
 		if off+length > len(msg) {
 		if off+length > len(msg) {
-			return nsec, len(msg), &Error{err: "overflowing NSEC block"}
+			return nsec, len(msg), &Error{err: "overflowing NSEC(3) block in type bitmap"}
 		}
 		}
 
 
 		// Walk the bytes in the window and extract the type bits
 		// Walk the bytes in the window and extract the type bits
@@ -558,6 +546,16 @@ func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) {
 	if len(bitmap) == 0 {
 	if len(bitmap) == 0 {
 		return off, nil
 		return off, nil
 	}
 	}
+	if off > len(msg) {
+		return off, &Error{err: "overflow packing nsec"}
+	}
+	toZero := msg[off:]
+	if maxLen := typeBitMapLen(bitmap); maxLen < len(toZero) {
+		toZero = toZero[:maxLen]
+	}
+	for i := range toZero {
+		toZero[i] = 0
+	}
 	var lastwindow, lastlength uint16
 	var lastwindow, lastlength uint16
 	for _, t := range bitmap {
 	for _, t := range bitmap {
 		window := t / 256
 		window := t / 256
@@ -615,7 +613,7 @@ func unpackDataSVCB(msg []byte, off int) ([]SVCBKeyValue, int, error) {
 }
 }
 
 
 func packDataSVCB(pairs []SVCBKeyValue, msg []byte, off int) (int, error) {
 func packDataSVCB(pairs []SVCBKeyValue, msg []byte, off int) (int, error) {
-	pairs = append([]SVCBKeyValue(nil), pairs...)
+	pairs = cloneSlice(pairs)
 	sort.Slice(pairs, func(i, j int) bool {
 	sort.Slice(pairs, func(i, j int) bool {
 		return pairs[i].Key() < pairs[j].Key()
 		return pairs[i].Key() < pairs[j].Key()
 	})
 	})
@@ -781,6 +779,8 @@ func unpackDataAplPrefix(msg []byte, off int) (APLPrefix, int, error) {
 	if off+afdlen > len(msg) {
 	if off+afdlen > len(msg) {
 		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL address"}
 		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL address"}
 	}
 	}
+
+	// Address MUST NOT contain trailing zero bytes per RFC3123 Sections 4.1 and 4.2.
 	off += copy(ip, msg[off:off+afdlen])
 	off += copy(ip, msg[off:off+afdlen])
 	if afdlen > 0 {
 	if afdlen > 0 {
 		last := ip[afdlen-1]
 		last := ip[afdlen-1]
@@ -792,13 +792,43 @@ func unpackDataAplPrefix(msg []byte, off int) (APLPrefix, int, error) {
 		IP:   ip,
 		IP:   ip,
 		Mask: net.CIDRMask(int(prefix), 8*len(ip)),
 		Mask: net.CIDRMask(int(prefix), 8*len(ip)),
 	}
 	}
-	network := ipnet.IP.Mask(ipnet.Mask)
-	if !network.Equal(ipnet.IP) {
-		return APLPrefix{}, len(msg), &Error{err: "invalid APL address length"}
-	}
 
 
 	return APLPrefix{
 	return APLPrefix{
 		Negation: (nlen & 0x80) != 0,
 		Negation: (nlen & 0x80) != 0,
 		Network:  ipnet,
 		Network:  ipnet,
 	}, off, nil
 	}, off, nil
 }
 }
+
+func unpackIPSECGateway(msg []byte, off int, gatewayType uint8) (net.IP, string, int, error) {
+	var retAddr net.IP
+	var retString string
+	var err error
+
+	switch gatewayType {
+	case IPSECGatewayNone: // do nothing
+	case IPSECGatewayIPv4:
+		retAddr, off, err = unpackDataA(msg, off)
+	case IPSECGatewayIPv6:
+		retAddr, off, err = unpackDataAAAA(msg, off)
+	case IPSECGatewayHost:
+		retString, off, err = UnpackDomainName(msg, off)
+	}
+
+	return retAddr, retString, off, err
+}
+
+func packIPSECGateway(gatewayAddr net.IP, gatewayString string, msg []byte, off int, gatewayType uint8, compression compressionMap, compress bool) (int, error) {
+	var err error
+
+	switch gatewayType {
+	case IPSECGatewayNone: // do nothing
+	case IPSECGatewayIPv4:
+		off, err = packDataA(gatewayAddr, msg, off)
+	case IPSECGatewayIPv6:
+		off, err = packDataAAAA(gatewayAddr, msg, off)
+	case IPSECGatewayHost:
+		off, err = packDomainName(gatewayString, msg, off, compression, compress)
+	}
+
+	return off, err
+}

+ 26 - 39
vendor/github.com/miekg/dns/scan.go

@@ -10,13 +10,13 @@ import (
 	"strings"
 	"strings"
 )
 )
 
 
-const maxTok = 2048 // Largest token we can return.
+const maxTok = 512 // Token buffer start size, and growth size amount.
 
 
 // The maximum depth of $INCLUDE directives supported by the
 // The maximum depth of $INCLUDE directives supported by the
 // ZoneParser API.
 // ZoneParser API.
 const maxIncludeDepth = 7
 const maxIncludeDepth = 7
 
 
-// Tokinize a RFC 1035 zone file. The tokenizer will normalize it:
+// Tokenize a RFC 1035 zone file. The tokenizer will normalize it:
 // * Add ownernames if they are left blank;
 // * Add ownernames if they are left blank;
 // * Suppress sequences of spaces;
 // * Suppress sequences of spaces;
 // * Make each RR fit on one line (_NEWLINE is send as last)
 // * Make each RR fit on one line (_NEWLINE is send as last)
@@ -605,8 +605,6 @@ func (zp *ZoneParser) Next() (RR, bool) {
 			if !isPrivate && zp.c.Peek().token == "" {
 			if !isPrivate && zp.c.Peek().token == "" {
 				// This is a dynamic update rr.
 				// This is a dynamic update rr.
 
 
-				// TODO(tmthrgd): Previously slurpRemainder was only called
-				// for certain RR types, which may have been important.
 				if err := slurpRemainder(zp.c); err != nil {
 				if err := slurpRemainder(zp.c); err != nil {
 					return zp.setParseError(err.err, err.lex)
 					return zp.setParseError(err.err, err.lex)
 				}
 				}
@@ -765,8 +763,8 @@ func (zl *zlexer) Next() (lex, bool) {
 	}
 	}
 
 
 	var (
 	var (
-		str [maxTok]byte // Hold string text
-		com [maxTok]byte // Hold comment text
+		str = make([]byte, maxTok) // Hold string text
+		com = make([]byte, maxTok) // Hold comment text
 
 
 		stri int // Offset in str (0 means empty)
 		stri int // Offset in str (0 means empty)
 		comi int // Offset in com (0 means empty)
 		comi int // Offset in com (0 means empty)
@@ -785,14 +783,12 @@ func (zl *zlexer) Next() (lex, bool) {
 		l.line, l.column = zl.line, zl.column
 		l.line, l.column = zl.line, zl.column
 
 
 		if stri >= len(str) {
 		if stri >= len(str) {
-			l.token = "token length insufficient for parsing"
-			l.err = true
-			return *l, true
+			// if buffer length is insufficient, increase it.
+			str = append(str[:], make([]byte, maxTok)...)
 		}
 		}
 		if comi >= len(com) {
 		if comi >= len(com) {
-			l.token = "comment length insufficient for parsing"
-			l.err = true
-			return *l, true
+			// if buffer length is insufficient, increase it.
+			com = append(com[:], make([]byte, maxTok)...)
 		}
 		}
 
 
 		switch x {
 		switch x {
@@ -816,7 +812,7 @@ func (zl *zlexer) Next() (lex, bool) {
 			if stri == 0 {
 			if stri == 0 {
 				// Space directly in the beginning, handled in the grammar
 				// Space directly in the beginning, handled in the grammar
 			} else if zl.owner {
 			} else if zl.owner {
-				// If we have a string and its the first, make it an owner
+				// If we have a string and it's the first, make it an owner
 				l.value = zOwner
 				l.value = zOwner
 				l.token = string(str[:stri])
 				l.token = string(str[:stri])
 
 
@@ -1218,42 +1214,34 @@ func stringToCm(token string) (e, m uint8, ok bool) {
 	if token[len(token)-1] == 'M' || token[len(token)-1] == 'm' {
 	if token[len(token)-1] == 'M' || token[len(token)-1] == 'm' {
 		token = token[0 : len(token)-1]
 		token = token[0 : len(token)-1]
 	}
 	}
-	s := strings.SplitN(token, ".", 2)
-	var meters, cmeters, val int
-	var err error
-	switch len(s) {
-	case 2:
-		if cmeters, err = strconv.Atoi(s[1]); err != nil {
-			return
-		}
+
+	var (
+		meters, cmeters, val int
+		err                  error
+	)
+	mStr, cmStr, hasCM := strings.Cut(token, ".")
+	if hasCM {
 		// There's no point in having more than 2 digits in this part, and would rather make the implementation complicated ('123' should be treated as '12').
 		// There's no point in having more than 2 digits in this part, and would rather make the implementation complicated ('123' should be treated as '12').
 		// So we simply reject it.
 		// So we simply reject it.
 		// We also make sure the first character is a digit to reject '+-' signs.
 		// We also make sure the first character is a digit to reject '+-' signs.
-		if len(s[1]) > 2 || s[1][0] < '0' || s[1][0] > '9' {
+		cmeters, err = strconv.Atoi(cmStr)
+		if err != nil || len(cmStr) > 2 || cmStr[0] < '0' || cmStr[0] > '9' {
 			return
 			return
 		}
 		}
-		if len(s[1]) == 1 {
+		if len(cmStr) == 1 {
 			// 'nn.1' must be treated as 'nn-meters and 10cm, not 1cm.
 			// 'nn.1' must be treated as 'nn-meters and 10cm, not 1cm.
 			cmeters *= 10
 			cmeters *= 10
 		}
 		}
-		if s[0] == "" {
-			// This will allow omitting the 'meter' part, like .01 (meaning 0.01m = 1cm).
-			break
-		}
-		fallthrough
-	case 1:
-		if meters, err = strconv.Atoi(s[0]); err != nil {
-			return
-		}
+	}
+	// This slighly ugly condition will allow omitting the 'meter' part, like .01 (meaning 0.01m = 1cm).
+	if !hasCM || mStr != "" {
+		meters, err = strconv.Atoi(mStr)
 		// RFC1876 states the max value is 90000000.00.  The latter two conditions enforce it.
 		// RFC1876 states the max value is 90000000.00.  The latter two conditions enforce it.
-		if s[0][0] < '0' || s[0][0] > '9' || meters > 90000000 || (meters == 90000000 && cmeters != 0) {
+		if err != nil || mStr[0] < '0' || mStr[0] > '9' || meters > 90000000 || (meters == 90000000 && cmeters != 0) {
 			return
 			return
 		}
 		}
-	case 0:
-		// huh?
-		return 0, 0, false
 	}
 	}
-	ok = true
+
 	if meters > 0 {
 	if meters > 0 {
 		e = 2
 		e = 2
 		val = meters
 		val = meters
@@ -1265,8 +1253,7 @@ func stringToCm(token string) (e, m uint8, ok bool) {
 		e++
 		e++
 		val /= 10
 		val /= 10
 	}
 	}
-	m = uint8(val)
-	return
+	return e, uint8(val), true
 }
 }
 
 
 func toAbsoluteName(name, origin string) (absolute string, ok bool) {
 func toAbsoluteName(name, origin string) (absolute string, ok bool) {

+ 126 - 8
vendor/github.com/miekg/dns/scan_rr.go

@@ -1,8 +1,8 @@
 package dns
 package dns
 
 
 import (
 import (
-	"bytes"
 	"encoding/base64"
 	"encoding/base64"
+	"errors"
 	"net"
 	"net"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
@@ -11,15 +11,15 @@ import (
 // A remainder of the rdata with embedded spaces, return the parsed string (sans the spaces)
 // A remainder of the rdata with embedded spaces, return the parsed string (sans the spaces)
 // or an error
 // or an error
 func endingToString(c *zlexer, errstr string) (string, *ParseError) {
 func endingToString(c *zlexer, errstr string) (string, *ParseError) {
-	var buffer bytes.Buffer
+	var s strings.Builder
 	l, _ := c.Next() // zString
 	l, _ := c.Next() // zString
 	for l.value != zNewline && l.value != zEOF {
 	for l.value != zNewline && l.value != zEOF {
 		if l.err {
 		if l.err {
-			return buffer.String(), &ParseError{"", errstr, l}
+			return s.String(), &ParseError{"", errstr, l}
 		}
 		}
 		switch l.value {
 		switch l.value {
 		case zString:
 		case zString:
-			buffer.WriteString(l.token)
+			s.WriteString(l.token)
 		case zBlank: // Ok
 		case zBlank: // Ok
 		default:
 		default:
 			return "", &ParseError{"", errstr, l}
 			return "", &ParseError{"", errstr, l}
@@ -27,7 +27,7 @@ func endingToString(c *zlexer, errstr string) (string, *ParseError) {
 		l, _ = c.Next()
 		l, _ = c.Next()
 	}
 	}
 
 
-	return buffer.String(), nil
+	return s.String(), nil
 }
 }
 
 
 // A remainder of the rdata with embedded spaces, split on unquoted whitespace
 // A remainder of the rdata with embedded spaces, split on unquoted whitespace
@@ -903,11 +903,18 @@ func (rr *RRSIG) parse(c *zlexer, o string) *ParseError {
 
 
 	c.Next() // zBlank
 	c.Next() // zBlank
 	l, _ = c.Next()
 	l, _ = c.Next()
-	i, e := strconv.ParseUint(l.token, 10, 8)
-	if e != nil || l.err {
+	if l.err {
 		return &ParseError{"", "bad RRSIG Algorithm", l}
 		return &ParseError{"", "bad RRSIG Algorithm", l}
 	}
 	}
-	rr.Algorithm = uint8(i)
+	i, e := strconv.ParseUint(l.token, 10, 8)
+	rr.Algorithm = uint8(i) // if 0 we'll check the mnemonic in the if
+	if e != nil {
+		v, ok := StringToAlgorithm[l.token]
+		if !ok {
+			return &ParseError{"", "bad RRSIG Algorithm", l}
+		}
+		rr.Algorithm = v
+	}
 
 
 	c.Next() // zBlank
 	c.Next() // zBlank
 	l, _ = c.Next()
 	l, _ = c.Next()
@@ -1216,6 +1223,117 @@ func (rr *DS) parse(c *zlexer, o string) *ParseError      { return rr.parseDS(c,
 func (rr *DLV) parse(c *zlexer, o string) *ParseError     { return rr.parseDS(c, o, "DLV") }
 func (rr *DLV) parse(c *zlexer, o string) *ParseError     { return rr.parseDS(c, o, "DLV") }
 func (rr *CDS) parse(c *zlexer, o string) *ParseError     { return rr.parseDS(c, o, "CDS") }
 func (rr *CDS) parse(c *zlexer, o string) *ParseError     { return rr.parseDS(c, o, "CDS") }
 
 
+func (rr *IPSECKEY) parse(c *zlexer, o string) *ParseError {
+	l, _ := c.Next()
+	num, err := strconv.ParseUint(l.token, 10, 8)
+	if err != nil || l.err {
+		return &ParseError{"", "bad IPSECKEY value", l}
+	}
+	rr.Precedence = uint8(num)
+	c.Next() // zBlank
+
+	l, _ = c.Next()
+	num, err = strconv.ParseUint(l.token, 10, 8)
+	if err != nil || l.err {
+		return &ParseError{"", "bad IPSECKEY value", l}
+	}
+	rr.GatewayType = uint8(num)
+	c.Next() // zBlank
+
+	l, _ = c.Next()
+	num, err = strconv.ParseUint(l.token, 10, 8)
+	if err != nil || l.err {
+		return &ParseError{"", "bad IPSECKEY value", l}
+	}
+	rr.Algorithm = uint8(num)
+	c.Next() // zBlank
+
+	l, _ = c.Next()
+	if l.err {
+		return &ParseError{"", "bad IPSECKEY gateway", l}
+	}
+
+	rr.GatewayAddr, rr.GatewayHost, err = parseAddrHostUnion(l.token, o, rr.GatewayType)
+	if err != nil {
+		return &ParseError{"", "IPSECKEY " + err.Error(), l}
+	}
+
+	c.Next() // zBlank
+
+	s, pErr := endingToString(c, "bad IPSECKEY PublicKey")
+	if pErr != nil {
+		return pErr
+	}
+	rr.PublicKey = s
+	return slurpRemainder(c)
+}
+
+func (rr *AMTRELAY) parse(c *zlexer, o string) *ParseError {
+	l, _ := c.Next()
+	num, err := strconv.ParseUint(l.token, 10, 8)
+	if err != nil || l.err {
+		return &ParseError{"", "bad AMTRELAY value", l}
+	}
+	rr.Precedence = uint8(num)
+	c.Next() // zBlank
+
+	l, _ = c.Next()
+	if l.err || !(l.token == "0" || l.token == "1") {
+		return &ParseError{"", "bad discovery value", l}
+	}
+	if l.token == "1" {
+		rr.GatewayType = 0x80
+	}
+
+	c.Next() // zBlank
+
+	l, _ = c.Next()
+	num, err = strconv.ParseUint(l.token, 10, 8)
+	if err != nil || l.err {
+		return &ParseError{"", "bad AMTRELAY value", l}
+	}
+	rr.GatewayType |= uint8(num)
+	c.Next() // zBlank
+
+	l, _ = c.Next()
+	if l.err {
+		return &ParseError{"", "bad AMTRELAY gateway", l}
+	}
+
+	rr.GatewayAddr, rr.GatewayHost, err = parseAddrHostUnion(l.token, o, rr.GatewayType&0x7f)
+	if err != nil {
+		return &ParseError{"", "AMTRELAY " + err.Error(), l}
+	}
+
+	return slurpRemainder(c)
+}
+
+// same constants and parsing between IPSECKEY and AMTRELAY
+func parseAddrHostUnion(token, o string, gatewayType uint8) (addr net.IP, host string, err error) {
+	switch gatewayType {
+	case IPSECGatewayNone:
+		if token != "." {
+			return addr, host, errors.New("gateway type none with gateway set")
+		}
+	case IPSECGatewayIPv4, IPSECGatewayIPv6:
+		addr = net.ParseIP(token)
+		if addr == nil {
+			return addr, host, errors.New("gateway IP invalid")
+		}
+		if (addr.To4() == nil) == (gatewayType == IPSECGatewayIPv4) {
+			return addr, host, errors.New("gateway IP family mismatch")
+		}
+	case IPSECGatewayHost:
+		var ok bool
+		host, ok = toAbsoluteName(token, o)
+		if !ok {
+			return addr, host, errors.New("invalid gateway host")
+		}
+	}
+
+	return addr, host, nil
+}
+
 func (rr *RKEY) parse(c *zlexer, o string) *ParseError {
 func (rr *RKEY) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
 	l, _ := c.Next()
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	i, e := strconv.ParseUint(l.token, 10, 16)

+ 34 - 22
vendor/github.com/miekg/dns/server.go

@@ -18,7 +18,7 @@ import (
 const maxTCPQueries = 128
 const maxTCPQueries = 128
 
 
 // aLongTimeAgo is a non-zero time, far in the past, used for
 // aLongTimeAgo is a non-zero time, far in the past, used for
-// immediate cancelation of network operations.
+// immediate cancellation of network operations.
 var aLongTimeAgo = time.Unix(1, 0)
 var aLongTimeAgo = time.Unix(1, 0)
 
 
 // Handler is implemented by any value that implements ServeDNS.
 // Handler is implemented by any value that implements ServeDNS.
@@ -71,12 +71,12 @@ type response struct {
 	tsigTimersOnly bool
 	tsigTimersOnly bool
 	tsigStatus     error
 	tsigStatus     error
 	tsigRequestMAC string
 	tsigRequestMAC string
-	tsigSecret     map[string]string // the tsig secrets
-	udp            net.PacketConn    // i/o connection if UDP was used
-	tcp            net.Conn          // i/o connection if TCP was used
-	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
+	tsigProvider   TsigProvider
+	udp            net.PacketConn // i/o connection if UDP was used
+	tcp            net.Conn       // i/o connection if TCP was used
+	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
 }
 }
 
 
 // handleRefused returns a HandlerFunc that returns REFUSED for every request it gets.
 // handleRefused returns a HandlerFunc that returns REFUSED for every request it gets.
@@ -211,6 +211,8 @@ type Server struct {
 	WriteTimeout time.Duration
 	WriteTimeout time.Duration
 	// TCP idle timeout for multiple queries, if nil, defaults to 8 * time.Second (RFC 5966).
 	// TCP idle timeout for multiple queries, if nil, defaults to 8 * time.Second (RFC 5966).
 	IdleTimeout func() time.Duration
 	IdleTimeout func() time.Duration
+	// An implementation of the TsigProvider interface. If defined it replaces TsigSecret and is used for all TSIG operations.
+	TsigProvider TsigProvider
 	// Secret(s) for Tsig map[<zonename>]<base64 secret>. The zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2).
 	// Secret(s) for Tsig map[<zonename>]<base64 secret>. The zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2).
 	TsigSecret map[string]string
 	TsigSecret map[string]string
 	// If NotifyStartedFunc is set it is called once the server has started listening.
 	// If NotifyStartedFunc is set it is called once the server has started listening.
@@ -222,8 +224,12 @@ type Server struct {
 	// Maximum number of TCP queries before we close the socket. Default is maxTCPQueries (unlimited if -1).
 	// Maximum number of TCP queries before we close the socket. Default is maxTCPQueries (unlimited if -1).
 	MaxTCPQueries int
 	MaxTCPQueries int
 	// Whether to set the SO_REUSEPORT socket option, allowing multiple listeners to be bound to a single address.
 	// Whether to set the SO_REUSEPORT socket option, allowing multiple listeners to be bound to a single address.
-	// It is only supported on go1.11+ and when using ListenAndServe.
+	// It is only supported on certain GOOSes and when using ListenAndServe.
 	ReusePort bool
 	ReusePort bool
+	// Whether to set the SO_REUSEADDR socket option, allowing multiple listeners to be bound to a single address.
+	// Crucially this allows binding when an existing server is listening on `0.0.0.0` or `::`.
+	// It is only supported on certain GOOSes and when using ListenAndServe.
+	ReuseAddr bool
 	// AcceptMsgFunc will check the incoming message and will reject it early in the process.
 	// AcceptMsgFunc will check the incoming message and will reject it early in the process.
 	// By default DefaultMsgAcceptFunc will be used.
 	// By default DefaultMsgAcceptFunc will be used.
 	MsgAcceptFunc MsgAcceptFunc
 	MsgAcceptFunc MsgAcceptFunc
@@ -238,6 +244,16 @@ type Server struct {
 	udpPool sync.Pool
 	udpPool sync.Pool
 }
 }
 
 
+func (srv *Server) tsigProvider() TsigProvider {
+	if srv.TsigProvider != nil {
+		return srv.TsigProvider
+	}
+	if srv.TsigSecret != nil {
+		return tsigSecretProvider(srv.TsigSecret)
+	}
+	return nil
+}
+
 func (srv *Server) isStarted() bool {
 func (srv *Server) isStarted() bool {
 	srv.lock.RLock()
 	srv.lock.RLock()
 	started := srv.started
 	started := srv.started
@@ -292,7 +308,7 @@ func (srv *Server) ListenAndServe() error {
 
 
 	switch srv.Net {
 	switch srv.Net {
 	case "tcp", "tcp4", "tcp6":
 	case "tcp", "tcp4", "tcp6":
-		l, err := listenTCP(srv.Net, addr, srv.ReusePort)
+		l, err := listenTCP(srv.Net, addr, srv.ReusePort, srv.ReuseAddr)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
@@ -305,7 +321,7 @@ func (srv *Server) ListenAndServe() error {
 			return errors.New("dns: neither Certificates nor GetCertificate set in Config")
 			return errors.New("dns: neither Certificates nor GetCertificate set in Config")
 		}
 		}
 		network := strings.TrimSuffix(srv.Net, "-tls")
 		network := strings.TrimSuffix(srv.Net, "-tls")
-		l, err := listenTCP(network, addr, srv.ReusePort)
+		l, err := listenTCP(network, addr, srv.ReusePort, srv.ReuseAddr)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
@@ -315,7 +331,7 @@ func (srv *Server) ListenAndServe() error {
 		unlock()
 		unlock()
 		return srv.serveTCP(l)
 		return srv.serveTCP(l)
 	case "udp", "udp4", "udp6":
 	case "udp", "udp4", "udp6":
-		l, err := listenUDP(srv.Net, addr, srv.ReusePort)
+		l, err := listenUDP(srv.Net, addr, srv.ReusePort, srv.ReuseAddr)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
@@ -526,7 +542,7 @@ func (srv *Server) serveUDP(l net.PacketConn) error {
 
 
 // Serve a new TCP connection.
 // Serve a new TCP connection.
 func (srv *Server) serveTCPConn(wg *sync.WaitGroup, rw net.Conn) {
 func (srv *Server) serveTCPConn(wg *sync.WaitGroup, rw net.Conn) {
-	w := &response{tsigSecret: srv.TsigSecret, tcp: rw}
+	w := &response{tsigProvider: srv.tsigProvider(), tcp: rw}
 	if srv.DecorateWriter != nil {
 	if srv.DecorateWriter != nil {
 		w.writer = srv.DecorateWriter(w)
 		w.writer = srv.DecorateWriter(w)
 	} else {
 	} else {
@@ -581,7 +597,7 @@ func (srv *Server) serveTCPConn(wg *sync.WaitGroup, rw net.Conn) {
 
 
 // Serve a new UDP request.
 // Serve a new UDP request.
 func (srv *Server) serveUDPPacket(wg *sync.WaitGroup, m []byte, u net.PacketConn, udpSession *SessionUDP, pcSession net.Addr) {
 func (srv *Server) serveUDPPacket(wg *sync.WaitGroup, m []byte, u net.PacketConn, udpSession *SessionUDP, pcSession net.Addr) {
-	w := &response{tsigSecret: srv.TsigSecret, udp: u, udpSession: udpSession, pcSession: pcSession}
+	w := &response{tsigProvider: srv.tsigProvider(), udp: u, udpSession: udpSession, pcSession: pcSession}
 	if srv.DecorateWriter != nil {
 	if srv.DecorateWriter != nil {
 		w.writer = srv.DecorateWriter(w)
 		w.writer = srv.DecorateWriter(w)
 	} else {
 	} else {
@@ -632,15 +648,11 @@ func (srv *Server) serveDNS(m []byte, w *response) {
 	}
 	}
 
 
 	w.tsigStatus = nil
 	w.tsigStatus = nil
-	if w.tsigSecret != nil {
+	if w.tsigProvider != nil {
 		if t := req.IsTsig(); t != nil {
 		if t := req.IsTsig(); t != nil {
-			if secret, ok := w.tsigSecret[t.Hdr.Name]; ok {
-				w.tsigStatus = TsigVerify(m, secret, "", false)
-			} else {
-				w.tsigStatus = ErrSecret
-			}
+			w.tsigStatus = TsigVerifyWithProvider(m, w.tsigProvider, "", false)
 			w.tsigTimersOnly = false
 			w.tsigTimersOnly = false
-			w.tsigRequestMAC = req.Extra[len(req.Extra)-1].(*TSIG).MAC
+			w.tsigRequestMAC = t.MAC
 		}
 		}
 	}
 	}
 
 
@@ -718,9 +730,9 @@ func (w *response) WriteMsg(m *Msg) (err error) {
 	}
 	}
 
 
 	var data []byte
 	var data []byte
-	if w.tsigSecret != nil { // if no secrets, dont check for the tsig (which is a longer check)
+	if w.tsigProvider != nil { // if no provider, dont check for the tsig (which is a longer check)
 		if t := m.IsTsig(); t != nil {
 		if t := m.IsTsig(); t != nil {
-			data, w.tsigRequestMAC, err = TsigGenerate(m, w.tsigSecret[t.Hdr.Name], w.tsigRequestMAC, w.tsigTimersOnly)
+			data, w.tsigRequestMAC, err = TsigGenerateWithProvider(m, w.tsigProvider, w.tsigRequestMAC, w.tsigTimersOnly)
 			if err != nil {
 			if err != nil {
 				return err
 				return err
 			}
 			}

+ 25 - 28
vendor/github.com/miekg/dns/sig0.go

@@ -3,6 +3,7 @@ package dns
 import (
 import (
 	"crypto"
 	"crypto"
 	"crypto/ecdsa"
 	"crypto/ecdsa"
+	"crypto/ed25519"
 	"crypto/rsa"
 	"crypto/rsa"
 	"encoding/binary"
 	"encoding/binary"
 	"math/big"
 	"math/big"
@@ -38,18 +39,17 @@ func (rr *SIG) Sign(k crypto.Signer, m *Msg) ([]byte, error) {
 	}
 	}
 	buf = buf[:off:cap(buf)]
 	buf = buf[:off:cap(buf)]
 
 
-	hash, ok := AlgorithmToHash[rr.Algorithm]
-	if !ok {
-		return nil, ErrAlg
+	h, cryptohash, err := hashFromAlgorithm(rr.Algorithm)
+	if err != nil {
+		return nil, err
 	}
 	}
 
 
-	hasher := hash.New()
 	// Write SIG rdata
 	// Write SIG rdata
-	hasher.Write(buf[len(mbuf)+1+2+2+4+2:])
+	h.Write(buf[len(mbuf)+1+2+2+4+2:])
 	// Write message
 	// Write message
-	hasher.Write(buf[:len(mbuf)])
+	h.Write(buf[:len(mbuf)])
 
 
-	signature, err := sign(k, hasher.Sum(nil), hash, rr.Algorithm)
+	signature, err := sign(k, h.Sum(nil), cryptohash, rr.Algorithm)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -82,20 +82,10 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
 		return ErrKey
 		return ErrKey
 	}
 	}
 
 
-	var hash crypto.Hash
-	switch rr.Algorithm {
-	case RSASHA1:
-		hash = crypto.SHA1
-	case RSASHA256, ECDSAP256SHA256:
-		hash = crypto.SHA256
-	case ECDSAP384SHA384:
-		hash = crypto.SHA384
-	case RSASHA512:
-		hash = crypto.SHA512
-	default:
-		return ErrAlg
-	}
-	hasher := hash.New()
+	h, cryptohash, err := hashFromAlgorithm(rr.Algorithm)
+	if err != nil {
+		return err
+	}
 
 
 	buflen := len(buf)
 	buflen := len(buf)
 	qdc := binary.BigEndian.Uint16(buf[4:])
 	qdc := binary.BigEndian.Uint16(buf[4:])
@@ -103,7 +93,6 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
 	auc := binary.BigEndian.Uint16(buf[8:])
 	auc := binary.BigEndian.Uint16(buf[8:])
 	adc := binary.BigEndian.Uint16(buf[10:])
 	adc := binary.BigEndian.Uint16(buf[10:])
 	offset := headerSize
 	offset := headerSize
-	var err error
 	for i := uint16(0); i < qdc && offset < buflen; i++ {
 	for i := uint16(0); i < qdc && offset < buflen; i++ {
 		_, offset, err = UnpackDomainName(buf, offset)
 		_, offset, err = UnpackDomainName(buf, offset)
 		if err != nil {
 		if err != nil {
@@ -166,21 +155,21 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
 		return &Error{err: "signer name doesn't match key name"}
 		return &Error{err: "signer name doesn't match key name"}
 	}
 	}
 	sigend := offset
 	sigend := offset
-	hasher.Write(buf[sigstart:sigend])
-	hasher.Write(buf[:10])
-	hasher.Write([]byte{
+	h.Write(buf[sigstart:sigend])
+	h.Write(buf[:10])
+	h.Write([]byte{
 		byte((adc - 1) << 8),
 		byte((adc - 1) << 8),
 		byte(adc - 1),
 		byte(adc - 1),
 	})
 	})
-	hasher.Write(buf[12:bodyend])
+	h.Write(buf[12:bodyend])
 
 
-	hashed := hasher.Sum(nil)
+	hashed := h.Sum(nil)
 	sig := buf[sigend:]
 	sig := buf[sigend:]
 	switch k.Algorithm {
 	switch k.Algorithm {
 	case RSASHA1, RSASHA256, RSASHA512:
 	case RSASHA1, RSASHA256, RSASHA512:
 		pk := k.publicKeyRSA()
 		pk := k.publicKeyRSA()
 		if pk != nil {
 		if pk != nil {
-			return rsa.VerifyPKCS1v15(pk, hash, hashed, sig)
+			return rsa.VerifyPKCS1v15(pk, cryptohash, hashed, sig)
 		}
 		}
 	case ECDSAP256SHA256, ECDSAP384SHA384:
 	case ECDSAP256SHA256, ECDSAP384SHA384:
 		pk := k.publicKeyECDSA()
 		pk := k.publicKeyECDSA()
@@ -192,6 +181,14 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
 			}
 			}
 			return ErrSig
 			return ErrSig
 		}
 		}
+	case ED25519:
+		pk := k.publicKeyED25519()
+		if pk != nil {
+			if ed25519.Verify(pk, hashed, sig) {
+				return nil
+			}
+			return ErrSig
+		}
 	}
 	}
 	return ErrKeyAlg
 	return ErrKeyAlg
 }
 }

+ 0 - 61
vendor/github.com/miekg/dns/singleinflight.go

@@ -1,61 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Adapted for dns package usage by Miek Gieben.
-
-package dns
-
-import "sync"
-import "time"
-
-// call is an in-flight or completed singleflight.Do call
-type call struct {
-	wg   sync.WaitGroup
-	val  *Msg
-	rtt  time.Duration
-	err  error
-	dups int
-}
-
-// singleflight represents a class of work and forms a namespace in
-// which units of work can be executed with duplicate suppression.
-type singleflight struct {
-	sync.Mutex                  // protects m
-	m          map[string]*call // lazily initialized
-
-	dontDeleteForTesting bool // this is only to be used by TestConcurrentExchanges
-}
-
-// Do executes and returns the results of the given function, making
-// sure that only one execution is in-flight for a given key at a
-// time. If a duplicate comes in, the duplicate caller waits for the
-// original to complete and receives the same results.
-// The return value shared indicates whether v was given to multiple callers.
-func (g *singleflight) Do(key string, fn func() (*Msg, time.Duration, error)) (v *Msg, rtt time.Duration, err error, shared bool) {
-	g.Lock()
-	if g.m == nil {
-		g.m = make(map[string]*call)
-	}
-	if c, ok := g.m[key]; ok {
-		c.dups++
-		g.Unlock()
-		c.wg.Wait()
-		return c.val, c.rtt, c.err, true
-	}
-	c := new(call)
-	c.wg.Add(1)
-	g.m[key] = c
-	g.Unlock()
-
-	c.val, c.rtt, c.err = fn()
-	c.wg.Done()
-
-	if !g.dontDeleteForTesting {
-		g.Lock()
-		delete(g.m, key)
-		g.Unlock()
-	}
-
-	return c.val, c.rtt, c.err, c.dups > 0
-}

+ 298 - 118
vendor/github.com/miekg/dns/svcb.go

@@ -4,6 +4,7 @@ import (
 	"bytes"
 	"bytes"
 	"encoding/binary"
 	"encoding/binary"
 	"errors"
 	"errors"
+	"fmt"
 	"net"
 	"net"
 	"sort"
 	"sort"
 	"strconv"
 	"strconv"
@@ -13,16 +14,18 @@ import (
 // SVCBKey is the type of the keys used in the SVCB RR.
 // SVCBKey is the type of the keys used in the SVCB RR.
 type SVCBKey uint16
 type SVCBKey uint16
 
 
-// Keys defined in draft-ietf-dnsop-svcb-https-01 Section 12.3.2.
+// Keys defined in draft-ietf-dnsop-svcb-https-08 Section 14.3.2.
 const (
 const (
-	SVCB_MANDATORY       SVCBKey = 0
-	SVCB_ALPN            SVCBKey = 1
-	SVCB_NO_DEFAULT_ALPN SVCBKey = 2
-	SVCB_PORT            SVCBKey = 3
-	SVCB_IPV4HINT        SVCBKey = 4
-	SVCB_ECHCONFIG       SVCBKey = 5
-	SVCB_IPV6HINT        SVCBKey = 6
-	svcb_RESERVED        SVCBKey = 65535
+	SVCB_MANDATORY SVCBKey = iota
+	SVCB_ALPN
+	SVCB_NO_DEFAULT_ALPN
+	SVCB_PORT
+	SVCB_IPV4HINT
+	SVCB_ECHCONFIG
+	SVCB_IPV6HINT
+	SVCB_DOHPATH // draft-ietf-add-svcb-dns-02 Section 9
+
+	svcb_RESERVED SVCBKey = 65535
 )
 )
 
 
 var svcbKeyToStringMap = map[SVCBKey]string{
 var svcbKeyToStringMap = map[SVCBKey]string{
@@ -31,8 +34,9 @@ var svcbKeyToStringMap = map[SVCBKey]string{
 	SVCB_NO_DEFAULT_ALPN: "no-default-alpn",
 	SVCB_NO_DEFAULT_ALPN: "no-default-alpn",
 	SVCB_PORT:            "port",
 	SVCB_PORT:            "port",
 	SVCB_IPV4HINT:        "ipv4hint",
 	SVCB_IPV4HINT:        "ipv4hint",
-	SVCB_ECHCONFIG:       "echconfig",
+	SVCB_ECHCONFIG:       "ech",
 	SVCB_IPV6HINT:        "ipv6hint",
 	SVCB_IPV6HINT:        "ipv6hint",
+	SVCB_DOHPATH:         "dohpath",
 }
 }
 
 
 var svcbStringToKeyMap = reverseSVCBKeyMap(svcbKeyToStringMap)
 var svcbStringToKeyMap = reverseSVCBKeyMap(svcbKeyToStringMap)
@@ -167,10 +171,14 @@ func (rr *SVCB) parse(c *zlexer, o string) *ParseError {
 		}
 		}
 		l, _ = c.Next()
 		l, _ = c.Next()
 	}
 	}
+
+	// "In AliasMode, records SHOULD NOT include any SvcParams, and recipients MUST
+	// ignore any SvcParams that are present."
+	// However, we don't check rr.Priority == 0 && len(xs) > 0 here
+	// It is the responsibility of the user of the library to check this.
+	// This is to encourage the fixing of the source of this error.
+
 	rr.Value = xs
 	rr.Value = xs
-	if rr.Priority == 0 && len(xs) > 0 {
-		return &ParseError{l.token, "SVCB aliasform can't have values", l}
-	}
 	return nil
 	return nil
 }
 }
 
 
@@ -191,6 +199,8 @@ func makeSVCBKeyValue(key SVCBKey) SVCBKeyValue {
 		return new(SVCBECHConfig)
 		return new(SVCBECHConfig)
 	case SVCB_IPV6HINT:
 	case SVCB_IPV6HINT:
 		return new(SVCBIPv6Hint)
 		return new(SVCBIPv6Hint)
+	case SVCB_DOHPATH:
+		return new(SVCBDoHPath)
 	case svcb_RESERVED:
 	case svcb_RESERVED:
 		return nil
 		return nil
 	default:
 	default:
@@ -200,16 +210,24 @@ func makeSVCBKeyValue(key SVCBKey) SVCBKeyValue {
 	}
 	}
 }
 }
 
 
-// SVCB RR. See RFC xxxx (https://tools.ietf.org/html/draft-ietf-dnsop-svcb-https-01).
+// 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.
 type SVCB struct {
 type SVCB struct {
 	Hdr      RR_Header
 	Hdr      RR_Header
-	Priority uint16
+	Priority uint16         // If zero, Value must be empty or discarded by the user of this library
 	Target   string         `dns:"domain-name"`
 	Target   string         `dns:"domain-name"`
-	Value    []SVCBKeyValue `dns:"pairs"` // Value must be empty if Priority is zero.
+	Value    []SVCBKeyValue `dns:"pairs"`
 }
 }
 
 
 // HTTPS RR. Everything valid for SVCB applies to HTTPS as well.
 // HTTPS RR. Everything valid for SVCB applies to HTTPS as well.
 // Except that the HTTPS record is intended for use with the HTTP and HTTPS protocols.
 // 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 {
 type HTTPS struct {
 	SVCB
 	SVCB
 }
 }
@@ -235,15 +253,29 @@ type SVCBKeyValue interface {
 }
 }
 
 
 // SVCBMandatory pair adds to required keys that must be interpreted for the RR
 // SVCBMandatory pair adds to required keys that must be interpreted for the RR
-// to be functional.
+// to be functional. If ignored, the whole RRSet must be ignored.
+// "port" and "no-default-alpn" are mandatory by default if present,
+// so they shouldn't be included here.
+//
+// It is incumbent upon the user of this library to reject the RRSet if
+// or avoid constructing such an RRSet that:
+// - "mandatory" is included as one of the keys of mandatory
+// - no key is listed multiple times in mandatory
+// - all keys listed in mandatory are present
+// - escape sequences are not used in mandatory
+// - mandatory, when present, lists at least one key
+//
 // Basic use pattern for creating a mandatory option:
 // Basic use pattern for creating a mandatory option:
 //
 //
 //	s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
 //	s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
 //	e := new(dns.SVCBMandatory)
 //	e := new(dns.SVCBMandatory)
-//	e.Code = []uint16{65403}
+//	e.Code = []uint16{dns.SVCB_ALPN}
 //	s.Value = append(s.Value, e)
 //	s.Value = append(s.Value, e)
+//	t := new(dns.SVCBAlpn)
+//	t.Alpn = []string{"xmpp-client"}
+//	s.Value = append(s.Value, t)
 type SVCBMandatory struct {
 type SVCBMandatory struct {
-	Code []SVCBKey // Must not include mandatory
+	Code []SVCBKey
 }
 }
 
 
 func (*SVCBMandatory) Key() SVCBKey { return SVCB_MANDATORY }
 func (*SVCBMandatory) Key() SVCBKey { return SVCB_MANDATORY }
@@ -257,7 +289,7 @@ func (s *SVCBMandatory) String() string {
 }
 }
 
 
 func (s *SVCBMandatory) pack() ([]byte, error) {
 func (s *SVCBMandatory) pack() ([]byte, error) {
-	codes := append([]SVCBKey(nil), s.Code...)
+	codes := cloneSlice(s.Code)
 	sort.Slice(codes, func(i, j int) bool {
 	sort.Slice(codes, func(i, j int) bool {
 		return codes[i] < codes[j]
 		return codes[i] < codes[j]
 	})
 	})
@@ -282,10 +314,11 @@ func (s *SVCBMandatory) unpack(b []byte) error {
 }
 }
 
 
 func (s *SVCBMandatory) parse(b string) error {
 func (s *SVCBMandatory) parse(b string) error {
-	str := strings.Split(b, ",")
-	codes := make([]SVCBKey, 0, len(str))
-	for _, e := range str {
-		codes = append(codes, svcbStringToKey(e))
+	codes := make([]SVCBKey, 0, strings.Count(b, ",")+1)
+	for len(b) > 0 {
+		var key string
+		key, b, _ = strings.Cut(b, ",")
+		codes = append(codes, svcbStringToKey(key))
 	}
 	}
 	s.Code = codes
 	s.Code = codes
 	return nil
 	return nil
@@ -296,13 +329,12 @@ func (s *SVCBMandatory) len() int {
 }
 }
 
 
 func (s *SVCBMandatory) copy() SVCBKeyValue {
 func (s *SVCBMandatory) copy() SVCBKeyValue {
-	return &SVCBMandatory{
-		append([]SVCBKey(nil), s.Code...),
-	}
+	return &SVCBMandatory{cloneSlice(s.Code)}
 }
 }
 
 
 // SVCBAlpn pair is used to list supported connection protocols.
 // SVCBAlpn pair is used to list supported connection protocols.
-// Protocol ids can be found at:
+// The user of this library must ensure that at least one protocol is listed when alpn is present.
+// Protocol IDs can be found at:
 // https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids
 // https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids
 // Basic use pattern for creating an alpn option:
 // Basic use pattern for creating an alpn option:
 //
 //
@@ -310,13 +342,57 @@ func (s *SVCBMandatory) copy() SVCBKeyValue {
 //	h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
 //	h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
 //	e := new(dns.SVCBAlpn)
 //	e := new(dns.SVCBAlpn)
 //	e.Alpn = []string{"h2", "http/1.1"}
 //	e.Alpn = []string{"h2", "http/1.1"}
-//	h.Value = append(o.Value, e)
+//	h.Value = append(h.Value, e)
 type SVCBAlpn struct {
 type SVCBAlpn struct {
 	Alpn []string
 	Alpn []string
 }
 }
 
 
-func (*SVCBAlpn) Key() SVCBKey     { return SVCB_ALPN }
-func (s *SVCBAlpn) String() string { return strings.Join(s.Alpn, ",") }
+func (*SVCBAlpn) Key() SVCBKey { return SVCB_ALPN }
+
+func (s *SVCBAlpn) String() string {
+	// An ALPN value is a comma-separated list of values, each of which can be
+	// an arbitrary binary value. In order to allow parsing, the comma and
+	// backslash characters are themselves escaped.
+	//
+	// However, this escaping is done in addition to the normal escaping which
+	// happens in zone files, meaning that these values must be
+	// double-escaped. This looks terrible, so if you see a never-ending
+	// sequence of backslash in a zone file this may be why.
+	//
+	// https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-08#appendix-A.1
+	var str strings.Builder
+	for i, alpn := range s.Alpn {
+		// 4*len(alpn) is the worst case where we escape every character in the alpn as \123, plus 1 byte for the ',' separating the alpn from others
+		str.Grow(4*len(alpn) + 1)
+		if i > 0 {
+			str.WriteByte(',')
+		}
+		for j := 0; j < len(alpn); j++ {
+			e := alpn[j]
+			if ' ' > e || e > '~' {
+				str.WriteString(escapeByte(e))
+				continue
+			}
+			switch e {
+			// We escape a few characters which may confuse humans or parsers.
+			case '"', ';', ' ':
+				str.WriteByte('\\')
+				str.WriteByte(e)
+			// The comma and backslash characters themselves must be
+			// doubly-escaped. We use `\\` for the first backslash and
+			// the escaped numeric value for the other value. We especially
+			// don't want a comma in the output.
+			case ',':
+				str.WriteString(`\\\044`)
+			case '\\':
+				str.WriteString(`\\\092`)
+			default:
+				str.WriteByte(e)
+			}
+		}
+	}
+	return str.String()
+}
 
 
 func (s *SVCBAlpn) pack() ([]byte, error) {
 func (s *SVCBAlpn) pack() ([]byte, error) {
 	// Liberally estimate the size of an alpn as 10 octets
 	// Liberally estimate the size of an alpn as 10 octets
@@ -351,7 +427,47 @@ func (s *SVCBAlpn) unpack(b []byte) error {
 }
 }
 
 
 func (s *SVCBAlpn) parse(b string) error {
 func (s *SVCBAlpn) parse(b string) error {
-	s.Alpn = strings.Split(b, ",")
+	if len(b) == 0 {
+		s.Alpn = []string{}
+		return nil
+	}
+
+	alpn := []string{}
+	a := []byte{}
+	for p := 0; p < len(b); {
+		c, q := nextByte(b, p)
+		if q == 0 {
+			return errors.New("dns: svcbalpn: unterminated escape")
+		}
+		p += q
+		// If we find a comma, we have finished reading an alpn.
+		if c == ',' {
+			if len(a) == 0 {
+				return errors.New("dns: svcbalpn: empty protocol identifier")
+			}
+			alpn = append(alpn, string(a))
+			a = []byte{}
+			continue
+		}
+		// If it's a backslash, we need to handle a comma-separated list.
+		if c == '\\' {
+			dc, dq := nextByte(b, p)
+			if dq == 0 {
+				return errors.New("dns: svcbalpn: unterminated escape decoding comma-separated list")
+			}
+			if dc != '\\' && dc != ',' {
+				return errors.New("dns: svcbalpn: bad escaped character decoding comma-separated list")
+			}
+			p += dq
+			c = dc
+		}
+		a = append(a, c)
+	}
+	// Add the final alpn.
+	if len(a) == 0 {
+		return errors.New("dns: svcbalpn: last protocol identifier empty")
+	}
+	s.Alpn = append(alpn, string(a))
 	return nil
 	return nil
 }
 }
 
 
@@ -364,15 +480,17 @@ func (s *SVCBAlpn) len() int {
 }
 }
 
 
 func (s *SVCBAlpn) copy() SVCBKeyValue {
 func (s *SVCBAlpn) copy() SVCBKeyValue {
-	return &SVCBAlpn{
-		append([]string(nil), s.Alpn...),
-	}
+	return &SVCBAlpn{cloneSlice(s.Alpn)}
 }
 }
 
 
 // SVCBNoDefaultAlpn pair signifies no support for default connection protocols.
 // SVCBNoDefaultAlpn pair signifies no support for default connection protocols.
+// Should be used in conjunction with alpn.
 // Basic use pattern for creating a no-default-alpn option:
 // Basic use pattern for creating a no-default-alpn option:
 //
 //
 //	s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
 //	s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
+//	t := new(dns.SVCBAlpn)
+//	t.Alpn = []string{"xmpp-client"}
+//	s.Value = append(s.Value, t)
 //	e := new(dns.SVCBNoDefaultAlpn)
 //	e := new(dns.SVCBNoDefaultAlpn)
 //	s.Value = append(s.Value, e)
 //	s.Value = append(s.Value, e)
 type SVCBNoDefaultAlpn struct{}
 type SVCBNoDefaultAlpn struct{}
@@ -385,14 +503,14 @@ func (*SVCBNoDefaultAlpn) len() int              { return 0 }
 
 
 func (*SVCBNoDefaultAlpn) unpack(b []byte) error {
 func (*SVCBNoDefaultAlpn) unpack(b []byte) error {
 	if len(b) != 0 {
 	if len(b) != 0 {
-		return errors.New("dns: svcbnodefaultalpn: no_default_alpn must have no value")
+		return errors.New("dns: svcbnodefaultalpn: no-default-alpn must have no value")
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
 func (*SVCBNoDefaultAlpn) parse(b string) error {
 func (*SVCBNoDefaultAlpn) parse(b string) error {
 	if b != "" {
 	if b != "" {
-		return errors.New("dns: svcbnodefaultalpn: no_default_alpn must have no value")
+		return errors.New("dns: svcbnodefaultalpn: no-default-alpn must have no value")
 	}
 	}
 	return nil
 	return nil
 }
 }
@@ -442,15 +560,15 @@ func (s *SVCBPort) parse(b string) error {
 // to the hinted IP address may be terminated and a new connection may be opened.
 // to the hinted IP address may be terminated and a new connection may be opened.
 // Basic use pattern for creating an ipv4hint option:
 // Basic use pattern for creating an ipv4hint option:
 //
 //
-//	h := new(dns.HTTPS)
-//	h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
-//	e := new(dns.SVCBIPv4Hint)
-//	e.Hint = []net.IP{net.IPv4(1,1,1,1).To4()}
+//		h := new(dns.HTTPS)
+//		h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
+//		e := new(dns.SVCBIPv4Hint)
+//		e.Hint = []net.IP{net.IPv4(1,1,1,1).To4()}
 //
 //
-//  Or
+//	 Or
 //
 //
-//	e.Hint = []net.IP{net.ParseIP("1.1.1.1").To4()}
-//	h.Value = append(h.Value, e)
+//		e.Hint = []net.IP{net.ParseIP("1.1.1.1").To4()}
+//		h.Value = append(h.Value, e)
 type SVCBIPv4Hint struct {
 type SVCBIPv4Hint struct {
 	Hint []net.IP
 	Hint []net.IP
 }
 }
@@ -474,6 +592,7 @@ func (s *SVCBIPv4Hint) unpack(b []byte) error {
 	if len(b) == 0 || len(b)%4 != 0 {
 	if len(b) == 0 || len(b)%4 != 0 {
 		return errors.New("dns: svcbipv4hint: ipv4 address byte array length is not a multiple of 4")
 		return errors.New("dns: svcbipv4hint: ipv4 address byte array length is not a multiple of 4")
 	}
 	}
+	b = cloneSlice(b)
 	x := make([]net.IP, 0, len(b)/4)
 	x := make([]net.IP, 0, len(b)/4)
 	for i := 0; i < len(b); i += 4 {
 	for i := 0; i < len(b); i += 4 {
 		x = append(x, net.IP(b[i:i+4]))
 		x = append(x, net.IP(b[i:i+4]))
@@ -495,35 +614,37 @@ func (s *SVCBIPv4Hint) String() string {
 }
 }
 
 
 func (s *SVCBIPv4Hint) parse(b string) error {
 func (s *SVCBIPv4Hint) parse(b string) error {
+	if b == "" {
+		return errors.New("dns: svcbipv4hint: empty hint")
+	}
 	if strings.Contains(b, ":") {
 	if strings.Contains(b, ":") {
 		return errors.New("dns: svcbipv4hint: expected ipv4, got ipv6")
 		return errors.New("dns: svcbipv4hint: expected ipv4, got ipv6")
 	}
 	}
-	str := strings.Split(b, ",")
-	dst := make([]net.IP, len(str))
-	for i, e := range str {
+
+	hint := make([]net.IP, 0, strings.Count(b, ",")+1)
+	for len(b) > 0 {
+		var e string
+		e, b, _ = strings.Cut(b, ",")
 		ip := net.ParseIP(e).To4()
 		ip := net.ParseIP(e).To4()
 		if ip == nil {
 		if ip == nil {
 			return errors.New("dns: svcbipv4hint: bad ip")
 			return errors.New("dns: svcbipv4hint: bad ip")
 		}
 		}
-		dst[i] = ip
+		hint = append(hint, ip)
 	}
 	}
-	s.Hint = dst
+	s.Hint = hint
 	return nil
 	return nil
 }
 }
 
 
 func (s *SVCBIPv4Hint) copy() SVCBKeyValue {
 func (s *SVCBIPv4Hint) copy() SVCBKeyValue {
 	hint := make([]net.IP, len(s.Hint))
 	hint := make([]net.IP, len(s.Hint))
 	for i, ip := range s.Hint {
 	for i, ip := range s.Hint {
-		hint[i] = copyIP(ip)
-	}
-
-	return &SVCBIPv4Hint{
-		Hint: hint,
+		hint[i] = cloneSlice(ip)
 	}
 	}
+	return &SVCBIPv4Hint{Hint: hint}
 }
 }
 
 
 // SVCBECHConfig pair contains the ECHConfig structure defined in draft-ietf-tls-esni [RFC xxxx].
 // SVCBECHConfig pair contains the ECHConfig structure defined in draft-ietf-tls-esni [RFC xxxx].
-// Basic use pattern for creating an echconfig option:
+// Basic use pattern for creating an ech option:
 //
 //
 //	h := new(dns.HTTPS)
 //	h := new(dns.HTTPS)
 //	h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
 //	h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
@@ -531,7 +652,7 @@ func (s *SVCBIPv4Hint) copy() SVCBKeyValue {
 //	e.ECH = []byte{0xfe, 0x08, ...}
 //	e.ECH = []byte{0xfe, 0x08, ...}
 //	h.Value = append(h.Value, e)
 //	h.Value = append(h.Value, e)
 type SVCBECHConfig struct {
 type SVCBECHConfig struct {
-	ECH []byte
+	ECH []byte // Specifically ECHConfigList including the redundant length prefix
 }
 }
 
 
 func (*SVCBECHConfig) Key() SVCBKey     { return SVCB_ECHCONFIG }
 func (*SVCBECHConfig) Key() SVCBKey     { return SVCB_ECHCONFIG }
@@ -539,23 +660,22 @@ func (s *SVCBECHConfig) String() string { return toBase64(s.ECH) }
 func (s *SVCBECHConfig) len() int       { return len(s.ECH) }
 func (s *SVCBECHConfig) len() int       { return len(s.ECH) }
 
 
 func (s *SVCBECHConfig) pack() ([]byte, error) {
 func (s *SVCBECHConfig) pack() ([]byte, error) {
-	return append([]byte(nil), s.ECH...), nil
+	return cloneSlice(s.ECH), nil
 }
 }
 
 
 func (s *SVCBECHConfig) copy() SVCBKeyValue {
 func (s *SVCBECHConfig) copy() SVCBKeyValue {
-	return &SVCBECHConfig{
-		append([]byte(nil), s.ECH...),
-	}
+	return &SVCBECHConfig{cloneSlice(s.ECH)}
 }
 }
 
 
 func (s *SVCBECHConfig) unpack(b []byte) error {
 func (s *SVCBECHConfig) unpack(b []byte) error {
-	s.ECH = append([]byte(nil), b...)
+	s.ECH = cloneSlice(b)
 	return nil
 	return nil
 }
 }
+
 func (s *SVCBECHConfig) parse(b string) error {
 func (s *SVCBECHConfig) parse(b string) error {
 	x, err := fromBase64([]byte(b))
 	x, err := fromBase64([]byte(b))
 	if err != nil {
 	if err != nil {
-		return errors.New("dns: svcbechconfig: bad base64 echconfig")
+		return errors.New("dns: svcbech: bad base64 ech")
 	}
 	}
 	s.ECH = x
 	s.ECH = x
 	return nil
 	return nil
@@ -594,6 +714,7 @@ func (s *SVCBIPv6Hint) unpack(b []byte) error {
 	if len(b) == 0 || len(b)%16 != 0 {
 	if len(b) == 0 || len(b)%16 != 0 {
 		return errors.New("dns: svcbipv6hint: ipv6 address byte array length not a multiple of 16")
 		return errors.New("dns: svcbipv6hint: ipv6 address byte array length not a multiple of 16")
 	}
 	}
+	b = cloneSlice(b)
 	x := make([]net.IP, 0, len(b)/16)
 	x := make([]net.IP, 0, len(b)/16)
 	for i := 0; i < len(b); i += 16 {
 	for i := 0; i < len(b); i += 16 {
 		ip := net.IP(b[i : i+16])
 		ip := net.IP(b[i : i+16])
@@ -618,30 +739,80 @@ func (s *SVCBIPv6Hint) String() string {
 }
 }
 
 
 func (s *SVCBIPv6Hint) parse(b string) error {
 func (s *SVCBIPv6Hint) parse(b string) error {
-	if strings.Contains(b, ".") {
-		return errors.New("dns: svcbipv6hint: expected ipv6, got ipv4")
+	if b == "" {
+		return errors.New("dns: svcbipv6hint: empty hint")
 	}
 	}
-	str := strings.Split(b, ",")
-	dst := make([]net.IP, len(str))
-	for i, e := range str {
+
+	hint := make([]net.IP, 0, strings.Count(b, ",")+1)
+	for len(b) > 0 {
+		var e string
+		e, b, _ = strings.Cut(b, ",")
 		ip := net.ParseIP(e)
 		ip := net.ParseIP(e)
 		if ip == nil {
 		if ip == nil {
 			return errors.New("dns: svcbipv6hint: bad ip")
 			return errors.New("dns: svcbipv6hint: bad ip")
 		}
 		}
-		dst[i] = ip
+		if ip.To4() != nil {
+			return errors.New("dns: svcbipv6hint: expected ipv6, got ipv4-mapped-ipv6")
+		}
+		hint = append(hint, ip)
 	}
 	}
-	s.Hint = dst
+	s.Hint = hint
 	return nil
 	return nil
 }
 }
 
 
 func (s *SVCBIPv6Hint) copy() SVCBKeyValue {
 func (s *SVCBIPv6Hint) copy() SVCBKeyValue {
 	hint := make([]net.IP, len(s.Hint))
 	hint := make([]net.IP, len(s.Hint))
 	for i, ip := range s.Hint {
 	for i, ip := range s.Hint {
-		hint[i] = copyIP(ip)
+		hint[i] = cloneSlice(ip)
+	}
+	return &SVCBIPv6Hint{Hint: hint}
+}
+
+// SVCBDoHPath pair is used to indicate the URI template that the
+// clients may use to construct a DNS over HTTPS URI.
+//
+// See RFC xxxx (https://datatracker.ietf.org/doc/html/draft-ietf-add-svcb-dns-02)
+// and RFC yyyy (https://datatracker.ietf.org/doc/html/draft-ietf-add-ddr-06).
+//
+// A basic example of using the dohpath option together with the alpn
+// option to indicate support for DNS over HTTPS on a certain path:
+//
+//	s := new(dns.SVCB)
+//	s.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}
+//	e := new(dns.SVCBAlpn)
+//	e.Alpn = []string{"h2", "h3"}
+//	p := new(dns.SVCBDoHPath)
+//	p.Template = "/dns-query{?dns}"
+//	s.Value = append(s.Value, e, p)
+//
+// The parsing currently doesn't validate that Template is a valid
+// RFC 6570 URI template.
+type SVCBDoHPath struct {
+	Template string
+}
+
+func (*SVCBDoHPath) Key() SVCBKey            { return SVCB_DOHPATH }
+func (s *SVCBDoHPath) String() string        { return svcbParamToStr([]byte(s.Template)) }
+func (s *SVCBDoHPath) len() int              { return len(s.Template) }
+func (s *SVCBDoHPath) pack() ([]byte, error) { return []byte(s.Template), nil }
+
+func (s *SVCBDoHPath) unpack(b []byte) error {
+	s.Template = string(b)
+	return nil
+}
+
+func (s *SVCBDoHPath) parse(b string) error {
+	template, err := svcbParseParam(b)
+	if err != nil {
+		return fmt.Errorf("dns: svcbdohpath: %w", err)
 	}
 	}
+	s.Template = string(template)
+	return nil
+}
 
 
-	return &SVCBIPv6Hint{
-		Hint: hint,
+func (s *SVCBDoHPath) copy() SVCBKeyValue {
+	return &SVCBDoHPath{
+		Template: s.Template,
 	}
 	}
 }
 }
 
 
@@ -661,18 +832,63 @@ type SVCBLocal struct {
 }
 }
 
 
 func (s *SVCBLocal) Key() SVCBKey          { return s.KeyCode }
 func (s *SVCBLocal) Key() SVCBKey          { return s.KeyCode }
-func (s *SVCBLocal) pack() ([]byte, error) { return append([]byte(nil), s.Data...), nil }
+func (s *SVCBLocal) String() string        { return svcbParamToStr(s.Data) }
+func (s *SVCBLocal) pack() ([]byte, error) { return cloneSlice(s.Data), nil }
 func (s *SVCBLocal) len() int              { return len(s.Data) }
 func (s *SVCBLocal) len() int              { return len(s.Data) }
 
 
 func (s *SVCBLocal) unpack(b []byte) error {
 func (s *SVCBLocal) unpack(b []byte) error {
-	s.Data = append([]byte(nil), b...)
+	s.Data = cloneSlice(b)
+	return nil
+}
+
+func (s *SVCBLocal) parse(b string) error {
+	data, err := svcbParseParam(b)
+	if err != nil {
+		return fmt.Errorf("dns: svcblocal: svcb private/experimental key %w", err)
+	}
+	s.Data = data
 	return nil
 	return nil
 }
 }
 
 
-func (s *SVCBLocal) String() string {
+func (s *SVCBLocal) copy() SVCBKeyValue {
+	return &SVCBLocal{s.KeyCode, cloneSlice(s.Data)}
+}
+
+func (rr *SVCB) String() string {
+	s := rr.Hdr.String() +
+		strconv.Itoa(int(rr.Priority)) + " " +
+		sprintName(rr.Target)
+	for _, e := range rr.Value {
+		s += " " + e.Key().String() + "=\"" + e.String() + "\""
+	}
+	return s
+}
+
+// areSVCBPairArraysEqual checks if SVCBKeyValue arrays are equal after sorting their
+// copies. arrA and arrB have equal lengths, otherwise zduplicate.go wouldn't call this function.
+func areSVCBPairArraysEqual(a []SVCBKeyValue, b []SVCBKeyValue) bool {
+	a = cloneSlice(a)
+	b = cloneSlice(b)
+	sort.Slice(a, func(i, j int) bool { return a[i].Key() < a[j].Key() })
+	sort.Slice(b, func(i, j int) bool { return b[i].Key() < b[j].Key() })
+	for i, e := range a {
+		if e.Key() != b[i].Key() {
+			return false
+		}
+		b1, err1 := e.pack()
+		b2, err2 := b[i].pack()
+		if err1 != nil || err2 != nil || !bytes.Equal(b1, b2) {
+			return false
+		}
+	}
+	return true
+}
+
+// svcbParamStr converts the value of an SVCB parameter into a DNS presentation-format string.
+func svcbParamToStr(s []byte) string {
 	var str strings.Builder
 	var str strings.Builder
-	str.Grow(4 * len(s.Data))
-	for _, e := range s.Data {
+	str.Grow(4 * len(s))
+	for _, e := range s {
 		if ' ' <= e && e <= '~' {
 		if ' ' <= e && e <= '~' {
 			switch e {
 			switch e {
 			case '"', ';', ' ', '\\':
 			case '"', ';', ' ', '\\':
@@ -688,7 +904,8 @@ func (s *SVCBLocal) String() string {
 	return str.String()
 	return str.String()
 }
 }
 
 
-func (s *SVCBLocal) parse(b string) error {
+// svcbParseParam parses a DNS presentation-format string into an SVCB parameter value.
+func svcbParseParam(b string) ([]byte, error) {
 	data := make([]byte, 0, len(b))
 	data := make([]byte, 0, len(b))
 	for i := 0; i < len(b); {
 	for i := 0; i < len(b); {
 		if b[i] != '\\' {
 		if b[i] != '\\' {
@@ -697,7 +914,7 @@ func (s *SVCBLocal) parse(b string) error {
 			continue
 			continue
 		}
 		}
 		if i+1 == len(b) {
 		if i+1 == len(b) {
-			return errors.New("dns: svcblocal: svcb private/experimental key escape unterminated")
+			return nil, errors.New("escape unterminated")
 		}
 		}
 		if isDigit(b[i+1]) {
 		if isDigit(b[i+1]) {
 			if i+3 < len(b) && isDigit(b[i+2]) && isDigit(b[i+3]) {
 			if i+3 < len(b) && isDigit(b[i+2]) && isDigit(b[i+3]) {
@@ -708,48 +925,11 @@ func (s *SVCBLocal) parse(b string) error {
 					continue
 					continue
 				}
 				}
 			}
 			}
-			return errors.New("dns: svcblocal: svcb private/experimental key bad escaped octet")
+			return nil, errors.New("bad escaped octet")
 		} else {
 		} else {
 			data = append(data, b[i+1])
 			data = append(data, b[i+1])
 			i += 2
 			i += 2
 		}
 		}
 	}
 	}
-	s.Data = data
-	return nil
-}
-
-func (s *SVCBLocal) copy() SVCBKeyValue {
-	return &SVCBLocal{s.KeyCode,
-		append([]byte(nil), s.Data...),
-	}
-}
-
-func (rr *SVCB) String() string {
-	s := rr.Hdr.String() +
-		strconv.Itoa(int(rr.Priority)) + " " +
-		sprintName(rr.Target)
-	for _, e := range rr.Value {
-		s += " " + e.Key().String() + "=\"" + e.String() + "\""
-	}
-	return s
-}
-
-// areSVCBPairArraysEqual checks if SVCBKeyValue arrays are equal after sorting their
-// copies. arrA and arrB have equal lengths, otherwise zduplicate.go wouldn't call this function.
-func areSVCBPairArraysEqual(a []SVCBKeyValue, b []SVCBKeyValue) bool {
-	a = append([]SVCBKeyValue(nil), a...)
-	b = append([]SVCBKeyValue(nil), b...)
-	sort.Slice(a, func(i, j int) bool { return a[i].Key() < a[j].Key() })
-	sort.Slice(b, func(i, j int) bool { return b[i].Key() < b[j].Key() })
-	for i, e := range a {
-		if e.Key() != b[i].Key() {
-			return false
-		}
-		b1, err1 := e.pack()
-		b2, err2 := b[i].pack()
-		if err1 != nil || err2 != nil || !bytes.Equal(b1, b2) {
-			return false
-		}
-	}
-	return true
+	return data, nil
 }
 }

+ 10 - 0
vendor/github.com/miekg/dns/tools.go

@@ -0,0 +1,10 @@
+//go:build tools
+// +build tools
+
+// We include our tool dependencies for `go generate` here to ensure they're
+// properly tracked by the go tool. See the Go Wiki for the rationale behind this:
+// https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module.
+
+package dns
+
+import _ "golang.org/x/tools/go/packages"

+ 46 - 19
vendor/github.com/miekg/dns/tsig.go

@@ -74,6 +74,24 @@ func (key tsigHMACProvider) Verify(msg []byte, t *TSIG) error {
 	return nil
 	return nil
 }
 }
 
 
+type tsigSecretProvider map[string]string
+
+func (ts tsigSecretProvider) Generate(msg []byte, t *TSIG) ([]byte, error) {
+	key, ok := ts[t.Hdr.Name]
+	if !ok {
+		return nil, ErrSecret
+	}
+	return tsigHMACProvider(key).Generate(msg, t)
+}
+
+func (ts tsigSecretProvider) Verify(msg []byte, t *TSIG) error {
+	key, ok := ts[t.Hdr.Name]
+	if !ok {
+		return ErrSecret
+	}
+	return tsigHMACProvider(key).Verify(msg, t)
+}
+
 // TSIG is the RR the holds the transaction signature of a message.
 // TSIG is the RR the holds the transaction signature of a message.
 // See RFC 2845 and RFC 4635.
 // See RFC 2845 and RFC 4635.
 type TSIG struct {
 type TSIG struct {
@@ -140,18 +158,17 @@ type timerWireFmt struct {
 }
 }
 
 
 // TsigGenerate fills out the TSIG record attached to the message.
 // TsigGenerate fills out the TSIG record attached to the message.
-// The message should contain
-// a "stub" TSIG RR with the algorithm, key name (owner name of the RR),
-// time fudge (defaults to 300 seconds) and the current time
-// The TSIG MAC is saved in that Tsig RR.
-// When TsigGenerate is called for the first time requestMAC is set to the empty string and
-// timersOnly is false.
-// If something goes wrong an error is returned, otherwise it is nil.
+// The message should contain a "stub" TSIG RR with the algorithm, key name
+// (owner name of the RR), time fudge (defaults to 300 seconds) and the current
+// time The TSIG MAC is saved in that Tsig RR. When TsigGenerate is called for
+// the first time requestMAC should be set to the empty string and timersOnly to
+// false.
 func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, string, error) {
 func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, string, error) {
-	return tsigGenerateProvider(m, tsigHMACProvider(secret), requestMAC, timersOnly)
+	return TsigGenerateWithProvider(m, tsigHMACProvider(secret), requestMAC, timersOnly)
 }
 }
 
 
-func tsigGenerateProvider(m *Msg, provider TsigProvider, requestMAC string, timersOnly bool) ([]byte, string, error) {
+// TsigGenerateWithProvider is similar to TsigGenerate, but allows for a custom TsigProvider.
+func TsigGenerateWithProvider(m *Msg, provider TsigProvider, requestMAC string, timersOnly bool) ([]byte, string, error) {
 	if m.IsTsig() == nil {
 	if m.IsTsig() == nil {
 		panic("dns: TSIG not last RR in additional")
 		panic("dns: TSIG not last RR in additional")
 	}
 	}
@@ -162,20 +179,29 @@ func tsigGenerateProvider(m *Msg, provider TsigProvider, requestMAC string, time
 	if err != nil {
 	if err != nil {
 		return nil, "", err
 		return nil, "", err
 	}
 	}
+
 	buf, err := tsigBuffer(mbuf, rr, requestMAC, timersOnly)
 	buf, err := tsigBuffer(mbuf, rr, requestMAC, timersOnly)
 	if err != nil {
 	if err != nil {
 		return nil, "", err
 		return nil, "", err
 	}
 	}
 
 
 	t := new(TSIG)
 	t := new(TSIG)
-	// Copy all TSIG fields except MAC and its size, which are filled using the computed digest.
+	// Copy all TSIG fields except MAC, its size, and time signed which are filled when signing.
 	*t = *rr
 	*t = *rr
-	mac, err := provider.Generate(buf, rr)
-	if err != nil {
-		return nil, "", err
+	t.TimeSigned = 0
+	t.MAC = ""
+	t.MACSize = 0
+
+	// Sign unless there is a key or MAC validation error (RFC 8945 5.3.2)
+	if rr.Error != RcodeBadKey && rr.Error != RcodeBadSig {
+		mac, err := provider.Generate(buf, rr)
+		if err != nil {
+			return nil, "", err
+		}
+		t.TimeSigned = rr.TimeSigned
+		t.MAC = hex.EncodeToString(mac)
+		t.MACSize = uint16(len(t.MAC) / 2) // Size is half!
 	}
 	}
-	t.MAC = hex.EncodeToString(mac)
-	t.MACSize = uint16(len(t.MAC) / 2) // Size is half!
 
 
 	tbuf := make([]byte, Len(t))
 	tbuf := make([]byte, Len(t))
 	off, err := PackRR(t, tbuf, 0, nil, false)
 	off, err := PackRR(t, tbuf, 0, nil, false)
@@ -189,14 +215,15 @@ func tsigGenerateProvider(m *Msg, provider TsigProvider, requestMAC string, time
 	return mbuf, t.MAC, nil
 	return mbuf, t.MAC, nil
 }
 }
 
 
-// TsigVerify verifies the TSIG on a message.
-// If the signature does not validate err contains the
-// error, otherwise it is nil.
+// TsigVerify verifies the TSIG on a message. If the signature does not
+// validate the returned error contains the cause. If the signature is OK, the
+// error is nil.
 func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) error {
 func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) error {
 	return tsigVerify(msg, tsigHMACProvider(secret), requestMAC, timersOnly, uint64(time.Now().Unix()))
 	return tsigVerify(msg, tsigHMACProvider(secret), requestMAC, timersOnly, uint64(time.Now().Unix()))
 }
 }
 
 
-func tsigVerifyProvider(msg []byte, provider TsigProvider, requestMAC string, timersOnly bool) error {
+// TsigVerifyWithProvider is similar to TsigVerify, but allows for a custom TsigProvider.
+func TsigVerifyWithProvider(msg []byte, provider TsigProvider, requestMAC string, timersOnly bool) error {
 	return tsigVerify(msg, provider, requestMAC, timersOnly, uint64(time.Now().Unix()))
 	return tsigVerify(msg, provider, requestMAC, timersOnly, uint64(time.Now().Unix()))
 }
 }
 
 

+ 109 - 20
vendor/github.com/miekg/dns/types.go

@@ -65,6 +65,7 @@ const (
 	TypeAPL        uint16 = 42
 	TypeAPL        uint16 = 42
 	TypeDS         uint16 = 43
 	TypeDS         uint16 = 43
 	TypeSSHFP      uint16 = 44
 	TypeSSHFP      uint16 = 44
+	TypeIPSECKEY   uint16 = 45
 	TypeRRSIG      uint16 = 46
 	TypeRRSIG      uint16 = 46
 	TypeNSEC       uint16 = 47
 	TypeNSEC       uint16 = 47
 	TypeDNSKEY     uint16 = 48
 	TypeDNSKEY     uint16 = 48
@@ -98,6 +99,7 @@ const (
 	TypeURI        uint16 = 256
 	TypeURI        uint16 = 256
 	TypeCAA        uint16 = 257
 	TypeCAA        uint16 = 257
 	TypeAVC        uint16 = 258
 	TypeAVC        uint16 = 258
+	TypeAMTRELAY   uint16 = 260
 
 
 	TypeTKEY uint16 = 249
 	TypeTKEY uint16 = 249
 	TypeTSIG uint16 = 250
 	TypeTSIG uint16 = 250
@@ -159,6 +161,22 @@ const (
 	ZoneMDHashAlgSHA512 = 2
 	ZoneMDHashAlgSHA512 = 2
 )
 )
 
 
+// Used in IPSEC https://datatracker.ietf.org/doc/html/rfc4025#section-2.3
+const (
+	IPSECGatewayNone uint8 = iota
+	IPSECGatewayIPv4
+	IPSECGatewayIPv6
+	IPSECGatewayHost
+)
+
+// Used in AMTRELAY https://datatracker.ietf.org/doc/html/rfc8777#section-4.2.3
+const (
+	AMTRELAYNone = IPSECGatewayNone
+	AMTRELAYIPv4 = IPSECGatewayIPv4
+	AMTRELAYIPv6 = IPSECGatewayIPv6
+	AMTRELAYHost = IPSECGatewayHost
+)
+
 // Header is the wire format for the DNS packet header.
 // Header is the wire format for the DNS packet header.
 type Header struct {
 type Header struct {
 	Id                                 uint16
 	Id                                 uint16
@@ -180,7 +198,7 @@ const (
 	_CD = 1 << 4  // checking disabled
 	_CD = 1 << 4  // checking disabled
 )
 )
 
 
-// Various constants used in the LOC RR. See RFC 1887.
+// Various constants used in the LOC RR. See RFC 1876.
 const (
 const (
 	LOC_EQUATOR       = 1 << 31 // RFC 1876, Section 2.
 	LOC_EQUATOR       = 1 << 31 // RFC 1876, Section 2.
 	LOC_PRIMEMERIDIAN = 1 << 31 // RFC 1876, Section 2.
 	LOC_PRIMEMERIDIAN = 1 << 31 // RFC 1876, Section 2.
@@ -218,6 +236,9 @@ var CertTypeToString = map[uint16]string{
 	CertOID:     "OID",
 	CertOID:     "OID",
 }
 }
 
 
+// Prefix for IPv4 encoded as IPv6 address
+const ipv4InIPv6Prefix = "::ffff:"
+
 //go:generate go run types_generate.go
 //go:generate go run types_generate.go
 
 
 // Question holds a DNS question. Usually there is just one. While the
 // Question holds a DNS question. Usually there is just one. While the
@@ -613,8 +634,8 @@ func nextByte(s string, offset int) (byte, int) {
 		return 0, 0
 		return 0, 0
 	case 2, 3: // too short to be \ddd
 	case 2, 3: // too short to be \ddd
 	default: // maybe \ddd
 	default: // maybe \ddd
-		if isDigit(s[offset+1]) && isDigit(s[offset+2]) && isDigit(s[offset+3]) {
-			return dddStringToByte(s[offset+1:]), 4
+		if isDDD(s[offset+1:]) {
+			return dddToByte(s[offset+1:]), 4
 		}
 		}
 	}
 	}
 	// not \ddd, just an RFC 1035 "quoted" character
 	// not \ddd, just an RFC 1035 "quoted" character
@@ -733,6 +754,11 @@ func (rr *AAAA) String() string {
 	if rr.AAAA == nil {
 	if rr.AAAA == nil {
 		return rr.Hdr.String()
 		return rr.Hdr.String()
 	}
 	}
+
+	if rr.AAAA.To4() != nil {
+		return rr.Hdr.String() + ipv4InIPv6Prefix + rr.AAAA.String()
+	}
+
 	return rr.Hdr.String() + rr.AAAA.String()
 	return rr.Hdr.String() + rr.AAAA.String()
 }
 }
 
 
@@ -774,7 +800,10 @@ type LOC struct {
 
 
 // cmToM takes a cm value expressed in RFC 1876 SIZE mantissa/exponent
 // cmToM takes a cm value expressed in RFC 1876 SIZE mantissa/exponent
 // format and returns a string in m (two decimals for the cm).
 // format and returns a string in m (two decimals for the cm).
-func cmToM(m, e uint8) string {
+func cmToM(x uint8) string {
+	m := x & 0xf0 >> 4
+	e := x & 0x0f
+
 	if e < 2 {
 	if e < 2 {
 		if e == 1 {
 		if e == 1 {
 			m *= 10
 			m *= 10
@@ -830,10 +859,9 @@ func (rr *LOC) String() string {
 		s += fmt.Sprintf("%.0fm ", alt)
 		s += fmt.Sprintf("%.0fm ", alt)
 	}
 	}
 
 
-	s += cmToM(rr.Size&0xf0>>4, rr.Size&0x0f) + "m "
-	s += cmToM(rr.HorizPre&0xf0>>4, rr.HorizPre&0x0f) + "m "
-	s += cmToM(rr.VertPre&0xf0>>4, rr.VertPre&0x0f) + "m"
-
+	s += cmToM(rr.Size) + "m "
+	s += cmToM(rr.HorizPre) + "m "
+	s += cmToM(rr.VertPre) + "m"
 	return s
 	return s
 }
 }
 
 
@@ -994,6 +1022,69 @@ func (rr *DNSKEY) String() string {
 		" " + rr.PublicKey
 		" " + rr.PublicKey
 }
 }
 
 
+// IPSECKEY RR. See RFC 4025.
+type IPSECKEY struct {
+	Hdr         RR_Header
+	Precedence  uint8
+	GatewayType uint8
+	Algorithm   uint8
+	GatewayAddr net.IP `dns:"-"` // packing/unpacking/parsing/etc handled together with GatewayHost
+	GatewayHost string `dns:"ipsechost"`
+	PublicKey   string `dns:"base64"`
+}
+
+func (rr *IPSECKEY) String() string {
+	var gateway string
+	switch rr.GatewayType {
+	case IPSECGatewayIPv4, IPSECGatewayIPv6:
+		gateway = rr.GatewayAddr.String()
+	case IPSECGatewayHost:
+		gateway = rr.GatewayHost
+	case IPSECGatewayNone:
+		fallthrough
+	default:
+		gateway = "."
+	}
+
+	return rr.Hdr.String() + strconv.Itoa(int(rr.Precedence)) +
+		" " + strconv.Itoa(int(rr.GatewayType)) +
+		" " + strconv.Itoa(int(rr.Algorithm)) +
+		" " + gateway +
+		" " + rr.PublicKey
+}
+
+// AMTRELAY RR. See RFC 8777.
+type AMTRELAY struct {
+	Hdr         RR_Header
+	Precedence  uint8
+	GatewayType uint8  // discovery is packed in here at bit 0x80
+	GatewayAddr net.IP `dns:"-"` // packing/unpacking/parsing/etc handled together with GatewayHost
+	GatewayHost string `dns:"amtrelayhost"`
+}
+
+func (rr *AMTRELAY) String() string {
+	var gateway string
+	switch rr.GatewayType & 0x7f {
+	case AMTRELAYIPv4, AMTRELAYIPv6:
+		gateway = rr.GatewayAddr.String()
+	case AMTRELAYHost:
+		gateway = rr.GatewayHost
+	case AMTRELAYNone:
+		fallthrough
+	default:
+		gateway = "."
+	}
+	boolS := "0"
+	if rr.GatewayType&0x80 == 0x80 {
+		boolS = "1"
+	}
+
+	return rr.Hdr.String() + strconv.Itoa(int(rr.Precedence)) +
+		" " + boolS +
+		" " + strconv.Itoa(int(rr.GatewayType&0x7f)) +
+		" " + gateway
+}
+
 // RKEY RR. See https://www.iana.org/assignments/dns-parameters/RKEY/rkey-completed-template.
 // RKEY RR. See https://www.iana.org/assignments/dns-parameters/RKEY/rkey-completed-template.
 type RKEY struct {
 type RKEY struct {
 	Hdr       RR_Header
 	Hdr       RR_Header
@@ -1434,7 +1525,7 @@ func (a *APLPrefix) str() string {
 	case net.IPv6len:
 	case net.IPv6len:
 		// add prefix for IPv4-mapped IPv6
 		// add prefix for IPv4-mapped IPv6
 		if v4 := a.Network.IP.To4(); v4 != nil {
 		if v4 := a.Network.IP.To4(); v4 != nil {
-			sb.WriteString("::ffff:")
+			sb.WriteString(ipv4InIPv6Prefix)
 		}
 		}
 		sb.WriteString(a.Network.IP.String())
 		sb.WriteString(a.Network.IP.String())
 	}
 	}
@@ -1450,7 +1541,7 @@ func (a *APLPrefix) str() string {
 // equals reports whether two APL prefixes are identical.
 // equals reports whether two APL prefixes are identical.
 func (a *APLPrefix) equals(b *APLPrefix) bool {
 func (a *APLPrefix) equals(b *APLPrefix) bool {
 	return a.Negation == b.Negation &&
 	return a.Negation == b.Negation &&
-		bytes.Equal(a.Network.IP, b.Network.IP) &&
+		a.Network.IP.Equal(b.Network.IP) &&
 		bytes.Equal(a.Network.Mask, b.Network.Mask)
 		bytes.Equal(a.Network.Mask, b.Network.Mask)
 }
 }
 
 
@@ -1518,21 +1609,19 @@ func euiToString(eui uint64, bits int) (hex string) {
 	return
 	return
 }
 }
 
 
-// copyIP returns a copy of ip.
-func copyIP(ip net.IP) net.IP {
-	p := make(net.IP, len(ip))
-	copy(p, ip)
-	return p
+// cloneSlice returns a shallow copy of s.
+func cloneSlice[E any, S ~[]E](s S) S {
+	if s == nil {
+		return nil
+	}
+	return append(S(nil), s...)
 }
 }
 
 
 // copyNet returns a copy of a subnet.
 // copyNet returns a copy of a subnet.
 func copyNet(n net.IPNet) net.IPNet {
 func copyNet(n net.IPNet) net.IPNet {
-	m := make(net.IPMask, len(n.Mask))
-	copy(m, n.Mask)
-
 	return net.IPNet{
 	return net.IPNet{
-		IP:   copyIP(n.IP),
-		Mask: m,
+		IP:   cloneSlice(n.IP),
+		Mask: cloneSlice(n.Mask),
 	}
 	}
 }
 }
 
 

+ 1 - 0
vendor/github.com/miekg/dns/udp.go

@@ -1,3 +1,4 @@
+//go:build !windows
 // +build !windows
 // +build !windows
 
 
 package dns
 package dns

+ 4 - 4
vendor/github.com/miekg/dns/udp_windows.go

@@ -1,5 +1,9 @@
+//go:build windows
 // +build windows
 // +build windows
 
 
+// TODO(tmthrgd): Remove this Windows-specific code if go.dev/issue/7175 and
+//   go.dev/issue/7174 are ever fixed.
+
 package dns
 package dns
 
 
 import "net"
 import "net"
@@ -14,7 +18,6 @@ func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
 
 
 // ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
 // ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
 // net.UDPAddr.
 // net.UDPAddr.
-// TODO(fastest963): Once go1.10 is released, use ReadMsgUDP.
 func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
 func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
 	n, raddr, err := conn.ReadFrom(b)
 	n, raddr, err := conn.ReadFrom(b)
 	if err != nil {
 	if err != nil {
@@ -24,12 +27,9 @@ func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
 }
 }
 
 
 // WriteToSessionUDP acts just like net.UDPConn.WriteTo(), but uses a *SessionUDP instead of a net.Addr.
 // WriteToSessionUDP acts just like net.UDPConn.WriteTo(), but uses a *SessionUDP instead of a net.Addr.
-// TODO(fastest963): Once go1.10 is released, use WriteMsgUDP.
 func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
 func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
 	return conn.WriteTo(b, session.raddr)
 	return conn.WriteTo(b, session.raddr)
 }
 }
 
 
-// TODO(fastest963): Once go1.10 is released and we can use *MsgUDP methods
-// use the standard method in udp.go for these.
 func setUDPSocketOptions(*net.UDPConn) error { return nil }
 func setUDPSocketOptions(*net.UDPConn) error { return nil }
 func parseDstFromOOB([]byte, net.IP) net.IP  { return nil }
 func parseDstFromOOB([]byte, net.IP) net.IP  { return nil }

+ 3 - 1
vendor/github.com/miekg/dns/update.go

@@ -32,7 +32,9 @@ func (u *Msg) Used(rr []RR) {
 		u.Answer = make([]RR, 0, len(rr))
 		u.Answer = make([]RR, 0, len(rr))
 	}
 	}
 	for _, r := range rr {
 	for _, r := range rr {
-		r.Header().Class = u.Question[0].Qclass
+		hdr := r.Header()
+		hdr.Class = u.Question[0].Qclass
+		hdr.Ttl = 0
 		u.Answer = append(u.Answer, r)
 		u.Answer = append(u.Answer, r)
 	}
 	}
 }
 }

+ 1 - 1
vendor/github.com/miekg/dns/version.go

@@ -3,7 +3,7 @@ package dns
 import "fmt"
 import "fmt"
 
 
 // Version is current version of this library.
 // Version is current version of this library.
-var Version = v{1, 1, 43}
+var Version = v{1, 1, 57}
 
 
 // v holds the version of this library.
 // v holds the version of this library.
 type v struct {
 type v struct {

+ 30 - 16
vendor/github.com/miekg/dns/xfr.go

@@ -17,11 +17,22 @@ type Transfer struct {
 	DialTimeout    time.Duration     // net.DialTimeout, defaults to 2 seconds
 	DialTimeout    time.Duration     // net.DialTimeout, defaults to 2 seconds
 	ReadTimeout    time.Duration     // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds
 	ReadTimeout    time.Duration     // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds
 	WriteTimeout   time.Duration     // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds
 	WriteTimeout   time.Duration     // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds
+	TsigProvider   TsigProvider      // An implementation of the TsigProvider interface. If defined it replaces TsigSecret and is used for all TSIG operations.
 	TsigSecret     map[string]string // Secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
 	TsigSecret     map[string]string // Secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
 	tsigTimersOnly bool
 	tsigTimersOnly bool
 }
 }
 
 
-// Think we need to away to stop the transfer
+func (t *Transfer) tsigProvider() TsigProvider {
+	if t.TsigProvider != nil {
+		return t.TsigProvider
+	}
+	if t.TsigSecret != nil {
+		return tsigSecretProvider(t.TsigSecret)
+	}
+	return nil
+}
+
+// TODO: Think we need to away to stop the transfer
 
 
 // In performs an incoming transfer with the server in a.
 // In performs an incoming transfer with the server in a.
 // If you would like to set the source IP, or some other attribute
 // If you would like to set the source IP, or some other attribute
@@ -33,7 +44,6 @@ type Transfer struct {
 //	dnscon := &dns.Conn{Conn:con}
 //	dnscon := &dns.Conn{Conn:con}
 //	transfer = &dns.Transfer{Conn: dnscon}
 //	transfer = &dns.Transfer{Conn: dnscon}
 //	channel, err := transfer.In(message, master)
 //	channel, err := transfer.In(message, master)
-//
 func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) {
 func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) {
 	switch q.Question[0].Qtype {
 	switch q.Question[0].Qtype {
 	case TypeAXFR, TypeIXFR:
 	case TypeAXFR, TypeIXFR:
@@ -70,8 +80,13 @@ func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) {
 
 
 func (t *Transfer) inAxfr(q *Msg, c chan *Envelope) {
 func (t *Transfer) inAxfr(q *Msg, c chan *Envelope) {
 	first := true
 	first := true
-	defer t.Close()
-	defer close(c)
+	defer func() {
+		// First close the connection, then the channel. This allows functions blocked on
+		// the channel to assume that the connection is closed and no further operations are
+		// pending when they resume.
+		t.Close()
+		close(c)
+	}()
 	timeout := dnsTimeout
 	timeout := dnsTimeout
 	if t.ReadTimeout != 0 {
 	if t.ReadTimeout != 0 {
 		timeout = t.ReadTimeout
 		timeout = t.ReadTimeout
@@ -121,8 +136,13 @@ func (t *Transfer) inIxfr(q *Msg, c chan *Envelope) {
 	axfr := true
 	axfr := true
 	n := 0
 	n := 0
 	qser := q.Ns[0].(*SOA).Serial
 	qser := q.Ns[0].(*SOA).Serial
-	defer t.Close()
-	defer close(c)
+	defer func() {
+		// First close the connection, then the channel. This allows functions blocked on
+		// the channel to assume that the connection is closed and no further operations are
+		// pending when they resume.
+		t.Close()
+		close(c)
+	}()
 	timeout := dnsTimeout
 	timeout := dnsTimeout
 	if t.ReadTimeout != 0 {
 	if t.ReadTimeout != 0 {
 		timeout = t.ReadTimeout
 		timeout = t.ReadTimeout
@@ -224,12 +244,9 @@ func (t *Transfer) ReadMsg() (*Msg, error) {
 	if err := m.Unpack(p); err != nil {
 	if err := m.Unpack(p); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	if ts := m.IsTsig(); ts != nil && t.TsigSecret != nil {
-		if _, ok := t.TsigSecret[ts.Hdr.Name]; !ok {
-			return m, ErrSecret
-		}
+	if ts, tp := m.IsTsig(), t.tsigProvider(); ts != nil && tp != nil {
 		// Need to work on the original message p, as that was used to calculate the tsig.
 		// Need to work on the original message p, as that was used to calculate the tsig.
-		err = TsigVerify(p, t.TsigSecret[ts.Hdr.Name], t.tsigRequestMAC, t.tsigTimersOnly)
+		err = TsigVerifyWithProvider(p, tp, t.tsigRequestMAC, t.tsigTimersOnly)
 		t.tsigRequestMAC = ts.MAC
 		t.tsigRequestMAC = ts.MAC
 	}
 	}
 	return m, err
 	return m, err
@@ -238,11 +255,8 @@ func (t *Transfer) ReadMsg() (*Msg, error) {
 // WriteMsg writes a message through the transfer connection t.
 // WriteMsg writes a message through the transfer connection t.
 func (t *Transfer) WriteMsg(m *Msg) (err error) {
 func (t *Transfer) WriteMsg(m *Msg) (err error) {
 	var out []byte
 	var out []byte
-	if ts := m.IsTsig(); ts != nil && t.TsigSecret != nil {
-		if _, ok := t.TsigSecret[ts.Hdr.Name]; !ok {
-			return ErrSecret
-		}
-		out, t.tsigRequestMAC, err = TsigGenerate(m, t.TsigSecret[ts.Hdr.Name], t.tsigRequestMAC, t.tsigTimersOnly)
+	if ts, tp := m.IsTsig(), t.tsigProvider(); ts != nil && tp != nil {
+		out, t.tsigRequestMAC, err = TsigGenerateWithProvider(m, tp, t.tsigRequestMAC, t.tsigTimersOnly)
 	} else {
 	} else {
 		out, err = m.Pack()
 		out, err = m.Pack()
 	}
 	}

+ 58 - 0
vendor/github.com/miekg/dns/zduplicate.go

@@ -43,6 +43,32 @@ func (r1 *AFSDB) isDuplicate(_r2 RR) bool {
 	return true
 	return true
 }
 }
 
 
+func (r1 *AMTRELAY) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*AMTRELAY)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Precedence != r2.Precedence {
+		return false
+	}
+	if r1.GatewayType != r2.GatewayType {
+		return false
+	}
+	switch r1.GatewayType {
+	case IPSECGatewayIPv4, IPSECGatewayIPv6:
+		if !r1.GatewayAddr.Equal(r2.GatewayAddr) {
+			return false
+		}
+	case IPSECGatewayHost:
+		if !isDuplicateName(r1.GatewayHost, r2.GatewayHost) {
+			return false
+		}
+	}
+
+	return true
+}
+
 func (r1 *ANY) isDuplicate(_r2 RR) bool {
 func (r1 *ANY) isDuplicate(_r2 RR) bool {
 	r2, ok := _r2.(*ANY)
 	r2, ok := _r2.(*ANY)
 	if !ok {
 	if !ok {
@@ -423,6 +449,38 @@ func (r1 *HTTPS) isDuplicate(_r2 RR) bool {
 	return true
 	return true
 }
 }
 
 
+func (r1 *IPSECKEY) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*IPSECKEY)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Precedence != r2.Precedence {
+		return false
+	}
+	if r1.GatewayType != r2.GatewayType {
+		return false
+	}
+	if r1.Algorithm != r2.Algorithm {
+		return false
+	}
+	switch r1.GatewayType {
+	case IPSECGatewayIPv4, IPSECGatewayIPv6:
+		if !r1.GatewayAddr.Equal(r2.GatewayAddr) {
+			return false
+		}
+	case IPSECGatewayHost:
+		if !isDuplicateName(r1.GatewayHost, r2.GatewayHost) {
+			return false
+		}
+	}
+
+	if r1.PublicKey != r2.PublicKey {
+		return false
+	}
+	return true
+}
+
 func (r1 *KEY) isDuplicate(_r2 RR) bool {
 func (r1 *KEY) isDuplicate(_r2 RR) bool {
 	r2, ok := _r2.(*KEY)
 	r2, ok := _r2.(*KEY)
 	if !ok {
 	if !ok {

+ 110 - 0
vendor/github.com/miekg/dns/zmsg.go

@@ -32,6 +32,22 @@ func (rr *AFSDB) pack(msg []byte, off int, compression compressionMap, compress
 	return off, nil
 	return off, nil
 }
 }
 
 
+func (rr *AMTRELAY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packUint8(rr.Precedence, msg, off)
+	if err != nil {
+		return off, err
+	}
+	off, err = packUint8(rr.GatewayType, msg, off)
+	if err != nil {
+		return off, err
+	}
+	off, err = packIPSECGateway(rr.GatewayAddr, rr.GatewayHost, msg, off, rr.GatewayType, compression, false)
+	if err != nil {
+		return off, err
+	}
+	return off, nil
+}
+
 func (rr *ANY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 func (rr *ANY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	return off, nil
 	return off, nil
 }
 }
@@ -332,6 +348,30 @@ func (rr *HTTPS) pack(msg []byte, off int, compression compressionMap, compress
 	return off, nil
 	return off, nil
 }
 }
 
 
+func (rr *IPSECKEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packUint8(rr.Precedence, msg, off)
+	if err != nil {
+		return off, err
+	}
+	off, err = packUint8(rr.GatewayType, msg, off)
+	if err != nil {
+		return off, err
+	}
+	off, err = packUint8(rr.Algorithm, msg, off)
+	if err != nil {
+		return off, err
+	}
+	off, err = packIPSECGateway(rr.GatewayAddr, rr.GatewayHost, msg, off, rr.GatewayType, compression, false)
+	if err != nil {
+		return off, err
+	}
+	off, err = packStringBase64(rr.PublicKey, msg, off)
+	if err != nil {
+		return off, err
+	}
+	return off, nil
+}
+
 func (rr *KEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 func (rr *KEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint16(rr.Flags, msg, off)
 	off, err = packUint16(rr.Flags, msg, off)
 	if err != nil {
 	if err != nil {
@@ -1180,6 +1220,34 @@ func (rr *AFSDB) unpack(msg []byte, off int) (off1 int, err error) {
 	return off, nil
 	return off, nil
 }
 }
 
 
+func (rr *AMTRELAY) unpack(msg []byte, off int) (off1 int, err error) {
+	rdStart := off
+	_ = rdStart
+
+	rr.Precedence, off, err = unpackUint8(msg, off)
+	if err != nil {
+		return off, err
+	}
+	if off == len(msg) {
+		return off, nil
+	}
+	rr.GatewayType, off, err = unpackUint8(msg, off)
+	if err != nil {
+		return off, err
+	}
+	if off == len(msg) {
+		return off, nil
+	}
+	if off == len(msg) {
+		return off, nil
+	}
+	rr.GatewayAddr, rr.GatewayHost, off, err = unpackIPSECGateway(msg, off, rr.GatewayType)
+	if err != nil {
+		return off, err
+	}
+	return off, nil
+}
+
 func (rr *ANY) unpack(msg []byte, off int) (off1 int, err error) {
 func (rr *ANY) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	rdStart := off
 	_ = rdStart
 	_ = rdStart
@@ -1636,6 +1704,48 @@ func (rr *HTTPS) unpack(msg []byte, off int) (off1 int, err error) {
 	return off, nil
 	return off, nil
 }
 }
 
 
+func (rr *IPSECKEY) unpack(msg []byte, off int) (off1 int, err error) {
+	rdStart := off
+	_ = rdStart
+
+	rr.Precedence, off, err = unpackUint8(msg, off)
+	if err != nil {
+		return off, err
+	}
+	if off == len(msg) {
+		return off, nil
+	}
+	rr.GatewayType, off, err = unpackUint8(msg, off)
+	if err != nil {
+		return off, err
+	}
+	if off == len(msg) {
+		return off, nil
+	}
+	rr.Algorithm, off, err = unpackUint8(msg, off)
+	if err != nil {
+		return off, err
+	}
+	if off == len(msg) {
+		return off, nil
+	}
+	if off == len(msg) {
+		return off, nil
+	}
+	rr.GatewayAddr, rr.GatewayHost, off, err = unpackIPSECGateway(msg, off, rr.GatewayType)
+	if err != nil {
+		return off, 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, nil
+}
+
 func (rr *KEY) unpack(msg []byte, off int) (off1 int, err error) {
 func (rr *KEY) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	rdStart := off
 	_ = rdStart
 	_ = rdStart

+ 404 - 49
vendor/github.com/miekg/dns/ztypes.go

@@ -12,6 +12,7 @@ var TypeToRR = map[uint16]func() RR{
 	TypeA:          func() RR { return new(A) },
 	TypeA:          func() RR { return new(A) },
 	TypeAAAA:       func() RR { return new(AAAA) },
 	TypeAAAA:       func() RR { return new(AAAA) },
 	TypeAFSDB:      func() RR { return new(AFSDB) },
 	TypeAFSDB:      func() RR { return new(AFSDB) },
+	TypeAMTRELAY:   func() RR { return new(AMTRELAY) },
 	TypeANY:        func() RR { return new(ANY) },
 	TypeANY:        func() RR { return new(ANY) },
 	TypeAPL:        func() RR { return new(APL) },
 	TypeAPL:        func() RR { return new(APL) },
 	TypeAVC:        func() RR { return new(AVC) },
 	TypeAVC:        func() RR { return new(AVC) },
@@ -34,6 +35,7 @@ var TypeToRR = map[uint16]func() RR{
 	TypeHINFO:      func() RR { return new(HINFO) },
 	TypeHINFO:      func() RR { return new(HINFO) },
 	TypeHIP:        func() RR { return new(HIP) },
 	TypeHIP:        func() RR { return new(HIP) },
 	TypeHTTPS:      func() RR { return new(HTTPS) },
 	TypeHTTPS:      func() RR { return new(HTTPS) },
+	TypeIPSECKEY:   func() RR { return new(IPSECKEY) },
 	TypeKEY:        func() RR { return new(KEY) },
 	TypeKEY:        func() RR { return new(KEY) },
 	TypeKX:         func() RR { return new(KX) },
 	TypeKX:         func() RR { return new(KX) },
 	TypeL32:        func() RR { return new(L32) },
 	TypeL32:        func() RR { return new(L32) },
@@ -90,6 +92,7 @@ var TypeToString = map[uint16]string{
 	TypeA:          "A",
 	TypeA:          "A",
 	TypeAAAA:       "AAAA",
 	TypeAAAA:       "AAAA",
 	TypeAFSDB:      "AFSDB",
 	TypeAFSDB:      "AFSDB",
+	TypeAMTRELAY:   "AMTRELAY",
 	TypeANY:        "ANY",
 	TypeANY:        "ANY",
 	TypeAPL:        "APL",
 	TypeAPL:        "APL",
 	TypeATMA:       "ATMA",
 	TypeATMA:       "ATMA",
@@ -114,6 +117,7 @@ var TypeToString = map[uint16]string{
 	TypeHINFO:      "HINFO",
 	TypeHINFO:      "HINFO",
 	TypeHIP:        "HIP",
 	TypeHIP:        "HIP",
 	TypeHTTPS:      "HTTPS",
 	TypeHTTPS:      "HTTPS",
+	TypeIPSECKEY:   "IPSECKEY",
 	TypeISDN:       "ISDN",
 	TypeISDN:       "ISDN",
 	TypeIXFR:       "IXFR",
 	TypeIXFR:       "IXFR",
 	TypeKEY:        "KEY",
 	TypeKEY:        "KEY",
@@ -176,6 +180,7 @@ var TypeToString = map[uint16]string{
 func (rr *A) Header() *RR_Header          { return &rr.Hdr }
 func (rr *A) Header() *RR_Header          { return &rr.Hdr }
 func (rr *AAAA) Header() *RR_Header       { return &rr.Hdr }
 func (rr *AAAA) Header() *RR_Header       { return &rr.Hdr }
 func (rr *AFSDB) Header() *RR_Header      { return &rr.Hdr }
 func (rr *AFSDB) Header() *RR_Header      { return &rr.Hdr }
+func (rr *AMTRELAY) Header() *RR_Header   { return &rr.Hdr }
 func (rr *ANY) Header() *RR_Header        { return &rr.Hdr }
 func (rr *ANY) Header() *RR_Header        { return &rr.Hdr }
 func (rr *APL) Header() *RR_Header        { return &rr.Hdr }
 func (rr *APL) Header() *RR_Header        { return &rr.Hdr }
 func (rr *AVC) Header() *RR_Header        { return &rr.Hdr }
 func (rr *AVC) Header() *RR_Header        { return &rr.Hdr }
@@ -198,6 +203,7 @@ func (rr *GPOS) Header() *RR_Header       { return &rr.Hdr }
 func (rr *HINFO) Header() *RR_Header      { return &rr.Hdr }
 func (rr *HINFO) Header() *RR_Header      { return &rr.Hdr }
 func (rr *HIP) Header() *RR_Header        { return &rr.Hdr }
 func (rr *HIP) Header() *RR_Header        { return &rr.Hdr }
 func (rr *HTTPS) Header() *RR_Header      { return &rr.Hdr }
 func (rr *HTTPS) Header() *RR_Header      { return &rr.Hdr }
+func (rr *IPSECKEY) Header() *RR_Header   { return &rr.Hdr }
 func (rr *KEY) Header() *RR_Header        { return &rr.Hdr }
 func (rr *KEY) Header() *RR_Header        { return &rr.Hdr }
 func (rr *KX) Header() *RR_Header         { return &rr.Hdr }
 func (rr *KX) Header() *RR_Header         { return &rr.Hdr }
 func (rr *L32) Header() *RR_Header        { return &rr.Hdr }
 func (rr *L32) Header() *RR_Header        { return &rr.Hdr }
@@ -257,6 +263,7 @@ func (rr *A) len(off int, compression map[string]struct{}) int {
 	}
 	}
 	return l
 	return l
 }
 }
+
 func (rr *AAAA) len(off int, compression map[string]struct{}) int {
 func (rr *AAAA) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	if len(rr.AAAA) != 0 {
 	if len(rr.AAAA) != 0 {
@@ -264,16 +271,34 @@ func (rr *AAAA) len(off int, compression map[string]struct{}) int {
 	}
 	}
 	return l
 	return l
 }
 }
+
 func (rr *AFSDB) len(off int, compression map[string]struct{}) int {
 func (rr *AFSDB) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 2 // Subtype
 	l += 2 // Subtype
 	l += domainNameLen(rr.Hostname, off+l, compression, false)
 	l += domainNameLen(rr.Hostname, off+l, compression, false)
 	return l
 	return l
 }
 }
+
+func (rr *AMTRELAY) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l++ // Precedence
+	l++ // GatewayType
+	switch rr.GatewayType {
+	case AMTRELAYIPv4:
+		l += net.IPv4len
+	case AMTRELAYIPv6:
+		l += net.IPv6len
+	case AMTRELAYHost:
+		l += len(rr.GatewayHost) + 1
+	}
+	return l
+}
+
 func (rr *ANY) len(off int, compression map[string]struct{}) int {
 func (rr *ANY) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	return l
 	return l
 }
 }
+
 func (rr *APL) len(off int, compression map[string]struct{}) int {
 func (rr *APL) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	for _, x := range rr.Prefixes {
 	for _, x := range rr.Prefixes {
@@ -281,6 +306,7 @@ func (rr *APL) len(off int, compression map[string]struct{}) int {
 	}
 	}
 	return l
 	return l
 }
 }
+
 func (rr *AVC) len(off int, compression map[string]struct{}) int {
 func (rr *AVC) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	for _, x := range rr.Txt {
 	for _, x := range rr.Txt {
@@ -288,6 +314,7 @@ func (rr *AVC) len(off int, compression map[string]struct{}) int {
 	}
 	}
 	return l
 	return l
 }
 }
+
 func (rr *CAA) len(off int, compression map[string]struct{}) int {
 func (rr *CAA) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l++ // Flag
 	l++ // Flag
@@ -295,6 +322,7 @@ func (rr *CAA) len(off int, compression map[string]struct{}) int {
 	l += len(rr.Value)
 	l += len(rr.Value)
 	return l
 	return l
 }
 }
+
 func (rr *CERT) len(off int, compression map[string]struct{}) int {
 func (rr *CERT) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 2 // Type
 	l += 2 // Type
@@ -303,21 +331,25 @@ func (rr *CERT) len(off int, compression map[string]struct{}) int {
 	l += base64.StdEncoding.DecodedLen(len(rr.Certificate))
 	l += base64.StdEncoding.DecodedLen(len(rr.Certificate))
 	return l
 	return l
 }
 }
+
 func (rr *CNAME) len(off int, compression map[string]struct{}) int {
 func (rr *CNAME) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += domainNameLen(rr.Target, off+l, compression, true)
 	l += domainNameLen(rr.Target, off+l, compression, true)
 	return l
 	return l
 }
 }
+
 func (rr *DHCID) len(off int, compression map[string]struct{}) int {
 func (rr *DHCID) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += base64.StdEncoding.DecodedLen(len(rr.Digest))
 	l += base64.StdEncoding.DecodedLen(len(rr.Digest))
 	return l
 	return l
 }
 }
+
 func (rr *DNAME) len(off int, compression map[string]struct{}) int {
 func (rr *DNAME) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += domainNameLen(rr.Target, off+l, compression, false)
 	l += domainNameLen(rr.Target, off+l, compression, false)
 	return l
 	return l
 }
 }
+
 func (rr *DNSKEY) len(off int, compression map[string]struct{}) int {
 func (rr *DNSKEY) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 2 // Flags
 	l += 2 // Flags
@@ -326,6 +358,7 @@ func (rr *DNSKEY) len(off int, compression map[string]struct{}) int {
 	l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
 	l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
 	return l
 	return l
 }
 }
+
 func (rr *DS) len(off int, compression map[string]struct{}) int {
 func (rr *DS) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 2 // KeyTag
 	l += 2 // KeyTag
@@ -334,26 +367,31 @@ func (rr *DS) len(off int, compression map[string]struct{}) int {
 	l += len(rr.Digest) / 2
 	l += len(rr.Digest) / 2
 	return l
 	return l
 }
 }
+
 func (rr *EID) len(off int, compression map[string]struct{}) int {
 func (rr *EID) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += len(rr.Endpoint) / 2
 	l += len(rr.Endpoint) / 2
 	return l
 	return l
 }
 }
+
 func (rr *EUI48) len(off int, compression map[string]struct{}) int {
 func (rr *EUI48) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 6 // Address
 	l += 6 // Address
 	return l
 	return l
 }
 }
+
 func (rr *EUI64) len(off int, compression map[string]struct{}) int {
 func (rr *EUI64) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 8 // Address
 	l += 8 // Address
 	return l
 	return l
 }
 }
+
 func (rr *GID) len(off int, compression map[string]struct{}) int {
 func (rr *GID) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 4 // Gid
 	l += 4 // Gid
 	return l
 	return l
 }
 }
+
 func (rr *GPOS) len(off int, compression map[string]struct{}) int {
 func (rr *GPOS) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += len(rr.Longitude) + 1
 	l += len(rr.Longitude) + 1
@@ -361,12 +399,14 @@ func (rr *GPOS) len(off int, compression map[string]struct{}) int {
 	l += len(rr.Altitude) + 1
 	l += len(rr.Altitude) + 1
 	return l
 	return l
 }
 }
+
 func (rr *HINFO) len(off int, compression map[string]struct{}) int {
 func (rr *HINFO) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += len(rr.Cpu) + 1
 	l += len(rr.Cpu) + 1
 	l += len(rr.Os) + 1
 	l += len(rr.Os) + 1
 	return l
 	return l
 }
 }
+
 func (rr *HIP) len(off int, compression map[string]struct{}) int {
 func (rr *HIP) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l++    // HitLength
 	l++    // HitLength
@@ -379,12 +419,31 @@ func (rr *HIP) len(off int, compression map[string]struct{}) int {
 	}
 	}
 	return l
 	return l
 }
 }
+
+func (rr *IPSECKEY) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l++ // Precedence
+	l++ // GatewayType
+	l++ // Algorithm
+	switch rr.GatewayType {
+	case IPSECGatewayIPv4:
+		l += net.IPv4len
+	case IPSECGatewayIPv6:
+		l += net.IPv6len
+	case IPSECGatewayHost:
+		l += len(rr.GatewayHost) + 1
+	}
+	l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
+	return l
+}
+
 func (rr *KX) len(off int, compression map[string]struct{}) int {
 func (rr *KX) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
 	l += 2 // Preference
 	l += domainNameLen(rr.Exchanger, off+l, compression, false)
 	l += domainNameLen(rr.Exchanger, off+l, compression, false)
 	return l
 	return l
 }
 }
+
 func (rr *L32) len(off int, compression map[string]struct{}) int {
 func (rr *L32) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
 	l += 2 // Preference
@@ -393,12 +452,14 @@ func (rr *L32) len(off int, compression map[string]struct{}) int {
 	}
 	}
 	return l
 	return l
 }
 }
+
 func (rr *L64) len(off int, compression map[string]struct{}) int {
 func (rr *L64) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
 	l += 2 // Preference
 	l += 8 // Locator64
 	l += 8 // Locator64
 	return l
 	return l
 }
 }
+
 func (rr *LOC) len(off int, compression map[string]struct{}) int {
 func (rr *LOC) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l++    // Version
 	l++    // Version
@@ -410,49 +471,58 @@ func (rr *LOC) len(off int, compression map[string]struct{}) int {
 	l += 4 // Altitude
 	l += 4 // Altitude
 	return l
 	return l
 }
 }
+
 func (rr *LP) len(off int, compression map[string]struct{}) int {
 func (rr *LP) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
 	l += 2 // Preference
 	l += domainNameLen(rr.Fqdn, off+l, compression, false)
 	l += domainNameLen(rr.Fqdn, off+l, compression, false)
 	return l
 	return l
 }
 }
+
 func (rr *MB) len(off int, compression map[string]struct{}) int {
 func (rr *MB) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += domainNameLen(rr.Mb, off+l, compression, true)
 	l += domainNameLen(rr.Mb, off+l, compression, true)
 	return l
 	return l
 }
 }
+
 func (rr *MD) len(off int, compression map[string]struct{}) int {
 func (rr *MD) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += domainNameLen(rr.Md, off+l, compression, true)
 	l += domainNameLen(rr.Md, off+l, compression, true)
 	return l
 	return l
 }
 }
+
 func (rr *MF) len(off int, compression map[string]struct{}) int {
 func (rr *MF) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += domainNameLen(rr.Mf, off+l, compression, true)
 	l += domainNameLen(rr.Mf, off+l, compression, true)
 	return l
 	return l
 }
 }
+
 func (rr *MG) len(off int, compression map[string]struct{}) int {
 func (rr *MG) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += domainNameLen(rr.Mg, off+l, compression, true)
 	l += domainNameLen(rr.Mg, off+l, compression, true)
 	return l
 	return l
 }
 }
+
 func (rr *MINFO) len(off int, compression map[string]struct{}) int {
 func (rr *MINFO) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += domainNameLen(rr.Rmail, off+l, compression, true)
 	l += domainNameLen(rr.Rmail, off+l, compression, true)
 	l += domainNameLen(rr.Email, off+l, compression, true)
 	l += domainNameLen(rr.Email, off+l, compression, true)
 	return l
 	return l
 }
 }
+
 func (rr *MR) len(off int, compression map[string]struct{}) int {
 func (rr *MR) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += domainNameLen(rr.Mr, off+l, compression, true)
 	l += domainNameLen(rr.Mr, off+l, compression, true)
 	return l
 	return l
 }
 }
+
 func (rr *MX) len(off int, compression map[string]struct{}) int {
 func (rr *MX) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
 	l += 2 // Preference
 	l += domainNameLen(rr.Mx, off+l, compression, true)
 	l += domainNameLen(rr.Mx, off+l, compression, true)
 	return l
 	return l
 }
 }
+
 func (rr *NAPTR) len(off int, compression map[string]struct{}) int {
 func (rr *NAPTR) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 2 // Order
 	l += 2 // Order
@@ -463,17 +533,20 @@ func (rr *NAPTR) len(off int, compression map[string]struct{}) int {
 	l += domainNameLen(rr.Replacement, off+l, compression, false)
 	l += domainNameLen(rr.Replacement, off+l, compression, false)
 	return l
 	return l
 }
 }
+
 func (rr *NID) len(off int, compression map[string]struct{}) int {
 func (rr *NID) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
 	l += 2 // Preference
 	l += 8 // NodeID
 	l += 8 // NodeID
 	return l
 	return l
 }
 }
+
 func (rr *NIMLOC) len(off int, compression map[string]struct{}) int {
 func (rr *NIMLOC) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += len(rr.Locator) / 2
 	l += len(rr.Locator) / 2
 	return l
 	return l
 }
 }
+
 func (rr *NINFO) len(off int, compression map[string]struct{}) int {
 func (rr *NINFO) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	for _, x := range rr.ZSData {
 	for _, x := range rr.ZSData {
@@ -481,16 +554,19 @@ func (rr *NINFO) len(off int, compression map[string]struct{}) int {
 	}
 	}
 	return l
 	return l
 }
 }
+
 func (rr *NS) len(off int, compression map[string]struct{}) int {
 func (rr *NS) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += domainNameLen(rr.Ns, off+l, compression, true)
 	l += domainNameLen(rr.Ns, off+l, compression, true)
 	return l
 	return l
 }
 }
+
 func (rr *NSAPPTR) len(off int, compression map[string]struct{}) int {
 func (rr *NSAPPTR) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += domainNameLen(rr.Ptr, off+l, compression, false)
 	l += domainNameLen(rr.Ptr, off+l, compression, false)
 	return l
 	return l
 }
 }
+
 func (rr *NSEC3PARAM) len(off int, compression map[string]struct{}) int {
 func (rr *NSEC3PARAM) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l++    // Hash
 	l++    // Hash
@@ -500,21 +576,25 @@ func (rr *NSEC3PARAM) len(off int, compression map[string]struct{}) int {
 	l += len(rr.Salt) / 2
 	l += len(rr.Salt) / 2
 	return l
 	return l
 }
 }
+
 func (rr *NULL) len(off int, compression map[string]struct{}) int {
 func (rr *NULL) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += len(rr.Data)
 	l += len(rr.Data)
 	return l
 	return l
 }
 }
+
 func (rr *OPENPGPKEY) len(off int, compression map[string]struct{}) int {
 func (rr *OPENPGPKEY) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
 	l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
 	return l
 	return l
 }
 }
+
 func (rr *PTR) len(off int, compression map[string]struct{}) int {
 func (rr *PTR) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += domainNameLen(rr.Ptr, off+l, compression, true)
 	l += domainNameLen(rr.Ptr, off+l, compression, true)
 	return l
 	return l
 }
 }
+
 func (rr *PX) len(off int, compression map[string]struct{}) int {
 func (rr *PX) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
 	l += 2 // Preference
@@ -522,11 +602,13 @@ func (rr *PX) len(off int, compression map[string]struct{}) int {
 	l += domainNameLen(rr.Mapx400, off+l, compression, false)
 	l += domainNameLen(rr.Mapx400, off+l, compression, false)
 	return l
 	return l
 }
 }
+
 func (rr *RFC3597) len(off int, compression map[string]struct{}) int {
 func (rr *RFC3597) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += len(rr.Rdata) / 2
 	l += len(rr.Rdata) / 2
 	return l
 	return l
 }
 }
+
 func (rr *RKEY) len(off int, compression map[string]struct{}) int {
 func (rr *RKEY) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 2 // Flags
 	l += 2 // Flags
@@ -535,12 +617,14 @@ func (rr *RKEY) len(off int, compression map[string]struct{}) int {
 	l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
 	l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
 	return l
 	return l
 }
 }
+
 func (rr *RP) len(off int, compression map[string]struct{}) int {
 func (rr *RP) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += domainNameLen(rr.Mbox, off+l, compression, false)
 	l += domainNameLen(rr.Mbox, off+l, compression, false)
 	l += domainNameLen(rr.Txt, off+l, compression, false)
 	l += domainNameLen(rr.Txt, off+l, compression, false)
 	return l
 	return l
 }
 }
+
 func (rr *RRSIG) len(off int, compression map[string]struct{}) int {
 func (rr *RRSIG) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 2 // TypeCovered
 	l += 2 // TypeCovered
@@ -554,12 +638,14 @@ func (rr *RRSIG) len(off int, compression map[string]struct{}) int {
 	l += base64.StdEncoding.DecodedLen(len(rr.Signature))
 	l += base64.StdEncoding.DecodedLen(len(rr.Signature))
 	return l
 	return l
 }
 }
+
 func (rr *RT) len(off int, compression map[string]struct{}) int {
 func (rr *RT) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
 	l += 2 // Preference
 	l += domainNameLen(rr.Host, off+l, compression, false)
 	l += domainNameLen(rr.Host, off+l, compression, false)
 	return l
 	return l
 }
 }
+
 func (rr *SMIMEA) len(off int, compression map[string]struct{}) int {
 func (rr *SMIMEA) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l++ // Usage
 	l++ // Usage
@@ -568,6 +654,7 @@ func (rr *SMIMEA) len(off int, compression map[string]struct{}) int {
 	l += len(rr.Certificate) / 2
 	l += len(rr.Certificate) / 2
 	return l
 	return l
 }
 }
+
 func (rr *SOA) len(off int, compression map[string]struct{}) int {
 func (rr *SOA) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += domainNameLen(rr.Ns, off+l, compression, true)
 	l += domainNameLen(rr.Ns, off+l, compression, true)
@@ -579,6 +666,7 @@ func (rr *SOA) len(off int, compression map[string]struct{}) int {
 	l += 4 // Minttl
 	l += 4 // Minttl
 	return l
 	return l
 }
 }
+
 func (rr *SPF) len(off int, compression map[string]struct{}) int {
 func (rr *SPF) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	for _, x := range rr.Txt {
 	for _, x := range rr.Txt {
@@ -586,6 +674,7 @@ func (rr *SPF) len(off int, compression map[string]struct{}) int {
 	}
 	}
 	return l
 	return l
 }
 }
+
 func (rr *SRV) len(off int, compression map[string]struct{}) int {
 func (rr *SRV) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 2 // Priority
 	l += 2 // Priority
@@ -594,6 +683,7 @@ func (rr *SRV) len(off int, compression map[string]struct{}) int {
 	l += domainNameLen(rr.Target, off+l, compression, false)
 	l += domainNameLen(rr.Target, off+l, compression, false)
 	return l
 	return l
 }
 }
+
 func (rr *SSHFP) len(off int, compression map[string]struct{}) int {
 func (rr *SSHFP) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l++ // Algorithm
 	l++ // Algorithm
@@ -601,6 +691,7 @@ func (rr *SSHFP) len(off int, compression map[string]struct{}) int {
 	l += len(rr.FingerPrint) / 2
 	l += len(rr.FingerPrint) / 2
 	return l
 	return l
 }
 }
+
 func (rr *SVCB) len(off int, compression map[string]struct{}) int {
 func (rr *SVCB) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 2 // Priority
 	l += 2 // Priority
@@ -610,6 +701,7 @@ func (rr *SVCB) len(off int, compression map[string]struct{}) int {
 	}
 	}
 	return l
 	return l
 }
 }
+
 func (rr *TA) len(off int, compression map[string]struct{}) int {
 func (rr *TA) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 2 // KeyTag
 	l += 2 // KeyTag
@@ -618,12 +710,14 @@ func (rr *TA) len(off int, compression map[string]struct{}) int {
 	l += len(rr.Digest) / 2
 	l += len(rr.Digest) / 2
 	return l
 	return l
 }
 }
+
 func (rr *TALINK) len(off int, compression map[string]struct{}) int {
 func (rr *TALINK) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += domainNameLen(rr.PreviousName, off+l, compression, false)
 	l += domainNameLen(rr.PreviousName, off+l, compression, false)
 	l += domainNameLen(rr.NextName, off+l, compression, false)
 	l += domainNameLen(rr.NextName, off+l, compression, false)
 	return l
 	return l
 }
 }
+
 func (rr *TKEY) len(off int, compression map[string]struct{}) int {
 func (rr *TKEY) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += domainNameLen(rr.Algorithm, off+l, compression, false)
 	l += domainNameLen(rr.Algorithm, off+l, compression, false)
@@ -637,6 +731,7 @@ func (rr *TKEY) len(off int, compression map[string]struct{}) int {
 	l += len(rr.OtherData) / 2
 	l += len(rr.OtherData) / 2
 	return l
 	return l
 }
 }
+
 func (rr *TLSA) len(off int, compression map[string]struct{}) int {
 func (rr *TLSA) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l++ // Usage
 	l++ // Usage
@@ -645,6 +740,7 @@ func (rr *TLSA) len(off int, compression map[string]struct{}) int {
 	l += len(rr.Certificate) / 2
 	l += len(rr.Certificate) / 2
 	return l
 	return l
 }
 }
+
 func (rr *TSIG) len(off int, compression map[string]struct{}) int {
 func (rr *TSIG) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += domainNameLen(rr.Algorithm, off+l, compression, false)
 	l += domainNameLen(rr.Algorithm, off+l, compression, false)
@@ -658,6 +754,7 @@ func (rr *TSIG) len(off int, compression map[string]struct{}) int {
 	l += len(rr.OtherData) / 2
 	l += len(rr.OtherData) / 2
 	return l
 	return l
 }
 }
+
 func (rr *TXT) len(off int, compression map[string]struct{}) int {
 func (rr *TXT) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	for _, x := range rr.Txt {
 	for _, x := range rr.Txt {
@@ -665,16 +762,19 @@ func (rr *TXT) len(off int, compression map[string]struct{}) int {
 	}
 	}
 	return l
 	return l
 }
 }
+
 func (rr *UID) len(off int, compression map[string]struct{}) int {
 func (rr *UID) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 4 // Uid
 	l += 4 // Uid
 	return l
 	return l
 }
 }
+
 func (rr *UINFO) len(off int, compression map[string]struct{}) int {
 func (rr *UINFO) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += len(rr.Uinfo) + 1
 	l += len(rr.Uinfo) + 1
 	return l
 	return l
 }
 }
+
 func (rr *URI) len(off int, compression map[string]struct{}) int {
 func (rr *URI) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 2 // Priority
 	l += 2 // Priority
@@ -682,11 +782,13 @@ func (rr *URI) len(off int, compression map[string]struct{}) int {
 	l += len(rr.Target)
 	l += len(rr.Target)
 	return l
 	return l
 }
 }
+
 func (rr *X25) len(off int, compression map[string]struct{}) int {
 func (rr *X25) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += len(rr.PSDNAddress) + 1
 	l += len(rr.PSDNAddress) + 1
 	return l
 	return l
 }
 }
+
 func (rr *ZONEMD) len(off int, compression map[string]struct{}) int {
 func (rr *ZONEMD) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l := rr.Hdr.len(off, compression)
 	l += 4 // Serial
 	l += 4 // Serial
@@ -698,17 +800,31 @@ func (rr *ZONEMD) len(off int, compression map[string]struct{}) int {
 
 
 // copy() functions
 // copy() functions
 func (rr *A) copy() RR {
 func (rr *A) copy() RR {
-	return &A{rr.Hdr, copyIP(rr.A)}
+	return &A{rr.Hdr, cloneSlice(rr.A)}
 }
 }
+
 func (rr *AAAA) copy() RR {
 func (rr *AAAA) copy() RR {
-	return &AAAA{rr.Hdr, copyIP(rr.AAAA)}
+	return &AAAA{rr.Hdr, cloneSlice(rr.AAAA)}
 }
 }
+
 func (rr *AFSDB) copy() RR {
 func (rr *AFSDB) copy() RR {
 	return &AFSDB{rr.Hdr, rr.Subtype, rr.Hostname}
 	return &AFSDB{rr.Hdr, rr.Subtype, rr.Hostname}
 }
 }
+
+func (rr *AMTRELAY) copy() RR {
+	return &AMTRELAY{
+		rr.Hdr,
+		rr.Precedence,
+		rr.GatewayType,
+		cloneSlice(rr.GatewayAddr),
+		rr.GatewayHost,
+	}
+}
+
 func (rr *ANY) copy() RR {
 func (rr *ANY) copy() RR {
 	return &ANY{rr.Hdr}
 	return &ANY{rr.Hdr}
 }
 }
+
 func (rr *APL) copy() RR {
 func (rr *APL) copy() RR {
 	Prefixes := make([]APLPrefix, len(rr.Prefixes))
 	Prefixes := make([]APLPrefix, len(rr.Prefixes))
 	for i, e := range rr.Prefixes {
 	for i, e := range rr.Prefixes {
@@ -716,150 +832,270 @@ func (rr *APL) copy() RR {
 	}
 	}
 	return &APL{rr.Hdr, Prefixes}
 	return &APL{rr.Hdr, Prefixes}
 }
 }
+
 func (rr *AVC) copy() RR {
 func (rr *AVC) copy() RR {
-	Txt := make([]string, len(rr.Txt))
-	copy(Txt, rr.Txt)
-	return &AVC{rr.Hdr, Txt}
+	return &AVC{rr.Hdr, cloneSlice(rr.Txt)}
 }
 }
+
 func (rr *CAA) copy() RR {
 func (rr *CAA) copy() RR {
-	return &CAA{rr.Hdr, rr.Flag, rr.Tag, rr.Value}
+	return &CAA{
+		rr.Hdr,
+		rr.Flag,
+		rr.Tag,
+		rr.Value,
+	}
 }
 }
+
 func (rr *CDNSKEY) copy() RR {
 func (rr *CDNSKEY) copy() RR {
 	return &CDNSKEY{*rr.DNSKEY.copy().(*DNSKEY)}
 	return &CDNSKEY{*rr.DNSKEY.copy().(*DNSKEY)}
 }
 }
+
 func (rr *CDS) copy() RR {
 func (rr *CDS) copy() RR {
 	return &CDS{*rr.DS.copy().(*DS)}
 	return &CDS{*rr.DS.copy().(*DS)}
 }
 }
+
 func (rr *CERT) copy() RR {
 func (rr *CERT) copy() RR {
-	return &CERT{rr.Hdr, rr.Type, rr.KeyTag, rr.Algorithm, rr.Certificate}
+	return &CERT{
+		rr.Hdr,
+		rr.Type,
+		rr.KeyTag,
+		rr.Algorithm,
+		rr.Certificate,
+	}
 }
 }
+
 func (rr *CNAME) copy() RR {
 func (rr *CNAME) copy() RR {
 	return &CNAME{rr.Hdr, rr.Target}
 	return &CNAME{rr.Hdr, rr.Target}
 }
 }
+
 func (rr *CSYNC) copy() RR {
 func (rr *CSYNC) copy() RR {
-	TypeBitMap := make([]uint16, len(rr.TypeBitMap))
-	copy(TypeBitMap, rr.TypeBitMap)
-	return &CSYNC{rr.Hdr, rr.Serial, rr.Flags, TypeBitMap}
+	return &CSYNC{
+		rr.Hdr,
+		rr.Serial,
+		rr.Flags,
+		cloneSlice(rr.TypeBitMap),
+	}
 }
 }
+
 func (rr *DHCID) copy() RR {
 func (rr *DHCID) copy() RR {
 	return &DHCID{rr.Hdr, rr.Digest}
 	return &DHCID{rr.Hdr, rr.Digest}
 }
 }
+
 func (rr *DLV) copy() RR {
 func (rr *DLV) copy() RR {
 	return &DLV{*rr.DS.copy().(*DS)}
 	return &DLV{*rr.DS.copy().(*DS)}
 }
 }
+
 func (rr *DNAME) copy() RR {
 func (rr *DNAME) copy() RR {
 	return &DNAME{rr.Hdr, rr.Target}
 	return &DNAME{rr.Hdr, rr.Target}
 }
 }
+
 func (rr *DNSKEY) copy() RR {
 func (rr *DNSKEY) copy() RR {
-	return &DNSKEY{rr.Hdr, rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey}
+	return &DNSKEY{
+		rr.Hdr,
+		rr.Flags,
+		rr.Protocol,
+		rr.Algorithm,
+		rr.PublicKey,
+	}
 }
 }
+
 func (rr *DS) copy() RR {
 func (rr *DS) copy() RR {
-	return &DS{rr.Hdr, rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
+	return &DS{
+		rr.Hdr,
+		rr.KeyTag,
+		rr.Algorithm,
+		rr.DigestType,
+		rr.Digest,
+	}
 }
 }
+
 func (rr *EID) copy() RR {
 func (rr *EID) copy() RR {
 	return &EID{rr.Hdr, rr.Endpoint}
 	return &EID{rr.Hdr, rr.Endpoint}
 }
 }
+
 func (rr *EUI48) copy() RR {
 func (rr *EUI48) copy() RR {
 	return &EUI48{rr.Hdr, rr.Address}
 	return &EUI48{rr.Hdr, rr.Address}
 }
 }
+
 func (rr *EUI64) copy() RR {
 func (rr *EUI64) copy() RR {
 	return &EUI64{rr.Hdr, rr.Address}
 	return &EUI64{rr.Hdr, rr.Address}
 }
 }
+
 func (rr *GID) copy() RR {
 func (rr *GID) copy() RR {
 	return &GID{rr.Hdr, rr.Gid}
 	return &GID{rr.Hdr, rr.Gid}
 }
 }
+
 func (rr *GPOS) copy() RR {
 func (rr *GPOS) copy() RR {
-	return &GPOS{rr.Hdr, rr.Longitude, rr.Latitude, rr.Altitude}
+	return &GPOS{
+		rr.Hdr,
+		rr.Longitude,
+		rr.Latitude,
+		rr.Altitude,
+	}
 }
 }
+
 func (rr *HINFO) copy() RR {
 func (rr *HINFO) copy() RR {
 	return &HINFO{rr.Hdr, rr.Cpu, rr.Os}
 	return &HINFO{rr.Hdr, rr.Cpu, rr.Os}
 }
 }
+
 func (rr *HIP) copy() RR {
 func (rr *HIP) copy() RR {
-	RendezvousServers := make([]string, len(rr.RendezvousServers))
-	copy(RendezvousServers, rr.RendezvousServers)
-	return &HIP{rr.Hdr, rr.HitLength, rr.PublicKeyAlgorithm, rr.PublicKeyLength, rr.Hit, rr.PublicKey, RendezvousServers}
+	return &HIP{
+		rr.Hdr,
+		rr.HitLength,
+		rr.PublicKeyAlgorithm,
+		rr.PublicKeyLength,
+		rr.Hit,
+		rr.PublicKey,
+		cloneSlice(rr.RendezvousServers),
+	}
 }
 }
+
 func (rr *HTTPS) copy() RR {
 func (rr *HTTPS) copy() RR {
 	return &HTTPS{*rr.SVCB.copy().(*SVCB)}
 	return &HTTPS{*rr.SVCB.copy().(*SVCB)}
 }
 }
+
+func (rr *IPSECKEY) copy() RR {
+	return &IPSECKEY{
+		rr.Hdr,
+		rr.Precedence,
+		rr.GatewayType,
+		rr.Algorithm,
+		cloneSlice(rr.GatewayAddr),
+		rr.GatewayHost,
+		rr.PublicKey,
+	}
+}
+
 func (rr *KEY) copy() RR {
 func (rr *KEY) copy() RR {
 	return &KEY{*rr.DNSKEY.copy().(*DNSKEY)}
 	return &KEY{*rr.DNSKEY.copy().(*DNSKEY)}
 }
 }
+
 func (rr *KX) copy() RR {
 func (rr *KX) copy() RR {
 	return &KX{rr.Hdr, rr.Preference, rr.Exchanger}
 	return &KX{rr.Hdr, rr.Preference, rr.Exchanger}
 }
 }
+
 func (rr *L32) copy() RR {
 func (rr *L32) copy() RR {
-	return &L32{rr.Hdr, rr.Preference, copyIP(rr.Locator32)}
+	return &L32{rr.Hdr, rr.Preference, cloneSlice(rr.Locator32)}
 }
 }
+
 func (rr *L64) copy() RR {
 func (rr *L64) copy() RR {
 	return &L64{rr.Hdr, rr.Preference, rr.Locator64}
 	return &L64{rr.Hdr, rr.Preference, rr.Locator64}
 }
 }
+
 func (rr *LOC) copy() RR {
 func (rr *LOC) copy() RR {
-	return &LOC{rr.Hdr, rr.Version, rr.Size, rr.HorizPre, rr.VertPre, rr.Latitude, rr.Longitude, rr.Altitude}
+	return &LOC{
+		rr.Hdr,
+		rr.Version,
+		rr.Size,
+		rr.HorizPre,
+		rr.VertPre,
+		rr.Latitude,
+		rr.Longitude,
+		rr.Altitude,
+	}
 }
 }
+
 func (rr *LP) copy() RR {
 func (rr *LP) copy() RR {
 	return &LP{rr.Hdr, rr.Preference, rr.Fqdn}
 	return &LP{rr.Hdr, rr.Preference, rr.Fqdn}
 }
 }
+
 func (rr *MB) copy() RR {
 func (rr *MB) copy() RR {
 	return &MB{rr.Hdr, rr.Mb}
 	return &MB{rr.Hdr, rr.Mb}
 }
 }
+
 func (rr *MD) copy() RR {
 func (rr *MD) copy() RR {
 	return &MD{rr.Hdr, rr.Md}
 	return &MD{rr.Hdr, rr.Md}
 }
 }
+
 func (rr *MF) copy() RR {
 func (rr *MF) copy() RR {
 	return &MF{rr.Hdr, rr.Mf}
 	return &MF{rr.Hdr, rr.Mf}
 }
 }
+
 func (rr *MG) copy() RR {
 func (rr *MG) copy() RR {
 	return &MG{rr.Hdr, rr.Mg}
 	return &MG{rr.Hdr, rr.Mg}
 }
 }
+
 func (rr *MINFO) copy() RR {
 func (rr *MINFO) copy() RR {
 	return &MINFO{rr.Hdr, rr.Rmail, rr.Email}
 	return &MINFO{rr.Hdr, rr.Rmail, rr.Email}
 }
 }
+
 func (rr *MR) copy() RR {
 func (rr *MR) copy() RR {
 	return &MR{rr.Hdr, rr.Mr}
 	return &MR{rr.Hdr, rr.Mr}
 }
 }
+
 func (rr *MX) copy() RR {
 func (rr *MX) copy() RR {
 	return &MX{rr.Hdr, rr.Preference, rr.Mx}
 	return &MX{rr.Hdr, rr.Preference, rr.Mx}
 }
 }
+
 func (rr *NAPTR) copy() RR {
 func (rr *NAPTR) copy() RR {
-	return &NAPTR{rr.Hdr, rr.Order, rr.Preference, rr.Flags, rr.Service, rr.Regexp, rr.Replacement}
+	return &NAPTR{
+		rr.Hdr,
+		rr.Order,
+		rr.Preference,
+		rr.Flags,
+		rr.Service,
+		rr.Regexp,
+		rr.Replacement,
+	}
 }
 }
+
 func (rr *NID) copy() RR {
 func (rr *NID) copy() RR {
 	return &NID{rr.Hdr, rr.Preference, rr.NodeID}
 	return &NID{rr.Hdr, rr.Preference, rr.NodeID}
 }
 }
+
 func (rr *NIMLOC) copy() RR {
 func (rr *NIMLOC) copy() RR {
 	return &NIMLOC{rr.Hdr, rr.Locator}
 	return &NIMLOC{rr.Hdr, rr.Locator}
 }
 }
+
 func (rr *NINFO) copy() RR {
 func (rr *NINFO) copy() RR {
-	ZSData := make([]string, len(rr.ZSData))
-	copy(ZSData, rr.ZSData)
-	return &NINFO{rr.Hdr, ZSData}
+	return &NINFO{rr.Hdr, cloneSlice(rr.ZSData)}
 }
 }
+
 func (rr *NS) copy() RR {
 func (rr *NS) copy() RR {
 	return &NS{rr.Hdr, rr.Ns}
 	return &NS{rr.Hdr, rr.Ns}
 }
 }
+
 func (rr *NSAPPTR) copy() RR {
 func (rr *NSAPPTR) copy() RR {
 	return &NSAPPTR{rr.Hdr, rr.Ptr}
 	return &NSAPPTR{rr.Hdr, rr.Ptr}
 }
 }
+
 func (rr *NSEC) copy() RR {
 func (rr *NSEC) copy() RR {
-	TypeBitMap := make([]uint16, len(rr.TypeBitMap))
-	copy(TypeBitMap, rr.TypeBitMap)
-	return &NSEC{rr.Hdr, rr.NextDomain, TypeBitMap}
+	return &NSEC{rr.Hdr, rr.NextDomain, cloneSlice(rr.TypeBitMap)}
 }
 }
+
 func (rr *NSEC3) copy() RR {
 func (rr *NSEC3) copy() RR {
-	TypeBitMap := make([]uint16, len(rr.TypeBitMap))
-	copy(TypeBitMap, rr.TypeBitMap)
-	return &NSEC3{rr.Hdr, rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt, rr.HashLength, rr.NextDomain, TypeBitMap}
+	return &NSEC3{
+		rr.Hdr,
+		rr.Hash,
+		rr.Flags,
+		rr.Iterations,
+		rr.SaltLength,
+		rr.Salt,
+		rr.HashLength,
+		rr.NextDomain,
+		cloneSlice(rr.TypeBitMap),
+	}
 }
 }
+
 func (rr *NSEC3PARAM) copy() RR {
 func (rr *NSEC3PARAM) copy() RR {
-	return &NSEC3PARAM{rr.Hdr, rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt}
+	return &NSEC3PARAM{
+		rr.Hdr,
+		rr.Hash,
+		rr.Flags,
+		rr.Iterations,
+		rr.SaltLength,
+		rr.Salt,
+	}
 }
 }
+
 func (rr *NULL) copy() RR {
 func (rr *NULL) copy() RR {
 	return &NULL{rr.Hdr, rr.Data}
 	return &NULL{rr.Hdr, rr.Data}
 }
 }
+
 func (rr *OPENPGPKEY) copy() RR {
 func (rr *OPENPGPKEY) copy() RR {
 	return &OPENPGPKEY{rr.Hdr, rr.PublicKey}
 	return &OPENPGPKEY{rr.Hdr, rr.PublicKey}
 }
 }
+
 func (rr *OPT) copy() RR {
 func (rr *OPT) copy() RR {
 	Option := make([]EDNS0, len(rr.Option))
 	Option := make([]EDNS0, len(rr.Option))
 	for i, e := range rr.Option {
 	for i, e := range rr.Option {
@@ -867,86 +1103,205 @@ func (rr *OPT) copy() RR {
 	}
 	}
 	return &OPT{rr.Hdr, Option}
 	return &OPT{rr.Hdr, Option}
 }
 }
+
 func (rr *PTR) copy() RR {
 func (rr *PTR) copy() RR {
 	return &PTR{rr.Hdr, rr.Ptr}
 	return &PTR{rr.Hdr, rr.Ptr}
 }
 }
+
 func (rr *PX) copy() RR {
 func (rr *PX) copy() RR {
-	return &PX{rr.Hdr, rr.Preference, rr.Map822, rr.Mapx400}
+	return &PX{
+		rr.Hdr,
+		rr.Preference,
+		rr.Map822,
+		rr.Mapx400,
+	}
 }
 }
+
 func (rr *RFC3597) copy() RR {
 func (rr *RFC3597) copy() RR {
 	return &RFC3597{rr.Hdr, rr.Rdata}
 	return &RFC3597{rr.Hdr, rr.Rdata}
 }
 }
+
 func (rr *RKEY) copy() RR {
 func (rr *RKEY) copy() RR {
-	return &RKEY{rr.Hdr, rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey}
+	return &RKEY{
+		rr.Hdr,
+		rr.Flags,
+		rr.Protocol,
+		rr.Algorithm,
+		rr.PublicKey,
+	}
 }
 }
+
 func (rr *RP) copy() RR {
 func (rr *RP) copy() RR {
 	return &RP{rr.Hdr, rr.Mbox, rr.Txt}
 	return &RP{rr.Hdr, rr.Mbox, rr.Txt}
 }
 }
+
 func (rr *RRSIG) copy() RR {
 func (rr *RRSIG) copy() RR {
-	return &RRSIG{rr.Hdr, rr.TypeCovered, rr.Algorithm, rr.Labels, rr.OrigTtl, rr.Expiration, rr.Inception, rr.KeyTag, rr.SignerName, rr.Signature}
+	return &RRSIG{
+		rr.Hdr,
+		rr.TypeCovered,
+		rr.Algorithm,
+		rr.Labels,
+		rr.OrigTtl,
+		rr.Expiration,
+		rr.Inception,
+		rr.KeyTag,
+		rr.SignerName,
+		rr.Signature,
+	}
 }
 }
+
 func (rr *RT) copy() RR {
 func (rr *RT) copy() RR {
 	return &RT{rr.Hdr, rr.Preference, rr.Host}
 	return &RT{rr.Hdr, rr.Preference, rr.Host}
 }
 }
+
 func (rr *SIG) copy() RR {
 func (rr *SIG) copy() RR {
 	return &SIG{*rr.RRSIG.copy().(*RRSIG)}
 	return &SIG{*rr.RRSIG.copy().(*RRSIG)}
 }
 }
+
 func (rr *SMIMEA) copy() RR {
 func (rr *SMIMEA) copy() RR {
-	return &SMIMEA{rr.Hdr, rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate}
+	return &SMIMEA{
+		rr.Hdr,
+		rr.Usage,
+		rr.Selector,
+		rr.MatchingType,
+		rr.Certificate,
+	}
 }
 }
+
 func (rr *SOA) copy() RR {
 func (rr *SOA) copy() RR {
-	return &SOA{rr.Hdr, rr.Ns, rr.Mbox, rr.Serial, rr.Refresh, rr.Retry, rr.Expire, rr.Minttl}
+	return &SOA{
+		rr.Hdr,
+		rr.Ns,
+		rr.Mbox,
+		rr.Serial,
+		rr.Refresh,
+		rr.Retry,
+		rr.Expire,
+		rr.Minttl,
+	}
 }
 }
+
 func (rr *SPF) copy() RR {
 func (rr *SPF) copy() RR {
-	Txt := make([]string, len(rr.Txt))
-	copy(Txt, rr.Txt)
-	return &SPF{rr.Hdr, Txt}
+	return &SPF{rr.Hdr, cloneSlice(rr.Txt)}
 }
 }
+
 func (rr *SRV) copy() RR {
 func (rr *SRV) copy() RR {
-	return &SRV{rr.Hdr, rr.Priority, rr.Weight, rr.Port, rr.Target}
+	return &SRV{
+		rr.Hdr,
+		rr.Priority,
+		rr.Weight,
+		rr.Port,
+		rr.Target,
+	}
 }
 }
+
 func (rr *SSHFP) copy() RR {
 func (rr *SSHFP) copy() RR {
-	return &SSHFP{rr.Hdr, rr.Algorithm, rr.Type, rr.FingerPrint}
+	return &SSHFP{
+		rr.Hdr,
+		rr.Algorithm,
+		rr.Type,
+		rr.FingerPrint,
+	}
 }
 }
+
 func (rr *SVCB) copy() RR {
 func (rr *SVCB) copy() RR {
 	Value := make([]SVCBKeyValue, len(rr.Value))
 	Value := make([]SVCBKeyValue, len(rr.Value))
 	for i, e := range rr.Value {
 	for i, e := range rr.Value {
 		Value[i] = e.copy()
 		Value[i] = e.copy()
 	}
 	}
-	return &SVCB{rr.Hdr, rr.Priority, rr.Target, Value}
+	return &SVCB{
+		rr.Hdr,
+		rr.Priority,
+		rr.Target,
+		Value,
+	}
 }
 }
+
 func (rr *TA) copy() RR {
 func (rr *TA) copy() RR {
-	return &TA{rr.Hdr, rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
+	return &TA{
+		rr.Hdr,
+		rr.KeyTag,
+		rr.Algorithm,
+		rr.DigestType,
+		rr.Digest,
+	}
 }
 }
+
 func (rr *TALINK) copy() RR {
 func (rr *TALINK) copy() RR {
 	return &TALINK{rr.Hdr, rr.PreviousName, rr.NextName}
 	return &TALINK{rr.Hdr, rr.PreviousName, rr.NextName}
 }
 }
+
 func (rr *TKEY) copy() RR {
 func (rr *TKEY) copy() RR {
-	return &TKEY{rr.Hdr, rr.Algorithm, rr.Inception, rr.Expiration, rr.Mode, rr.Error, rr.KeySize, rr.Key, rr.OtherLen, rr.OtherData}
+	return &TKEY{
+		rr.Hdr,
+		rr.Algorithm,
+		rr.Inception,
+		rr.Expiration,
+		rr.Mode,
+		rr.Error,
+		rr.KeySize,
+		rr.Key,
+		rr.OtherLen,
+		rr.OtherData,
+	}
 }
 }
+
 func (rr *TLSA) copy() RR {
 func (rr *TLSA) copy() RR {
-	return &TLSA{rr.Hdr, rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate}
+	return &TLSA{
+		rr.Hdr,
+		rr.Usage,
+		rr.Selector,
+		rr.MatchingType,
+		rr.Certificate,
+	}
 }
 }
+
 func (rr *TSIG) copy() RR {
 func (rr *TSIG) copy() RR {
-	return &TSIG{rr.Hdr, rr.Algorithm, rr.TimeSigned, rr.Fudge, rr.MACSize, rr.MAC, rr.OrigId, rr.Error, rr.OtherLen, rr.OtherData}
+	return &TSIG{
+		rr.Hdr,
+		rr.Algorithm,
+		rr.TimeSigned,
+		rr.Fudge,
+		rr.MACSize,
+		rr.MAC,
+		rr.OrigId,
+		rr.Error,
+		rr.OtherLen,
+		rr.OtherData,
+	}
 }
 }
+
 func (rr *TXT) copy() RR {
 func (rr *TXT) copy() RR {
-	Txt := make([]string, len(rr.Txt))
-	copy(Txt, rr.Txt)
-	return &TXT{rr.Hdr, Txt}
+	return &TXT{rr.Hdr, cloneSlice(rr.Txt)}
 }
 }
+
 func (rr *UID) copy() RR {
 func (rr *UID) copy() RR {
 	return &UID{rr.Hdr, rr.Uid}
 	return &UID{rr.Hdr, rr.Uid}
 }
 }
+
 func (rr *UINFO) copy() RR {
 func (rr *UINFO) copy() RR {
 	return &UINFO{rr.Hdr, rr.Uinfo}
 	return &UINFO{rr.Hdr, rr.Uinfo}
 }
 }
+
 func (rr *URI) copy() RR {
 func (rr *URI) copy() RR {
-	return &URI{rr.Hdr, rr.Priority, rr.Weight, rr.Target}
+	return &URI{
+		rr.Hdr,
+		rr.Priority,
+		rr.Weight,
+		rr.Target,
+	}
 }
 }
+
 func (rr *X25) copy() RR {
 func (rr *X25) copy() RR {
 	return &X25{rr.Hdr, rr.PSDNAddress}
 	return &X25{rr.Hdr, rr.PSDNAddress}
 }
 }
+
 func (rr *ZONEMD) copy() RR {
 func (rr *ZONEMD) copy() RR {
-	return &ZONEMD{rr.Hdr, rr.Serial, rr.Scheme, rr.Hash, rr.Digest}
+	return &ZONEMD{
+		rr.Hdr,
+		rr.Serial,
+		rr.Scheme,
+		rr.Hash,
+		rr.Digest,
+	}
 }
 }

+ 2 - 2
vendor/modules.txt

@@ -687,8 +687,8 @@ github.com/klauspost/compress/zstd/internal/xxhash
 # github.com/matttproud/golang_protobuf_extensions v1.0.4
 # github.com/matttproud/golang_protobuf_extensions v1.0.4
 ## explicit; go 1.9
 ## explicit; go 1.9
 github.com/matttproud/golang_protobuf_extensions/pbutil
 github.com/matttproud/golang_protobuf_extensions/pbutil
-# github.com/miekg/dns v1.1.43
-## explicit; go 1.14
+# github.com/miekg/dns v1.1.57
+## explicit; go 1.19
 github.com/miekg/dns
 github.com/miekg/dns
 # github.com/mistifyio/go-zfs/v3 v3.0.1
 # github.com/mistifyio/go-zfs/v3 v3.0.1
 ## explicit; go 1.14
 ## explicit; go 1.14