diff --git a/go.mod b/go.mod
index 570174d1f613c306b0cb916d6af05e174f1d04a7..e82cfae00ba0648f30ac56ec6af1234b12de157e 100644
--- a/go.mod
+++ b/go.mod
@@ -10,7 +10,7 @@ require (
 	github.com/google/subcommands v1.2.0
 	github.com/jmcvetta/randutil v0.0.0-20150817122601-2bb1b664bcff
 	github.com/lpar/gzipped v1.1.1-0.20190413023519-5d9a18ea7f47
-	github.com/miekg/dns v1.1.8
+	github.com/miekg/dns v1.1.35
 	github.com/prometheus/client_golang v1.9.0
 	go.etcd.io/etcd v0.5.0-alpha.5.0.20190401205724-a621d807f061
 	golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
diff --git a/go.sum b/go.sum
index 6d295aac5f7852b28c981ac829c95ebd484e33c2..a9df491cfb38e1065d3d9e29b510eeedf25b98c8 100644
--- a/go.sum
+++ b/go.sum
@@ -194,6 +194,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5
 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
 github.com/miekg/dns v1.1.8 h1:1QYRAKU3lN5cRfLCkPU08hwvLJFhvjP6MqNMmQz6ZVI=
 github.com/miekg/dns v1.1.8/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
+github.com/miekg/dns v1.1.35 h1:oTfOaDH+mZkdcgdIjH6yBajRGtIwcwcaR+rt23ZSrJs=
+github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
 github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
 github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
@@ -382,6 +384,7 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR
 golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
 golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -411,6 +414,7 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
 golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -443,6 +447,7 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
 golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
 golang.org/x/tools v0.0.0-20200103221440-774c71fcf114 h1:DnSr2mCsxyCE6ZgIkmcWUQY2R5cH/6wL7eIxEmQOMSE=
 golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/vendor/github.com/miekg/dns/.travis.yml b/vendor/github.com/miekg/dns/.travis.yml
index 013b5ae44d410f356bdd02271ee4bb225544e3c2..7d9b172756642817b35d524b17e3a50c9459dddf 100644
--- a/vendor/github.com/miekg/dns/.travis.yml
+++ b/vendor/github.com/miekg/dns/.travis.yml
@@ -2,17 +2,15 @@ language: go
 sudo: false
 
 go:
-  - 1.10.x
-  - 1.11.x
-  - 1.12.x
+  - 1.14.x
+  - 1.15.x
   - tip
 
-before_install:
-  # don't use the miekg/dns when testing forks
-  - mkdir -p $GOPATH/src/github.com/miekg
-  - ln -s $TRAVIS_BUILD_DIR $GOPATH/src/github.com/miekg/ || true
+env:
+  - GO111MODULE=on
 
 script:
+  - go generate ./... && test `git ls-files --modified | wc -l` = 0
   - go test -race -v -bench=. -coverprofile=coverage.txt -covermode=atomic ./...
 
 after_success:
diff --git a/vendor/github.com/miekg/dns/CODEOWNERS b/vendor/github.com/miekg/dns/CODEOWNERS
new file mode 100644
index 0000000000000000000000000000000000000000..e0917031bc1855e313ace1693aa102fecb7d5846
--- /dev/null
+++ b/vendor/github.com/miekg/dns/CODEOWNERS
@@ -0,0 +1 @@
+* @miekg @tmthrgd
diff --git a/vendor/github.com/miekg/dns/Gopkg.lock b/vendor/github.com/miekg/dns/Gopkg.lock
deleted file mode 100644
index 686632207a129f9bfbbb413fadb60f875eb8a606..0000000000000000000000000000000000000000
--- a/vendor/github.com/miekg/dns/Gopkg.lock
+++ /dev/null
@@ -1,57 +0,0 @@
-# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
-
-
-[[projects]]
-  branch = "master"
-  digest = "1:6914c49eed986dfb8dffb33516fa129c49929d4d873f41e073c83c11c372b870"
-  name = "golang.org/x/crypto"
-  packages = [
-    "ed25519",
-    "ed25519/internal/edwards25519",
-  ]
-  pruneopts = ""
-  revision = "e3636079e1a4c1f337f212cc5cd2aca108f6c900"
-
-[[projects]]
-  branch = "master"
-  digest = "1:08e41d63f8dac84d83797368b56cf0b339e42d0224e5e56668963c28aec95685"
-  name = "golang.org/x/net"
-  packages = [
-    "bpf",
-    "context",
-    "internal/iana",
-    "internal/socket",
-    "ipv4",
-    "ipv6",
-  ]
-  pruneopts = ""
-  revision = "4dfa2610cdf3b287375bbba5b8f2a14d3b01d8de"
-
-[[projects]]
-  branch = "master"
-  digest = "1:b2ea75de0ccb2db2ac79356407f8a4cd8f798fe15d41b381c00abf3ae8e55ed1"
-  name = "golang.org/x/sync"
-  packages = ["errgroup"]
-  pruneopts = ""
-  revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca"
-
-[[projects]]
-  branch = "master"
-  digest = "1:149a432fabebb8221a80f77731b1cd63597197ded4f14af606ebe3a0959004ec"
-  name = "golang.org/x/sys"
-  packages = ["unix"]
-  pruneopts = ""
-  revision = "e4b3c5e9061176387e7cea65e4dc5853801f3fb7"
-
-[solve-meta]
-  analyzer-name = "dep"
-  analyzer-version = 1
-  input-imports = [
-    "golang.org/x/crypto/ed25519",
-    "golang.org/x/net/ipv4",
-    "golang.org/x/net/ipv6",
-    "golang.org/x/sync/errgroup",
-    "golang.org/x/sys/unix",
-  ]
-  solver-name = "gps-cdcl"
-  solver-version = 1
diff --git a/vendor/github.com/miekg/dns/Gopkg.toml b/vendor/github.com/miekg/dns/Gopkg.toml
deleted file mode 100644
index 85e6ff31b222812853594e3b668a9185ba758629..0000000000000000000000000000000000000000
--- a/vendor/github.com/miekg/dns/Gopkg.toml
+++ /dev/null
@@ -1,38 +0,0 @@
-
-# Gopkg.toml example
-#
-# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
-# for detailed Gopkg.toml documentation.
-#
-# required = ["github.com/user/thing/cmd/thing"]
-# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
-#
-# [[constraint]]
-#   name = "github.com/user/project"
-#   version = "1.0.0"
-#
-# [[constraint]]
-#   name = "github.com/user/project2"
-#   branch = "dev"
-#   source = "github.com/myfork/project2"
-#
-# [[override]]
-#  name = "github.com/x/y"
-#  version = "2.4.0"
-
-
-[[constraint]]
-  branch = "master"
-  name = "golang.org/x/crypto"
-
-[[constraint]]
-  branch = "master"
-  name = "golang.org/x/net"
-
-[[constraint]]
-  branch = "master"
-  name = "golang.org/x/sys"
-
-[[constraint]]
-  branch = "master"
-  name = "golang.org/x/sync"
diff --git a/vendor/github.com/miekg/dns/LICENSE b/vendor/github.com/miekg/dns/LICENSE
index 5763fa7fe5d963c854627c7fd5b8a76534f5c0d1..55f12ab7772a5cdd762858874abee28b1438b3ae 100644
--- a/vendor/github.com/miekg/dns/LICENSE
+++ b/vendor/github.com/miekg/dns/LICENSE
@@ -1,7 +1,3 @@
-Extensions of the original work are copyright (c) 2011 Miek Gieben
-
-As this is fork of the official Go code the same license applies:
-
 Copyright (c) 2009 The Go Authors. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -30,3 +26,5 @@ 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.
 
+As this is fork of the official Go code the same license applies.
+Extensions of the original work are copyright (c) 2011 Miek Gieben
diff --git a/vendor/github.com/miekg/dns/README.md b/vendor/github.com/miekg/dns/README.md
index dc2a8228f8927ffdc9daac405131f1f7f2faa1ba..fc8394e2697a339d7929361b4b0ff0f7153cb16a 100644
--- a/vendor/github.com/miekg/dns/README.md
+++ b/vendor/github.com/miekg/dns/README.md
@@ -26,8 +26,8 @@ avoiding breaking changes wherever reasonable. We support the last two versions
 A not-so-up-to-date-list-that-may-be-actually-current:
 
 * https://github.com/coredns/coredns
-* https://cloudflare.com
 * https://github.com/abh/geodns
+* https://github.com/baidu/bfe
 * http://www.statdns.com/
 * http://www.dnsinspect.com/
 * https://github.com/chuangbo/jianbing-dictionary-dns
@@ -41,11 +41,9 @@ A not-so-up-to-date-list-that-may-be-actually-current:
 * https://github.com/StalkR/dns-reverse-proxy
 * https://github.com/tianon/rawdns
 * https://mesosphere.github.io/mesos-dns/
-* https://pulse.turbobytes.com/
 * https://github.com/fcambus/statzone
 * https://github.com/benschw/dns-clb-go
 * https://github.com/corny/dnscheck for <http://public-dns.info/>
-* https://namesmith.io
 * https://github.com/miekg/unbound
 * https://github.com/miekg/exdns
 * https://dnslookup.org
@@ -54,21 +52,23 @@ A not-so-up-to-date-list-that-may-be-actually-current:
 * https://github.com/mehrdadrad/mylg
 * https://github.com/bamarni/dockness
 * https://github.com/fffaraz/microdns
-* http://kelda.io
 * https://github.com/ipdcode/hades <https://jd.com>
 * https://github.com/StackExchange/dnscontrol/
 * https://www.dnsperf.com/
 * https://dnssectest.net/
-* https://dns.apebits.com
 * https://github.com/oif/apex
 * https://github.com/jedisct1/dnscrypt-proxy
 * https://github.com/jedisct1/rpdns
 * https://github.com/xor-gate/sshfp
 * https://github.com/rs/dnstrace
 * https://blitiri.com.ar/p/dnss ([github mirror](https://github.com/albertito/dnss))
-* https://github.com/semihalev/sdns
 * https://render.com
 * https://github.com/peterzen/goresolver
+* https://github.com/folbricht/routedns
+* https://domainr.com/
+* https://zonedb.org/
+* https://router7.org/
+* https://github.com/fortio/dnsping
 
 Send pull request if you want to be listed here.
 
@@ -93,8 +93,8 @@ DNS Authors 2012-
 
 # Building
 
-Building is done with the `go` tool. If you have setup your GOPATH correctly, the following should
-work:
+This library uses Go modules and uses semantic versioning. Building is done with the `go` tool, so
+the following should work:
 
     go get github.com/miekg/dns
     go build github.com/miekg/dns
@@ -126,6 +126,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
 * 2915 - NAPTR record
 * 2929 - DNS IANA Considerations
 * 3110 - RSASHA1 DNS keys
+* 3123 - APL record
 * 3225 - DO bit (DNSSEC OK)
 * 340{1,2,3} - NAPTR record
 * 3445 - Limiting the scope of (DNS)KEY
@@ -152,6 +153,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
 * 6844 - CAA record
 * 6891 - EDNS0 update
 * 6895 - DNS IANA considerations
+* 6944 - DNSSEC DNSKEY Algorithm Status
 * 6975 - Algorithm Understanding in DNSSEC
 * 7043 - EUI48/EUI64 records
 * 7314 - DNS (EDNS) EXPIRE Option
diff --git a/vendor/github.com/miekg/dns/acceptfunc.go b/vendor/github.com/miekg/dns/acceptfunc.go
index 78c076c2535c940cf488006b850af028f8b656ce..825617fe215beb320733eafdfa0c31087dbe0528 100644
--- a/vendor/github.com/miekg/dns/acceptfunc.go
+++ b/vendor/github.com/miekg/dns/acceptfunc.go
@@ -6,22 +6,30 @@ type MsgAcceptFunc func(dh Header) MsgAcceptAction
 
 // DefaultMsgAcceptFunc checks the request and will reject if:
 //
-// * isn't a request (don't respond in that case).
+// * isn't a request (don't respond in that case)
+//
 // * opcode isn't OpcodeQuery or OpcodeNotify
+//
 // * Zero bit isn't zero
+//
 // * has more than 1 question in the question section
+//
 // * has more than 1 RR in the Answer section
+//
 // * has more than 0 RRs in the Authority section
+//
 // * has more than 2 RRs in the Additional section
+//
 var DefaultMsgAcceptFunc MsgAcceptFunc = defaultMsgAcceptFunc
 
 // MsgAcceptAction represents the action to be taken.
 type MsgAcceptAction int
 
 const (
-	MsgAccept MsgAcceptAction = iota // Accept the message
-	MsgReject                        // Reject the message with a RcodeFormatError
-	MsgIgnore                        // Ignore the error and send nothing back.
+	MsgAccept               MsgAcceptAction = iota // Accept the message
+	MsgReject                                      // Reject the message with a RcodeFormatError
+	MsgIgnore                                      // Ignore the error and send nothing back.
+	MsgRejectNotImplemented                        // Reject the message with a RcodeNotImplemented
 )
 
 func defaultMsgAcceptFunc(dh Header) MsgAcceptAction {
@@ -32,12 +40,9 @@ func defaultMsgAcceptFunc(dh Header) MsgAcceptAction {
 	// Don't allow dynamic updates, because then the sections can contain a whole bunch of RRs.
 	opcode := int(dh.Bits>>11) & 0xF
 	if opcode != OpcodeQuery && opcode != OpcodeNotify {
-		return MsgReject
+		return MsgRejectNotImplemented
 	}
 
-	if isZero := dh.Bits&_Z != 0; isZero {
-		return MsgReject
-	}
 	if dh.Qdcount != 1 {
 		return MsgReject
 	}
diff --git a/vendor/github.com/miekg/dns/client.go b/vendor/github.com/miekg/dns/client.go
index 20cafe271b1826bae26713f6ccddb4ca9e5d04d1..e7ff786a237fc48fc1104814b55013d389810a76 100644
--- a/vendor/github.com/miekg/dns/client.go
+++ b/vendor/github.com/miekg/dns/client.go
@@ -6,6 +6,7 @@ import (
 	"context"
 	"crypto/tls"
 	"encoding/binary"
+	"fmt"
 	"io"
 	"net"
 	"strings"
@@ -33,7 +34,7 @@ type Client struct {
 	Dialer    *net.Dialer // a net.Dialer used to set local address, timeouts and more
 	// 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
-	// Client.Dialer) or context.Context.Deadline (see the deprecated 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
@@ -105,7 +106,7 @@ func (c *Client) Dial(address string) (conn *Conn, err error) {
 	if err != nil {
 		return nil, err
 	}
-
+	conn.UDPSize = c.UDPSize
 	return conn, nil
 }
 
@@ -123,37 +124,47 @@ func (c *Client) Dial(address string) (conn *Conn, err error) {
 // of 512 bytes
 // To specify a local address or a timeout, the caller has to set the `Client.Dialer`
 // attribute appropriately
+
 func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, err error) {
-	if !c.SingleInflight {
-		return c.exchange(m, address)
-	}
+	co, err := c.Dial(address)
 
-	t := "nop"
-	if t1, ok := TypeToString[m.Question[0].Qtype]; ok {
-		t = t1
+	if err != nil {
+		return nil, 0, err
 	}
-	cl := "nop"
-	if cl1, ok := ClassToString[m.Question[0].Qclass]; ok {
-		cl = cl1
+	defer co.Close()
+	return c.ExchangeWithConn(m, co)
+}
+
+// ExchangeWithConn has the same behavior as Exchange, just with a predetermined connection
+// that will be used instead of creating a new one.
+// Usage pattern with a *dns.Client:
+//	c := new(dns.Client)
+//	// connection management logic goes here
+//
+//	conn := c.Dial(address)
+//	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.
+func (c *Client) ExchangeWithConn(m *Msg, conn *Conn) (r *Msg, rtt time.Duration, err error) {
+	if !c.SingleInflight {
+		return c.exchange(m, conn)
 	}
-	r, rtt, err, shared := c.group.Do(m.Question[0].Name+t+cl, func() (*Msg, time.Duration, error) {
-		return c.exchange(m, address)
+
+	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
 }
 
-func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
-	var co *Conn
-
-	co, err = c.Dial(a)
-
-	if err != nil {
-		return nil, 0, err
-	}
-	defer co.Close()
+func (c *Client) exchange(m *Msg, co *Conn) (r *Msg, rtt time.Duration, err error) {
 
 	opt := m.IsEdns0()
 	// If EDNS0 is used use that for size.
@@ -174,9 +185,20 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
 	}
 
 	co.SetReadDeadline(time.Now().Add(c.getTimeoutForRequest(c.readTimeout())))
-	r, err = co.ReadMsg()
-	if err == nil && r.Id != m.Id {
-		err = ErrId
+	if _, ok := co.Conn.(net.PacketConn); ok {
+		for {
+			r, err = co.ReadMsg()
+			// Ignore replies with mismatched IDs because they might be
+			// responses to earlier queries that timed out.
+			if err != nil || r.Id == m.Id {
+				break
+			}
+		}
+	} else {
+		r, err = co.ReadMsg()
+		if err == nil && r.Id != m.Id {
+			err = ErrId
+		}
 	}
 	rtt = time.Since(t)
 	return r, rtt, err
@@ -219,22 +241,22 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
 		n   int
 		err error
 	)
-	switch co.Conn.(type) {
-	case *net.TCPConn, *tls.Conn:
-		var length uint16
-		if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
-			return nil, err
-		}
 
-		p = make([]byte, length)
-		n, err = io.ReadFull(co.Conn, p)
-	default:
+	if _, ok := co.Conn.(net.PacketConn); ok {
 		if co.UDPSize > MinMsgSize {
 			p = make([]byte, co.UDPSize)
 		} else {
 			p = make([]byte, MinMsgSize)
 		}
 		n, err = co.Read(p)
+	} else {
+		var length uint16
+		if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
+			return nil, err
+		}
+
+		p = make([]byte, length)
+		n, err = io.ReadFull(co.Conn, p)
 	}
 
 	if err != nil {
@@ -260,21 +282,20 @@ func (co *Conn) Read(p []byte) (n int, err error) {
 		return 0, ErrConnEmpty
 	}
 
-	switch co.Conn.(type) {
-	case *net.TCPConn, *tls.Conn:
-		var length uint16
-		if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
-			return 0, err
-		}
-		if int(length) > len(p) {
-			return 0, io.ErrShortBuffer
-		}
+	if _, ok := co.Conn.(net.PacketConn); ok {
+		// UDP connection
+		return co.Conn.Read(p)
+	}
 
-		return io.ReadFull(co.Conn, p[:length])
+	var length uint16
+	if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
+		return 0, err
+	}
+	if int(length) > len(p) {
+		return 0, io.ErrShortBuffer
 	}
 
-	// UDP connection
-	return co.Conn.Read(p)
+	return io.ReadFull(co.Conn, p[:length])
 }
 
 // WriteMsg sends a message through the connection co.
@@ -301,21 +322,20 @@ func (co *Conn) WriteMsg(m *Msg) (err error) {
 }
 
 // Write implements the net.Conn Write method.
-func (co *Conn) Write(p []byte) (n int, err error) {
-	switch co.Conn.(type) {
-	case *net.TCPConn, *tls.Conn:
-		if len(p) > MaxMsgSize {
-			return 0, &Error{err: "message too large"}
-		}
-
-		l := make([]byte, 2)
-		binary.BigEndian.PutUint16(l, uint16(len(p)))
+func (co *Conn) Write(p []byte) (int, error) {
+	if len(p) > MaxMsgSize {
+		return 0, &Error{err: "message too large"}
+	}
 
-		n, err := (&net.Buffers{l, p}).WriteTo(co.Conn)
-		return int(n), err
+	if _, ok := co.Conn.(net.PacketConn); ok {
+		return co.Conn.Write(p)
 	}
 
-	return co.Conn.Write(p)
+	l := make([]byte, 2)
+	binary.BigEndian.PutUint16(l, uint16(len(p)))
+
+	n, err := (&net.Buffers{l, p}).WriteTo(co.Conn)
+	return int(n), err
 }
 
 // Return the appropriate timeout for a specific request
diff --git a/vendor/github.com/miekg/dns/defaults.go b/vendor/github.com/miekg/dns/defaults.go
index b059f6fc677adb1f303ddb8aed84c01319688eb7..d874e3008c21adcf5a585c352a1b2ca831b51f06 100644
--- a/vendor/github.com/miekg/dns/defaults.go
+++ b/vendor/github.com/miekg/dns/defaults.go
@@ -105,7 +105,7 @@ func (dns *Msg) SetAxfr(z string) *Msg {
 
 // SetTsig appends a TSIG RR to the message.
 // This is only a skeleton TSIG RR that is added as the last RR in the
-// additional section. The Tsig is calculated when the message is being send.
+// additional section. The TSIG is calculated when the message is being send.
 func (dns *Msg) SetTsig(z, algo string, fudge uint16, timesigned int64) *Msg {
 	t := new(TSIG)
 	t.Hdr = RR_Header{z, TypeTSIG, ClassANY, 0, 0}
@@ -317,6 +317,12 @@ func Fqdn(s string) string {
 	return s + "."
 }
 
+// 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.
+func CanonicalName(s string) string {
+	return strings.ToLower(Fqdn(s))
+}
+
 // Copied from the official Go code.
 
 // ReverseAddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP
@@ -364,7 +370,7 @@ func (t Type) String() string {
 // String returns the string representation for the class c.
 func (c Class) String() string {
 	if s, ok := ClassToString[uint16(c)]; ok {
-		// Only emit mnemonics when they are unambiguous, specically ANY is in both.
+		// Only emit mnemonics when they are unambiguous, specially ANY is in both.
 		if _, ok := StringToType[s]; !ok {
 			return s
 		}
diff --git a/vendor/github.com/miekg/dns/dns.go b/vendor/github.com/miekg/dns/dns.go
index f57337b89eb83b58be011cb74c26b87cf4a3960c..ad83a27ecfab87249548474cbb861afae76fa468 100644
--- a/vendor/github.com/miekg/dns/dns.go
+++ b/vendor/github.com/miekg/dns/dns.go
@@ -54,7 +54,7 @@ type RR interface {
 	// parse parses an RR from zone file format.
 	//
 	// This will only be called on a new and empty RR type with only the header populated.
-	parse(c *zlexer, origin, file string) *ParseError
+	parse(c *zlexer, origin string) *ParseError
 
 	// isDuplicate returns whether the two RRs are duplicates.
 	isDuplicate(r2 RR) bool
@@ -105,7 +105,7 @@ func (h *RR_Header) unpack(msg []byte, off int) (int, error) {
 	panic("dns: internal error: unpack should never be called on RR_Header")
 }
 
-func (h *RR_Header) parse(c *zlexer, origin, file string) *ParseError {
+func (h *RR_Header) parse(c *zlexer, origin string) *ParseError {
 	panic("dns: internal error: parse should never be called on RR_Header")
 }
 
diff --git a/vendor/github.com/miekg/dns/dnssec.go b/vendor/github.com/miekg/dns/dnssec.go
index faf1dc6590380a30587bcc15668ceb05b6618507..900f6e059d89f42c1d658296f1f514936156ce13 100644
--- a/vendor/github.com/miekg/dns/dnssec.go
+++ b/vendor/github.com/miekg/dns/dnssec.go
@@ -3,10 +3,8 @@ package dns
 import (
 	"bytes"
 	"crypto"
-	"crypto/dsa"
 	"crypto/ecdsa"
 	"crypto/elliptic"
-	_ "crypto/md5"
 	"crypto/rand"
 	"crypto/rsa"
 	_ "crypto/sha1"
@@ -141,8 +139,8 @@ func (k *DNSKEY) KeyTag() uint16 {
 	switch k.Algorithm {
 	case RSAMD5:
 		// Look at the bottom two bytes of the modules, which the last
-		// item in the pubkey. We could do this faster by looking directly
-		// at the base64 values. But I'm lazy.
+		// item in the pubkey.
+		// This algorithm has been deprecated, but keep this key-tag calculation.
 		modulus, _ := fromBase64([]byte(k.PublicKey))
 		if len(modulus) > 1 {
 			x := binary.BigEndian.Uint16(modulus[len(modulus)-2:])
@@ -200,7 +198,7 @@ func (k *DNSKEY) ToDS(h uint8) *DS {
 	wire = wire[:n]
 
 	owner := make([]byte, 255)
-	off, err1 := PackDomainName(strings.ToLower(k.Hdr.Name), owner, 0, nil, false)
+	off, err1 := PackDomainName(CanonicalName(k.Hdr.Name), owner, 0, nil, false)
 	if err1 != nil {
 		return nil
 	}
@@ -285,7 +283,7 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
 	sigwire.Inception = rr.Inception
 	sigwire.KeyTag = rr.KeyTag
 	// For signing, lowercase this name
-	sigwire.SignerName = strings.ToLower(rr.SignerName)
+	sigwire.SignerName = CanonicalName(rr.SignerName)
 
 	// Create the desired binary blob
 	signdata := make([]byte, DefaultMsgSize)
@@ -318,6 +316,10 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
 		}
 
 		rr.Signature = toBase64(signature)
+		return nil
+	case RSAMD5, DSA, DSANSEC3SHA1:
+		// See RFC 6944.
+		return ErrAlg
 	default:
 		h := hash.New()
 		h.Write(signdata)
@@ -329,9 +331,8 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
 		}
 
 		rr.Signature = toBase64(signature)
+		return nil
 	}
-
-	return nil
 }
 
 func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte, error) {
@@ -343,7 +344,6 @@ func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte,
 	switch alg {
 	case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512:
 		return signature, nil
-
 	case ECDSAP256SHA256, ECDSAP384SHA384:
 		ecdsaSignature := &struct {
 			R, S *big.Int
@@ -363,20 +363,11 @@ func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte,
 		signature := intToBytes(ecdsaSignature.R, intlen)
 		signature = append(signature, intToBytes(ecdsaSignature.S, intlen)...)
 		return signature, nil
-
-	// There is no defined interface for what a DSA backed crypto.Signer returns
-	case DSA, DSANSEC3SHA1:
-		// 	t := divRoundUp(divRoundUp(p.PublicKey.Y.BitLen(), 8)-64, 8)
-		// 	signature := []byte{byte(t)}
-		// 	signature = append(signature, intToBytes(r1, 20)...)
-		// 	signature = append(signature, intToBytes(s1, 20)...)
-		// 	rr.Signature = signature
-
 	case ED25519:
 		return signature, nil
+	default:
+		return nil, ErrAlg
 	}
-
-	return nil, ErrAlg
 }
 
 // Verify validates an RRSet with the signature and key. This is only the
@@ -420,7 +411,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
 	sigwire.Expiration = rr.Expiration
 	sigwire.Inception = rr.Inception
 	sigwire.KeyTag = rr.KeyTag
-	sigwire.SignerName = strings.ToLower(rr.SignerName)
+	sigwire.SignerName = CanonicalName(rr.SignerName)
 	// Create the desired binary blob
 	signeddata := make([]byte, DefaultMsgSize)
 	n, err := packSigWire(sigwire, signeddata)
@@ -445,7 +436,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
 	}
 
 	switch rr.Algorithm {
-	case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512, RSAMD5:
+	case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512:
 		// TODO(mg): this can be done quicker, ie. cache the pubkey data somewhere??
 		pubkey := k.publicKeyRSA() // Get the key
 		if pubkey == nil {
@@ -597,30 +588,6 @@ func (k *DNSKEY) publicKeyECDSA() *ecdsa.PublicKey {
 	return pubkey
 }
 
-func (k *DNSKEY) publicKeyDSA() *dsa.PublicKey {
-	keybuf, err := fromBase64([]byte(k.PublicKey))
-	if err != nil {
-		return nil
-	}
-	if len(keybuf) < 22 {
-		return nil
-	}
-	t, keybuf := int(keybuf[0]), keybuf[1:]
-	size := 64 + t*8
-	q, keybuf := keybuf[:20], keybuf[20:]
-	if len(keybuf) != 3*size {
-		return nil
-	}
-	p, keybuf := keybuf[:size], keybuf[size:]
-	g, y := keybuf[:size], keybuf[size:]
-	pubkey := new(dsa.PublicKey)
-	pubkey.Parameters.Q = new(big.Int).SetBytes(q)
-	pubkey.Parameters.P = new(big.Int).SetBytes(p)
-	pubkey.Parameters.G = new(big.Int).SetBytes(g)
-	pubkey.Y = new(big.Int).SetBytes(y)
-	return pubkey
-}
-
 func (k *DNSKEY) publicKeyED25519() ed25519.PublicKey {
 	keybuf, err := fromBase64([]byte(k.PublicKey))
 	if err != nil {
@@ -656,7 +623,7 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
 			h.Name = "*." + strings.Join(labels[len(labels)-int(s.Labels):], ".") + "."
 		}
 		// RFC 4034: 6.2.  Canonical RR Form. (2) - domain name to lowercase
-		h.Name = strings.ToLower(h.Name)
+		h.Name = CanonicalName(h.Name)
 		// 6.2. Canonical RR Form. (3) - domain rdata to lowercase.
 		//   NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
 		//   HINFO, MINFO, MX, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
@@ -669,49 +636,49 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
 		//	conversion.
 		switch x := r1.(type) {
 		case *NS:
-			x.Ns = strings.ToLower(x.Ns)
+			x.Ns = CanonicalName(x.Ns)
 		case *MD:
-			x.Md = strings.ToLower(x.Md)
+			x.Md = CanonicalName(x.Md)
 		case *MF:
-			x.Mf = strings.ToLower(x.Mf)
+			x.Mf = CanonicalName(x.Mf)
 		case *CNAME:
-			x.Target = strings.ToLower(x.Target)
+			x.Target = CanonicalName(x.Target)
 		case *SOA:
-			x.Ns = strings.ToLower(x.Ns)
-			x.Mbox = strings.ToLower(x.Mbox)
+			x.Ns = CanonicalName(x.Ns)
+			x.Mbox = CanonicalName(x.Mbox)
 		case *MB:
-			x.Mb = strings.ToLower(x.Mb)
+			x.Mb = CanonicalName(x.Mb)
 		case *MG:
-			x.Mg = strings.ToLower(x.Mg)
+			x.Mg = CanonicalName(x.Mg)
 		case *MR:
-			x.Mr = strings.ToLower(x.Mr)
+			x.Mr = CanonicalName(x.Mr)
 		case *PTR:
-			x.Ptr = strings.ToLower(x.Ptr)
+			x.Ptr = CanonicalName(x.Ptr)
 		case *MINFO:
-			x.Rmail = strings.ToLower(x.Rmail)
-			x.Email = strings.ToLower(x.Email)
+			x.Rmail = CanonicalName(x.Rmail)
+			x.Email = CanonicalName(x.Email)
 		case *MX:
-			x.Mx = strings.ToLower(x.Mx)
+			x.Mx = CanonicalName(x.Mx)
 		case *RP:
-			x.Mbox = strings.ToLower(x.Mbox)
-			x.Txt = strings.ToLower(x.Txt)
+			x.Mbox = CanonicalName(x.Mbox)
+			x.Txt = CanonicalName(x.Txt)
 		case *AFSDB:
-			x.Hostname = strings.ToLower(x.Hostname)
+			x.Hostname = CanonicalName(x.Hostname)
 		case *RT:
-			x.Host = strings.ToLower(x.Host)
+			x.Host = CanonicalName(x.Host)
 		case *SIG:
-			x.SignerName = strings.ToLower(x.SignerName)
+			x.SignerName = CanonicalName(x.SignerName)
 		case *PX:
-			x.Map822 = strings.ToLower(x.Map822)
-			x.Mapx400 = strings.ToLower(x.Mapx400)
+			x.Map822 = CanonicalName(x.Map822)
+			x.Mapx400 = CanonicalName(x.Mapx400)
 		case *NAPTR:
-			x.Replacement = strings.ToLower(x.Replacement)
+			x.Replacement = CanonicalName(x.Replacement)
 		case *KX:
-			x.Exchanger = strings.ToLower(x.Exchanger)
+			x.Exchanger = CanonicalName(x.Exchanger)
 		case *SRV:
-			x.Target = strings.ToLower(x.Target)
+			x.Target = CanonicalName(x.Target)
 		case *DNAME:
-			x.Target = strings.ToLower(x.Target)
+			x.Target = CanonicalName(x.Target)
 		}
 		// 6.2. Canonical RR Form. (5) - origTTL
 		wire := make([]byte, Len(r1)+1) // +1 to be safe(r)
diff --git a/vendor/github.com/miekg/dns/dnssec_keygen.go b/vendor/github.com/miekg/dns/dnssec_keygen.go
index 33e913ac527d8166f2aee23f94199741bae2dd5e..2ab7b6d73b80cfea2122fef01dfdee9d1afe693d 100644
--- a/vendor/github.com/miekg/dns/dnssec_keygen.go
+++ b/vendor/github.com/miekg/dns/dnssec_keygen.go
@@ -2,7 +2,6 @@ package dns
 
 import (
 	"crypto"
-	"crypto/dsa"
 	"crypto/ecdsa"
 	"crypto/elliptic"
 	"crypto/rand"
@@ -20,11 +19,7 @@ import (
 // bits should be set to the size of the algorithm.
 func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
 	switch k.Algorithm {
-	case DSA, DSANSEC3SHA1:
-		if bits != 1024 {
-			return nil, ErrKeySize
-		}
-	case RSAMD5, RSASHA1, RSASHA256, RSASHA1NSEC3SHA1:
+	case RSASHA1, RSASHA256, RSASHA1NSEC3SHA1:
 		if bits < 512 || bits > 4096 {
 			return nil, ErrKeySize
 		}
@@ -44,23 +39,12 @@ func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
 		if bits != 256 {
 			return nil, ErrKeySize
 		}
+	default:
+		return nil, ErrAlg
 	}
 
 	switch k.Algorithm {
-	case DSA, DSANSEC3SHA1:
-		params := new(dsa.Parameters)
-		if err := dsa.GenerateParameters(params, rand.Reader, dsa.L1024N160); err != nil {
-			return nil, err
-		}
-		priv := new(dsa.PrivateKey)
-		priv.PublicKey.Parameters = *params
-		err := dsa.GenerateKey(priv, rand.Reader)
-		if err != nil {
-			return nil, err
-		}
-		k.setPublicKeyDSA(params.Q, params.P, params.G, priv.PublicKey.Y)
-		return priv, nil
-	case RSAMD5, RSASHA1, RSASHA256, RSASHA512, RSASHA1NSEC3SHA1:
+	case RSASHA1, RSASHA256, RSASHA512, RSASHA1NSEC3SHA1:
 		priv, err := rsa.GenerateKey(rand.Reader, bits)
 		if err != nil {
 			return nil, err
@@ -120,16 +104,6 @@ func (k *DNSKEY) setPublicKeyECDSA(_X, _Y *big.Int) bool {
 	return true
 }
 
-// Set the public key for DSA
-func (k *DNSKEY) setPublicKeyDSA(_Q, _P, _G, _Y *big.Int) bool {
-	if _Q == nil || _P == nil || _G == nil || _Y == nil {
-		return false
-	}
-	buf := dsaToBuf(_Q, _P, _G, _Y)
-	k.PublicKey = toBase64(buf)
-	return true
-}
-
 // Set the public key for Ed25519
 func (k *DNSKEY) setPublicKeyED25519(_K ed25519.PublicKey) bool {
 	if _K == nil {
@@ -164,15 +138,3 @@ func curveToBuf(_X, _Y *big.Int, intlen int) []byte {
 	buf = append(buf, intToBytes(_Y, intlen)...)
 	return buf
 }
-
-// Set the public key for X and Y for Curve. The two
-// values are just concatenated.
-func dsaToBuf(_Q, _P, _G, _Y *big.Int) []byte {
-	t := divRoundUp(divRoundUp(_G.BitLen(), 8)-64, 8)
-	buf := []byte{byte(t)}
-	buf = append(buf, intToBytes(_Q, 20)...)
-	buf = append(buf, intToBytes(_P, 64+t*8)...)
-	buf = append(buf, intToBytes(_G, 64+t*8)...)
-	buf = append(buf, intToBytes(_Y, 64+t*8)...)
-	return buf
-}
diff --git a/vendor/github.com/miekg/dns/dnssec_keyscan.go b/vendor/github.com/miekg/dns/dnssec_keyscan.go
index e9dd69573e61b5ed8b83876edf645bff825edea7..6cbc28483f139683820381323389c7989ee0cfd4 100644
--- a/vendor/github.com/miekg/dns/dnssec_keyscan.go
+++ b/vendor/github.com/miekg/dns/dnssec_keyscan.go
@@ -3,7 +3,6 @@ package dns
 import (
 	"bufio"
 	"crypto"
-	"crypto/dsa"
 	"crypto/ecdsa"
 	"crypto/rsa"
 	"io"
@@ -44,26 +43,7 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, er
 		return nil, ErrPrivKey
 	}
 	switch uint8(algo) {
-	case DSA:
-		priv, err := readPrivateKeyDSA(m)
-		if err != nil {
-			return nil, err
-		}
-		pub := k.publicKeyDSA()
-		if pub == nil {
-			return nil, ErrKey
-		}
-		priv.PublicKey = *pub
-		return priv, nil
-	case RSAMD5:
-		fallthrough
-	case RSASHA1:
-		fallthrough
-	case RSASHA1NSEC3SHA1:
-		fallthrough
-	case RSASHA256:
-		fallthrough
-	case RSASHA512:
+	case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512:
 		priv, err := readPrivateKeyRSA(m)
 		if err != nil {
 			return nil, err
@@ -74,11 +54,7 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, er
 		}
 		priv.PublicKey = *pub
 		return priv, nil
-	case ECCGOST:
-		return nil, ErrPrivKey
-	case ECDSAP256SHA256:
-		fallthrough
-	case ECDSAP384SHA384:
+	case ECDSAP256SHA256, ECDSAP384SHA384:
 		priv, err := readPrivateKeyECDSA(m)
 		if err != nil {
 			return nil, err
@@ -92,7 +68,7 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, er
 	case ED25519:
 		return readPrivateKeyED25519(m)
 	default:
-		return nil, ErrPrivKey
+		return nil, ErrAlg
 	}
 }
 
@@ -129,24 +105,6 @@ func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) {
 	return p, nil
 }
 
-func readPrivateKeyDSA(m map[string]string) (*dsa.PrivateKey, error) {
-	p := new(dsa.PrivateKey)
-	p.X = new(big.Int)
-	for k, v := range m {
-		switch k {
-		case "private_value(x)":
-			v1, err := fromBase64([]byte(v))
-			if err != nil {
-				return nil, err
-			}
-			p.X.SetBytes(v1)
-		case "created", "publish", "activate":
-			/* not used in Go (yet) */
-		}
-	}
-	return p, nil
-}
-
 func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) {
 	p := new(ecdsa.PrivateKey)
 	p.D = new(big.Int)
diff --git a/vendor/github.com/miekg/dns/dnssec_privkey.go b/vendor/github.com/miekg/dns/dnssec_privkey.go
index 4493c9d57455056ae0ae33feb27374f2b625af39..072e445dadfa7564941b1c270f04df22003a16ed 100644
--- a/vendor/github.com/miekg/dns/dnssec_privkey.go
+++ b/vendor/github.com/miekg/dns/dnssec_privkey.go
@@ -2,7 +2,6 @@ package dns
 
 import (
 	"crypto"
-	"crypto/dsa"
 	"crypto/ecdsa"
 	"crypto/rsa"
 	"math/big"
@@ -17,8 +16,8 @@ var bigIntOne = big.NewInt(1)
 
 // PrivateKeyString converts a PrivateKey to a string. This string has the same
 // format as the private-key-file of BIND9 (Private-key-format: v1.3).
-// It needs some info from the key (the algorithm), so its a method of the DNSKEY
-// It supports rsa.PrivateKey, ecdsa.PrivateKey and dsa.PrivateKey
+// It needs some info from the key (the algorithm), so its a method of the DNSKEY.
+// It supports *rsa.PrivateKey, *ecdsa.PrivateKey and ed25519.PrivateKey.
 func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
 	algorithm := strconv.Itoa(int(r.Algorithm))
 	algorithm += " (" + AlgorithmToString[r.Algorithm] + ")"
@@ -67,21 +66,6 @@ func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
 			"Algorithm: " + algorithm + "\n" +
 			"PrivateKey: " + private + "\n"
 
-	case *dsa.PrivateKey:
-		T := divRoundUp(divRoundUp(p.PublicKey.Parameters.G.BitLen(), 8)-64, 8)
-		prime := toBase64(intToBytes(p.PublicKey.Parameters.P, 64+T*8))
-		subprime := toBase64(intToBytes(p.PublicKey.Parameters.Q, 20))
-		base := toBase64(intToBytes(p.PublicKey.Parameters.G, 64+T*8))
-		priv := toBase64(intToBytes(p.X, 20))
-		pub := toBase64(intToBytes(p.PublicKey.Y, 64+T*8))
-		return format +
-			"Algorithm: " + algorithm + "\n" +
-			"Prime(p): " + prime + "\n" +
-			"Subprime(q): " + subprime + "\n" +
-			"Base(g): " + base + "\n" +
-			"Private_value(x): " + priv + "\n" +
-			"Public_value(y): " + pub + "\n"
-
 	case ed25519.PrivateKey:
 		private := toBase64(p.Seed())
 		return format +
diff --git a/vendor/github.com/miekg/dns/doc.go b/vendor/github.com/miekg/dns/doc.go
index d3d7cec9ef5cab2442bbe05c7136fc57c25517e7..6861de774b7070cceda84acd7bf5c50c813627ce 100644
--- a/vendor/github.com/miekg/dns/doc.go
+++ b/vendor/github.com/miekg/dns/doc.go
@@ -83,7 +83,7 @@ with:
 
 	in, err := dns.Exchange(m1, "127.0.0.1:53")
 
-When this functions returns you will get dns message. A dns message consists
+When this functions returns you will get DNS message. A DNS message consists
 out of four sections.
 The question section: in.Question, the answer section: in.Answer,
 the authority section: in.Ns and the additional section: in.Extra.
@@ -209,7 +209,7 @@ Basic use pattern validating and replying to a message that has TSIG set.
 				// *Msg r has an TSIG record and it was validated
 				m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix())
 			} else {
-				// *Msg r has an TSIG records and it was not valided
+				// *Msg r has an TSIG records and it was not validated
 			}
 		}
 		w.WriteMsg(m)
@@ -221,7 +221,7 @@ 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
 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.
 
 EDNS0
@@ -238,9 +238,8 @@ Basic use pattern for creating an (empty) OPT RR:
 
 The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891) interfaces.
 Currently only a few have been standardized: EDNS0_NSID (RFC 5001) and
-EDNS0_SUBNET (draft-vandergaast-edns-client-subnet-02). Note that these options
-may be combined in an OPT RR. Basic use pattern for a server to check if (and
-which) options are set:
+EDNS0_SUBNET (RFC 7871). Note that these options may be combined in an OPT RR.
+Basic use pattern for a server to check if (and which) options are set:
 
 	// o is a dns.OPT
 	for _, s := range o.Option {
@@ -261,7 +260,7 @@ From RFC 2931:
     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
-the shared secret approach in TSIG. Supported algorithms: DSA, ECDSAP256SHA256,
+the shared secret approach in TSIG. Supported algorithms: ECDSAP256SHA256,
 ECDSAP384SHA384, RSASHA1, RSASHA256 and RSASHA512.
 
 Signing subsequent messages in multi-message sessions is not implemented.
diff --git a/vendor/github.com/miekg/dns/duplicate.go b/vendor/github.com/miekg/dns/duplicate.go
index 00cda0aa29f6d18647a531fdca446a9ed533b1ca..d21ae1cac156a646c84339ee546067e7efb662bb 100644
--- a/vendor/github.com/miekg/dns/duplicate.go
+++ b/vendor/github.com/miekg/dns/duplicate.go
@@ -3,9 +3,8 @@ package dns
 //go:generate go run duplicate_generate.go
 
 // IsDuplicate checks of r1 and r2 are duplicates of each other, excluding the TTL.
-// So this means the header data is equal *and* the RDATA is the same. Return true
-// is so, otherwise false.
-// It's is a protocol violation to have identical RRs in a message.
+// So this means the header data is equal *and* the RDATA is the same. Returns true
+// if so, otherwise false. It's a protocol violation to have identical RRs in a message.
 func IsDuplicate(r1, r2 RR) bool {
 	// Check whether the record header is identical.
 	if !r1.Header().isDuplicate(r2.Header()) {
diff --git a/vendor/github.com/miekg/dns/edns.go b/vendor/github.com/miekg/dns/edns.go
index ca8873e140a047e1faf069c107435a69857ca5e1..04808d57897d78be558bb170ccd0551c06fc2f8d 100644
--- a/vendor/github.com/miekg/dns/edns.go
+++ b/vendor/github.com/miekg/dns/edns.go
@@ -88,7 +88,7 @@ func (rr *OPT) len(off int, compression map[string]struct{}) int {
 	return l
 }
 
-func (rr *OPT) parse(c *zlexer, origin, file string) *ParseError {
+func (rr *OPT) parse(c *zlexer, origin string) *ParseError {
 	panic("dns: internal error: parse should never be called on OPT")
 }
 
@@ -360,7 +360,7 @@ func (e *EDNS0_COOKIE) copy() EDNS0           { return &EDNS0_COOKIE{e.Code, e.C
 // The EDNS0_UL (Update Lease) (draft RFC) option is used to tell the server to set
 // an expiration on an update RR. This is helpful for clients that cannot clean
 // up after themselves. This is a draft RFC and more information can be found at
-// http://files.dns-sd.org/draft-sekar-dns-ul.txt
+// https://tools.ietf.org/html/draft-sekar-dns-ul-02
 //
 //	o := new(dns.OPT)
 //	o.Hdr.Name = "."
@@ -370,24 +370,36 @@ func (e *EDNS0_COOKIE) copy() EDNS0           { return &EDNS0_COOKIE{e.Code, e.C
 //	e.Lease = 120 // in seconds
 //	o.Option = append(o.Option, e)
 type EDNS0_UL struct {
-	Code  uint16 // Always EDNS0UL
-	Lease uint32
+	Code     uint16 // Always EDNS0UL
+	Lease    uint32
+	KeyLease uint32
 }
 
 // Option implements the EDNS0 interface.
 func (e *EDNS0_UL) Option() uint16 { return EDNS0UL }
-func (e *EDNS0_UL) String() string { return strconv.FormatUint(uint64(e.Lease), 10) }
-func (e *EDNS0_UL) copy() EDNS0    { return &EDNS0_UL{e.Code, e.Lease} }
+func (e *EDNS0_UL) String() string { return fmt.Sprintf("%d %d", e.Lease, e.KeyLease) }
+func (e *EDNS0_UL) copy() EDNS0    { return &EDNS0_UL{e.Code, e.Lease, e.KeyLease} }
 
 // Copied: http://golang.org/src/pkg/net/dnsmsg.go
 func (e *EDNS0_UL) pack() ([]byte, error) {
-	b := make([]byte, 4)
+	var b []byte
+	if e.KeyLease == 0 {
+		b = make([]byte, 4)
+	} else {
+		b = make([]byte, 8)
+		binary.BigEndian.PutUint32(b[4:], e.KeyLease)
+	}
 	binary.BigEndian.PutUint32(b, e.Lease)
 	return b, nil
 }
 
 func (e *EDNS0_UL) unpack(b []byte) error {
-	if len(b) < 4 {
+	switch len(b) {
+	case 4:
+		e.KeyLease = 0
+	case 8:
+		e.KeyLease = binary.BigEndian.Uint32(b[4:])
+	default:
 		return ErrBuf
 	}
 	e.Lease = binary.BigEndian.Uint32(b)
@@ -531,6 +543,10 @@ func (e *EDNS0_EXPIRE) pack() ([]byte, error) {
 }
 
 func (e *EDNS0_EXPIRE) unpack(b []byte) error {
+	if len(b) == 0 {
+		// zero-length EXPIRE query, see RFC 7314 Section 2
+		return nil
+	}
 	if len(b) < 4 {
 		return ErrBuf
 	}
diff --git a/vendor/github.com/miekg/dns/fuzz.go b/vendor/github.com/miekg/dns/fuzz.go
index a8a09184d4049a1487b5753103065c5fe98bfa7d..57410acda75ee515a9104b2d2c0a240b50231c70 100644
--- a/vendor/github.com/miekg/dns/fuzz.go
+++ b/vendor/github.com/miekg/dns/fuzz.go
@@ -2,6 +2,8 @@
 
 package dns
 
+import "strings"
+
 func Fuzz(data []byte) int {
 	msg := new(Msg)
 
@@ -16,7 +18,14 @@ func Fuzz(data []byte) int {
 }
 
 func FuzzNewRR(data []byte) int {
-	if _, err := NewRR(string(data)); err != nil {
+	str := string(data)
+	// Do not fuzz lines that include the $INCLUDE keyword and hint the fuzzer
+	// at avoiding them.
+	// See GH#1025 for context.
+	if strings.Contains(strings.ToUpper(str), "$INCLUDE") {
+		return -1
+	}
+	if _, err := NewRR(str); err != nil {
 		return 0
 	}
 	return 1
diff --git a/vendor/github.com/miekg/dns/generate.go b/vendor/github.com/miekg/dns/generate.go
index 97bc39f58a82883d1424ded025b92269418cc287..f713074a181c05406dcb60cb6b3ef6562e0dbc81 100644
--- a/vendor/github.com/miekg/dns/generate.go
+++ b/vendor/github.com/miekg/dns/generate.go
@@ -20,13 +20,13 @@ import (
 // of $ after that are interpreted.
 func (zp *ZoneParser) generate(l lex) (RR, bool) {
 	token := l.token
-	step := 1
+	step := int64(1)
 	if i := strings.IndexByte(token, '/'); i >= 0 {
 		if i+1 == len(token) {
 			return zp.setParseError("bad step in $GENERATE range", l)
 		}
 
-		s, err := strconv.Atoi(token[i+1:])
+		s, err := strconv.ParseInt(token[i+1:], 10, 64)
 		if err != nil || s <= 0 {
 			return zp.setParseError("bad step in $GENERATE range", l)
 		}
@@ -40,20 +40,24 @@ func (zp *ZoneParser) generate(l lex) (RR, bool) {
 		return zp.setParseError("bad start-stop in $GENERATE range", l)
 	}
 
-	start, err := strconv.Atoi(sx[0])
+	start, err := strconv.ParseInt(sx[0], 10, 64)
 	if err != nil {
 		return zp.setParseError("bad start in $GENERATE range", l)
 	}
 
-	end, err := strconv.Atoi(sx[1])
+	end, err := strconv.ParseInt(sx[1], 10, 64)
 	if err != nil {
 		return zp.setParseError("bad stop in $GENERATE range", l)
 	}
-	if end < 0 || start < 0 || end < start {
+	if end < 0 || start < 0 || end < start || (end-start)/step > 65535 {
 		return zp.setParseError("bad range in $GENERATE range", l)
 	}
 
-	zp.c.Next() // _BLANK
+	// _BLANK
+	l, ok := zp.c.Next()
+	if !ok || l.value != zBlank {
+		return zp.setParseError("garbage after $GENERATE range", l)
+	}
 
 	// Create a complete new string, which we then parse again.
 	var s string
@@ -71,16 +75,17 @@ func (zp *ZoneParser) generate(l lex) (RR, bool) {
 	r := &generateReader{
 		s: s,
 
-		cur:   start,
-		start: start,
-		end:   end,
-		step:  step,
+		cur:   int(start),
+		start: int(start),
+		end:   int(end),
+		step:  int(step),
 
 		file: zp.file,
 		lex:  &l,
 	}
 	zp.sub = NewZoneParser(r, zp.origin, zp.file)
 	zp.sub.includeDepth, zp.sub.includeAllowed = zp.includeDepth, zp.includeAllowed
+	zp.sub.generateDisallowed = true
 	zp.sub.SetDefaultTTL(defaultTtl)
 	return zp.subNext()
 }
@@ -183,7 +188,7 @@ func (r *generateReader) ReadByte() (byte, error) {
 			if errMsg != "" {
 				return 0, r.parseError(errMsg, si+3+sep)
 			}
-			if r.start+offset < 0 || r.end+offset > 1<<31-1 {
+			if r.start+offset < 0 || int64(r.end) + int64(offset) > 1<<31-1 {
 				return 0, r.parseError("bad offset in $GENERATE", si+3+sep)
 			}
 
@@ -224,19 +229,19 @@ func modToPrintf(s string) (string, int, string) {
 		return "", 0, "bad base in $GENERATE"
 	}
 
-	offset, err := strconv.Atoi(offStr)
+	offset, err := strconv.ParseInt(offStr, 10, 64)
 	if err != nil {
 		return "", 0, "bad offset in $GENERATE"
 	}
 
-	width, err := strconv.Atoi(widthStr)
+	width, err := strconv.ParseInt(widthStr, 10, 64)
 	if err != nil || width < 0 || width > 255 {
 		return "", 0, "bad width in $GENERATE"
 	}
 
 	if width == 0 {
-		return "%" + base, offset, ""
+		return "%" + base, int(offset), ""
 	}
 
-	return "%0" + widthStr + base, offset, ""
+	return "%0" + widthStr + base, int(offset), ""
 }
diff --git a/vendor/github.com/miekg/dns/go.mod b/vendor/github.com/miekg/dns/go.mod
new file mode 100644
index 0000000000000000000000000000000000000000..6003d0573c6eb266d6ef9eae6ad45eabb613c41a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/go.mod
@@ -0,0 +1,11 @@
+module github.com/miekg/dns
+
+go 1.12
+
+require (
+	golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
+	golang.org/x/net v0.0.0-20190923162816-aa69164e4478
+	golang.org/x/sync v0.0.0-20190423024810-112230192c58
+	golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe
+	golang.org/x/tools v0.0.0-20191216052735-49a3e744a425 // indirect
+)
diff --git a/vendor/github.com/miekg/dns/go.sum b/vendor/github.com/miekg/dns/go.sum
new file mode 100644
index 0000000000000000000000000000000000000000..96bda3a94128ad4fcb0ff726d4ff99aa74b840e2
--- /dev/null
+++ b/vendor/github.com/miekg/dns/go.sum
@@ -0,0 +1,39 @@
+golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4 h1:Vk3wNqEZwyGyei9yq5ekj7frek2u7HUfffJ1/opblzc=
+golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 h1:Gv7RPwsi3eZ2Fgewe3CBsuOebPwO27PoXzRpJPsvSSM=
+golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M=
+golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/net v0.0.0-20180926154720-4dfa2610cdf3 h1:dgd4x4kJt7G4k4m93AYLzM8Ni6h2qLTfh9n9vXJT3/0=
+golang.org/x/net v0.0.0-20180926154720-4dfa2610cdf3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
+golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
+golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180928133829-e4b3c5e90611 h1:O33LKL7WyJgjN9CvxfTIomjIClbd/Kq86/iipowHQU0=
+golang.org/x/sys v0.0.0-20180928133829-e4b3c5e90611/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190904154756-749cb33beabd h1:DBH9mDw0zluJT/R+nGuV3jWFWLFaHyYZWD4tOT+cjn0=
+golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe h1:6fAMxZRR6sl1Uq8U61gxU+kPTs2tR8uOySCbBP7BN/M=
+golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191216052735-49a3e744a425 h1:VvQyQJN0tSuecqgcIxMWnnfG5kSmgy9KZR9sW3W5QeA=
+golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/vendor/github.com/miekg/dns/labels.go b/vendor/github.com/miekg/dns/labels.go
index e32d2a1d2546feb0d5def17c2e09fd1c078d24a2..df1675dfd28037db42dce1a6a199fbc87ce724f3 100644
--- a/vendor/github.com/miekg/dns/labels.go
+++ b/vendor/github.com/miekg/dns/labels.go
@@ -83,7 +83,7 @@ func CompareDomainName(s1, s2 string) (n int) {
 	return
 }
 
-// CountLabel counts the the number of labels in the string s.
+// CountLabel counts the number of labels in the string s.
 // s must be a syntactically valid domain name.
 func CountLabel(s string) (labels int) {
 	if s == "." {
@@ -126,20 +126,23 @@ func Split(s string) []int {
 // The bool end is true when the end of the string has been reached.
 // Also see PrevLabel.
 func NextLabel(s string, offset int) (i int, end bool) {
-	quote := false
+	if s == "" {
+		return 0, true
+	}
 	for i = offset; i < len(s)-1; i++ {
-		switch s[i] {
-		case '\\':
-			quote = !quote
-		default:
-			quote = false
-		case '.':
-			if quote {
-				quote = !quote
-				continue
-			}
-			return i + 1, false
+		if s[i] != '.' {
+			continue
+		}
+		j := i - 1
+		for j >= 0 && s[j] == '\\' {
+			j--
+		}
+
+		if (j-i)%2 == 0 {
+			continue
 		}
+
+		return i + 1, false
 	}
 	return i + 1, true
 }
@@ -149,17 +152,38 @@ func NextLabel(s string, offset int) (i int, end bool) {
 // The bool start is true when the start of the string has been overshot.
 // Also see NextLabel.
 func PrevLabel(s string, n int) (i int, start bool) {
+	if s == "" {
+		return 0, true
+	}
 	if n == 0 {
 		return len(s), false
 	}
-	lab := Split(s)
-	if lab == nil {
-		return 0, true
+
+	l := len(s) - 1
+	if s[l] == '.' {
+		l--
 	}
-	if n > len(lab) {
-		return 0, true
+
+	for ; l >= 0 && n > 0; l-- {
+		if s[l] != '.' {
+			continue
+		}
+		j := l - 1
+		for j >= 0 && s[j] == '\\' {
+			j--
+		}
+
+		if (j-l)%2 == 0 {
+			continue
+		}
+
+		n--
+		if n == 0 {
+			return l + 1, false
+		}
 	}
-	return lab[len(lab)-n], false
+
+	return 0, n > 1
 }
 
 // equal compares a and b while ignoring case. It returns true when equal otherwise false.
diff --git a/vendor/github.com/miekg/dns/msg.go b/vendor/github.com/miekg/dns/msg.go
index e04fb5d77a78fcef58a1eed903123bf3a9e751c8..7001f6da79c88ee68f90c6438814f5b39b6e579d 100644
--- a/vendor/github.com/miekg/dns/msg.go
+++ b/vendor/github.com/miekg/dns/msg.go
@@ -11,14 +11,12 @@ package dns
 //go:generate go run msg_generate.go
 
 import (
-	crand "crypto/rand"
+	"crypto/rand"
 	"encoding/binary"
 	"fmt"
 	"math/big"
-	"math/rand"
 	"strconv"
 	"strings"
-	"sync"
 )
 
 const (
@@ -73,53 +71,23 @@ var (
 	ErrTime          error = &Error{err: "bad time"}      // ErrTime indicates a timing error in TSIG authentication.
 )
 
-// Id by default, returns a 16 bits random number to be used as a
-// message id. The random provided should be good enough. This being a
-// variable the function can be reassigned to a custom function.
-// For instance, to make it return a static value:
+// Id by default returns a 16-bit random number to be used as a message id. The
+// number is drawn from a cryptographically secure random number generator.
+// This being a variable the function can be reassigned to a custom function.
+// For instance, to make it return a static value for testing:
 //
 //	dns.Id = func() uint16 { return 3 }
 var Id = id
 
-var (
-	idLock sync.Mutex
-	idRand *rand.Rand
-)
-
 // id returns a 16 bits random number to be used as a
 // message id. The random provided should be good enough.
 func id() uint16 {
-	idLock.Lock()
-
-	if idRand == nil {
-		// This (partially) works around
-		// https://github.com/golang/go/issues/11833 by only
-		// seeding idRand upon the first call to id.
-
-		var seed int64
-		var buf [8]byte
-
-		if _, err := crand.Read(buf[:]); err == nil {
-			seed = int64(binary.LittleEndian.Uint64(buf[:]))
-		} else {
-			seed = rand.Int63()
-		}
-
-		idRand = rand.New(rand.NewSource(seed))
+	var output uint16
+	err := binary.Read(rand.Reader, binary.BigEndian, &output)
+	if err != nil {
+		panic("dns: reading random id failed: " + err.Error())
 	}
-
-	// The call to idRand.Uint32 must be within the
-	// mutex lock because *rand.Rand is not safe for
-	// concurrent use.
-	//
-	// There is no added performance overhead to calling
-	// idRand.Uint32 inside a mutex lock over just
-	// calling rand.Uint32 as the global math/rand rng
-	// is internally protected by a sync.Mutex.
-	id := uint16(idRand.Uint32())
-
-	idLock.Unlock()
-	return id
+	return output
 }
 
 // MsgHdr is a a manually-unpacked version of (id, bits).
@@ -430,17 +398,12 @@ Loop:
 				return "", lenmsg, ErrLongDomain
 			}
 			for _, b := range msg[off : off+c] {
-				switch b {
-				case '.', '(', ')', ';', ' ', '@':
-					fallthrough
-				case '"', '\\':
+				if isDomainNameLabelSpecial(b) {
 					s = append(s, '\\', b)
-				default:
-					if b < ' ' || b > '~' { // unprintable, use \DDD
-						s = append(s, escapeByte(b)...)
-					} else {
-						s = append(s, b)
-					}
+				} else if b < ' ' || b > '~' {
+					s = append(s, escapeByte(b)...)
+				} else {
+					s = append(s, b)
 				}
 			}
 			s = append(s, '.')
@@ -693,7 +656,6 @@ func unpackRRslice(l int, msg []byte, off int) (dst1 []RR, off1 int, err error)
 		}
 		// If offset does not increase anymore, l is a lie
 		if off1 == off {
-			l = i
 			break
 		}
 		dst = append(dst, r)
diff --git a/vendor/github.com/miekg/dns/msg_helpers.go b/vendor/github.com/miekg/dns/msg_helpers.go
index ecd9280f472519bc3232a65c5e0f961638509f2d..47625ed0902d627c2311539a226652a5777e2a9f 100644
--- a/vendor/github.com/miekg/dns/msg_helpers.go
+++ b/vendor/github.com/miekg/dns/msg_helpers.go
@@ -6,6 +6,7 @@ import (
 	"encoding/binary"
 	"encoding/hex"
 	"net"
+	"sort"
 	"strings"
 )
 
@@ -265,24 +266,36 @@ func unpackString(msg []byte, off int) (string, int, error) {
 		return "", off, &Error{err: "overflow unpacking txt"}
 	}
 	l := int(msg[off])
-	if off+l+1 > len(msg) {
+	off++
+	if off+l > len(msg) {
 		return "", off, &Error{err: "overflow unpacking txt"}
 	}
 	var s strings.Builder
-	s.Grow(l)
-	for _, b := range msg[off+1 : off+1+l] {
+	consumed := 0
+	for i, b := range msg[off : off+l] {
 		switch {
 		case b == '"' || b == '\\':
+			if consumed == 0 {
+				s.Grow(l * 2)
+			}
+			s.Write(msg[off+consumed : off+i])
 			s.WriteByte('\\')
 			s.WriteByte(b)
+			consumed = i + 1
 		case b < ' ' || b > '~': // unprintable
+			if consumed == 0 {
+				s.Grow(l * 2)
+			}
+			s.Write(msg[off+consumed : off+i])
 			s.WriteString(escapeByte(b))
-		default:
-			s.WriteByte(b)
+			consumed = i + 1
 		}
 	}
-	off += 1 + l
-	return s.String(), off, nil
+	if consumed == 0 { // no escaping needed
+		return string(msg[off : off+l]), off + l, nil
+	}
+	s.Write(msg[off+consumed : off+l])
+	return s.String(), off + l, nil
 }
 
 func packString(s string, msg []byte, off int) (int, error) {
@@ -411,100 +424,60 @@ Option:
 	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
+	}
+
+	return edns, off, nil
+}
+
+func makeDataOpt(code uint16) EDNS0 {
 	switch code {
 	case EDNS0NSID:
-		e := new(EDNS0_NSID)
-		if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
-			return nil, len(msg), err
-		}
-		edns = append(edns, e)
-		off += int(optlen)
+		return new(EDNS0_NSID)
 	case EDNS0SUBNET:
-		e := new(EDNS0_SUBNET)
-		if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
-			return nil, len(msg), err
-		}
-		edns = append(edns, e)
-		off += int(optlen)
+		return new(EDNS0_SUBNET)
 	case EDNS0COOKIE:
-		e := new(EDNS0_COOKIE)
-		if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
-			return nil, len(msg), err
-		}
-		edns = append(edns, e)
-		off += int(optlen)
+		return new(EDNS0_COOKIE)
+	case EDNS0EXPIRE:
+		return new(EDNS0_EXPIRE)
 	case EDNS0UL:
-		e := new(EDNS0_UL)
-		if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
-			return nil, len(msg), err
-		}
-		edns = append(edns, e)
-		off += int(optlen)
+		return new(EDNS0_UL)
 	case EDNS0LLQ:
-		e := new(EDNS0_LLQ)
-		if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
-			return nil, len(msg), err
-		}
-		edns = append(edns, e)
-		off += int(optlen)
+		return new(EDNS0_LLQ)
 	case EDNS0DAU:
-		e := new(EDNS0_DAU)
-		if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
-			return nil, len(msg), err
-		}
-		edns = append(edns, e)
-		off += int(optlen)
+		return new(EDNS0_DAU)
 	case EDNS0DHU:
-		e := new(EDNS0_DHU)
-		if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
-			return nil, len(msg), err
-		}
-		edns = append(edns, e)
-		off += int(optlen)
+		return new(EDNS0_DHU)
 	case EDNS0N3U:
-		e := new(EDNS0_N3U)
-		if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
-			return nil, len(msg), err
-		}
-		edns = append(edns, e)
-		off += int(optlen)
+		return new(EDNS0_N3U)
 	case EDNS0PADDING:
-		e := new(EDNS0_PADDING)
-		if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
-			return nil, len(msg), err
-		}
-		edns = append(edns, e)
-		off += int(optlen)
+		return new(EDNS0_PADDING)
 	default:
 		e := new(EDNS0_LOCAL)
 		e.Code = code
-		if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
-			return nil, len(msg), err
-		}
-		edns = append(edns, e)
-		off += int(optlen)
+		return e
 	}
-
-	if off < len(msg) {
-		goto Option
-	}
-
-	return edns, off, nil
 }
 
 func packDataOpt(options []EDNS0, msg []byte, off int) (int, error) {
 	for _, el := range options {
 		b, err := el.pack()
-		if err != nil || off+3 > len(msg) {
+		if err != nil || off+4 > len(msg) {
 			return len(msg), &Error{err: "overflow packing opt"}
 		}
 		binary.BigEndian.PutUint16(msg[off:], el.Option())      // Option code
 		binary.BigEndian.PutUint16(msg[off+2:], uint16(len(b))) // Length
 		off += 4
 		if off+len(b) > len(msg) {
-			copy(msg[off:], b)
-			off = len(msg)
-			continue
+			return len(msg), &Error{err: "overflow packing opt"}
 		}
 		// Actual data
 		copy(msg[off:off+len(b)], b)
@@ -587,6 +560,29 @@ func unpackDataNsec(msg []byte, off int) ([]uint16, int, error) {
 	return nsec, off, nil
 }
 
+// typeBitMapLen is a helper function which computes the "maximum" length of
+// a the NSEC Type BitMap field.
+func typeBitMapLen(bitmap []uint16) int {
+	var l int
+	var lastwindow, lastlength uint16
+	for _, t := range bitmap {
+		window := t / 256
+		length := (t-window*256)/8 + 1
+		if window > lastwindow && lastlength != 0 { // New window, jump to the new offset
+			l += int(lastlength) + 2
+			lastlength = 0
+		}
+		if window < lastwindow || length < lastlength {
+			// packDataNsec would return Error{err: "nsec bits out of order"} here, but
+			// when computing the length, we want do be liberal.
+			continue
+		}
+		lastwindow, lastlength = window, length
+	}
+	l += int(lastlength) + 2
+	return l
+}
+
 func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) {
 	if len(bitmap) == 0 {
 		return off, nil
@@ -617,6 +613,65 @@ func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) {
 	return off, nil
 }
 
+func unpackDataSVCB(msg []byte, off int) ([]SVCBKeyValue, int, error) {
+	var xs []SVCBKeyValue
+	var code uint16
+	var length uint16
+	var err error
+	for off < len(msg) {
+		code, off, err = unpackUint16(msg, off)
+		if err != nil {
+			return nil, len(msg), &Error{err: "overflow unpacking SVCB"}
+		}
+		length, off, err = unpackUint16(msg, off)
+		if err != nil || off+int(length) > len(msg) {
+			return nil, len(msg), &Error{err: "overflow unpacking SVCB"}
+		}
+		e := makeSVCBKeyValue(SVCBKey(code))
+		if e == nil {
+			return nil, len(msg), &Error{err: "bad SVCB key"}
+		}
+		if err := e.unpack(msg[off : off+int(length)]); err != nil {
+			return nil, len(msg), err
+		}
+		if len(xs) > 0 && e.Key() <= xs[len(xs)-1].Key() {
+			return nil, len(msg), &Error{err: "SVCB keys not in strictly increasing order"}
+		}
+		xs = append(xs, e)
+		off += int(length)
+	}
+	return xs, off, nil
+}
+
+func packDataSVCB(pairs []SVCBKeyValue, msg []byte, off int) (int, error) {
+	pairs = append([]SVCBKeyValue(nil), pairs...)
+	sort.Slice(pairs, func(i, j int) bool {
+		return pairs[i].Key() < pairs[j].Key()
+	})
+	prev := svcb_RESERVED
+	for _, el := range pairs {
+		if el.Key() == prev {
+			return len(msg), &Error{err: "repeated SVCB keys are not allowed"}
+		}
+		prev = el.Key()
+		packed, err := el.pack()
+		if err != nil {
+			return len(msg), err
+		}
+		off, err = packUint16(uint16(el.Key()), msg, off)
+		if err != nil {
+			return len(msg), &Error{err: "overflow packing SVCB"}
+		}
+		off, err = packUint16(uint16(len(packed)), msg, off)
+		if err != nil || off+len(packed) > len(msg) {
+			return len(msg), &Error{err: "overflow packing SVCB"}
+		}
+		copy(msg[off:off+len(packed)], packed)
+		off += len(packed)
+	}
+	return off, nil
+}
+
 func unpackDataDomainNames(msg []byte, off, end int) ([]string, int, error) {
 	var (
 		servers []string
@@ -646,3 +701,133 @@ func packDataDomainNames(names []string, msg []byte, off int, compression compre
 	}
 	return off, nil
 }
+
+func packDataApl(data []APLPrefix, msg []byte, off int) (int, error) {
+	var err error
+	for i := range data {
+		off, err = packDataAplPrefix(&data[i], msg, off)
+		if err != nil {
+			return len(msg), err
+		}
+	}
+	return off, nil
+}
+
+func packDataAplPrefix(p *APLPrefix, msg []byte, off int) (int, error) {
+	if len(p.Network.IP) != len(p.Network.Mask) {
+		return len(msg), &Error{err: "address and mask lengths don't match"}
+	}
+
+	var err error
+	prefix, _ := p.Network.Mask.Size()
+	addr := p.Network.IP.Mask(p.Network.Mask)[:(prefix+7)/8]
+
+	switch len(p.Network.IP) {
+	case net.IPv4len:
+		off, err = packUint16(1, msg, off)
+	case net.IPv6len:
+		off, err = packUint16(2, msg, off)
+	default:
+		err = &Error{err: "unrecognized address family"}
+	}
+	if err != nil {
+		return len(msg), err
+	}
+
+	off, err = packUint8(uint8(prefix), msg, off)
+	if err != nil {
+		return len(msg), err
+	}
+
+	var n uint8
+	if p.Negation {
+		n = 0x80
+	}
+
+	// trim trailing zero bytes as specified in RFC3123 Sections 4.1 and 4.2.
+	i := len(addr) - 1
+	for ; i >= 0 && addr[i] == 0; i-- {
+	}
+	addr = addr[:i+1]
+
+	adflen := uint8(len(addr)) & 0x7f
+	off, err = packUint8(n|adflen, msg, off)
+	if err != nil {
+		return len(msg), err
+	}
+
+	if off+len(addr) > len(msg) {
+		return len(msg), &Error{err: "overflow packing APL prefix"}
+	}
+	off += copy(msg[off:], addr)
+
+	return off, nil
+}
+
+func unpackDataApl(msg []byte, off int) ([]APLPrefix, int, error) {
+	var result []APLPrefix
+	for off < len(msg) {
+		prefix, end, err := unpackDataAplPrefix(msg, off)
+		if err != nil {
+			return nil, len(msg), err
+		}
+		off = end
+		result = append(result, prefix)
+	}
+	return result, off, nil
+}
+
+func unpackDataAplPrefix(msg []byte, off int) (APLPrefix, int, error) {
+	family, off, err := unpackUint16(msg, off)
+	if err != nil {
+		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL prefix"}
+	}
+	prefix, off, err := unpackUint8(msg, off)
+	if err != nil {
+		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL prefix"}
+	}
+	nlen, off, err := unpackUint8(msg, off)
+	if err != nil {
+		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL prefix"}
+	}
+
+	var ip []byte
+	switch family {
+	case 1:
+		ip = make([]byte, net.IPv4len)
+	case 2:
+		ip = make([]byte, net.IPv6len)
+	default:
+		return APLPrefix{}, len(msg), &Error{err: "unrecognized APL address family"}
+	}
+	if int(prefix) > 8*len(ip) {
+		return APLPrefix{}, len(msg), &Error{err: "APL prefix too long"}
+	}
+	afdlen := int(nlen & 0x7f)
+	if afdlen > len(ip) {
+		return APLPrefix{}, len(msg), &Error{err: "APL length too long"}
+	}
+	if off+afdlen > len(msg) {
+		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL address"}
+	}
+	off += copy(ip, msg[off:off+afdlen])
+	if afdlen > 0 {
+		last := ip[afdlen-1]
+		if last == 0 {
+			return APLPrefix{}, len(msg), &Error{err: "extra APL address bits"}
+		}
+	}
+	ipnet := net.IPNet{
+		IP:   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{
+		Negation: (nlen & 0x80) != 0,
+		Network:  ipnet,
+	}, off, nil
+}
diff --git a/vendor/github.com/miekg/dns/msg_truncate.go b/vendor/github.com/miekg/dns/msg_truncate.go
index 4763fc610f932b189d0b6780e69be21ed1b5ebc3..156c5a0e876a6259519389c66473d04b009a71a4 100644
--- a/vendor/github.com/miekg/dns/msg_truncate.go
+++ b/vendor/github.com/miekg/dns/msg_truncate.go
@@ -4,12 +4,18 @@ package dns
 // size by removing records that exceed the requested size.
 //
 // It will first check if the reply fits without compression and then with
-// compression. If it won't fit with compression, Scrub then walks the
+// compression. If it won't fit with compression, Truncate then walks the
 // record adding as many records as possible without exceeding the
 // requested buffer size.
 //
-// The TC bit will be set if any answer records were excluded from the
-// message. This indicates to that the client should retry over TCP.
+// The TC bit will be set if any records were excluded from the message.
+// If the TC bit is already set on the message it will be retained.
+// TC indicates that the client should retry over TCP.
+//
+// According to RFC 2181, the TC bit should only be set if not all of the
+// "required" RRs can be included in the response. Unfortunately, we have
+// no way of knowing which RRs are required so we set the TC bit if any RR
+// had to be omitted from the response.
 //
 // The appropriate buffer size can be retrieved from the requests OPT
 // record, if present, and is transport specific otherwise. dns.MinMsgSize
@@ -23,11 +29,11 @@ func (dns *Msg) Truncate(size int) {
 	}
 
 	// RFC 6891 mandates that the payload size in an OPT record
-	// less than 512 bytes must be treated as equal to 512 bytes.
+	// less than 512 (MinMsgSize) bytes must be treated as equal to 512 bytes.
 	//
 	// For ease of use, we impose that restriction here.
-	if size < 512 {
-		size = 512
+	if size < MinMsgSize {
+		size = MinMsgSize
 	}
 
 	l := msgLenWithCompressionMap(dns, nil) // uncompressed length
@@ -68,12 +74,12 @@ func (dns *Msg) Truncate(size int) {
 
 	var numExtra int
 	if l < size {
-		l, numExtra = truncateLoop(dns.Extra, size, l, compression)
+		_, numExtra = truncateLoop(dns.Extra, size, l, compression)
 	}
 
-	// According to RFC 2181, the TC bit should only be set if not all
-	// of the answer RRs can be included in the response.
-	dns.Truncated = len(dns.Answer) > numAnswer
+	// See the function documentation for when we set this.
+	dns.Truncated = dns.Truncated || len(dns.Answer) > numAnswer ||
+		len(dns.Ns) > numNS || len(dns.Extra) > numExtra
 
 	dns.Answer = dns.Answer[:numAnswer]
 	dns.Ns = dns.Ns[:numNS]
diff --git a/vendor/github.com/miekg/dns/nsecx.go b/vendor/github.com/miekg/dns/nsecx.go
index 8f071a47399dfb9a57ed17c76a1e01cbd8b567d9..f8826817b398151996844ea9e66c583f8bb3a110 100644
--- a/vendor/github.com/miekg/dns/nsecx.go
+++ b/vendor/github.com/miekg/dns/nsecx.go
@@ -43,7 +43,7 @@ func HashName(label string, ha uint8, iter uint16, salt string) string {
 	return toBase32(nsec3)
 }
 
-// Cover returns true if a name is covered by the NSEC3 record
+// Cover returns true if a name is covered by the NSEC3 record.
 func (rr *NSEC3) Cover(name string) bool {
 	nameHash := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
 	owner := strings.ToUpper(rr.Hdr.Name)
diff --git a/vendor/github.com/miekg/dns/privaterr.go b/vendor/github.com/miekg/dns/privaterr.go
index d9c0d26774f0531fb58f2aa65ce24677cf8766b6..cda6cae31e1245573db0eb868ad6fc963bf87bb8 100644
--- a/vendor/github.com/miekg/dns/privaterr.go
+++ b/vendor/github.com/miekg/dns/privaterr.go
@@ -1,9 +1,6 @@
 package dns
 
-import (
-	"fmt"
-	"strings"
-)
+import "strings"
 
 // PrivateRdata is an interface used for implementing "Private Use" RR types, see
 // RFC 6895. This allows one to experiment with new RR types, without requesting an
@@ -16,9 +13,8 @@ type PrivateRdata interface {
 	// Pack is used when packing a private RR into a buffer.
 	Pack([]byte) (int, error)
 	// Unpack is used when unpacking a private RR from a buffer.
-	// TODO(miek): diff. signature than Pack, see edns0.go for instance.
 	Unpack([]byte) (int, error)
-	// Copy copies the Rdata.
+	// Copy copies the Rdata into the PrivateRdata argument.
 	Copy(PrivateRdata) error
 	// Len returns the length in octets of the Rdata.
 	Len() int
@@ -29,22 +25,8 @@ type PrivateRdata interface {
 type PrivateRR struct {
 	Hdr  RR_Header
 	Data PrivateRdata
-}
-
-func mkPrivateRR(rrtype uint16) *PrivateRR {
-	// Panics if RR is not an instance of PrivateRR.
-	rrfunc, ok := TypeToRR[rrtype]
-	if !ok {
-		panic(fmt.Sprintf("dns: invalid operation with Private RR type %d", rrtype))
-	}
-
-	anyrr := rrfunc()
-	rr, ok := anyrr.(*PrivateRR)
-	if !ok {
-		panic(fmt.Sprintf("dns: RR is not a PrivateRR, TypeToRR[%d] generator returned %T", rrtype, anyrr))
-	}
 
-	return rr
+	generator func() PrivateRdata // for copy
 }
 
 // Header return the RR header of r.
@@ -61,13 +43,12 @@ func (r *PrivateRR) len(off int, compression map[string]struct{}) int {
 
 func (r *PrivateRR) copy() RR {
 	// make new RR like this:
-	rr := mkPrivateRR(r.Hdr.Rrtype)
-	rr.Hdr = r.Hdr
+	rr := &PrivateRR{r.Hdr, r.generator(), r.generator}
 
-	err := r.Data.Copy(rr.Data)
-	if err != nil {
-		panic("dns: got value that could not be used to copy Private rdata")
+	if err := r.Data.Copy(rr.Data); err != nil {
+		panic("dns: got value that could not be used to copy Private rdata: " + err.Error())
 	}
+
 	return rr
 }
 
@@ -86,7 +67,7 @@ func (r *PrivateRR) unpack(msg []byte, off int) (int, error) {
 	return off, err
 }
 
-func (r *PrivateRR) parse(c *zlexer, origin, file string) *ParseError {
+func (r *PrivateRR) parse(c *zlexer, origin string) *ParseError {
 	var l lex
 	text := make([]string, 0, 2) // could be 0..N elements, median is probably 1
 Fetch:
@@ -103,7 +84,7 @@ Fetch:
 
 	err := r.Data.Parse(text)
 	if err != nil {
-		return &ParseError{file, err.Error(), l}
+		return &ParseError{"", err.Error(), l}
 	}
 
 	return nil
@@ -116,7 +97,7 @@ func (r1 *PrivateRR) isDuplicate(r2 RR) bool { return false }
 func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) {
 	rtypestr = strings.ToUpper(rtypestr)
 
-	TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator()} }
+	TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator(), generator} }
 	TypeToString[rtype] = rtypestr
 	StringToType[rtypestr] = rtype
 }
diff --git a/vendor/github.com/miekg/dns/scan.go b/vendor/github.com/miekg/dns/scan.go
index a8691bca70ac8dd5f63e465e51267cb06b0bb55c..aa2840efba890cf768537d27f6fce97e81e1b695 100644
--- a/vendor/github.com/miekg/dns/scan.go
+++ b/vendor/github.com/miekg/dns/scan.go
@@ -87,31 +87,18 @@ type lex struct {
 	column int    // column in the file
 }
 
-// Token holds the token that are returned when a zone file is parsed.
-type Token struct {
-	// The scanned resource record when error is not nil.
-	RR
-	// When an error occurred, this has the error specifics.
-	Error *ParseError
-	// A potential comment positioned after the RR and on the same line.
-	Comment string
-}
-
 // ttlState describes the state necessary to fill in an omitted RR TTL
 type ttlState struct {
 	ttl           uint32 // ttl is the current default TTL
 	isByDirective bool   // isByDirective indicates whether ttl was set by a $TTL directive
 }
 
-// NewRR reads the RR contained in the string s. Only the first RR is
-// returned. If s contains no records, NewRR will return nil with no
-// error.
-//
-// The class defaults to IN and TTL defaults to 3600. The full zone
-// file syntax like $TTL, $ORIGIN, etc. is supported.
+// NewRR reads the RR contained in the string s. Only the first RR is returned.
+// If s contains no records, NewRR will return nil with no error.
 //
-// All fields of the returned RR are set, except RR.Header().Rdlength
-// which is set to 0.
+// The class defaults to IN and TTL defaults to 3600. The full zone file syntax
+// like $TTL, $ORIGIN, etc. is supported. All fields of the returned RR are
+// set, except RR.Header().Rdlength which is set to 0.
 func NewRR(s string) (RR, error) {
 	if len(s) > 0 && s[len(s)-1] != '\n' { // We need a closing newline
 		return ReadRR(strings.NewReader(s+"\n"), "")
@@ -133,69 +120,6 @@ func ReadRR(r io.Reader, file string) (RR, error) {
 	return rr, zp.Err()
 }
 
-// ParseZone reads a RFC 1035 style zonefile from r. It returns
-// *Tokens on the returned channel, each consisting of either a
-// parsed RR and optional comment or a nil RR and an error. The
-// channel is closed by ParseZone when the end of r is reached.
-//
-// The string file is used in error reporting and to resolve relative
-// $INCLUDE directives. The string origin is used as the initial
-// origin, as if the file would start with an $ORIGIN directive.
-//
-// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are all
-// supported.
-//
-// Basic usage pattern when reading from a string (z) containing the
-// zone data:
-//
-//	for x := range dns.ParseZone(strings.NewReader(z), "", "") {
-//		if x.Error != nil {
-//                  // log.Println(x.Error)
-//              } else {
-//                  // Do something with x.RR
-//              }
-//	}
-//
-// Comments specified after an RR (and on the same line!) are
-// returned too:
-//
-//	foo. IN A 10.0.0.1 ; this is a comment
-//
-// The text "; this is comment" is returned in Token.Comment.
-// Comments inside the RR are returned concatenated along with the
-// RR. Comments on a line by themselves are discarded.
-//
-// To prevent memory leaks it is important to always fully drain the
-// returned channel. If an error occurs, it will always be the last
-// Token sent on the channel.
-//
-// Deprecated: New users should prefer the ZoneParser API.
-func ParseZone(r io.Reader, origin, file string) chan *Token {
-	t := make(chan *Token, 10000)
-	go parseZone(r, origin, file, t)
-	return t
-}
-
-func parseZone(r io.Reader, origin, file string, t chan *Token) {
-	defer close(t)
-
-	zp := NewZoneParser(r, origin, file)
-	zp.SetIncludeAllowed(true)
-
-	for rr, ok := zp.Next(); ok; rr, ok = zp.Next() {
-		t <- &Token{RR: rr, Comment: zp.Comment()}
-	}
-
-	if err := zp.Err(); err != nil {
-		pe, ok := err.(*ParseError)
-		if !ok {
-			pe = &ParseError{file: file, err: err.Error()}
-		}
-
-		t <- &Token{Error: pe}
-	}
-}
-
 // ZoneParser is a parser for an RFC 1035 style zonefile.
 //
 // Each parsed RR in the zone is returned sequentially from Next. An
@@ -203,6 +127,7 @@ func parseZone(r io.Reader, origin, file string, t chan *Token) {
 //
 // The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are all
 // supported. Although $INCLUDE is disabled by default.
+// Note that $GENERATE's range support up to a maximum of 65535 steps.
 //
 // Basic usage pattern when reading from a string (z) containing the
 // zone data:
@@ -245,7 +170,8 @@ type ZoneParser struct {
 
 	includeDepth uint8
 
-	includeAllowed bool
+	includeAllowed     bool
+	generateDisallowed bool
 }
 
 // NewZoneParser returns an RFC 1035 style zonefile parser that reads
@@ -503,9 +429,8 @@ func (zp *ZoneParser) Next() (RR, bool) {
 				return zp.setParseError("expecting $TTL value, not this...", l)
 			}
 
-			if e := slurpRemainder(zp.c, zp.file); e != nil {
-				zp.parseErr = e
-				return nil, false
+			if err := slurpRemainder(zp.c); err != nil {
+				return zp.setParseError(err.err, err.lex)
 			}
 
 			ttl, ok := stringToTTL(l.token)
@@ -527,9 +452,8 @@ func (zp *ZoneParser) Next() (RR, bool) {
 				return zp.setParseError("expecting $ORIGIN value, not this...", l)
 			}
 
-			if e := slurpRemainder(zp.c, zp.file); e != nil {
-				zp.parseErr = e
-				return nil, false
+			if err := slurpRemainder(zp.c); err != nil {
+				return zp.setParseError(err.err, err.lex)
 			}
 
 			name, ok := toAbsoluteName(l.token, zp.origin)
@@ -547,6 +471,9 @@ func (zp *ZoneParser) Next() (RR, bool) {
 
 			st = zExpectDirGenerate
 		case zExpectDirGenerate:
+			if zp.generateDisallowed {
+				return zp.setParseError("nested $GENERATE directive not allowed", l)
+			}
 			if l.value != zString {
 				return zp.setParseError("expecting $GENERATE value, not this...", l)
 			}
@@ -650,19 +577,44 @@ func (zp *ZoneParser) Next() (RR, bool) {
 
 			st = zExpectRdata
 		case zExpectRdata:
-			r, e := setRR(*h, zp.c, zp.origin, zp.file)
-			if e != nil {
-				// If e.lex is nil than we have encounter a unknown RR type
-				// in that case we substitute our current lex token
-				if e.lex.token == "" && e.lex.value == 0 {
-					e.lex = l // Uh, dirty
+			var rr RR
+			if newFn, ok := TypeToRR[h.Rrtype]; ok && canParseAsRR(h.Rrtype) {
+				rr = newFn()
+				*rr.Header() = *h
+			} else {
+				rr = &RFC3597{Hdr: *h}
+			}
+
+			_, isPrivate := rr.(*PrivateRR)
+			if !isPrivate && zp.c.Peek().token == "" {
+				// 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 {
+					return zp.setParseError(err.err, err.lex)
+				}
+
+				return rr, true
+			} else if l.value == zNewline {
+				return zp.setParseError("unexpected newline", l)
+			}
+
+			if err := rr.parse(zp.c, zp.origin); err != nil {
+				// err is a concrete *ParseError without the file field set.
+				// The setParseError call below will construct a new
+				// *ParseError with file set to zp.file.
+
+				// If err.lex is nil than we have encounter an unknown RR type
+				// in that case we substitute our current lex token.
+				if err.lex == (lex{}) {
+					return zp.setParseError(err.err, l)
 				}
 
-				zp.parseErr = e
-				return nil, false
+				return zp.setParseError(err.err, err.lex)
 			}
 
-			return r, true
+			return rr, true
 		}
 	}
 
@@ -671,6 +623,18 @@ func (zp *ZoneParser) Next() (RR, bool) {
 	return nil, false
 }
 
+// canParseAsRR returns true if the record type can be parsed as a
+// concrete RR. It blacklists certain record types that must be parsed
+// according to RFC 3597 because they lack a presentation format.
+func canParseAsRR(rrtype uint16) bool {
+	switch rrtype {
+	case TypeANY, TypeNULL, TypeOPT, TypeTSIG:
+		return false
+	default:
+		return true
+	}
+}
+
 type zlexer struct {
 	br io.ByteReader
 
@@ -682,7 +646,8 @@ type zlexer struct {
 	comBuf  string
 	comment string
 
-	l lex
+	l       lex
+	cachedL *lex
 
 	brace  int
 	quote  bool
@@ -748,13 +713,37 @@ func (zl *zlexer) readByte() (byte, bool) {
 	return c, true
 }
 
+func (zl *zlexer) Peek() lex {
+	if zl.nextL {
+		return zl.l
+	}
+
+	l, ok := zl.Next()
+	if !ok {
+		return l
+	}
+
+	if zl.nextL {
+		// Cache l. Next returns zl.cachedL then zl.l.
+		zl.cachedL = &l
+	} else {
+		// In this case l == zl.l, so we just tell Next to return zl.l.
+		zl.nextL = true
+	}
+
+	return l
+}
+
 func (zl *zlexer) Next() (lex, bool) {
 	l := &zl.l
-	if zl.nextL {
+	switch {
+	case zl.cachedL != nil:
+		l, zl.cachedL = zl.cachedL, nil
+		return *l, true
+	case zl.nextL:
 		zl.nextL = false
 		return *l, true
-	}
-	if l.err {
+	case l.err:
 		// Parsing errors should be sticky.
 		return lex{value: zEOF}, false
 	}
@@ -908,6 +897,11 @@ func (zl *zlexer) Next() (lex, bool) {
 				// was inside braces and we delayed adding it until now.
 				com[comi] = ' ' // convert newline to space
 				comi++
+				if comi >= len(com) {
+					l.token = "comment length insufficient for parsing"
+					l.err = true
+					return *l, true
+				}
 			}
 
 			com[comi] = ';'
@@ -1216,11 +1210,29 @@ func stringToCm(token string) (e, m uint8, ok bool) {
 		if cmeters, err = strconv.Atoi(s[1]); err != nil {
 			return
 		}
+		// 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.
+		// 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' {
+			return
+		}
+		if len(s[1]) == 1 {
+			// 'nn.1' must be treated as 'nn-meters and 10cm, not 1cm.
+			cmeters *= 10
+		}
+		if len(s[0]) == 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
 		}
+		// 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) {
+			return
+		}
 	case 0:
 		// huh?
 		return 0, 0, false
@@ -1233,13 +1245,10 @@ func stringToCm(token string) (e, m uint8, ok bool) {
 		e = 0
 		val = cmeters
 	}
-	for val > 10 {
+	for val >= 10 {
 		e++
 		val /= 10
 	}
-	if e > 9 {
-		ok = false
-	}
 	m = uint8(val)
 	return
 }
@@ -1281,6 +1290,9 @@ func appendOrigin(name, origin string) string {
 
 // LOC record helper function
 func locCheckNorth(token string, latitude uint32) (uint32, bool) {
+	if latitude > 90 * 1000 * 60 * 60 {
+		return latitude, false
+	}
 	switch token {
 	case "n", "N":
 		return LOC_EQUATOR + latitude, true
@@ -1292,6 +1304,9 @@ func locCheckNorth(token string, latitude uint32) (uint32, bool) {
 
 // LOC record helper function
 func locCheckEast(token string, longitude uint32) (uint32, bool) {
+	if longitude > 180 * 1000 * 60 * 60 {
+		return longitude, false
+	}
 	switch token {
 	case "e", "E":
 		return LOC_EQUATOR + longitude, true
@@ -1302,18 +1317,18 @@ func locCheckEast(token string, longitude uint32) (uint32, bool) {
 }
 
 // "Eat" the rest of the "line"
-func slurpRemainder(c *zlexer, f string) *ParseError {
+func slurpRemainder(c *zlexer) *ParseError {
 	l, _ := c.Next()
 	switch l.value {
 	case zBlank:
 		l, _ = c.Next()
 		if l.value != zNewline && l.value != zEOF {
-			return &ParseError{f, "garbage after rdata", l}
+			return &ParseError{"", "garbage after rdata", l}
 		}
 	case zNewline:
 	case zEOF:
 	default:
-		return &ParseError{f, "garbage after rdata", l}
+		return &ParseError{"", "garbage after rdata", l}
 	}
 	return nil
 }
diff --git a/vendor/github.com/miekg/dns/scan_rr.go b/vendor/github.com/miekg/dns/scan_rr.go
index 6096f9b0c5a687c7578de4a1a999e7aa235a3986..69f10052f4ebe57bc94470ca560cb208628de9ff 100644
--- a/vendor/github.com/miekg/dns/scan_rr.go
+++ b/vendor/github.com/miekg/dns/scan_rr.go
@@ -1,75 +1,42 @@
 package dns
 
 import (
+	"bytes"
 	"encoding/base64"
 	"net"
 	"strconv"
 	"strings"
 )
 
-// Parse the rdata of each rrtype.
-// All data from the channel c is either zString or zBlank.
-// After the rdata there may come a zBlank and then a zNewline
-// or immediately a zNewline. If this is not the case we flag
-// an *ParseError: garbage after rdata.
-func setRR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) {
-	var rr RR
-	if newFn, ok := TypeToRR[h.Rrtype]; ok && canParseAsRR(h.Rrtype) {
-		rr = newFn()
-		*rr.Header() = h
-	} else {
-		rr = &RFC3597{Hdr: h}
-	}
-
-	err := rr.parse(c, o, f)
-	if err != nil {
-		return nil, err
-	}
-
-	return rr, nil
-}
-
-// canParseAsRR returns true if the record type can be parsed as a
-// concrete RR. It blacklists certain record types that must be parsed
-// according to RFC 3597 because they lack a presentation format.
-func canParseAsRR(rrtype uint16) bool {
-	switch rrtype {
-	case TypeANY, TypeNULL, TypeOPT, TypeTSIG:
-		return false
-	default:
-		return true
-	}
-}
-
 // A remainder of the rdata with embedded spaces, return the parsed string (sans the spaces)
 // or an error
-func endingToString(c *zlexer, errstr, f string) (string, *ParseError) {
-	var s string
+func endingToString(c *zlexer, errstr string) (string, *ParseError) {
+	var buffer bytes.Buffer
 	l, _ := c.Next() // zString
 	for l.value != zNewline && l.value != zEOF {
 		if l.err {
-			return s, &ParseError{f, errstr, l}
+			return buffer.String(), &ParseError{"", errstr, l}
 		}
 		switch l.value {
 		case zString:
-			s += l.token
+			buffer.WriteString(l.token)
 		case zBlank: // Ok
 		default:
-			return "", &ParseError{f, errstr, l}
+			return "", &ParseError{"", errstr, l}
 		}
 		l, _ = c.Next()
 	}
 
-	return s, nil
+	return buffer.String(), nil
 }
 
 // A remainder of the rdata with embedded spaces, split on unquoted whitespace
 // and return the parsed string slice or an error
-func endingToTxtSlice(c *zlexer, errstr, f string) ([]string, *ParseError) {
+func endingToTxtSlice(c *zlexer, errstr string) ([]string, *ParseError) {
 	// Get the remaining data until we see a zNewline
 	l, _ := c.Next()
 	if l.err {
-		return nil, &ParseError{f, errstr, l}
+		return nil, &ParseError{"", errstr, l}
 	}
 
 	// Build the slice
@@ -78,7 +45,7 @@ func endingToTxtSlice(c *zlexer, errstr, f string) ([]string, *ParseError) {
 	empty := false
 	for l.value != zNewline && l.value != zEOF {
 		if l.err {
-			return nil, &ParseError{f, errstr, l}
+			return nil, &ParseError{"", errstr, l}
 		}
 		switch l.value {
 		case zString:
@@ -105,7 +72,7 @@ func endingToTxtSlice(c *zlexer, errstr, f string) ([]string, *ParseError) {
 		case zBlank:
 			if quote {
 				// zBlank can only be seen in between txt parts.
-				return nil, &ParseError{f, errstr, l}
+				return nil, &ParseError{"", errstr, l}
 			}
 		case zQuote:
 			if empty && quote {
@@ -114,24 +81,20 @@ func endingToTxtSlice(c *zlexer, errstr, f string) ([]string, *ParseError) {
 			quote = !quote
 			empty = true
 		default:
-			return nil, &ParseError{f, errstr, l}
+			return nil, &ParseError{"", errstr, l}
 		}
 		l, _ = c.Next()
 	}
 
 	if quote {
-		return nil, &ParseError{f, errstr, l}
+		return nil, &ParseError{"", errstr, l}
 	}
 
 	return s, nil
 }
 
-func (rr *A) parse(c *zlexer, o, f string) *ParseError {
+func (rr *A) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	rr.A = net.ParseIP(l.token)
 	// IPv4 addresses cannot include ":".
 	// We do this rather than use net.IP's To4() because
@@ -139,82 +102,58 @@ func (rr *A) parse(c *zlexer, o, f string) *ParseError {
 	// IPv4.
 	isIPv4 := !strings.Contains(l.token, ":")
 	if rr.A == nil || !isIPv4 || l.err {
-		return &ParseError{f, "bad A A", l}
+		return &ParseError{"", "bad A A", l}
 	}
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *AAAA) parse(c *zlexer, o, f string) *ParseError {
+func (rr *AAAA) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	rr.AAAA = net.ParseIP(l.token)
 	// IPv6 addresses must include ":", and IPv4
 	// addresses cannot include ":".
 	isIPv6 := strings.Contains(l.token, ":")
 	if rr.AAAA == nil || !isIPv6 || l.err {
-		return &ParseError{f, "bad AAAA AAAA", l}
+		return &ParseError{"", "bad AAAA AAAA", l}
 	}
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *NS) parse(c *zlexer, o, f string) *ParseError {
+func (rr *NS) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	rr.Ns = l.token
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return &ParseError{f, "bad NS Ns", l}
+		return &ParseError{"", "bad NS Ns", l}
 	}
 	rr.Ns = name
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *PTR) parse(c *zlexer, o, f string) *ParseError {
+func (rr *PTR) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	rr.Ptr = l.token
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return &ParseError{f, "bad PTR Ptr", l}
+		return &ParseError{"", "bad PTR Ptr", l}
 	}
 	rr.Ptr = name
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *NSAPPTR) parse(c *zlexer, o, f string) *ParseError {
+func (rr *NSAPPTR) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	rr.Ptr = l.token
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return &ParseError{f, "bad NSAP-PTR Ptr", l}
+		return &ParseError{"", "bad NSAP-PTR Ptr", l}
 	}
 	rr.Ptr = name
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *RP) parse(c *zlexer, o, f string) *ParseError {
+func (rr *RP) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	rr.Mbox = l.token
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	mbox, mboxOk := toAbsoluteName(l.token, o)
 	if l.err || !mboxOk {
-		return &ParseError{f, "bad RP Mbox", l}
+		return &ParseError{"", "bad RP Mbox", l}
 	}
 	rr.Mbox = mbox
 
@@ -224,60 +163,45 @@ func (rr *RP) parse(c *zlexer, o, f string) *ParseError {
 
 	txt, txtOk := toAbsoluteName(l.token, o)
 	if l.err || !txtOk {
-		return &ParseError{f, "bad RP Txt", l}
+		return &ParseError{"", "bad RP Txt", l}
 	}
 	rr.Txt = txt
 
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *MR) parse(c *zlexer, o, f string) *ParseError {
+func (rr *MR) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	rr.Mr = l.token
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return &ParseError{f, "bad MR Mr", l}
+		return &ParseError{"", "bad MR Mr", l}
 	}
 	rr.Mr = name
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *MB) parse(c *zlexer, o, f string) *ParseError {
+func (rr *MB) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	rr.Mb = l.token
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return &ParseError{f, "bad MB Mb", l}
+		return &ParseError{"", "bad MB Mb", l}
 	}
 	rr.Mb = name
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *MG) parse(c *zlexer, o, f string) *ParseError {
+func (rr *MG) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	rr.Mg = l.token
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return &ParseError{f, "bad MG Mg", l}
+		return &ParseError{"", "bad MG Mg", l}
 	}
 	rr.Mg = name
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *HINFO) parse(c *zlexer, o, f string) *ParseError {
-	chunks, e := endingToTxtSlice(c, "bad HINFO Fields", f)
+func (rr *HINFO) parse(c *zlexer, o string) *ParseError {
+	chunks, e := endingToTxtSlice(c, "bad HINFO Fields")
 	if e != nil {
 		return e
 	}
@@ -299,16 +223,11 @@ func (rr *HINFO) parse(c *zlexer, o, f string) *ParseError {
 	return nil
 }
 
-func (rr *MINFO) parse(c *zlexer, o, f string) *ParseError {
+func (rr *MINFO) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	rr.Rmail = l.token
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	rmail, rmailOk := toAbsoluteName(l.token, o)
 	if l.err || !rmailOk {
-		return &ParseError{f, "bad MINFO Rmail", l}
+		return &ParseError{"", "bad MINFO Rmail", l}
 	}
 	rr.Rmail = rmail
 
@@ -318,52 +237,38 @@ func (rr *MINFO) parse(c *zlexer, o, f string) *ParseError {
 
 	email, emailOk := toAbsoluteName(l.token, o)
 	if l.err || !emailOk {
-		return &ParseError{f, "bad MINFO Email", l}
+		return &ParseError{"", "bad MINFO Email", l}
 	}
 	rr.Email = email
 
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *MF) parse(c *zlexer, o, f string) *ParseError {
+func (rr *MF) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	rr.Mf = l.token
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return &ParseError{f, "bad MF Mf", l}
+		return &ParseError{"", "bad MF Mf", l}
 	}
 	rr.Mf = name
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *MD) parse(c *zlexer, o, f string) *ParseError {
+func (rr *MD) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	rr.Md = l.token
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return &ParseError{f, "bad MD Md", l}
+		return &ParseError{"", "bad MD Md", l}
 	}
 	rr.Md = name
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *MX) parse(c *zlexer, o, f string) *ParseError {
+func (rr *MX) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return &ParseError{f, "bad MX Pref", l}
+		return &ParseError{"", "bad MX Pref", l}
 	}
 	rr.Preference = uint16(i)
 
@@ -373,22 +278,18 @@ func (rr *MX) parse(c *zlexer, o, f string) *ParseError {
 
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return &ParseError{f, "bad MX Mx", l}
+		return &ParseError{"", "bad MX Mx", l}
 	}
 	rr.Mx = name
 
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *RT) parse(c *zlexer, o, f string) *ParseError {
+func (rr *RT) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil {
-		return &ParseError{f, "bad RT Preference", l}
+		return &ParseError{"", "bad RT Preference", l}
 	}
 	rr.Preference = uint16(i)
 
@@ -398,22 +299,18 @@ func (rr *RT) parse(c *zlexer, o, f string) *ParseError {
 
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return &ParseError{f, "bad RT Host", l}
+		return &ParseError{"", "bad RT Host", l}
 	}
 	rr.Host = name
 
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *AFSDB) parse(c *zlexer, o, f string) *ParseError {
+func (rr *AFSDB) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return &ParseError{f, "bad AFSDB Subtype", l}
+		return &ParseError{"", "bad AFSDB Subtype", l}
 	}
 	rr.Subtype = uint16(i)
 
@@ -423,34 +320,26 @@ func (rr *AFSDB) parse(c *zlexer, o, f string) *ParseError {
 
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return &ParseError{f, "bad AFSDB Hostname", l}
+		return &ParseError{"", "bad AFSDB Hostname", l}
 	}
 	rr.Hostname = name
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *X25) parse(c *zlexer, o, f string) *ParseError {
+func (rr *X25) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	if l.err {
-		return &ParseError{f, "bad X25 PSDNAddress", l}
+		return &ParseError{"", "bad X25 PSDNAddress", l}
 	}
 	rr.PSDNAddress = l.token
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *KX) parse(c *zlexer, o, f string) *ParseError {
+func (rr *KX) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return &ParseError{f, "bad KX Pref", l}
+		return &ParseError{"", "bad KX Pref", l}
 	}
 	rr.Preference = uint16(i)
 
@@ -460,52 +349,37 @@ func (rr *KX) parse(c *zlexer, o, f string) *ParseError {
 
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return &ParseError{f, "bad KX Exchanger", l}
+		return &ParseError{"", "bad KX Exchanger", l}
 	}
 	rr.Exchanger = name
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *CNAME) parse(c *zlexer, o, f string) *ParseError {
+func (rr *CNAME) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	rr.Target = l.token
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return &ParseError{f, "bad CNAME Target", l}
+		return &ParseError{"", "bad CNAME Target", l}
 	}
 	rr.Target = name
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *DNAME) parse(c *zlexer, o, f string) *ParseError {
+func (rr *DNAME) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	rr.Target = l.token
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return &ParseError{f, "bad DNAME Target", l}
+		return &ParseError{"", "bad DNAME Target", l}
 	}
 	rr.Target = name
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *SOA) parse(c *zlexer, o, f string) *ParseError {
+func (rr *SOA) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	rr.Ns = l.token
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	ns, nsOk := toAbsoluteName(l.token, o)
 	if l.err || !nsOk {
-		return &ParseError{f, "bad SOA Ns", l}
+		return &ParseError{"", "bad SOA Ns", l}
 	}
 	rr.Ns = ns
 
@@ -515,7 +389,7 @@ func (rr *SOA) parse(c *zlexer, o, f string) *ParseError {
 
 	mbox, mboxOk := toAbsoluteName(l.token, o)
 	if l.err || !mboxOk {
-		return &ParseError{f, "bad SOA Mbox", l}
+		return &ParseError{"", "bad SOA Mbox", l}
 	}
 	rr.Mbox = mbox
 
@@ -528,16 +402,16 @@ func (rr *SOA) parse(c *zlexer, o, f string) *ParseError {
 	for i := 0; i < 5; i++ {
 		l, _ = c.Next()
 		if l.err {
-			return &ParseError{f, "bad SOA zone parameter", l}
+			return &ParseError{"", "bad SOA zone parameter", l}
 		}
-		if j, e := strconv.ParseUint(l.token, 10, 32); e != nil {
+		if j, err := strconv.ParseUint(l.token, 10, 32); err != nil {
 			if i == 0 {
 				// Serial must be a number
-				return &ParseError{f, "bad SOA zone parameter", l}
+				return &ParseError{"", "bad SOA zone parameter", l}
 			}
 			// We allow other fields to be unitful duration strings
 			if v, ok = stringToTTL(l.token); !ok {
-				return &ParseError{f, "bad SOA zone parameter", l}
+				return &ParseError{"", "bad SOA zone parameter", l}
 
 			}
 		} else {
@@ -560,34 +434,30 @@ func (rr *SOA) parse(c *zlexer, o, f string) *ParseError {
 			rr.Minttl = v
 		}
 	}
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *SRV) parse(c *zlexer, o, f string) *ParseError {
+func (rr *SRV) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return &ParseError{f, "bad SRV Priority", l}
+		return &ParseError{"", "bad SRV Priority", l}
 	}
 	rr.Priority = uint16(i)
 
 	c.Next()        // zBlank
 	l, _ = c.Next() // zString
-	i, e = strconv.ParseUint(l.token, 10, 16)
-	if e != nil || l.err {
-		return &ParseError{f, "bad SRV Weight", l}
+	i, e1 := strconv.ParseUint(l.token, 10, 16)
+	if e1 != nil || l.err {
+		return &ParseError{"", "bad SRV Weight", l}
 	}
 	rr.Weight = uint16(i)
 
 	c.Next()        // zBlank
 	l, _ = c.Next() // zString
-	i, e = strconv.ParseUint(l.token, 10, 16)
-	if e != nil || l.err {
-		return &ParseError{f, "bad SRV Port", l}
+	i, e2 := strconv.ParseUint(l.token, 10, 16)
+	if e2 != nil || l.err {
+		return &ParseError{"", "bad SRV Port", l}
 	}
 	rr.Port = uint16(i)
 
@@ -597,29 +467,25 @@ func (rr *SRV) parse(c *zlexer, o, f string) *ParseError {
 
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return &ParseError{f, "bad SRV Target", l}
+		return &ParseError{"", "bad SRV Target", l}
 	}
 	rr.Target = name
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *NAPTR) parse(c *zlexer, o, f string) *ParseError {
+func (rr *NAPTR) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return &ParseError{f, "bad NAPTR Order", l}
+		return &ParseError{"", "bad NAPTR Order", l}
 	}
 	rr.Order = uint16(i)
 
 	c.Next()        // zBlank
 	l, _ = c.Next() // zString
-	i, e = strconv.ParseUint(l.token, 10, 16)
-	if e != nil || l.err {
-		return &ParseError{f, "bad NAPTR Preference", l}
+	i, e1 := strconv.ParseUint(l.token, 10, 16)
+	if e1 != nil || l.err {
+		return &ParseError{"", "bad NAPTR Preference", l}
 	}
 	rr.Preference = uint16(i)
 
@@ -627,57 +493,57 @@ func (rr *NAPTR) parse(c *zlexer, o, f string) *ParseError {
 	c.Next()        // zBlank
 	l, _ = c.Next() // _QUOTE
 	if l.value != zQuote {
-		return &ParseError{f, "bad NAPTR Flags", l}
+		return &ParseError{"", "bad NAPTR Flags", l}
 	}
 	l, _ = c.Next() // Either String or Quote
 	if l.value == zString {
 		rr.Flags = l.token
 		l, _ = c.Next() // _QUOTE
 		if l.value != zQuote {
-			return &ParseError{f, "bad NAPTR Flags", l}
+			return &ParseError{"", "bad NAPTR Flags", l}
 		}
 	} else if l.value == zQuote {
 		rr.Flags = ""
 	} else {
-		return &ParseError{f, "bad NAPTR Flags", l}
+		return &ParseError{"", "bad NAPTR Flags", l}
 	}
 
 	// Service
 	c.Next()        // zBlank
 	l, _ = c.Next() // _QUOTE
 	if l.value != zQuote {
-		return &ParseError{f, "bad NAPTR Service", l}
+		return &ParseError{"", "bad NAPTR Service", l}
 	}
 	l, _ = c.Next() // Either String or Quote
 	if l.value == zString {
 		rr.Service = l.token
 		l, _ = c.Next() // _QUOTE
 		if l.value != zQuote {
-			return &ParseError{f, "bad NAPTR Service", l}
+			return &ParseError{"", "bad NAPTR Service", l}
 		}
 	} else if l.value == zQuote {
 		rr.Service = ""
 	} else {
-		return &ParseError{f, "bad NAPTR Service", l}
+		return &ParseError{"", "bad NAPTR Service", l}
 	}
 
 	// Regexp
 	c.Next()        // zBlank
 	l, _ = c.Next() // _QUOTE
 	if l.value != zQuote {
-		return &ParseError{f, "bad NAPTR Regexp", l}
+		return &ParseError{"", "bad NAPTR Regexp", l}
 	}
 	l, _ = c.Next() // Either String or Quote
 	if l.value == zString {
 		rr.Regexp = l.token
 		l, _ = c.Next() // _QUOTE
 		if l.value != zQuote {
-			return &ParseError{f, "bad NAPTR Regexp", l}
+			return &ParseError{"", "bad NAPTR Regexp", l}
 		}
 	} else if l.value == zQuote {
 		rr.Regexp = ""
 	} else {
-		return &ParseError{f, "bad NAPTR Regexp", l}
+		return &ParseError{"", "bad NAPTR Regexp", l}
 	}
 
 	// After quote no space??
@@ -687,22 +553,17 @@ func (rr *NAPTR) parse(c *zlexer, o, f string) *ParseError {
 
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return &ParseError{f, "bad NAPTR Replacement", l}
+		return &ParseError{"", "bad NAPTR Replacement", l}
 	}
 	rr.Replacement = name
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *TALINK) parse(c *zlexer, o, f string) *ParseError {
+func (rr *TALINK) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	rr.PreviousName = l.token
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	previousName, previousNameOk := toAbsoluteName(l.token, o)
 	if l.err || !previousNameOk {
-		return &ParseError{f, "bad TALINK PreviousName", l}
+		return &ParseError{"", "bad TALINK PreviousName", l}
 	}
 	rr.PreviousName = previousName
 
@@ -712,28 +573,25 @@ func (rr *TALINK) parse(c *zlexer, o, f string) *ParseError {
 
 	nextName, nextNameOk := toAbsoluteName(l.token, o)
 	if l.err || !nextNameOk {
-		return &ParseError{f, "bad TALINK NextName", l}
+		return &ParseError{"", "bad TALINK NextName", l}
 	}
 	rr.NextName = nextName
 
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *LOC) parse(c *zlexer, o, f string) *ParseError {
+func (rr *LOC) parse(c *zlexer, o string) *ParseError {
 	// Non zero defaults for LOC record, see RFC 1876, Section 3.
-	rr.HorizPre = 165 // 10000
-	rr.VertPre = 162  // 10
-	rr.Size = 18      // 1
+	rr.Size = 0x12     // 1e2 cm (1m)
+	rr.HorizPre = 0x16 // 1e6 cm (10000m)
+	rr.VertPre = 0x13  // 1e3 cm (10m)
 	ok := false
 
 	// North
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return nil
-	}
 	i, e := strconv.ParseUint(l.token, 10, 32)
-	if e != nil || l.err {
-		return &ParseError{f, "bad LOC Latitude", l}
+	if e != nil || l.err || i > 90 {
+		return &ParseError{"", "bad LOC Latitude", l}
 	}
 	rr.Latitude = 1000 * 60 * 60 * uint32(i)
 
@@ -743,16 +601,16 @@ func (rr *LOC) parse(c *zlexer, o, f string) *ParseError {
 	if rr.Latitude, ok = locCheckNorth(l.token, rr.Latitude); ok {
 		goto East
 	}
-	i, e = strconv.ParseUint(l.token, 10, 32)
-	if e != nil || l.err {
-		return &ParseError{f, "bad LOC Latitude minutes", l}
+	if i, err := strconv.ParseUint(l.token, 10, 32); err != nil || l.err || i > 59 {
+		return &ParseError{"", "bad LOC Latitude minutes", l}
+	} else {
+		rr.Latitude += 1000 * 60 * uint32(i)
 	}
-	rr.Latitude += 1000 * 60 * uint32(i)
 
 	c.Next() // zBlank
 	l, _ = c.Next()
-	if i, e := strconv.ParseFloat(l.token, 32); e != nil || l.err {
-		return &ParseError{f, "bad LOC Latitude seconds", l}
+	if i, err := strconv.ParseFloat(l.token, 32); err != nil || l.err || i < 0 || i >= 60 {
+		return &ParseError{"", "bad LOC Latitude seconds", l}
 	} else {
 		rr.Latitude += uint32(1000 * i)
 	}
@@ -763,14 +621,14 @@ func (rr *LOC) parse(c *zlexer, o, f string) *ParseError {
 		goto East
 	}
 	// If still alive, flag an error
-	return &ParseError{f, "bad LOC Latitude North/South", l}
+	return &ParseError{"", "bad LOC Latitude North/South", l}
 
 East:
 	// East
 	c.Next() // zBlank
 	l, _ = c.Next()
-	if i, e := strconv.ParseUint(l.token, 10, 32); e != nil || l.err {
-		return &ParseError{f, "bad LOC Longitude", l}
+	if i, err := strconv.ParseUint(l.token, 10, 32); err != nil || l.err || i > 180 {
+		return &ParseError{"", "bad LOC Longitude", l}
 	} else {
 		rr.Longitude = 1000 * 60 * 60 * uint32(i)
 	}
@@ -780,15 +638,15 @@ East:
 	if rr.Longitude, ok = locCheckEast(l.token, rr.Longitude); ok {
 		goto Altitude
 	}
-	if i, e := strconv.ParseUint(l.token, 10, 32); e != nil || l.err {
-		return &ParseError{f, "bad LOC Longitude minutes", l}
+	if i, err := strconv.ParseUint(l.token, 10, 32); err != nil || l.err || i > 59 {
+		return &ParseError{"", "bad LOC Longitude minutes", l}
 	} else {
 		rr.Longitude += 1000 * 60 * uint32(i)
 	}
 	c.Next() // zBlank
 	l, _ = c.Next()
-	if i, e := strconv.ParseFloat(l.token, 32); e != nil || l.err {
-		return &ParseError{f, "bad LOC Longitude seconds", l}
+	if i, err := strconv.ParseFloat(l.token, 32); err != nil || l.err || i < 0 || i >= 60 {
+		return &ParseError{"", "bad LOC Longitude seconds", l}
 	} else {
 		rr.Longitude += uint32(1000 * i)
 	}
@@ -799,19 +657,19 @@ East:
 		goto Altitude
 	}
 	// If still alive, flag an error
-	return &ParseError{f, "bad LOC Longitude East/West", l}
+	return &ParseError{"", "bad LOC Longitude East/West", l}
 
 Altitude:
 	c.Next() // zBlank
 	l, _ = c.Next()
 	if len(l.token) == 0 || l.err {
-		return &ParseError{f, "bad LOC Altitude", l}
+		return &ParseError{"", "bad LOC Altitude", l}
 	}
 	if l.token[len(l.token)-1] == 'M' || l.token[len(l.token)-1] == 'm' {
 		l.token = l.token[0 : len(l.token)-1]
 	}
-	if i, e := strconv.ParseFloat(l.token, 32); e != nil {
-		return &ParseError{f, "bad LOC Altitude", l}
+	if i, err := strconv.ParseFloat(l.token, 64); err != nil {
+		return &ParseError{"", "bad LOC Altitude", l}
 	} else {
 		rr.Altitude = uint32(i*100.0 + 10000000.0 + 0.5)
 	}
@@ -824,52 +682,48 @@ Altitude:
 		case zString:
 			switch count {
 			case 0: // Size
-				e, m, ok := stringToCm(l.token)
+				exp, m, ok := stringToCm(l.token)
 				if !ok {
-					return &ParseError{f, "bad LOC Size", l}
+					return &ParseError{"", "bad LOC Size", l}
 				}
-				rr.Size = e&0x0f | m<<4&0xf0
+				rr.Size = exp&0x0f | m<<4&0xf0
 			case 1: // HorizPre
-				e, m, ok := stringToCm(l.token)
+				exp, m, ok := stringToCm(l.token)
 				if !ok {
-					return &ParseError{f, "bad LOC HorizPre", l}
+					return &ParseError{"", "bad LOC HorizPre", l}
 				}
-				rr.HorizPre = e&0x0f | m<<4&0xf0
+				rr.HorizPre = exp&0x0f | m<<4&0xf0
 			case 2: // VertPre
-				e, m, ok := stringToCm(l.token)
+				exp, m, ok := stringToCm(l.token)
 				if !ok {
-					return &ParseError{f, "bad LOC VertPre", l}
+					return &ParseError{"", "bad LOC VertPre", l}
 				}
-				rr.VertPre = e&0x0f | m<<4&0xf0
+				rr.VertPre = exp&0x0f | m<<4&0xf0
 			}
 			count++
 		case zBlank:
 			// Ok
 		default:
-			return &ParseError{f, "bad LOC Size, HorizPre or VertPre", l}
+			return &ParseError{"", "bad LOC Size, HorizPre or VertPre", l}
 		}
 		l, _ = c.Next()
 	}
 	return nil
 }
 
-func (rr *HIP) parse(c *zlexer, o, f string) *ParseError {
+func (rr *HIP) parse(c *zlexer, o string) *ParseError {
 	// HitLength is not represented
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return nil
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 8)
 	if e != nil || l.err {
-		return &ParseError{f, "bad HIP PublicKeyAlgorithm", l}
+		return &ParseError{"", "bad HIP PublicKeyAlgorithm", l}
 	}
 	rr.PublicKeyAlgorithm = uint8(i)
 
 	c.Next()        // zBlank
 	l, _ = c.Next() // zString
 	if len(l.token) == 0 || l.err {
-		return &ParseError{f, "bad HIP Hit", l}
+		return &ParseError{"", "bad HIP Hit", l}
 	}
 	rr.Hit = l.token // This can not contain spaces, see RFC 5205 Section 6.
 	rr.HitLength = uint8(len(rr.Hit)) / 2
@@ -877,7 +731,7 @@ func (rr *HIP) parse(c *zlexer, o, f string) *ParseError {
 	c.Next()        // zBlank
 	l, _ = c.Next() // zString
 	if len(l.token) == 0 || l.err {
-		return &ParseError{f, "bad HIP PublicKey", l}
+		return &ParseError{"", "bad HIP PublicKey", l}
 	}
 	rr.PublicKey = l.token // This cannot contain spaces
 	rr.PublicKeyLength = uint16(base64.StdEncoding.DecodedLen(len(rr.PublicKey)))
@@ -890,13 +744,13 @@ func (rr *HIP) parse(c *zlexer, o, f string) *ParseError {
 		case zString:
 			name, nameOk := toAbsoluteName(l.token, o)
 			if l.err || !nameOk {
-				return &ParseError{f, "bad HIP RendezvousServers", l}
+				return &ParseError{"", "bad HIP RendezvousServers", l}
 			}
 			xs = append(xs, name)
 		case zBlank:
 			// Ok
 		default:
-			return &ParseError{f, "bad HIP RendezvousServers", l}
+			return &ParseError{"", "bad HIP RendezvousServers", l}
 		}
 		l, _ = c.Next()
 	}
@@ -905,16 +759,12 @@ func (rr *HIP) parse(c *zlexer, o, f string) *ParseError {
 	return nil
 }
 
-func (rr *CERT) parse(c *zlexer, o, f string) *ParseError {
+func (rr *CERT) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return nil
-	}
-
 	if v, ok := StringToCertType[l.token]; ok {
 		rr.Type = v
-	} else if i, e := strconv.ParseUint(l.token, 10, 16); e != nil {
-		return &ParseError{f, "bad CERT Type", l}
+	} else if i, err := strconv.ParseUint(l.token, 10, 16); err != nil {
+		return &ParseError{"", "bad CERT Type", l}
 	} else {
 		rr.Type = uint16(i)
 	}
@@ -922,19 +772,19 @@ func (rr *CERT) parse(c *zlexer, o, f string) *ParseError {
 	l, _ = c.Next() // zString
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return &ParseError{f, "bad CERT KeyTag", l}
+		return &ParseError{"", "bad CERT KeyTag", l}
 	}
 	rr.KeyTag = uint16(i)
 	c.Next()        // zBlank
 	l, _ = c.Next() // zString
 	if v, ok := StringToAlgorithm[l.token]; ok {
 		rr.Algorithm = v
-	} else if i, e := strconv.ParseUint(l.token, 10, 8); e != nil {
-		return &ParseError{f, "bad CERT Algorithm", l}
+	} else if i, err := strconv.ParseUint(l.token, 10, 8); err != nil {
+		return &ParseError{"", "bad CERT Algorithm", l}
 	} else {
 		rr.Algorithm = uint8(i)
 	}
-	s, e1 := endingToString(c, "bad CERT Certificate", f)
+	s, e1 := endingToString(c, "bad CERT Certificate")
 	if e1 != nil {
 		return e1
 	}
@@ -942,8 +792,8 @@ func (rr *CERT) parse(c *zlexer, o, f string) *ParseError {
 	return nil
 }
 
-func (rr *OPENPGPKEY) parse(c *zlexer, o, f string) *ParseError {
-	s, e := endingToString(c, "bad OPENPGPKEY PublicKey", f)
+func (rr *OPENPGPKEY) parse(c *zlexer, o string) *ParseError {
+	s, e := endingToString(c, "bad OPENPGPKEY PublicKey")
 	if e != nil {
 		return e
 	}
@@ -951,25 +801,22 @@ func (rr *OPENPGPKEY) parse(c *zlexer, o, f string) *ParseError {
 	return nil
 }
 
-func (rr *CSYNC) parse(c *zlexer, o, f string) *ParseError {
+func (rr *CSYNC) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return nil
-	}
 	j, e := strconv.ParseUint(l.token, 10, 32)
 	if e != nil {
 		// Serial must be a number
-		return &ParseError{f, "bad CSYNC serial", l}
+		return &ParseError{"", "bad CSYNC serial", l}
 	}
 	rr.Serial = uint32(j)
 
 	c.Next() // zBlank
 
 	l, _ = c.Next()
-	j, e = strconv.ParseUint(l.token, 10, 16)
-	if e != nil {
+	j, e1 := strconv.ParseUint(l.token, 10, 16)
+	if e1 != nil {
 		// Serial must be a number
-		return &ParseError{f, "bad CSYNC flags", l}
+		return &ParseError{"", "bad CSYNC flags", l}
 	}
 	rr.Flags = uint16(j)
 
@@ -987,38 +834,32 @@ func (rr *CSYNC) parse(c *zlexer, o, f string) *ParseError {
 			tokenUpper := strings.ToUpper(l.token)
 			if k, ok = StringToType[tokenUpper]; !ok {
 				if k, ok = typeToInt(l.token); !ok {
-					return &ParseError{f, "bad CSYNC TypeBitMap", l}
+					return &ParseError{"", "bad CSYNC TypeBitMap", l}
 				}
 			}
 			rr.TypeBitMap = append(rr.TypeBitMap, k)
 		default:
-			return &ParseError{f, "bad CSYNC TypeBitMap", l}
+			return &ParseError{"", "bad CSYNC TypeBitMap", l}
 		}
 		l, _ = c.Next()
 	}
 	return nil
 }
 
-func (rr *SIG) parse(c *zlexer, o, f string) *ParseError {
-	return rr.RRSIG.parse(c, o, f)
-}
+func (rr *SIG) parse(c *zlexer, o string) *ParseError { return rr.RRSIG.parse(c, o) }
 
-func (rr *RRSIG) parse(c *zlexer, o, f string) *ParseError {
+func (rr *RRSIG) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return nil
-	}
-
 	tokenUpper := strings.ToUpper(l.token)
 	if t, ok := StringToType[tokenUpper]; !ok {
 		if strings.HasPrefix(tokenUpper, "TYPE") {
 			t, ok = typeToInt(l.token)
 			if !ok {
-				return &ParseError{f, "bad RRSIG Typecovered", l}
+				return &ParseError{"", "bad RRSIG Typecovered", l}
 			}
 			rr.TypeCovered = t
 		} else {
-			return &ParseError{f, "bad RRSIG Typecovered", l}
+			return &ParseError{"", "bad RRSIG Typecovered", l}
 		}
 	} else {
 		rr.TypeCovered = t
@@ -1026,25 +867,25 @@ func (rr *RRSIG) parse(c *zlexer, o, f string) *ParseError {
 
 	c.Next() // zBlank
 	l, _ = c.Next()
-	i, err := strconv.ParseUint(l.token, 10, 8)
-	if err != nil || l.err {
-		return &ParseError{f, "bad RRSIG Algorithm", l}
+	i, e := strconv.ParseUint(l.token, 10, 8)
+	if e != nil || l.err {
+		return &ParseError{"", "bad RRSIG Algorithm", l}
 	}
 	rr.Algorithm = uint8(i)
 
 	c.Next() // zBlank
 	l, _ = c.Next()
-	i, err = strconv.ParseUint(l.token, 10, 8)
-	if err != nil || l.err {
-		return &ParseError{f, "bad RRSIG Labels", l}
+	i, e1 := strconv.ParseUint(l.token, 10, 8)
+	if e1 != nil || l.err {
+		return &ParseError{"", "bad RRSIG Labels", l}
 	}
 	rr.Labels = uint8(i)
 
 	c.Next() // zBlank
 	l, _ = c.Next()
-	i, err = strconv.ParseUint(l.token, 10, 32)
-	if err != nil || l.err {
-		return &ParseError{f, "bad RRSIG OrigTtl", l}
+	i, e2 := strconv.ParseUint(l.token, 10, 32)
+	if e2 != nil || l.err {
+		return &ParseError{"", "bad RRSIG OrigTtl", l}
 	}
 	rr.OrigTtl = uint32(i)
 
@@ -1052,11 +893,10 @@ func (rr *RRSIG) parse(c *zlexer, o, f string) *ParseError {
 	l, _ = c.Next()
 	if i, err := StringToTime(l.token); err != nil {
 		// Try to see if all numeric and use it as epoch
-		if i, err := strconv.ParseInt(l.token, 10, 64); err == nil {
-			// TODO(miek): error out on > MAX_UINT32, same below
+		if i, err := strconv.ParseUint(l.token, 10, 32); err == nil {
 			rr.Expiration = uint32(i)
 		} else {
-			return &ParseError{f, "bad RRSIG Expiration", l}
+			return &ParseError{"", "bad RRSIG Expiration", l}
 		}
 	} else {
 		rr.Expiration = i
@@ -1065,10 +905,10 @@ func (rr *RRSIG) parse(c *zlexer, o, f string) *ParseError {
 	c.Next() // zBlank
 	l, _ = c.Next()
 	if i, err := StringToTime(l.token); err != nil {
-		if i, err := strconv.ParseInt(l.token, 10, 64); err == nil {
+		if i, err := strconv.ParseUint(l.token, 10, 32); err == nil {
 			rr.Inception = uint32(i)
 		} else {
-			return &ParseError{f, "bad RRSIG Inception", l}
+			return &ParseError{"", "bad RRSIG Inception", l}
 		}
 	} else {
 		rr.Inception = i
@@ -1076,9 +916,9 @@ func (rr *RRSIG) parse(c *zlexer, o, f string) *ParseError {
 
 	c.Next() // zBlank
 	l, _ = c.Next()
-	i, err = strconv.ParseUint(l.token, 10, 16)
-	if err != nil || l.err {
-		return &ParseError{f, "bad RRSIG KeyTag", l}
+	i, e3 := strconv.ParseUint(l.token, 10, 16)
+	if e3 != nil || l.err {
+		return &ParseError{"", "bad RRSIG KeyTag", l}
 	}
 	rr.KeyTag = uint16(i)
 
@@ -1087,29 +927,24 @@ func (rr *RRSIG) parse(c *zlexer, o, f string) *ParseError {
 	rr.SignerName = l.token
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return &ParseError{f, "bad RRSIG SignerName", l}
+		return &ParseError{"", "bad RRSIG SignerName", l}
 	}
 	rr.SignerName = name
 
-	s, e := endingToString(c, "bad RRSIG Signature", f)
-	if e != nil {
-		return e
+	s, e4 := endingToString(c, "bad RRSIG Signature")
+	if e4 != nil {
+		return e4
 	}
 	rr.Signature = s
 
 	return nil
 }
 
-func (rr *NSEC) parse(c *zlexer, o, f string) *ParseError {
+func (rr *NSEC) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	rr.NextDomain = l.token
-	if len(l.token) == 0 { // dynamic update rr.
-		return nil
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return &ParseError{f, "bad NSEC NextDomain", l}
+		return &ParseError{"", "bad NSEC NextDomain", l}
 	}
 	rr.NextDomain = name
 
@@ -1127,47 +962,43 @@ func (rr *NSEC) parse(c *zlexer, o, f string) *ParseError {
 			tokenUpper := strings.ToUpper(l.token)
 			if k, ok = StringToType[tokenUpper]; !ok {
 				if k, ok = typeToInt(l.token); !ok {
-					return &ParseError{f, "bad NSEC TypeBitMap", l}
+					return &ParseError{"", "bad NSEC TypeBitMap", l}
 				}
 			}
 			rr.TypeBitMap = append(rr.TypeBitMap, k)
 		default:
-			return &ParseError{f, "bad NSEC TypeBitMap", l}
+			return &ParseError{"", "bad NSEC TypeBitMap", l}
 		}
 		l, _ = c.Next()
 	}
 	return nil
 }
 
-func (rr *NSEC3) parse(c *zlexer, o, f string) *ParseError {
+func (rr *NSEC3) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return nil
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 8)
 	if e != nil || l.err {
-		return &ParseError{f, "bad NSEC3 Hash", l}
+		return &ParseError{"", "bad NSEC3 Hash", l}
 	}
 	rr.Hash = uint8(i)
 	c.Next() // zBlank
 	l, _ = c.Next()
-	i, e = strconv.ParseUint(l.token, 10, 8)
-	if e != nil || l.err {
-		return &ParseError{f, "bad NSEC3 Flags", l}
+	i, e1 := strconv.ParseUint(l.token, 10, 8)
+	if e1 != nil || l.err {
+		return &ParseError{"", "bad NSEC3 Flags", l}
 	}
 	rr.Flags = uint8(i)
 	c.Next() // zBlank
 	l, _ = c.Next()
-	i, e = strconv.ParseUint(l.token, 10, 16)
-	if e != nil || l.err {
-		return &ParseError{f, "bad NSEC3 Iterations", l}
+	i, e2 := strconv.ParseUint(l.token, 10, 16)
+	if e2 != nil || l.err {
+		return &ParseError{"", "bad NSEC3 Iterations", l}
 	}
 	rr.Iterations = uint16(i)
 	c.Next()
 	l, _ = c.Next()
 	if len(l.token) == 0 || l.err {
-		return &ParseError{f, "bad NSEC3 Salt", l}
+		return &ParseError{"", "bad NSEC3 Salt", l}
 	}
 	if l.token != "-" {
 		rr.SaltLength = uint8(len(l.token)) / 2
@@ -1177,7 +1008,7 @@ func (rr *NSEC3) parse(c *zlexer, o, f string) *ParseError {
 	c.Next()
 	l, _ = c.Next()
 	if len(l.token) == 0 || l.err {
-		return &ParseError{f, "bad NSEC3 NextDomain", l}
+		return &ParseError{"", "bad NSEC3 NextDomain", l}
 	}
 	rr.HashLength = 20 // Fix for NSEC3 (sha1 160 bits)
 	rr.NextDomain = l.token
@@ -1196,60 +1027,52 @@ func (rr *NSEC3) parse(c *zlexer, o, f string) *ParseError {
 			tokenUpper := strings.ToUpper(l.token)
 			if k, ok = StringToType[tokenUpper]; !ok {
 				if k, ok = typeToInt(l.token); !ok {
-					return &ParseError{f, "bad NSEC3 TypeBitMap", l}
+					return &ParseError{"", "bad NSEC3 TypeBitMap", l}
 				}
 			}
 			rr.TypeBitMap = append(rr.TypeBitMap, k)
 		default:
-			return &ParseError{f, "bad NSEC3 TypeBitMap", l}
+			return &ParseError{"", "bad NSEC3 TypeBitMap", l}
 		}
 		l, _ = c.Next()
 	}
 	return nil
 }
 
-func (rr *NSEC3PARAM) parse(c *zlexer, o, f string) *ParseError {
+func (rr *NSEC3PARAM) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 8)
 	if e != nil || l.err {
-		return &ParseError{f, "bad NSEC3PARAM Hash", l}
+		return &ParseError{"", "bad NSEC3PARAM Hash", l}
 	}
 	rr.Hash = uint8(i)
 	c.Next() // zBlank
 	l, _ = c.Next()
-	i, e = strconv.ParseUint(l.token, 10, 8)
-	if e != nil || l.err {
-		return &ParseError{f, "bad NSEC3PARAM Flags", l}
+	i, e1 := strconv.ParseUint(l.token, 10, 8)
+	if e1 != nil || l.err {
+		return &ParseError{"", "bad NSEC3PARAM Flags", l}
 	}
 	rr.Flags = uint8(i)
 	c.Next() // zBlank
 	l, _ = c.Next()
-	i, e = strconv.ParseUint(l.token, 10, 16)
-	if e != nil || l.err {
-		return &ParseError{f, "bad NSEC3PARAM Iterations", l}
+	i, e2 := strconv.ParseUint(l.token, 10, 16)
+	if e2 != nil || l.err {
+		return &ParseError{"", "bad NSEC3PARAM Iterations", l}
 	}
 	rr.Iterations = uint16(i)
 	c.Next()
 	l, _ = c.Next()
 	if l.token != "-" {
-		rr.SaltLength = uint8(len(l.token))
+		rr.SaltLength = uint8(len(l.token) / 2)
 		rr.Salt = l.token
 	}
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *EUI48) parse(c *zlexer, o, f string) *ParseError {
+func (rr *EUI48) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	if len(l.token) != 17 || l.err {
-		return &ParseError{f, "bad EUI48 Address", l}
+		return &ParseError{"", "bad EUI48 Address", l}
 	}
 	addr := make([]byte, 12)
 	dash := 0
@@ -1258,7 +1081,7 @@ func (rr *EUI48) parse(c *zlexer, o, f string) *ParseError {
 		addr[i+1] = l.token[i+1+dash]
 		dash++
 		if l.token[i+1+dash] != '-' {
-			return &ParseError{f, "bad EUI48 Address", l}
+			return &ParseError{"", "bad EUI48 Address", l}
 		}
 	}
 	addr[10] = l.token[15]
@@ -1266,20 +1089,16 @@ func (rr *EUI48) parse(c *zlexer, o, f string) *ParseError {
 
 	i, e := strconv.ParseUint(string(addr), 16, 48)
 	if e != nil {
-		return &ParseError{f, "bad EUI48 Address", l}
+		return &ParseError{"", "bad EUI48 Address", l}
 	}
 	rr.Address = i
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *EUI64) parse(c *zlexer, o, f string) *ParseError {
+func (rr *EUI64) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	if len(l.token) != 23 || l.err {
-		return &ParseError{f, "bad EUI64 Address", l}
+		return &ParseError{"", "bad EUI64 Address", l}
 	}
 	addr := make([]byte, 16)
 	dash := 0
@@ -1288,7 +1107,7 @@ func (rr *EUI64) parse(c *zlexer, o, f string) *ParseError {
 		addr[i+1] = l.token[i+1+dash]
 		dash++
 		if l.token[i+1+dash] != '-' {
-			return &ParseError{f, "bad EUI64 Address", l}
+			return &ParseError{"", "bad EUI64 Address", l}
 		}
 	}
 	addr[14] = l.token[21]
@@ -1296,119 +1115,102 @@ func (rr *EUI64) parse(c *zlexer, o, f string) *ParseError {
 
 	i, e := strconv.ParseUint(string(addr), 16, 64)
 	if e != nil {
-		return &ParseError{f, "bad EUI68 Address", l}
+		return &ParseError{"", "bad EUI68 Address", l}
 	}
 	rr.Address = i
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *SSHFP) parse(c *zlexer, o, f string) *ParseError {
+func (rr *SSHFP) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return nil
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 8)
 	if e != nil || l.err {
-		return &ParseError{f, "bad SSHFP Algorithm", l}
+		return &ParseError{"", "bad SSHFP Algorithm", l}
 	}
 	rr.Algorithm = uint8(i)
 	c.Next() // zBlank
 	l, _ = c.Next()
-	i, e = strconv.ParseUint(l.token, 10, 8)
-	if e != nil || l.err {
-		return &ParseError{f, "bad SSHFP Type", l}
+	i, e1 := strconv.ParseUint(l.token, 10, 8)
+	if e1 != nil || l.err {
+		return &ParseError{"", "bad SSHFP Type", l}
 	}
 	rr.Type = uint8(i)
 	c.Next() // zBlank
-	s, e1 := endingToString(c, "bad SSHFP Fingerprint", f)
-	if e1 != nil {
-		return e1
+	s, e2 := endingToString(c, "bad SSHFP Fingerprint")
+	if e2 != nil {
+		return e2
 	}
 	rr.FingerPrint = s
 	return nil
 }
 
-func (rr *DNSKEY) parseDNSKEY(c *zlexer, o, f, typ string) *ParseError {
+func (rr *DNSKEY) parseDNSKEY(c *zlexer, o, typ string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return nil
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return &ParseError{f, "bad " + typ + " Flags", l}
+		return &ParseError{"", "bad " + typ + " Flags", l}
 	}
 	rr.Flags = uint16(i)
 	c.Next()        // zBlank
 	l, _ = c.Next() // zString
-	i, e = strconv.ParseUint(l.token, 10, 8)
-	if e != nil || l.err {
-		return &ParseError{f, "bad " + typ + " Protocol", l}
+	i, e1 := strconv.ParseUint(l.token, 10, 8)
+	if e1 != nil || l.err {
+		return &ParseError{"", "bad " + typ + " Protocol", l}
 	}
 	rr.Protocol = uint8(i)
 	c.Next()        // zBlank
 	l, _ = c.Next() // zString
-	i, e = strconv.ParseUint(l.token, 10, 8)
-	if e != nil || l.err {
-		return &ParseError{f, "bad " + typ + " Algorithm", l}
+	i, e2 := strconv.ParseUint(l.token, 10, 8)
+	if e2 != nil || l.err {
+		return &ParseError{"", "bad " + typ + " Algorithm", l}
 	}
 	rr.Algorithm = uint8(i)
-	s, e1 := endingToString(c, "bad "+typ+" PublicKey", f)
-	if e1 != nil {
-		return e1
+	s, e3 := endingToString(c, "bad "+typ+" PublicKey")
+	if e3 != nil {
+		return e3
 	}
 	rr.PublicKey = s
 	return nil
 }
 
-func (rr *DNSKEY) parse(c *zlexer, o, f string) *ParseError {
-	return rr.parseDNSKEY(c, o, f, "DNSKEY")
-}
-
-func (rr *KEY) parse(c *zlexer, o, f string) *ParseError {
-	return rr.parseDNSKEY(c, o, f, "KEY")
-}
-
-func (rr *CDNSKEY) parse(c *zlexer, o, f string) *ParseError {
-	return rr.parseDNSKEY(c, o, f, "CDNSKEY")
-}
+func (rr *DNSKEY) parse(c *zlexer, o string) *ParseError  { return rr.parseDNSKEY(c, o, "DNSKEY") }
+func (rr *KEY) parse(c *zlexer, o string) *ParseError     { return rr.parseDNSKEY(c, o, "KEY") }
+func (rr *CDNSKEY) parse(c *zlexer, o string) *ParseError { return rr.parseDNSKEY(c, o, "CDNSKEY") }
+func (rr *DS) parse(c *zlexer, o string) *ParseError      { return rr.parseDS(c, o, "DS") }
+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 *RKEY) parse(c *zlexer, o, f string) *ParseError {
+func (rr *RKEY) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return nil
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return &ParseError{f, "bad RKEY Flags", l}
+		return &ParseError{"", "bad RKEY Flags", l}
 	}
 	rr.Flags = uint16(i)
 	c.Next()        // zBlank
 	l, _ = c.Next() // zString
-	i, e = strconv.ParseUint(l.token, 10, 8)
-	if e != nil || l.err {
-		return &ParseError{f, "bad RKEY Protocol", l}
+	i, e1 := strconv.ParseUint(l.token, 10, 8)
+	if e1 != nil || l.err {
+		return &ParseError{"", "bad RKEY Protocol", l}
 	}
 	rr.Protocol = uint8(i)
 	c.Next()        // zBlank
 	l, _ = c.Next() // zString
-	i, e = strconv.ParseUint(l.token, 10, 8)
-	if e != nil || l.err {
-		return &ParseError{f, "bad RKEY Algorithm", l}
+	i, e2 := strconv.ParseUint(l.token, 10, 8)
+	if e2 != nil || l.err {
+		return &ParseError{"", "bad RKEY Algorithm", l}
 	}
 	rr.Algorithm = uint8(i)
-	s, e1 := endingToString(c, "bad RKEY PublicKey", f)
-	if e1 != nil {
-		return e1
+	s, e3 := endingToString(c, "bad RKEY PublicKey")
+	if e3 != nil {
+		return e3
 	}
 	rr.PublicKey = s
 	return nil
 }
 
-func (rr *EID) parse(c *zlexer, o, f string) *ParseError {
-	s, e := endingToString(c, "bad EID Endpoint", f)
+func (rr *EID) parse(c *zlexer, o string) *ParseError {
+	s, e := endingToString(c, "bad EID Endpoint")
 	if e != nil {
 		return e
 	}
@@ -1416,8 +1218,8 @@ func (rr *EID) parse(c *zlexer, o, f string) *ParseError {
 	return nil
 }
 
-func (rr *NIMLOC) parse(c *zlexer, o, f string) *ParseError {
-	s, e := endingToString(c, "bad NIMLOC Locator", f)
+func (rr *NIMLOC) parse(c *zlexer, o string) *ParseError {
+	s, e := endingToString(c, "bad NIMLOC Locator")
 	if e != nil {
 		return e
 	}
@@ -1425,52 +1227,44 @@ func (rr *NIMLOC) parse(c *zlexer, o, f string) *ParseError {
 	return nil
 }
 
-func (rr *GPOS) parse(c *zlexer, o, f string) *ParseError {
+func (rr *GPOS) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	_, e := strconv.ParseFloat(l.token, 64)
 	if e != nil || l.err {
-		return &ParseError{f, "bad GPOS Longitude", l}
+		return &ParseError{"", "bad GPOS Longitude", l}
 	}
 	rr.Longitude = l.token
 	c.Next() // zBlank
 	l, _ = c.Next()
-	_, e = strconv.ParseFloat(l.token, 64)
-	if e != nil || l.err {
-		return &ParseError{f, "bad GPOS Latitude", l}
+	_, e1 := strconv.ParseFloat(l.token, 64)
+	if e1 != nil || l.err {
+		return &ParseError{"", "bad GPOS Latitude", l}
 	}
 	rr.Latitude = l.token
 	c.Next() // zBlank
 	l, _ = c.Next()
-	_, e = strconv.ParseFloat(l.token, 64)
-	if e != nil || l.err {
-		return &ParseError{f, "bad GPOS Altitude", l}
+	_, e2 := strconv.ParseFloat(l.token, 64)
+	if e2 != nil || l.err {
+		return &ParseError{"", "bad GPOS Altitude", l}
 	}
 	rr.Altitude = l.token
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *DS) parseDS(c *zlexer, o, f, typ string) *ParseError {
+func (rr *DS) parseDS(c *zlexer, o, typ string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return nil
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return &ParseError{f, "bad " + typ + " KeyTag", l}
+		return &ParseError{"", "bad " + typ + " KeyTag", l}
 	}
 	rr.KeyTag = uint16(i)
 	c.Next() // zBlank
 	l, _ = c.Next()
-	if i, e = strconv.ParseUint(l.token, 10, 8); e != nil {
+	if i, err := strconv.ParseUint(l.token, 10, 8); err != nil {
 		tokenUpper := strings.ToUpper(l.token)
 		i, ok := StringToAlgorithm[tokenUpper]
 		if !ok || l.err {
-			return &ParseError{f, "bad " + typ + " Algorithm", l}
+			return &ParseError{"", "bad " + typ + " Algorithm", l}
 		}
 		rr.Algorithm = i
 	} else {
@@ -1478,49 +1272,33 @@ func (rr *DS) parseDS(c *zlexer, o, f, typ string) *ParseError {
 	}
 	c.Next() // zBlank
 	l, _ = c.Next()
-	i, e = strconv.ParseUint(l.token, 10, 8)
-	if e != nil || l.err {
-		return &ParseError{f, "bad " + typ + " DigestType", l}
+	i, e1 := strconv.ParseUint(l.token, 10, 8)
+	if e1 != nil || l.err {
+		return &ParseError{"", "bad " + typ + " DigestType", l}
 	}
 	rr.DigestType = uint8(i)
-	s, e1 := endingToString(c, "bad "+typ+" Digest", f)
-	if e1 != nil {
-		return e1
+	s, e2 := endingToString(c, "bad "+typ+" Digest")
+	if e2 != nil {
+		return e2
 	}
 	rr.Digest = s
 	return nil
 }
 
-func (rr *DS) parse(c *zlexer, o, f string) *ParseError {
-	return rr.parseDS(c, o, f, "DS")
-}
-
-func (rr *DLV) parse(c *zlexer, o, f string) *ParseError {
-	return rr.parseDS(c, o, f, "DLV")
-}
-
-func (rr *CDS) parse(c *zlexer, o, f string) *ParseError {
-	return rr.parseDS(c, o, f, "CDS")
-}
-
-func (rr *TA) parse(c *zlexer, o, f string) *ParseError {
+func (rr *TA) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return nil
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return &ParseError{f, "bad TA KeyTag", l}
+		return &ParseError{"", "bad TA KeyTag", l}
 	}
 	rr.KeyTag = uint16(i)
 	c.Next() // zBlank
 	l, _ = c.Next()
-	if i, e := strconv.ParseUint(l.token, 10, 8); e != nil {
+	if i, err := strconv.ParseUint(l.token, 10, 8); err != nil {
 		tokenUpper := strings.ToUpper(l.token)
 		i, ok := StringToAlgorithm[tokenUpper]
 		if !ok || l.err {
-			return &ParseError{f, "bad TA Algorithm", l}
+			return &ParseError{"", "bad TA Algorithm", l}
 		}
 		rr.Algorithm = i
 	} else {
@@ -1528,113 +1306,105 @@ func (rr *TA) parse(c *zlexer, o, f string) *ParseError {
 	}
 	c.Next() // zBlank
 	l, _ = c.Next()
-	i, e = strconv.ParseUint(l.token, 10, 8)
-	if e != nil || l.err {
-		return &ParseError{f, "bad TA DigestType", l}
+	i, e1 := strconv.ParseUint(l.token, 10, 8)
+	if e1 != nil || l.err {
+		return &ParseError{"", "bad TA DigestType", l}
 	}
 	rr.DigestType = uint8(i)
-	s, err := endingToString(c, "bad TA Digest", f)
-	if err != nil {
-		return err
+	s, e2 := endingToString(c, "bad TA Digest")
+	if e2 != nil {
+		return e2
 	}
 	rr.Digest = s
 	return nil
 }
 
-func (rr *TLSA) parse(c *zlexer, o, f string) *ParseError {
+func (rr *TLSA) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return nil
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 8)
 	if e != nil || l.err {
-		return &ParseError{f, "bad TLSA Usage", l}
+		return &ParseError{"", "bad TLSA Usage", l}
 	}
 	rr.Usage = uint8(i)
 	c.Next() // zBlank
 	l, _ = c.Next()
-	i, e = strconv.ParseUint(l.token, 10, 8)
-	if e != nil || l.err {
-		return &ParseError{f, "bad TLSA Selector", l}
+	i, e1 := strconv.ParseUint(l.token, 10, 8)
+	if e1 != nil || l.err {
+		return &ParseError{"", "bad TLSA Selector", l}
 	}
 	rr.Selector = uint8(i)
 	c.Next() // zBlank
 	l, _ = c.Next()
-	i, e = strconv.ParseUint(l.token, 10, 8)
-	if e != nil || l.err {
-		return &ParseError{f, "bad TLSA MatchingType", l}
+	i, e2 := strconv.ParseUint(l.token, 10, 8)
+	if e2 != nil || l.err {
+		return &ParseError{"", "bad TLSA MatchingType", l}
 	}
 	rr.MatchingType = uint8(i)
 	// So this needs be e2 (i.e. different than e), because...??t
-	s, e2 := endingToString(c, "bad TLSA Certificate", f)
-	if e2 != nil {
-		return e2
+	s, e3 := endingToString(c, "bad TLSA Certificate")
+	if e3 != nil {
+		return e3
 	}
 	rr.Certificate = s
 	return nil
 }
 
-func (rr *SMIMEA) parse(c *zlexer, o, f string) *ParseError {
+func (rr *SMIMEA) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return nil
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 8)
 	if e != nil || l.err {
-		return &ParseError{f, "bad SMIMEA Usage", l}
+		return &ParseError{"", "bad SMIMEA Usage", l}
 	}
 	rr.Usage = uint8(i)
 	c.Next() // zBlank
 	l, _ = c.Next()
-	i, e = strconv.ParseUint(l.token, 10, 8)
-	if e != nil || l.err {
-		return &ParseError{f, "bad SMIMEA Selector", l}
+	i, e1 := strconv.ParseUint(l.token, 10, 8)
+	if e1 != nil || l.err {
+		return &ParseError{"", "bad SMIMEA Selector", l}
 	}
 	rr.Selector = uint8(i)
 	c.Next() // zBlank
 	l, _ = c.Next()
-	i, e = strconv.ParseUint(l.token, 10, 8)
-	if e != nil || l.err {
-		return &ParseError{f, "bad SMIMEA MatchingType", l}
+	i, e2 := strconv.ParseUint(l.token, 10, 8)
+	if e2 != nil || l.err {
+		return &ParseError{"", "bad SMIMEA MatchingType", l}
 	}
 	rr.MatchingType = uint8(i)
 	// So this needs be e2 (i.e. different than e), because...??t
-	s, e2 := endingToString(c, "bad SMIMEA Certificate", f)
-	if e2 != nil {
-		return e2
+	s, e3 := endingToString(c, "bad SMIMEA Certificate")
+	if e3 != nil {
+		return e3
 	}
 	rr.Certificate = s
 	return nil
 }
 
-func (rr *RFC3597) parse(c *zlexer, o, f string) *ParseError {
+func (rr *RFC3597) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
 	if l.token != "\\#" {
-		return &ParseError{f, "bad RFC3597 Rdata", l}
+		return &ParseError{"", "bad RFC3597 Rdata", l}
 	}
 
 	c.Next() // zBlank
 	l, _ = c.Next()
 	rdlength, e := strconv.Atoi(l.token)
 	if e != nil || l.err {
-		return &ParseError{f, "bad RFC3597 Rdata ", l}
+		return &ParseError{"", "bad RFC3597 Rdata ", l}
 	}
 
-	s, e1 := endingToString(c, "bad RFC3597 Rdata", f)
+	s, e1 := endingToString(c, "bad RFC3597 Rdata")
 	if e1 != nil {
 		return e1
 	}
 	if rdlength*2 != len(s) {
-		return &ParseError{f, "bad RFC3597 Rdata", l}
+		return &ParseError{"", "bad RFC3597 Rdata", l}
 	}
 	rr.Rdata = s
 	return nil
 }
 
-func (rr *SPF) parse(c *zlexer, o, f string) *ParseError {
-	s, e := endingToTxtSlice(c, "bad SPF Txt", f)
+func (rr *SPF) parse(c *zlexer, o string) *ParseError {
+	s, e := endingToTxtSlice(c, "bad SPF Txt")
 	if e != nil {
 		return e
 	}
@@ -1642,8 +1412,8 @@ func (rr *SPF) parse(c *zlexer, o, f string) *ParseError {
 	return nil
 }
 
-func (rr *AVC) parse(c *zlexer, o, f string) *ParseError {
-	s, e := endingToTxtSlice(c, "bad AVC Txt", f)
+func (rr *AVC) parse(c *zlexer, o string) *ParseError {
+	s, e := endingToTxtSlice(c, "bad AVC Txt")
 	if e != nil {
 		return e
 	}
@@ -1651,9 +1421,9 @@ func (rr *AVC) parse(c *zlexer, o, f string) *ParseError {
 	return nil
 }
 
-func (rr *TXT) parse(c *zlexer, o, f string) *ParseError {
+func (rr *TXT) parse(c *zlexer, o string) *ParseError {
 	// no zBlank reading here, because all this rdata is TXT
-	s, e := endingToTxtSlice(c, "bad TXT Txt", f)
+	s, e := endingToTxtSlice(c, "bad TXT Txt")
 	if e != nil {
 		return e
 	}
@@ -1662,8 +1432,8 @@ func (rr *TXT) parse(c *zlexer, o, f string) *ParseError {
 }
 
 // identical to setTXT
-func (rr *NINFO) parse(c *zlexer, o, f string) *ParseError {
-	s, e := endingToTxtSlice(c, "bad NINFO ZSData", f)
+func (rr *NINFO) parse(c *zlexer, o string) *ParseError {
+	s, e := endingToTxtSlice(c, "bad NINFO ZSData")
 	if e != nil {
 		return e
 	}
@@ -1671,40 +1441,36 @@ func (rr *NINFO) parse(c *zlexer, o, f string) *ParseError {
 	return nil
 }
 
-func (rr *URI) parse(c *zlexer, o, f string) *ParseError {
+func (rr *URI) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return nil
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return &ParseError{f, "bad URI Priority", l}
+		return &ParseError{"", "bad URI Priority", l}
 	}
 	rr.Priority = uint16(i)
 	c.Next() // zBlank
 	l, _ = c.Next()
-	i, e = strconv.ParseUint(l.token, 10, 16)
-	if e != nil || l.err {
-		return &ParseError{f, "bad URI Weight", l}
+	i, e1 := strconv.ParseUint(l.token, 10, 16)
+	if e1 != nil || l.err {
+		return &ParseError{"", "bad URI Weight", l}
 	}
 	rr.Weight = uint16(i)
 
 	c.Next() // zBlank
-	s, err := endingToTxtSlice(c, "bad URI Target", f)
-	if err != nil {
-		return err
+	s, e2 := endingToTxtSlice(c, "bad URI Target")
+	if e2 != nil {
+		return e2
 	}
 	if len(s) != 1 {
-		return &ParseError{f, "bad URI Target", l}
+		return &ParseError{"", "bad URI Target", l}
 	}
 	rr.Target = s[0]
 	return nil
 }
 
-func (rr *DHCID) parse(c *zlexer, o, f string) *ParseError {
+func (rr *DHCID) parse(c *zlexer, o string) *ParseError {
 	// awesome record to parse!
-	s, e := endingToString(c, "bad DHCID Digest", f)
+	s, e := endingToString(c, "bad DHCID Digest")
 	if e != nil {
 		return e
 	}
@@ -1712,56 +1478,44 @@ func (rr *DHCID) parse(c *zlexer, o, f string) *ParseError {
 	return nil
 }
 
-func (rr *NID) parse(c *zlexer, o, f string) *ParseError {
+func (rr *NID) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return &ParseError{f, "bad NID Preference", l}
+		return &ParseError{"", "bad NID Preference", l}
 	}
 	rr.Preference = uint16(i)
 	c.Next()        // zBlank
 	l, _ = c.Next() // zString
-	u, err := stringToNodeID(l)
-	if err != nil || l.err {
-		return err
+	u, e1 := stringToNodeID(l)
+	if e1 != nil || l.err {
+		return e1
 	}
 	rr.NodeID = u
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *L32) parse(c *zlexer, o, f string) *ParseError {
+func (rr *L32) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return &ParseError{f, "bad L32 Preference", l}
+		return &ParseError{"", "bad L32 Preference", l}
 	}
 	rr.Preference = uint16(i)
 	c.Next()        // zBlank
 	l, _ = c.Next() // zString
 	rr.Locator32 = net.ParseIP(l.token)
 	if rr.Locator32 == nil || l.err {
-		return &ParseError{f, "bad L32 Locator", l}
+		return &ParseError{"", "bad L32 Locator", l}
 	}
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *LP) parse(c *zlexer, o, f string) *ParseError {
+func (rr *LP) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return &ParseError{f, "bad LP Preference", l}
+		return &ParseError{"", "bad LP Preference", l}
 	}
 	rr.Preference = uint16(i)
 
@@ -1770,64 +1524,51 @@ func (rr *LP) parse(c *zlexer, o, f string) *ParseError {
 	rr.Fqdn = l.token
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return &ParseError{f, "bad LP Fqdn", l}
+		return &ParseError{"", "bad LP Fqdn", l}
 	}
 	rr.Fqdn = name
-
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *L64) parse(c *zlexer, o, f string) *ParseError {
+func (rr *L64) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return &ParseError{f, "bad L64 Preference", l}
+		return &ParseError{"", "bad L64 Preference", l}
 	}
 	rr.Preference = uint16(i)
 	c.Next()        // zBlank
 	l, _ = c.Next() // zString
-	u, err := stringToNodeID(l)
-	if err != nil || l.err {
-		return err
+	u, e1 := stringToNodeID(l)
+	if e1 != nil || l.err {
+		return e1
 	}
 	rr.Locator64 = u
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *UID) parse(c *zlexer, o, f string) *ParseError {
+func (rr *UID) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 32)
 	if e != nil || l.err {
-		return &ParseError{f, "bad UID Uid", l}
+		return &ParseError{"", "bad UID Uid", l}
 	}
 	rr.Uid = uint32(i)
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *GID) parse(c *zlexer, o, f string) *ParseError {
+func (rr *GID) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 32)
 	if e != nil || l.err {
-		return &ParseError{f, "bad GID Gid", l}
+		return &ParseError{"", "bad GID Gid", l}
 	}
 	rr.Gid = uint32(i)
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *UINFO) parse(c *zlexer, o, f string) *ParseError {
-	s, e := endingToTxtSlice(c, "bad UINFO Uinfo", f)
+func (rr *UINFO) parse(c *zlexer, o string) *ParseError {
+	s, e := endingToTxtSlice(c, "bad UINFO Uinfo")
 	if e != nil {
 		return e
 	}
@@ -1838,15 +1579,11 @@ func (rr *UINFO) parse(c *zlexer, o, f string) *ParseError {
 	return nil
 }
 
-func (rr *PX) parse(c *zlexer, o, f string) *ParseError {
+func (rr *PX) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return slurpRemainder(c, f)
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return &ParseError{f, "bad PX Preference", l}
+		return &ParseError{"", "bad PX Preference", l}
 	}
 	rr.Preference = uint16(i)
 
@@ -1855,7 +1592,7 @@ func (rr *PX) parse(c *zlexer, o, f string) *ParseError {
 	rr.Map822 = l.token
 	map822, map822Ok := toAbsoluteName(l.token, o)
 	if l.err || !map822Ok {
-		return &ParseError{f, "bad PX Map822", l}
+		return &ParseError{"", "bad PX Map822", l}
 	}
 	rr.Map822 = map822
 
@@ -1864,82 +1601,142 @@ func (rr *PX) parse(c *zlexer, o, f string) *ParseError {
 	rr.Mapx400 = l.token
 	mapx400, mapx400Ok := toAbsoluteName(l.token, o)
 	if l.err || !mapx400Ok {
-		return &ParseError{f, "bad PX Mapx400", l}
+		return &ParseError{"", "bad PX Mapx400", l}
 	}
 	rr.Mapx400 = mapx400
-
-	return slurpRemainder(c, f)
+	return slurpRemainder(c)
 }
 
-func (rr *CAA) parse(c *zlexer, o, f string) *ParseError {
+func (rr *CAA) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return nil
-	}
-
-	i, err := strconv.ParseUint(l.token, 10, 8)
-	if err != nil || l.err {
-		return &ParseError{f, "bad CAA Flag", l}
+	i, e := strconv.ParseUint(l.token, 10, 8)
+	if e != nil || l.err {
+		return &ParseError{"", "bad CAA Flag", l}
 	}
 	rr.Flag = uint8(i)
 
 	c.Next()        // zBlank
 	l, _ = c.Next() // zString
 	if l.value != zString {
-		return &ParseError{f, "bad CAA Tag", l}
+		return &ParseError{"", "bad CAA Tag", l}
 	}
 	rr.Tag = l.token
 
 	c.Next() // zBlank
-	s, e := endingToTxtSlice(c, "bad CAA Value", f)
-	if e != nil {
-		return e
+	s, e1 := endingToTxtSlice(c, "bad CAA Value")
+	if e1 != nil {
+		return e1
 	}
 	if len(s) != 1 {
-		return &ParseError{f, "bad CAA Value", l}
+		return &ParseError{"", "bad CAA Value", l}
 	}
 	rr.Value = s[0]
 	return nil
 }
 
-func (rr *TKEY) parse(c *zlexer, o, f string) *ParseError {
+func (rr *TKEY) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
 
 	// Algorithm
 	if l.value != zString {
-		return &ParseError{f, "bad TKEY algorithm", l}
+		return &ParseError{"", "bad TKEY algorithm", l}
 	}
 	rr.Algorithm = l.token
 	c.Next() // zBlank
 
 	// Get the key length and key values
 	l, _ = c.Next()
-	i, err := strconv.ParseUint(l.token, 10, 8)
-	if err != nil || l.err {
-		return &ParseError{f, "bad TKEY key length", l}
+	i, e := strconv.ParseUint(l.token, 10, 8)
+	if e != nil || l.err {
+		return &ParseError{"", "bad TKEY key length", l}
 	}
 	rr.KeySize = uint16(i)
 	c.Next() // zBlank
 	l, _ = c.Next()
 	if l.value != zString {
-		return &ParseError{f, "bad TKEY key", l}
+		return &ParseError{"", "bad TKEY key", l}
 	}
 	rr.Key = l.token
 	c.Next() // zBlank
 
 	// Get the otherdata length and string data
 	l, _ = c.Next()
-	i, err = strconv.ParseUint(l.token, 10, 8)
-	if err != nil || l.err {
-		return &ParseError{f, "bad TKEY otherdata length", l}
+	i, e1 := strconv.ParseUint(l.token, 10, 8)
+	if e1 != nil || l.err {
+		return &ParseError{"", "bad TKEY otherdata length", l}
 	}
 	rr.OtherLen = uint16(i)
 	c.Next() // zBlank
 	l, _ = c.Next()
 	if l.value != zString {
-		return &ParseError{f, "bad TKEY otherday", l}
+		return &ParseError{"", "bad TKEY otherday", l}
 	}
 	rr.OtherData = l.token
+	return nil
+}
+
+func (rr *APL) parse(c *zlexer, o string) *ParseError {
+	var prefixes []APLPrefix
+
+	for {
+		l, _ := c.Next()
+		if l.value == zNewline || l.value == zEOF {
+			break
+		}
+		if l.value == zBlank && prefixes != nil {
+			continue
+		}
+		if l.value != zString {
+			return &ParseError{"", "unexpected APL field", l}
+		}
+
+		// Expected format: [!]afi:address/prefix
+
+		colon := strings.IndexByte(l.token, ':')
+		if colon == -1 {
+			return &ParseError{"", "missing colon in APL field", l}
+		}
+
+		family, cidr := l.token[:colon], l.token[colon+1:]
+
+		var negation bool
+		if family != "" && family[0] == '!' {
+			negation = true
+			family = family[1:]
+		}
+
+		afi, e := strconv.ParseUint(family, 10, 16)
+		if e != nil {
+			return &ParseError{"", "failed to parse APL family: " + e.Error(), l}
+		}
+		var addrLen int
+		switch afi {
+		case 1:
+			addrLen = net.IPv4len
+		case 2:
+			addrLen = net.IPv6len
+		default:
+			return &ParseError{"", "unrecognized APL family", l}
+		}
+
+		ip, subnet, e1 := net.ParseCIDR(cidr)
+		if e1 != nil {
+			return &ParseError{"", "failed to parse APL address: " + e1.Error(), l}
+		}
+		if !ip.Equal(subnet.IP) {
+			return &ParseError{"", "extra bits in APL address", l}
+		}
+
+		if len(subnet.IP) != addrLen {
+			return &ParseError{"", "address mismatch with the APL family", l}
+		}
+
+		prefixes = append(prefixes, APLPrefix{
+			Negation: negation,
+			Network:  *subnet,
+		})
+	}
 
+	rr.Prefixes = prefixes
 	return nil
 }
diff --git a/vendor/github.com/miekg/dns/serve_mux.go b/vendor/github.com/miekg/dns/serve_mux.go
index ae304db530a53d0120fdf0f67626ea28bc5e5dc8..e7f36e221824f1395cba7f4782f9d624fe09fed3 100644
--- a/vendor/github.com/miekg/dns/serve_mux.go
+++ b/vendor/github.com/miekg/dns/serve_mux.go
@@ -1,7 +1,6 @@
 package dns
 
 import (
-	"strings"
 	"sync"
 )
 
@@ -36,33 +35,9 @@ func (mux *ServeMux) match(q string, t uint16) Handler {
 		return nil
 	}
 
-	var handler Handler
-
-	// TODO(tmthrgd): Once https://go-review.googlesource.com/c/go/+/137575
-	// lands in a go release, replace the following with strings.ToLower.
-	var sb strings.Builder
-	for i := 0; i < len(q); i++ {
-		c := q[i]
-		if !(c >= 'A' && c <= 'Z') {
-			continue
-		}
-
-		sb.Grow(len(q))
-		sb.WriteString(q[:i])
-
-		for ; i < len(q); i++ {
-			c := q[i]
-			if c >= 'A' && c <= 'Z' {
-				c += 'a' - 'A'
-			}
-
-			sb.WriteByte(c)
-		}
-
-		q = sb.String()
-		break
-	}
+	q = CanonicalName(q)
 
+	var handler Handler
 	for off, end := 0, false; !end; off, end = NextLabel(q, off) {
 		if h, ok := mux.z[q[off:]]; ok {
 			if t != TypeDS {
@@ -90,7 +65,7 @@ func (mux *ServeMux) Handle(pattern string, handler Handler) {
 	if mux.z == nil {
 		mux.z = make(map[string]Handler)
 	}
-	mux.z[Fqdn(pattern)] = handler
+	mux.z[CanonicalName(pattern)] = handler
 	mux.m.Unlock()
 }
 
@@ -105,7 +80,7 @@ func (mux *ServeMux) HandleRemove(pattern string) {
 		panic("dns: invalid pattern " + pattern)
 	}
 	mux.m.Lock()
-	delete(mux.z, Fqdn(pattern))
+	delete(mux.z, CanonicalName(pattern))
 	mux.m.Unlock()
 }
 
@@ -116,7 +91,7 @@ func (mux *ServeMux) HandleRemove(pattern string) {
 // are redirected to the parent zone (if that is also registered),
 // otherwise the child gets the query.
 //
-// If no handler is found, or there is no question, a standard SERVFAIL
+// If no handler is found, or there is no question, a standard REFUSED
 // message is returned
 func (mux *ServeMux) ServeDNS(w ResponseWriter, req *Msg) {
 	var h Handler
@@ -127,7 +102,7 @@ func (mux *ServeMux) ServeDNS(w ResponseWriter, req *Msg) {
 	if h != nil {
 		h.ServeDNS(w, req)
 	} else {
-		HandleFailed(w, req)
+		handleRefused(w, req)
 	}
 }
 
diff --git a/vendor/github.com/miekg/dns/server.go b/vendor/github.com/miekg/dns/server.go
index b09d37172ae8ecc04cf9df07c579d4795fc98f8c..30dfd41def49c454d47752020bab32716678aba5 100644
--- a/vendor/github.com/miekg/dns/server.go
+++ b/vendor/github.com/miekg/dns/server.go
@@ -72,13 +72,22 @@ type response struct {
 	tsigStatus     error
 	tsigRequestMAC string
 	tsigSecret     map[string]string // the tsig secrets
-	udp            *net.UDPConn      // i/o connection if UDP was used
+	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.
+func handleRefused(w ResponseWriter, r *Msg) {
+	m := new(Msg)
+	m.SetRcode(r, RcodeRefused)
+	w.WriteMsg(m)
+}
+
 // HandleFailed returns a HandlerFunc that returns SERVFAIL for every request it gets.
+// Deprecated: This function is going away.
 func HandleFailed(w ResponseWriter, r *Msg) {
 	m := new(Msg)
 	m.SetRcode(r, RcodeServerFailure)
@@ -139,12 +148,24 @@ type Reader interface {
 	ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error)
 }
 
-// defaultReader is an adapter for the Server struct that implements the Reader interface
-// using the readTCP and readUDP func of the embedded Server.
+// PacketConnReader is an optional interface that Readers can implement to support using generic net.PacketConns.
+type PacketConnReader interface {
+	Reader
+
+	// ReadPacketConn reads a raw message from a generic net.PacketConn UDP connection. Implementations may
+	// alter connection properties, for example the read-deadline.
+	ReadPacketConn(conn net.PacketConn, timeout time.Duration) ([]byte, net.Addr, error)
+}
+
+// defaultReader is an adapter for the Server struct that implements the Reader and
+// PacketConnReader interfaces using the readTCP, readUDP and readPacketConn funcs
+// of the embedded Server.
 type defaultReader struct {
 	*Server
 }
 
+var _ PacketConnReader = defaultReader{}
+
 func (dr defaultReader) ReadTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
 	return dr.readTCP(conn, timeout)
 }
@@ -153,8 +174,14 @@ func (dr defaultReader) ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byt
 	return dr.readUDP(conn, timeout)
 }
 
+func (dr defaultReader) ReadPacketConn(conn net.PacketConn, timeout time.Duration) ([]byte, net.Addr, error) {
+	return dr.readPacketConn(conn, timeout)
+}
+
 // DecorateReader is a decorator hook for extending or supplanting the functionality of a Reader.
 // Implementations should never return a nil Reader.
+// Readers should also implement the optional PacketConnReader interface.
+// PacketConnReader is required to use a generic net.PacketConn.
 type DecorateReader func(Reader) Reader
 
 // DecorateWriter is a decorator hook for extending or supplanting the functionality of a Writer.
@@ -317,24 +344,22 @@ func (srv *Server) ActivateAndServe() error {
 
 	srv.init()
 
-	pConn := srv.PacketConn
-	l := srv.Listener
-	if pConn != nil {
+	if srv.PacketConn != nil {
 		// Check PacketConn interface's type is valid and value
 		// is not nil
-		if t, ok := pConn.(*net.UDPConn); ok && t != nil {
+		if t, ok := srv.PacketConn.(*net.UDPConn); ok && t != nil {
 			if e := setUDPSocketOptions(t); e != nil {
 				return e
 			}
-			srv.started = true
-			unlock()
-			return srv.serveUDP(t)
 		}
+		srv.started = true
+		unlock()
+		return srv.serveUDP(srv.PacketConn)
 	}
-	if l != nil {
+	if srv.Listener != nil {
 		srv.started = true
 		unlock()
-		return srv.serveTCP(l)
+		return srv.serveTCP(srv.Listener)
 	}
 	return &Error{err: "bad listeners"}
 }
@@ -438,18 +463,24 @@ func (srv *Server) serveTCP(l net.Listener) error {
 }
 
 // serveUDP starts a UDP listener for the server.
-func (srv *Server) serveUDP(l *net.UDPConn) error {
+func (srv *Server) serveUDP(l net.PacketConn) error {
 	defer l.Close()
 
-	if srv.NotifyStartedFunc != nil {
-		srv.NotifyStartedFunc()
-	}
-
 	reader := Reader(defaultReader{srv})
 	if srv.DecorateReader != nil {
 		reader = srv.DecorateReader(reader)
 	}
 
+	lUDP, isUDP := l.(*net.UDPConn)
+	readerPC, canPacketConn := reader.(PacketConnReader)
+	if !isUDP && !canPacketConn {
+		return &Error{err: "PacketConnReader was not implemented on Reader returned from DecorateReader but is required for net.PacketConn"}
+	}
+
+	if srv.NotifyStartedFunc != nil {
+		srv.NotifyStartedFunc()
+	}
+
 	var wg sync.WaitGroup
 	defer func() {
 		wg.Wait()
@@ -459,7 +490,17 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
 	rtimeout := srv.getReadTimeout()
 	// deadline is not used here
 	for srv.isStarted() {
-		m, s, err := reader.ReadUDP(l, rtimeout)
+		var (
+			m    []byte
+			sPC  net.Addr
+			sUDP *SessionUDP
+			err  error
+		)
+		if isUDP {
+			m, sUDP, err = reader.ReadUDP(lUDP, rtimeout)
+		} else {
+			m, sPC, err = readerPC.ReadPacketConn(l, rtimeout)
+		}
 		if err != nil {
 			if !srv.isStarted() {
 				return nil
@@ -476,7 +517,7 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
 			continue
 		}
 		wg.Add(1)
-		go srv.serveUDPPacket(&wg, m, l, s)
+		go srv.serveUDPPacket(&wg, m, l, sUDP, sPC)
 	}
 
 	return nil
@@ -538,8 +579,8 @@ func (srv *Server) serveTCPConn(wg *sync.WaitGroup, rw net.Conn) {
 }
 
 // Serve a new UDP request.
-func (srv *Server) serveUDPPacket(wg *sync.WaitGroup, m []byte, u *net.UDPConn, s *SessionUDP) {
-	w := &response{tsigSecret: srv.TsigSecret, udp: u, udpSession: s}
+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}
 	if srv.DecorateWriter != nil {
 		w.writer = srv.DecorateWriter(w)
 	} else {
@@ -560,26 +601,32 @@ func (srv *Server) serveDNS(m []byte, w *response) {
 	req := new(Msg)
 	req.setHdr(dh)
 
-	switch srv.MsgAcceptFunc(dh) {
+	switch action := srv.MsgAcceptFunc(dh); action {
 	case MsgAccept:
 		if req.unpack(dh, m, off) == nil {
 			break
 		}
 
 		fallthrough
-	case MsgReject:
+	case MsgReject, MsgRejectNotImplemented:
+		opcode := req.Opcode
 		req.SetRcodeFormatError(req)
+		req.Zero = false
+		if action == MsgRejectNotImplemented {
+			req.Opcode = opcode
+			req.Rcode = RcodeNotImplemented
+		}
+
 		// Are we allowed to delete any OPT records here?
 		req.Ns, req.Answer, req.Extra = nil, nil, nil
 
 		w.WriteMsg(req)
-
+		fallthrough
+	case MsgIgnore:
 		if w.udp != nil && cap(m) == srv.UDPSize {
 			srv.udpPool.Put(m[:srv.UDPSize])
 		}
 
-		return
-	case MsgIgnore:
 		return
 	}
 
@@ -645,6 +692,24 @@ func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *S
 	return m, s, nil
 }
 
+func (srv *Server) readPacketConn(conn net.PacketConn, timeout time.Duration) ([]byte, net.Addr, error) {
+	srv.lock.RLock()
+	if srv.started {
+		// See the comment in readTCP above.
+		conn.SetReadDeadline(time.Now().Add(timeout))
+	}
+	srv.lock.RUnlock()
+
+	m := srv.udpPool.Get().([]byte)
+	n, addr, err := conn.ReadFrom(m)
+	if err != nil {
+		srv.udpPool.Put(m)
+		return nil, nil, err
+	}
+	m = m[:n]
+	return m, addr, nil
+}
+
 // WriteMsg implements the ResponseWriter.WriteMsg method.
 func (w *response) WriteMsg(m *Msg) (err error) {
 	if w.closed {
@@ -678,7 +743,10 @@ func (w *response) Write(m []byte) (int, error) {
 
 	switch {
 	case w.udp != nil:
-		return WriteToSessionUDP(w.udp, m, w.udpSession)
+		if u, ok := w.udp.(*net.UDPConn); ok {
+			return WriteToSessionUDP(u, m, w.udpSession)
+		}
+		return w.udp.WriteTo(m, w.pcSession)
 	case w.tcp != nil:
 		if len(m) > MaxMsgSize {
 			return 0, &Error{err: "message too large"}
@@ -711,10 +779,12 @@ func (w *response) RemoteAddr() net.Addr {
 	switch {
 	case w.udpSession != nil:
 		return w.udpSession.RemoteAddr()
+	case w.pcSession != nil:
+		return w.pcSession
 	case w.tcp != nil:
 		return w.tcp.RemoteAddr()
 	default:
-		panic("dns: internal error: udpSession and tcp both nil")
+		panic("dns: internal error: udpSession, pcSession and tcp are all nil")
 	}
 }
 
diff --git a/vendor/github.com/miekg/dns/sig0.go b/vendor/github.com/miekg/dns/sig0.go
index 55cf1c3863ac219d40e26ea7695f169fe9f65dc0..9ef13ccf3926c7338fe3ab88e479cb4fdc55cef9 100644
--- a/vendor/github.com/miekg/dns/sig0.go
+++ b/vendor/github.com/miekg/dns/sig0.go
@@ -2,7 +2,6 @@ package dns
 
 import (
 	"crypto"
-	"crypto/dsa"
 	"crypto/ecdsa"
 	"crypto/rsa"
 	"encoding/binary"
@@ -85,7 +84,7 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
 
 	var hash crypto.Hash
 	switch rr.Algorithm {
-	case DSA, RSASHA1:
+	case RSASHA1:
 		hash = crypto.SHA1
 	case RSASHA256, ECDSAP256SHA256:
 		hash = crypto.SHA256
@@ -178,17 +177,6 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
 	hashed := hasher.Sum(nil)
 	sig := buf[sigend:]
 	switch k.Algorithm {
-	case DSA:
-		pk := k.publicKeyDSA()
-		sig = sig[1:]
-		r := new(big.Int).SetBytes(sig[:len(sig)/2])
-		s := new(big.Int).SetBytes(sig[len(sig)/2:])
-		if pk != nil {
-			if dsa.Verify(pk, hashed, r, s) {
-				return nil
-			}
-			return ErrSig
-		}
 	case RSASHA1, RSASHA256, RSASHA512:
 		pk := k.publicKeyRSA()
 		if pk != nil {
diff --git a/vendor/github.com/miekg/dns/svcb.go b/vendor/github.com/miekg/dns/svcb.go
new file mode 100644
index 0000000000000000000000000000000000000000..f44dc67d7b5098e0efd520c064396cfb93259c5c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/svcb.go
@@ -0,0 +1,744 @@
+package dns
+
+import (
+	"bytes"
+	"encoding/binary"
+	"errors"
+	"net"
+	"sort"
+	"strconv"
+	"strings"
+)
+
+type SVCBKey uint16
+
+// Keys defined in draft-ietf-dnsop-svcb-https-01 Section 12.3.2.
+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
+)
+
+var svcbKeyToStringMap = map[SVCBKey]string{
+	SVCB_MANDATORY:       "mandatory",
+	SVCB_ALPN:            "alpn",
+	SVCB_NO_DEFAULT_ALPN: "no-default-alpn",
+	SVCB_PORT:            "port",
+	SVCB_IPV4HINT:        "ipv4hint",
+	SVCB_ECHCONFIG:       "echconfig",
+	SVCB_IPV6HINT:        "ipv6hint",
+}
+
+var svcbStringToKeyMap = reverseSVCBKeyMap(svcbKeyToStringMap)
+
+func reverseSVCBKeyMap(m map[SVCBKey]string) map[string]SVCBKey {
+	n := make(map[string]SVCBKey, len(m))
+	for u, s := range m {
+		n[s] = u
+	}
+	return n
+}
+
+// String takes the numerical code of an SVCB key and returns its name.
+// Returns an empty string for reserved keys.
+// Accepts unassigned keys as well as experimental/private keys.
+func (key SVCBKey) String() string {
+	if x := svcbKeyToStringMap[key]; x != "" {
+		return x
+	}
+	if key == svcb_RESERVED {
+		return ""
+	}
+	return "key" + strconv.FormatUint(uint64(key), 10)
+}
+
+// svcbStringToKey returns the numerical code of an SVCB key.
+// Returns svcb_RESERVED for reserved/invalid keys.
+// Accepts unassigned keys as well as experimental/private keys.
+func svcbStringToKey(s string) SVCBKey {
+	if strings.HasPrefix(s, "key") {
+		a, err := strconv.ParseUint(s[3:], 10, 16)
+		// no leading zeros
+		// key shouldn't be registered
+		if err != nil || a == 65535 || s[3] == '0' || svcbKeyToStringMap[SVCBKey(a)] != "" {
+			return svcb_RESERVED
+		}
+		return SVCBKey(a)
+	}
+	if key, ok := svcbStringToKeyMap[s]; ok {
+		return key
+	}
+	return svcb_RESERVED
+}
+
+func (rr *SVCB) parse(c *zlexer, o string) *ParseError {
+	l, _ := c.Next()
+	i, e := strconv.ParseUint(l.token, 10, 16)
+	if e != nil || l.err {
+		return &ParseError{l.token, "bad SVCB priority", l}
+	}
+	rr.Priority = uint16(i)
+
+	c.Next()        // zBlank
+	l, _ = c.Next() // zString
+	rr.Target = l.token
+
+	name, nameOk := toAbsoluteName(l.token, o)
+	if l.err || !nameOk {
+		return &ParseError{l.token, "bad SVCB Target", l}
+	}
+	rr.Target = name
+
+	// Values (if any)
+	l, _ = c.Next()
+	var xs []SVCBKeyValue
+	// Helps require whitespace between pairs.
+	// Prevents key1000="a"key1001=...
+	canHaveNextKey := true
+	for l.value != zNewline && l.value != zEOF {
+		switch l.value {
+		case zString:
+			if !canHaveNextKey {
+				// The key we can now read was probably meant to be
+				// a part of the last value.
+				return &ParseError{l.token, "bad SVCB value quotation", l}
+			}
+
+			// In key=value pairs, value does not have to be quoted unless value
+			// contains whitespace. And keys don't need to have values.
+			// Similarly, keys with an equality signs after them don't need values.
+			// l.token includes at least up to the first equality sign.
+			idx := strings.IndexByte(l.token, '=')
+			var key, value string
+			if idx < 0 {
+				// Key with no value and no equality sign
+				key = l.token
+			} else if idx == 0 {
+				return &ParseError{l.token, "bad SVCB key", l}
+			} else {
+				key, value = l.token[:idx], l.token[idx+1:]
+
+				if value == "" {
+					// We have a key and an equality sign. Maybe we have nothing
+					// after "=" or we have a double quote.
+					l, _ = c.Next()
+					if l.value == zQuote {
+						// Only needed when value ends with double quotes.
+						// Any value starting with zQuote ends with it.
+						canHaveNextKey = false
+
+						l, _ = c.Next()
+						switch l.value {
+						case zString:
+							// We have a value in double quotes.
+							value = l.token
+							l, _ = c.Next()
+							if l.value != zQuote {
+								return &ParseError{l.token, "SVCB unterminated value", l}
+							}
+						case zQuote:
+							// There's nothing in double quotes.
+						default:
+							return &ParseError{l.token, "bad SVCB value", l}
+						}
+					}
+				}
+			}
+			kv := makeSVCBKeyValue(svcbStringToKey(key))
+			if kv == nil {
+				return &ParseError{l.token, "bad SVCB key", l}
+			}
+			if err := kv.parse(value); err != nil {
+				return &ParseError{l.token, err.Error(), l}
+			}
+			xs = append(xs, kv)
+		case zQuote:
+			return &ParseError{l.token, "SVCB key can't contain double quotes", l}
+		case zBlank:
+			canHaveNextKey = true
+		default:
+			return &ParseError{l.token, "bad SVCB values", l}
+		}
+		l, _ = c.Next()
+	}
+	rr.Value = xs
+	if rr.Priority == 0 && len(xs) > 0 {
+		return &ParseError{l.token, "SVCB aliasform can't have values", l}
+	}
+	return nil
+}
+
+// makeSVCBKeyValue returns an SVCBKeyValue struct with the key or nil for reserved keys.
+func makeSVCBKeyValue(key SVCBKey) SVCBKeyValue {
+	switch key {
+	case SVCB_MANDATORY:
+		return new(SVCBMandatory)
+	case SVCB_ALPN:
+		return new(SVCBAlpn)
+	case SVCB_NO_DEFAULT_ALPN:
+		return new(SVCBNoDefaultAlpn)
+	case SVCB_PORT:
+		return new(SVCBPort)
+	case SVCB_IPV4HINT:
+		return new(SVCBIPv4Hint)
+	case SVCB_ECHCONFIG:
+		return new(SVCBECHConfig)
+	case SVCB_IPV6HINT:
+		return new(SVCBIPv6Hint)
+	case svcb_RESERVED:
+		return nil
+	default:
+		e := new(SVCBLocal)
+		e.KeyCode = key
+		return e
+	}
+}
+
+// SVCB RR. See RFC xxxx (https://tools.ietf.org/html/draft-ietf-dnsop-svcb-https-01).
+type SVCB struct {
+	Hdr      RR_Header
+	Priority uint16
+	Target   string         `dns:"domain-name"`
+	Value    []SVCBKeyValue `dns:"pairs"` // Value must be empty if Priority is non-zero.
+}
+
+// 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.
+type HTTPS struct {
+	SVCB
+}
+
+func (rr *HTTPS) String() string {
+	return rr.SVCB.String()
+}
+
+func (rr *HTTPS) parse(c *zlexer, o string) *ParseError {
+	return rr.SVCB.parse(c, o)
+}
+
+// SVCBKeyValue defines a key=value pair for the SVCB RR type.
+// An SVCB RR can have multiple SVCBKeyValues appended to it.
+type SVCBKeyValue interface {
+	Key() SVCBKey          // Key returns the numerical key code.
+	pack() ([]byte, error) // pack returns the encoded value.
+	unpack([]byte) error   // unpack sets the value.
+	String() string        // String returns the string representation of the value.
+	parse(string) error    // parse sets the value to the given string representation of the value.
+	copy() SVCBKeyValue    // copy returns a deep-copy of the pair.
+	len() int              // len returns the length of value in the wire format.
+}
+
+// SVCBMandatory pair adds to required keys that must be interpreted for the RR
+// to be functional.
+// Basic use pattern for creating a mandatory option:
+//
+//	s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
+//	e := new(dns.SVCBMandatory)
+//	e.Code = []uint16{65403}
+//	s.Value = append(s.Value, e)
+type SVCBMandatory struct {
+	Code []SVCBKey // Must not include mandatory
+}
+
+func (*SVCBMandatory) Key() SVCBKey { return SVCB_MANDATORY }
+
+func (s *SVCBMandatory) String() string {
+	str := make([]string, len(s.Code))
+	for i, e := range s.Code {
+		str[i] = e.String()
+	}
+	return strings.Join(str, ",")
+}
+
+func (s *SVCBMandatory) pack() ([]byte, error) {
+	codes := append([]SVCBKey(nil), s.Code...)
+	sort.Slice(codes, func(i, j int) bool {
+		return codes[i] < codes[j]
+	})
+	b := make([]byte, 2*len(codes))
+	for i, e := range codes {
+		binary.BigEndian.PutUint16(b[2*i:], uint16(e))
+	}
+	return b, nil
+}
+
+func (s *SVCBMandatory) unpack(b []byte) error {
+	if len(b)%2 != 0 {
+		return errors.New("dns: svcbmandatory: value length is not a multiple of 2")
+	}
+	codes := make([]SVCBKey, 0, len(b)/2)
+	for i := 0; i < len(b); i += 2 {
+		// We assume strictly increasing order.
+		codes = append(codes, SVCBKey(binary.BigEndian.Uint16(b[i:])))
+	}
+	s.Code = codes
+	return nil
+}
+
+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))
+	}
+	s.Code = codes
+	return nil
+}
+
+func (s *SVCBMandatory) len() int {
+	return 2 * len(s.Code)
+}
+
+func (s *SVCBMandatory) copy() SVCBKeyValue {
+	return &SVCBMandatory{
+		append([]SVCBKey(nil), s.Code...),
+	}
+}
+
+// SVCBAlpn pair is used to list supported connection protocols.
+// Protocol ids can be found at:
+// https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids
+// Basic use pattern for creating an alpn option:
+//
+//	h := new(dns.HTTPS)
+//	h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
+//	e := new(dns.SVCBAlpn)
+//	e.Alpn = []string{"h2", "http/1.1"}
+//	h.Value = append(o.Value, e)
+type SVCBAlpn struct {
+	Alpn []string
+}
+
+func (*SVCBAlpn) Key() SVCBKey     { return SVCB_ALPN }
+func (s *SVCBAlpn) String() string { return strings.Join(s.Alpn, ",") }
+
+func (s *SVCBAlpn) pack() ([]byte, error) {
+	// Liberally estimate the size of an alpn as 10 octets
+	b := make([]byte, 0, 10*len(s.Alpn))
+	for _, e := range s.Alpn {
+		if len(e) == 0 {
+			return nil, errors.New("dns: svcbalpn: empty alpn-id")
+		}
+		if len(e) > 255 {
+			return nil, errors.New("dns: svcbalpn: alpn-id too long")
+		}
+		b = append(b, byte(len(e)))
+		b = append(b, e...)
+	}
+	return b, nil
+}
+
+func (s *SVCBAlpn) unpack(b []byte) error {
+	// Estimate the size of the smallest alpn as 4 bytes
+	alpn := make([]string, 0, len(b)/4)
+	for i := 0; i < len(b); {
+		length := int(b[i])
+		i++
+		if i+length > len(b) {
+			return errors.New("dns: svcbalpn: alpn array overflowing")
+		}
+		alpn = append(alpn, string(b[i:i+length]))
+		i += length
+	}
+	s.Alpn = alpn
+	return nil
+}
+
+func (s *SVCBAlpn) parse(b string) error {
+	s.Alpn = strings.Split(b, ",")
+	return nil
+}
+
+func (s *SVCBAlpn) len() int {
+	var l int
+	for _, e := range s.Alpn {
+		l += 1 + len(e)
+	}
+	return l
+}
+
+func (s *SVCBAlpn) copy() SVCBKeyValue {
+	return &SVCBAlpn{
+		append([]string(nil), s.Alpn...),
+	}
+}
+
+// SVCBNoDefaultAlpn pair signifies no support for default connection protocols.
+// Basic use pattern for creating a no-default-alpn option:
+//
+//	s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
+//	e := new(dns.SVCBNoDefaultAlpn)
+//	s.Value = append(s.Value, e)
+type SVCBNoDefaultAlpn struct{}
+
+func (*SVCBNoDefaultAlpn) Key() SVCBKey          { return SVCB_NO_DEFAULT_ALPN }
+func (*SVCBNoDefaultAlpn) copy() SVCBKeyValue    { return &SVCBNoDefaultAlpn{} }
+func (*SVCBNoDefaultAlpn) pack() ([]byte, error) { return []byte{}, nil }
+func (*SVCBNoDefaultAlpn) String() string        { return "" }
+func (*SVCBNoDefaultAlpn) len() int              { return 0 }
+
+func (*SVCBNoDefaultAlpn) unpack(b []byte) error {
+	if len(b) != 0 {
+		return errors.New("dns: svcbnodefaultalpn: no_default_alpn must have no value")
+	}
+	return nil
+}
+
+func (*SVCBNoDefaultAlpn) parse(b string) error {
+	if len(b) != 0 {
+		return errors.New("dns: svcbnodefaultalpn: no_default_alpn must have no value")
+	}
+	return nil
+}
+
+// SVCBPort pair defines the port for connection.
+// Basic use pattern for creating a port option:
+//
+//	s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
+//	e := new(dns.SVCBPort)
+//	e.Port = 80
+//	s.Value = append(s.Value, e)
+type SVCBPort struct {
+	Port uint16
+}
+
+func (*SVCBPort) Key() SVCBKey         { return SVCB_PORT }
+func (*SVCBPort) len() int             { return 2 }
+func (s *SVCBPort) String() string     { return strconv.FormatUint(uint64(s.Port), 10) }
+func (s *SVCBPort) copy() SVCBKeyValue { return &SVCBPort{s.Port} }
+
+func (s *SVCBPort) unpack(b []byte) error {
+	if len(b) != 2 {
+		return errors.New("dns: svcbport: port length is not exactly 2 octets")
+	}
+	s.Port = binary.BigEndian.Uint16(b)
+	return nil
+}
+
+func (s *SVCBPort) pack() ([]byte, error) {
+	b := make([]byte, 2)
+	binary.BigEndian.PutUint16(b, s.Port)
+	return b, nil
+}
+
+func (s *SVCBPort) parse(b string) error {
+	port, err := strconv.ParseUint(b, 10, 16)
+	if err != nil {
+		return errors.New("dns: svcbport: port out of range")
+	}
+	s.Port = uint16(port)
+	return nil
+}
+
+// SVCBIPv4Hint pair suggests an IPv4 address which may be used to open connections
+// if A and AAAA record responses for SVCB's Target domain haven't been received.
+// In that case, optionally, A and AAAA requests can be made, after which the connection
+// to the hinted IP address may be terminated and a new connection may be opened.
+// 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()}
+//
+//  Or
+//
+//	e.Hint = []net.IP{net.ParseIP("1.1.1.1").To4()}
+//	h.Value = append(h.Value, e)
+type SVCBIPv4Hint struct {
+	Hint []net.IP
+}
+
+func (*SVCBIPv4Hint) Key() SVCBKey { return SVCB_IPV4HINT }
+func (s *SVCBIPv4Hint) len() int   { return 4 * len(s.Hint) }
+
+func (s *SVCBIPv4Hint) pack() ([]byte, error) {
+	b := make([]byte, 0, 4*len(s.Hint))
+	for _, e := range s.Hint {
+		x := e.To4()
+		if x == nil {
+			return nil, errors.New("dns: svcbipv4hint: expected ipv4, hint is ipv6")
+		}
+		b = append(b, x...)
+	}
+	return b, nil
+}
+
+func (s *SVCBIPv4Hint) unpack(b []byte) error {
+	if len(b) == 0 || len(b)%4 != 0 {
+		return errors.New("dns: svcbipv4hint: ipv4 address byte array length is not a multiple of 4")
+	}
+	x := make([]net.IP, 0, len(b)/4)
+	for i := 0; i < len(b); i += 4 {
+		x = append(x, net.IP(b[i:i+4]))
+	}
+	s.Hint = x
+	return nil
+}
+
+func (s *SVCBIPv4Hint) String() string {
+	str := make([]string, len(s.Hint))
+	for i, e := range s.Hint {
+		x := e.To4()
+		if x == nil {
+			return "<nil>"
+		}
+		str[i] = x.String()
+	}
+	return strings.Join(str, ",")
+}
+
+func (s *SVCBIPv4Hint) parse(b string) error {
+	if strings.Contains(b, ":") {
+		return errors.New("dns: svcbipv4hint: expected ipv4, got ipv6")
+	}
+	str := strings.Split(b, ",")
+	dst := make([]net.IP, len(str))
+	for i, e := range str {
+		ip := net.ParseIP(e).To4()
+		if ip == nil {
+			return errors.New("dns: svcbipv4hint: bad ip")
+		}
+		dst[i] = ip
+	}
+	s.Hint = dst
+	return nil
+}
+
+func (s *SVCBIPv4Hint) copy() SVCBKeyValue {
+	return &SVCBIPv4Hint{
+		append([]net.IP(nil), s.Hint...),
+	}
+}
+
+// SVCBECHConfig pair contains the ECHConfig structure defined in draft-ietf-tls-esni [RFC xxxx].
+// Basic use pattern for creating an echconfig option:
+//
+//	h := new(dns.HTTPS)
+//	h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
+//	e := new(dns.SVCBECHConfig)
+//	e.ECH = []byte{0xfe, 0x08, ...}
+//	h.Value = append(h.Value, e)
+type SVCBECHConfig struct {
+	ECH []byte
+}
+
+func (*SVCBECHConfig) Key() SVCBKey     { return SVCB_ECHCONFIG }
+func (s *SVCBECHConfig) String() string { return toBase64(s.ECH) }
+func (s *SVCBECHConfig) len() int       { return len(s.ECH) }
+
+func (s *SVCBECHConfig) pack() ([]byte, error) {
+	return append([]byte(nil), s.ECH...), nil
+}
+
+func (s *SVCBECHConfig) copy() SVCBKeyValue {
+	return &SVCBECHConfig{
+		append([]byte(nil), s.ECH...),
+	}
+}
+
+func (s *SVCBECHConfig) unpack(b []byte) error {
+	s.ECH = append([]byte(nil), b...)
+	return nil
+}
+func (s *SVCBECHConfig) parse(b string) error {
+	x, err := fromBase64([]byte(b))
+	if err != nil {
+		return errors.New("dns: svcbechconfig: bad base64 echconfig")
+	}
+	s.ECH = x
+	return nil
+}
+
+// SVCBIPv6Hint pair suggests an IPv6 address which may be used to open connections
+// if A and AAAA record responses for SVCB's Target domain haven't been received.
+// In that case, optionally, A and AAAA requests can be made, after which the
+// connection to the hinted IP address may be terminated and a new connection may be opened.
+// Basic use pattern for creating an ipv6hint option:
+//
+//	h := new(dns.HTTPS)
+//	h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
+//	e := new(dns.SVCBIPv6Hint)
+//	e.Hint = []net.IP{net.ParseIP("2001:db8::1")}
+//	h.Value = append(h.Value, e)
+type SVCBIPv6Hint struct {
+	Hint []net.IP
+}
+
+func (*SVCBIPv6Hint) Key() SVCBKey { return SVCB_IPV6HINT }
+func (s *SVCBIPv6Hint) len() int   { return 16 * len(s.Hint) }
+
+func (s *SVCBIPv6Hint) pack() ([]byte, error) {
+	b := make([]byte, 0, 16*len(s.Hint))
+	for _, e := range s.Hint {
+		if len(e) != net.IPv6len || e.To4() != nil {
+			return nil, errors.New("dns: svcbipv6hint: expected ipv6, hint is ipv4")
+		}
+		b = append(b, e...)
+	}
+	return b, nil
+}
+
+func (s *SVCBIPv6Hint) unpack(b []byte) error {
+	if len(b) == 0 || len(b)%16 != 0 {
+		return errors.New("dns: svcbipv6hint: ipv6 address byte array length not a multiple of 16")
+	}
+	x := make([]net.IP, 0, len(b)/16)
+	for i := 0; i < len(b); i += 16 {
+		ip := net.IP(b[i : i+16])
+		if ip.To4() != nil {
+			return errors.New("dns: svcbipv6hint: expected ipv6, got ipv4")
+		}
+		x = append(x, ip)
+	}
+	s.Hint = x
+	return nil
+}
+
+func (s *SVCBIPv6Hint) String() string {
+	str := make([]string, len(s.Hint))
+	for i, e := range s.Hint {
+		if x := e.To4(); x != nil {
+			return "<nil>"
+		}
+		str[i] = e.String()
+	}
+	return strings.Join(str, ",")
+}
+
+func (s *SVCBIPv6Hint) parse(b string) error {
+	if strings.Contains(b, ".") {
+		return errors.New("dns: svcbipv6hint: expected ipv6, got ipv4")
+	}
+	str := strings.Split(b, ",")
+	dst := make([]net.IP, len(str))
+	for i, e := range str {
+		ip := net.ParseIP(e)
+		if ip == nil {
+			return errors.New("dns: svcbipv6hint: bad ip")
+		}
+		dst[i] = ip
+	}
+	s.Hint = dst
+	return nil
+}
+
+func (s *SVCBIPv6Hint) copy() SVCBKeyValue {
+	return &SVCBIPv6Hint{
+		append([]net.IP(nil), s.Hint...),
+	}
+}
+
+// SVCBLocal pair is intended for experimental/private use. The key is recommended
+// to be in the range [SVCB_PRIVATE_LOWER, SVCB_PRIVATE_UPPER].
+// Basic use pattern for creating a keyNNNNN option:
+//
+//	h := new(dns.HTTPS)
+//	h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
+//	e := new(dns.SVCBLocal)
+//	e.KeyCode = 65400
+//	e.Data = []byte("abc")
+//	h.Value = append(h.Value, e)
+type SVCBLocal struct {
+	KeyCode SVCBKey // Never 65535 or any assigned keys.
+	Data    []byte  // All byte sequences are allowed.
+}
+
+func (s *SVCBLocal) Key() SVCBKey          { return s.KeyCode }
+func (s *SVCBLocal) pack() ([]byte, error) { return append([]byte(nil), s.Data...), nil }
+func (s *SVCBLocal) len() int              { return len(s.Data) }
+
+func (s *SVCBLocal) unpack(b []byte) error {
+	s.Data = append([]byte(nil), b...)
+	return nil
+}
+
+func (s *SVCBLocal) String() string {
+	var str strings.Builder
+	str.Grow(4 * len(s.Data))
+	for _, e := range s.Data {
+		if ' ' <= e && e <= '~' {
+			switch e {
+			case '"', ';', ' ', '\\':
+				str.WriteByte('\\')
+				str.WriteByte(e)
+			default:
+				str.WriteByte(e)
+			}
+		} else {
+			str.WriteString(escapeByte(e))
+		}
+	}
+	return str.String()
+}
+
+func (s *SVCBLocal) parse(b string) error {
+	data := make([]byte, 0, len(b))
+	for i := 0; i < len(b); {
+		if b[i] != '\\' {
+			data = append(data, b[i])
+			i++
+			continue
+		}
+		if i+1 == len(b) {
+			return errors.New("dns: svcblocal: svcb private/experimental key escape unterminated")
+		}
+		if isDigit(b[i+1]) {
+			if i+3 < len(b) && isDigit(b[i+2]) && isDigit(b[i+3]) {
+				a, err := strconv.ParseUint(b[i+1:i+4], 10, 8)
+				if err == nil {
+					i += 4
+					data = append(data, byte(a))
+					continue
+				}
+			}
+			return errors.New("dns: svcblocal: svcb private/experimental key bad escaped octet")
+		} else {
+			data = append(data, b[i+1])
+			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
+}
diff --git a/vendor/github.com/miekg/dns/tsig.go b/vendor/github.com/miekg/dns/tsig.go
index afa462fa0731a6f5df6265588afb8561de0f8dc8..59904dd6a090aa400c03df281c154703ffd83993 100644
--- a/vendor/github.com/miekg/dns/tsig.go
+++ b/vendor/github.com/miekg/dns/tsig.go
@@ -2,7 +2,6 @@ package dns
 
 import (
 	"crypto/hmac"
-	"crypto/md5"
 	"crypto/sha1"
 	"crypto/sha256"
 	"crypto/sha512"
@@ -16,10 +15,13 @@ import (
 
 // HMAC hashing codes. These are transmitted as domain names.
 const (
-	HmacMD5    = "hmac-md5.sig-alg.reg.int."
 	HmacSHA1   = "hmac-sha1."
+	HmacSHA224 = "hmac-sha224."
 	HmacSHA256 = "hmac-sha256."
+	HmacSHA384 = "hmac-sha384."
 	HmacSHA512 = "hmac-sha512."
+
+	HmacMD5 = "hmac-md5.sig-alg.reg.int." // Deprecated: HmacMD5 is no longer supported.
 )
 
 // TSIG is the RR the holds the transaction signature of a message.
@@ -40,7 +42,7 @@ type TSIG struct {
 // TSIG has no official presentation format, but this will suffice.
 
 func (rr *TSIG) String() string {
-	s := "\n;; TSIG PSEUDOSECTION:\n"
+	s := "\n;; TSIG PSEUDOSECTION:\n; " // add another semi-colon to signify TSIG does not have a presentation format
 	s += rr.Hdr.String() +
 		" " + rr.Algorithm +
 		" " + tsigTimeToString(rr.TimeSigned) +
@@ -54,7 +56,7 @@ func (rr *TSIG) String() string {
 	return s
 }
 
-func (rr *TSIG) parse(c *zlexer, origin, file string) *ParseError {
+func (rr *TSIG) parse(c *zlexer, origin string) *ParseError {
 	panic("dns: internal error: parse should never be called on TSIG")
 }
 
@@ -111,32 +113,33 @@ func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, s
 	if err != nil {
 		return nil, "", err
 	}
-	buf := tsigBuffer(mbuf, rr, requestMAC, timersOnly)
+	buf, err := tsigBuffer(mbuf, rr, requestMAC, timersOnly)
+	if err != nil {
+		return nil, "", err
+	}
 
 	t := new(TSIG)
 	var h hash.Hash
-	switch strings.ToLower(rr.Algorithm) {
-	case HmacMD5:
-		h = hmac.New(md5.New, rawsecret)
+	switch CanonicalName(rr.Algorithm) {
 	case HmacSHA1:
 		h = hmac.New(sha1.New, rawsecret)
+	case HmacSHA224:
+		h = hmac.New(sha256.New224, rawsecret)
 	case HmacSHA256:
 		h = hmac.New(sha256.New, rawsecret)
+	case HmacSHA384:
+		h = hmac.New(sha512.New384, rawsecret)
 	case HmacSHA512:
 		h = hmac.New(sha512.New, rawsecret)
 	default:
 		return nil, "", ErrKeyAlg
 	}
 	h.Write(buf)
+	// Copy all TSIG fields except MAC and its size, which are filled using the computed digest.
+	*t = *rr
 	t.MAC = hex.EncodeToString(h.Sum(nil))
 	t.MACSize = uint16(len(t.MAC) / 2) // Size is half!
 
-	t.Hdr = RR_Header{Name: rr.Hdr.Name, Rrtype: TypeTSIG, Class: ClassANY, Ttl: 0}
-	t.Fudge = rr.Fudge
-	t.TimeSigned = rr.TimeSigned
-	t.Algorithm = rr.Algorithm
-	t.OrigId = m.Id
-
 	tbuf := make([]byte, Len(t))
 	off, err := PackRR(t, tbuf, 0, nil, false)
 	if err != nil {
@@ -153,6 +156,11 @@ func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, s
 // If the signature does not validate err contains the
 // error, otherwise it is nil.
 func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) error {
+	return tsigVerify(msg, secret, requestMAC, timersOnly, uint64(time.Now().Unix()))
+}
+
+// actual implementation of TsigVerify, taking the current time ('now') as a parameter for the convenience of tests.
+func tsigVerify(msg []byte, secret, requestMAC string, timersOnly bool, now uint64) error {
 	rawsecret, err := fromBase64([]byte(secret))
 	if err != nil {
 		return err
@@ -168,27 +176,21 @@ func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) error {
 		return err
 	}
 
-	buf := tsigBuffer(stripped, tsig, requestMAC, timersOnly)
-
-	// Fudge factor works both ways. A message can arrive before it was signed because
-	// of clock skew.
-	now := uint64(time.Now().Unix())
-	ti := now - tsig.TimeSigned
-	if now < tsig.TimeSigned {
-		ti = tsig.TimeSigned - now
-	}
-	if uint64(tsig.Fudge) < ti {
-		return ErrTime
+	buf, err := tsigBuffer(stripped, tsig, requestMAC, timersOnly)
+	if err != nil {
+		return err
 	}
 
 	var h hash.Hash
-	switch strings.ToLower(tsig.Algorithm) {
-	case HmacMD5:
-		h = hmac.New(md5.New, rawsecret)
+	switch CanonicalName(tsig.Algorithm) {
 	case HmacSHA1:
 		h = hmac.New(sha1.New, rawsecret)
+	case HmacSHA224:
+		h = hmac.New(sha256.New224, rawsecret)
 	case HmacSHA256:
 		h = hmac.New(sha256.New, rawsecret)
+	case HmacSHA384:
+		h = hmac.New(sha512.New384, rawsecret)
 	case HmacSHA512:
 		h = hmac.New(sha512.New, rawsecret)
 	default:
@@ -198,11 +200,24 @@ func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) error {
 	if !hmac.Equal(h.Sum(nil), msgMAC) {
 		return ErrSig
 	}
+
+	// Fudge factor works both ways. A message can arrive before it was signed because
+	// of clock skew.
+	// We check this after verifying the signature, following draft-ietf-dnsop-rfc2845bis
+	// instead of RFC2845, in order to prevent a security vulnerability as reported in CVE-2017-3142/3143.
+	ti := now - tsig.TimeSigned
+	if now < tsig.TimeSigned {
+		ti = tsig.TimeSigned - now
+	}
+	if uint64(tsig.Fudge) < ti {
+		return ErrTime
+	}
+
 	return nil
 }
 
 // Create a wiredata buffer for the MAC calculation.
-func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []byte {
+func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) ([]byte, error) {
 	var buf []byte
 	if rr.TimeSigned == 0 {
 		rr.TimeSigned = uint64(time.Now().Unix())
@@ -219,7 +234,10 @@ func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []b
 		m.MACSize = uint16(len(requestMAC) / 2)
 		m.MAC = requestMAC
 		buf = make([]byte, len(requestMAC)) // long enough
-		n, _ := packMacWire(m, buf)
+		n, err := packMacWire(m, buf)
+		if err != nil {
+			return nil, err
+		}
 		buf = buf[:n]
 	}
 
@@ -228,20 +246,26 @@ func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []b
 		tsig := new(timerWireFmt)
 		tsig.TimeSigned = rr.TimeSigned
 		tsig.Fudge = rr.Fudge
-		n, _ := packTimerWire(tsig, tsigvar)
+		n, err := packTimerWire(tsig, tsigvar)
+		if err != nil {
+			return nil, err
+		}
 		tsigvar = tsigvar[:n]
 	} else {
 		tsig := new(tsigWireFmt)
-		tsig.Name = strings.ToLower(rr.Hdr.Name)
+		tsig.Name = CanonicalName(rr.Hdr.Name)
 		tsig.Class = ClassANY
 		tsig.Ttl = rr.Hdr.Ttl
-		tsig.Algorithm = strings.ToLower(rr.Algorithm)
+		tsig.Algorithm = CanonicalName(rr.Algorithm)
 		tsig.TimeSigned = rr.TimeSigned
 		tsig.Fudge = rr.Fudge
 		tsig.Error = rr.Error
 		tsig.OtherLen = rr.OtherLen
 		tsig.OtherData = rr.OtherData
-		n, _ := packTsigWire(tsig, tsigvar)
+		n, err := packTsigWire(tsig, tsigvar)
+		if err != nil {
+			return nil, err
+		}
 		tsigvar = tsigvar[:n]
 	}
 
@@ -251,7 +275,7 @@ func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []b
 	} else {
 		buf = append(msgbuf, tsigvar...)
 	}
-	return buf
+	return buf, nil
 }
 
 // Strip the TSIG from the raw message.
diff --git a/vendor/github.com/miekg/dns/types.go b/vendor/github.com/miekg/dns/types.go
index 835f2fe7c30da86078e84134cd418e49d88a5c40..1f385bd229bfd9171f32cee157aa1308541d48e8 100644
--- a/vendor/github.com/miekg/dns/types.go
+++ b/vendor/github.com/miekg/dns/types.go
@@ -1,6 +1,7 @@
 package dns
 
 import (
+	"bytes"
 	"fmt"
 	"net"
 	"strconv"
@@ -61,6 +62,7 @@ const (
 	TypeCERT       uint16 = 37
 	TypeDNAME      uint16 = 39
 	TypeOPT        uint16 = 41 // EDNS
+	TypeAPL        uint16 = 42
 	TypeDS         uint16 = 43
 	TypeSSHFP      uint16 = 44
 	TypeRRSIG      uint16 = 46
@@ -79,6 +81,8 @@ const (
 	TypeCDNSKEY    uint16 = 60
 	TypeOPENPGPKEY uint16 = 61
 	TypeCSYNC      uint16 = 62
+	TypeSVCB       uint16 = 64
+	TypeHTTPS      uint16 = 65
 	TypeSPF        uint16 = 99
 	TypeUINFO      uint16 = 100
 	TypeUID        uint16 = 101
@@ -163,11 +167,11 @@ const (
 	_RD = 1 << 8  // recursion desired
 	_RA = 1 << 7  // recursion available
 	_Z  = 1 << 6  // Z
-	_AD = 1 << 5  // authticated data
+	_AD = 1 << 5  // authenticated data
 	_CD = 1 << 4  // checking disabled
 )
 
-// Various constants used in the LOC RR, See RFC 1887.
+// Various constants used in the LOC RR. See RFC 1887.
 const (
 	LOC_EQUATOR       = 1 << 31 // RFC 1876, Section 2.
 	LOC_PRIMEMERIDIAN = 1 << 31 // RFC 1876, Section 2.
@@ -207,8 +211,11 @@ var CertTypeToString = map[uint16]string{
 
 //go:generate go run types_generate.go
 
-// Question holds a DNS question. There can be multiple questions in the
-// question section of a message. Usually there is just one.
+// Question holds a DNS question. Usually there is just one. While the
+// original DNS RFCs allow multiple questions in the question section of a
+// message, in practice it never works. Because most DNS servers see multiple
+// questions as an error, it is recommended to only have one question per
+// message.
 type Question struct {
 	Name   string `dns:"cdomain-name"` // "cdomain-name" specifies encoding (and may be compressed)
 	Qtype  uint16
@@ -229,7 +236,7 @@ func (q *Question) String() (s string) {
 	return s
 }
 
-// ANY is a wildcard record. See RFC 1035, Section 3.2.3. ANY
+// ANY is a wild card record. See RFC 1035, Section 3.2.3. ANY
 // is named "*" there.
 type ANY struct {
 	Hdr RR_Header
@@ -238,7 +245,7 @@ type ANY struct {
 
 func (rr *ANY) String() string { return rr.Hdr.String() }
 
-func (rr *ANY) parse(c *zlexer, origin, file string) *ParseError {
+func (rr *ANY) parse(c *zlexer, origin string) *ParseError {
 	panic("dns: internal error: parse should never be called on ANY")
 }
 
@@ -253,7 +260,7 @@ func (rr *NULL) String() string {
 	return ";" + rr.Hdr.String() + rr.Data
 }
 
-func (rr *NULL) parse(c *zlexer, origin, file string) *ParseError {
+func (rr *NULL) parse(c *zlexer, origin string) *ParseError {
 	panic("dns: internal error: parse should never be called on NULL")
 }
 
@@ -438,25 +445,47 @@ func (rr *TXT) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
 
 func sprintName(s string) string {
 	var dst strings.Builder
-	dst.Grow(len(s))
+
 	for i := 0; i < len(s); {
-		if i+1 < len(s) && s[i] == '\\' && s[i+1] == '.' {
-			dst.WriteString(s[i : i+2])
-			i += 2
+		if s[i] == '.' {
+			if dst.Len() != 0 {
+				dst.WriteByte('.')
+			}
+			i++
 			continue
 		}
 
 		b, n := nextByte(s, i)
-		switch {
-		case n == 0:
-			i++ // dangling back slash
-		case b == '.':
-			dst.WriteByte('.')
-		default:
-			writeDomainNameByte(&dst, b)
+		if n == 0 {
+			// Drop "dangling" incomplete escapes.
+			if dst.Len() == 0 {
+				return s[:i]
+			}
+			break
+		}
+		if isDomainNameLabelSpecial(b) {
+			if dst.Len() == 0 {
+				dst.Grow(len(s) * 2)
+				dst.WriteString(s[:i])
+			}
+			dst.WriteByte('\\')
+			dst.WriteByte(b)
+		} else if b < ' ' || b > '~' { // unprintable, use \DDD
+			if dst.Len() == 0 {
+				dst.Grow(len(s) * 2)
+				dst.WriteString(s[:i])
+			}
+			dst.WriteString(escapeByte(b))
+		} else {
+			if dst.Len() != 0 {
+				dst.WriteByte(b)
+			}
 		}
 		i += n
 	}
+	if dst.Len() == 0 {
+		return s
+	}
 	return dst.String()
 }
 
@@ -472,15 +501,10 @@ func sprintTxtOctet(s string) string {
 		}
 
 		b, n := nextByte(s, i)
-		switch {
-		case n == 0:
+		if n == 0 {
 			i++ // dangling back slash
-		case b == '.':
-			dst.WriteByte('.')
-		case b < ' ' || b > '~':
-			dst.WriteString(escapeByte(b))
-		default:
-			dst.WriteByte(b)
+		} else {
+			writeTXTStringByte(&dst, b)
 		}
 		i += n
 	}
@@ -510,16 +534,6 @@ func sprintTxt(txt []string) string {
 	return out.String()
 }
 
-func writeDomainNameByte(s *strings.Builder, b byte) {
-	switch b {
-	case '.', ' ', '\'', '@', ';', '(', ')': // additional chars to escape
-		s.WriteByte('\\')
-		s.WriteByte(b)
-	default:
-		writeTXTStringByte(s, b)
-	}
-}
-
 func writeTXTStringByte(s *strings.Builder, b byte) {
 	switch {
 	case b == '"' || b == '\\':
@@ -566,6 +580,17 @@ func escapeByte(b byte) string {
 	return escapedByteLarge[int(b)*4 : int(b)*4+4]
 }
 
+// isDomainNameLabelSpecial returns true if
+// a domain name label byte should be prefixed
+// with an escaping backslash.
+func isDomainNameLabelSpecial(b byte) bool {
+	switch b {
+	case '.', ' ', '\'', '@', ';', '(', ')', '"', '\\':
+		return true
+	}
+	return false
+}
+
 func nextByte(s string, offset int) (byte, int) {
 	if offset >= len(s) {
 		return 0, 0
@@ -738,8 +763,8 @@ type LOC struct {
 	Altitude  uint32
 }
 
-// cmToM takes a cm value expressed in RFC1876 SIZE mantissa/exponent
-// format and returns a string in m (two decimals for the cm)
+// cmToM takes a cm value expressed in RFC 1876 SIZE mantissa/exponent
+// format and returns a string in m (two decimals for the cm).
 func cmToM(m, e uint8) string {
 	if e < 2 {
 		if e == 1 {
@@ -854,14 +879,7 @@ func (rr *NSEC) String() string {
 func (rr *NSEC) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l += domainNameLen(rr.NextDomain, off+l, compression, false)
-	lastwindow := uint32(2 ^ 32 + 1)
-	for _, t := range rr.TypeBitMap {
-		window := t / 256
-		if uint32(window) != lastwindow {
-			l += 1 + 32
-		}
-		lastwindow = uint32(window)
-	}
+	l += typeBitMapLen(rr.TypeBitMap)
 	return l
 }
 
@@ -1020,14 +1038,7 @@ func (rr *NSEC3) String() string {
 func (rr *NSEC3) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l += 6 + len(rr.Salt)/2 + 1 + len(rr.NextDomain) + 1
-	lastwindow := uint32(2 ^ 32 + 1)
-	for _, t := range rr.TypeBitMap {
-		window := t / 256
-		if uint32(window) != lastwindow {
-			l += 1 + 32
-		}
-		lastwindow = uint32(window)
-	}
+	l += typeBitMapLen(rr.TypeBitMap)
 	return l
 }
 
@@ -1111,6 +1122,7 @@ type URI struct {
 	Target   string `dns:"octet"`
 }
 
+// rr.Target to be parsed as a sequence of character encoded octets according to RFC 3986
 func (rr *URI) String() string {
 	return rr.Hdr.String() + strconv.Itoa(int(rr.Priority)) +
 		" " + strconv.Itoa(int(rr.Weight)) + " " + sprintTxtOctet(rr.Target)
@@ -1272,6 +1284,7 @@ type CAA struct {
 	Value string `dns:"octet"`
 }
 
+// rr.Value Is the character-string encoding of the value field as specified in RFC 1035, Section 5.1.
 func (rr *CAA) String() string {
 	return rr.Hdr.String() + strconv.Itoa(int(rr.Flag)) + " " + rr.Tag + " " + sprintTxtOctet(rr.Value)
 }
@@ -1344,15 +1357,90 @@ func (rr *CSYNC) String() string {
 func (rr *CSYNC) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l += 4 + 2
-	lastwindow := uint32(2 ^ 32 + 1)
-	for _, t := range rr.TypeBitMap {
-		window := t / 256
-		if uint32(window) != lastwindow {
-			l += 1 + 32
+	l += typeBitMapLen(rr.TypeBitMap)
+	return l
+}
+
+// APL RR. See RFC 3123.
+type APL struct {
+	Hdr      RR_Header
+	Prefixes []APLPrefix `dns:"apl"`
+}
+
+// APLPrefix is an address prefix hold by an APL record.
+type APLPrefix struct {
+	Negation bool
+	Network  net.IPNet
+}
+
+// String returns presentation form of the APL record.
+func (rr *APL) String() string {
+	var sb strings.Builder
+	sb.WriteString(rr.Hdr.String())
+	for i, p := range rr.Prefixes {
+		if i > 0 {
+			sb.WriteByte(' ')
 		}
-		lastwindow = uint32(window)
+		sb.WriteString(p.str())
 	}
-	return l
+	return sb.String()
+}
+
+// str returns presentation form of the APL prefix.
+func (p *APLPrefix) str() string {
+	var sb strings.Builder
+	if p.Negation {
+		sb.WriteByte('!')
+	}
+
+	switch len(p.Network.IP) {
+	case net.IPv4len:
+		sb.WriteByte('1')
+	case net.IPv6len:
+		sb.WriteByte('2')
+	}
+
+	sb.WriteByte(':')
+
+	switch len(p.Network.IP) {
+	case net.IPv4len:
+		sb.WriteString(p.Network.IP.String())
+	case net.IPv6len:
+		// add prefix for IPv4-mapped IPv6
+		if v4 := p.Network.IP.To4(); v4 != nil {
+			sb.WriteString("::ffff:")
+		}
+		sb.WriteString(p.Network.IP.String())
+	}
+
+	sb.WriteByte('/')
+
+	prefix, _ := p.Network.Mask.Size()
+	sb.WriteString(strconv.Itoa(prefix))
+
+	return sb.String()
+}
+
+// equals reports whether two APL prefixes are identical.
+func (a *APLPrefix) equals(b *APLPrefix) bool {
+	return a.Negation == b.Negation &&
+		bytes.Equal(a.Network.IP, b.Network.IP) &&
+		bytes.Equal(a.Network.Mask, b.Network.Mask)
+}
+
+// copy returns a copy of the APL prefix.
+func (p *APLPrefix) copy() APLPrefix {
+	return APLPrefix{
+		Negation: p.Negation,
+		Network:  copyNet(p.Network),
+	}
+}
+
+// len returns size of the prefix in wire format.
+func (p *APLPrefix) len() int {
+	// 4-byte header and the network address prefix (see Section 4 of RFC 3123)
+	prefix, _ := p.Network.Mask.Size()
+	return 4 + (prefix+7)/8
 }
 
 // TimeToString translates the RRSIG's incep. and expir. times to the
@@ -1411,6 +1499,17 @@ func copyIP(ip net.IP) net.IP {
 	return p
 }
 
+// copyNet returns a copy of a subnet.
+func copyNet(n net.IPNet) net.IPNet {
+	m := make(net.IPMask, len(n.Mask))
+	copy(m, n.Mask)
+
+	return net.IPNet{
+		IP:   copyIP(n.IP),
+		Mask: m,
+	}
+}
+
 // SplitN splits a string into N sized string chunks.
 // This might become an exported function once.
 func splitN(s string, n int) []string {
diff --git a/vendor/github.com/miekg/dns/version.go b/vendor/github.com/miekg/dns/version.go
index 0e21bd6a1ffc292d4426c873b33220b141a00138..5c75851b41dc1268ca246b2de8d2102f6bb9bf94 100644
--- a/vendor/github.com/miekg/dns/version.go
+++ b/vendor/github.com/miekg/dns/version.go
@@ -3,13 +3,13 @@ package dns
 import "fmt"
 
 // Version is current version of this library.
-var Version = V{1, 1, 8}
+var Version = v{1, 1, 35}
 
-// V holds the version of this library.
-type V struct {
+// v holds the version of this library.
+type v struct {
 	Major, Minor, Patch int
 }
 
-func (v V) String() string {
+func (v v) String() string {
 	return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
 }
diff --git a/vendor/github.com/miekg/dns/xfr.go b/vendor/github.com/miekg/dns/xfr.go
index 82afc52ea82e10d8ff17726e98b313e1d2de1350..43970e64f39b2a5b0e4f6ebfb8ae2832c86ffcf4 100644
--- a/vendor/github.com/miekg/dns/xfr.go
+++ b/vendor/github.com/miekg/dns/xfr.go
@@ -182,14 +182,17 @@ func (t *Transfer) inIxfr(q *Msg, c chan *Envelope) {
 //
 //	ch := make(chan *dns.Envelope)
 //	tr := new(dns.Transfer)
-//	go tr.Out(w, r, ch)
+//	var wg sync.WaitGroup
+//	go func() {
+//		tr.Out(w, r, ch)
+//		wg.Done()
+//	}()
 //	ch <- &dns.Envelope{RR: []dns.RR{soa, rr1, rr2, rr3, soa}}
 //	close(ch)
-//	w.Hijack()
-//	// w.Close() // Client closes connection
+//	wg.Wait() // wait until everything is written out
+//	w.Close() // close connection
 //
-// The server is responsible for sending the correct sequence of RRs through the
-// channel ch.
+// The server is responsible for sending the correct sequence of RRs through the channel ch.
 func (t *Transfer) Out(w ResponseWriter, q *Msg, ch chan *Envelope) error {
 	for x := range ch {
 		r := new(Msg)
@@ -198,11 +201,14 @@ func (t *Transfer) Out(w ResponseWriter, q *Msg, ch chan *Envelope) error {
 		r.Authoritative = true
 		// assume it fits TODO(miek): fix
 		r.Answer = append(r.Answer, x.RR...)
+		if tsig := q.IsTsig(); tsig != nil && w.TsigStatus() == nil {
+			r.SetTsig(tsig.Hdr.Name, tsig.Algorithm, tsig.Fudge, time.Now().Unix())
+		}
 		if err := w.WriteMsg(r); err != nil {
 			return err
 		}
+		w.TsigTimersOnly(true)
 	}
-	w.TsigTimersOnly(true)
 	return nil
 }
 
diff --git a/vendor/github.com/miekg/dns/zduplicate.go b/vendor/github.com/miekg/dns/zduplicate.go
index 74389162faf7f0aa3fccd145f10fe7f3f3e3f26f..0d3b34bd9b24f722de92f3551512670d605f70ff 100644
--- a/vendor/github.com/miekg/dns/zduplicate.go
+++ b/vendor/github.com/miekg/dns/zduplicate.go
@@ -52,6 +52,23 @@ func (r1 *ANY) isDuplicate(_r2 RR) bool {
 	return true
 }
 
+func (r1 *APL) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*APL)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if len(r1.Prefixes) != len(r2.Prefixes) {
+		return false
+	}
+	for i := 0; i < len(r1.Prefixes); i++ {
+		if !r1.Prefixes[i].equals(&r2.Prefixes[i]) {
+			return false
+		}
+	}
+	return true
+}
+
 func (r1 *AVC) isDuplicate(_r2 RR) bool {
 	r2, ok := _r2.(*AVC)
 	if !ok {
@@ -87,6 +104,48 @@ func (r1 *CAA) isDuplicate(_r2 RR) bool {
 	return true
 }
 
+func (r1 *CDNSKEY) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*CDNSKEY)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Flags != r2.Flags {
+		return false
+	}
+	if r1.Protocol != r2.Protocol {
+		return false
+	}
+	if r1.Algorithm != r2.Algorithm {
+		return false
+	}
+	if r1.PublicKey != r2.PublicKey {
+		return false
+	}
+	return true
+}
+
+func (r1 *CDS) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*CDS)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.KeyTag != r2.KeyTag {
+		return false
+	}
+	if r1.Algorithm != r2.Algorithm {
+		return false
+	}
+	if r1.DigestType != r2.DigestType {
+		return false
+	}
+	if r1.Digest != r2.Digest {
+		return false
+	}
+	return true
+}
+
 func (r1 *CERT) isDuplicate(_r2 RR) bool {
 	r2, ok := _r2.(*CERT)
 	if !ok {
@@ -155,6 +214,27 @@ func (r1 *DHCID) isDuplicate(_r2 RR) bool {
 	return true
 }
 
+func (r1 *DLV) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*DLV)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.KeyTag != r2.KeyTag {
+		return false
+	}
+	if r1.Algorithm != r2.Algorithm {
+		return false
+	}
+	if r1.DigestType != r2.DigestType {
+		return false
+	}
+	if r1.Digest != r2.Digest {
+		return false
+	}
+	return true
+}
+
 func (r1 *DNAME) isDuplicate(_r2 RR) bool {
 	r2, ok := _r2.(*DNAME)
 	if !ok {
@@ -322,6 +402,48 @@ func (r1 *HIP) isDuplicate(_r2 RR) bool {
 	return true
 }
 
+func (r1 *HTTPS) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*HTTPS)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Priority != r2.Priority {
+		return false
+	}
+	if !isDuplicateName(r1.Target, r2.Target) {
+		return false
+	}
+	if len(r1.Value) != len(r2.Value) {
+		return false
+	}
+	if !areSVCBPairArraysEqual(r1.Value, r2.Value) {
+		return false
+	}
+	return true
+}
+
+func (r1 *KEY) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*KEY)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Flags != r2.Flags {
+		return false
+	}
+	if r1.Protocol != r2.Protocol {
+		return false
+	}
+	if r1.Algorithm != r2.Algorithm {
+		return false
+	}
+	if r1.PublicKey != r2.PublicKey {
+		return false
+	}
+	return true
+}
+
 func (r1 *KX) isDuplicate(_r2 RR) bool {
 	r2, ok := _r2.(*KX)
 	if !ok {
@@ -832,6 +954,42 @@ func (r1 *RT) isDuplicate(_r2 RR) bool {
 	return true
 }
 
+func (r1 *SIG) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*SIG)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.TypeCovered != r2.TypeCovered {
+		return false
+	}
+	if r1.Algorithm != r2.Algorithm {
+		return false
+	}
+	if r1.Labels != r2.Labels {
+		return false
+	}
+	if r1.OrigTtl != r2.OrigTtl {
+		return false
+	}
+	if r1.Expiration != r2.Expiration {
+		return false
+	}
+	if r1.Inception != r2.Inception {
+		return false
+	}
+	if r1.KeyTag != r2.KeyTag {
+		return false
+	}
+	if !isDuplicateName(r1.SignerName, r2.SignerName) {
+		return false
+	}
+	if r1.Signature != r2.Signature {
+		return false
+	}
+	return true
+}
+
 func (r1 *SMIMEA) isDuplicate(_r2 RR) bool {
 	r2, ok := _r2.(*SMIMEA)
 	if !ok {
@@ -939,6 +1097,27 @@ func (r1 *SSHFP) isDuplicate(_r2 RR) bool {
 	return true
 }
 
+func (r1 *SVCB) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*SVCB)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Priority != r2.Priority {
+		return false
+	}
+	if !isDuplicateName(r1.Target, r2.Target) {
+		return false
+	}
+	if len(r1.Value) != len(r2.Value) {
+		return false
+	}
+	if !areSVCBPairArraysEqual(r1.Value, r2.Value) {
+		return false
+	}
+	return true
+}
+
 func (r1 *TA) isDuplicate(_r2 RR) bool {
 	r2, ok := _r2.(*TA)
 	if !ok {
diff --git a/vendor/github.com/miekg/dns/zmsg.go b/vendor/github.com/miekg/dns/zmsg.go
index c4cf4757e8a670295be1e51c42acbb0d9b29a91e..d24a10fa24267e1ee51f0d7d5b3a1b51ea0cf33b 100644
--- a/vendor/github.com/miekg/dns/zmsg.go
+++ b/vendor/github.com/miekg/dns/zmsg.go
@@ -36,6 +36,14 @@ func (rr *ANY) pack(msg []byte, off int, compression compressionMap, compress bo
 	return off, nil
 }
 
+func (rr *APL) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packDataApl(rr.Prefixes, msg, off)
+	if err != nil {
+		return off, err
+	}
+	return off, nil
+}
+
 func (rr *AVC) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packStringTxt(rr.Txt, msg, off)
 	if err != nil {
@@ -308,6 +316,22 @@ func (rr *HIP) pack(msg []byte, off int, compression compressionMap, compress bo
 	return off, nil
 }
 
+func (rr *HTTPS) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packUint16(rr.Priority, msg, off)
+	if err != nil {
+		return off, err
+	}
+	off, err = packDomainName(rr.Target, msg, off, compression, false)
+	if err != nil {
+		return off, err
+	}
+	off, err = packDataSVCB(rr.Value, 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) {
 	off, err = packUint16(rr.Flags, msg, off)
 	if err != nil {
@@ -898,6 +922,22 @@ func (rr *SSHFP) pack(msg []byte, off int, compression compressionMap, compress
 	return off, nil
 }
 
+func (rr *SVCB) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packUint16(rr.Priority, msg, off)
+	if err != nil {
+		return off, err
+	}
+	off, err = packDomainName(rr.Target, msg, off, compression, false)
+	if err != nil {
+		return off, err
+	}
+	off, err = packDataSVCB(rr.Value, msg, off)
+	if err != nil {
+		return off, err
+	}
+	return off, nil
+}
+
 func (rr *TA) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint16(rr.KeyTag, msg, off)
 	if err != nil {
@@ -1127,6 +1167,17 @@ func (rr *ANY) unpack(msg []byte, off int) (off1 int, err error) {
 	return off, nil
 }
 
+func (rr *APL) unpack(msg []byte, off int) (off1 int, err error) {
+	rdStart := off
+	_ = rdStart
+
+	rr.Prefixes, off, err = unpackDataApl(msg, off)
+	if err != nil {
+		return off, err
+	}
+	return off, nil
+}
+
 func (rr *AVC) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
@@ -1540,6 +1591,31 @@ func (rr *HIP) unpack(msg []byte, off int) (off1 int, err error) {
 	return off, nil
 }
 
+func (rr *HTTPS) unpack(msg []byte, off int) (off1 int, err error) {
+	rdStart := off
+	_ = rdStart
+
+	rr.Priority, off, err = unpackUint16(msg, off)
+	if err != nil {
+		return off, err
+	}
+	if off == len(msg) {
+		return off, nil
+	}
+	rr.Target, off, err = UnpackDomainName(msg, off)
+	if err != nil {
+		return off, err
+	}
+	if off == len(msg) {
+		return off, nil
+	}
+	rr.Value, off, err = unpackDataSVCB(msg, off)
+	if err != nil {
+		return off, err
+	}
+	return off, nil
+}
+
 func (rr *KEY) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
@@ -2442,6 +2518,31 @@ func (rr *SSHFP) unpack(msg []byte, off int) (off1 int, err error) {
 	return off, nil
 }
 
+func (rr *SVCB) unpack(msg []byte, off int) (off1 int, err error) {
+	rdStart := off
+	_ = rdStart
+
+	rr.Priority, off, err = unpackUint16(msg, off)
+	if err != nil {
+		return off, err
+	}
+	if off == len(msg) {
+		return off, nil
+	}
+	rr.Target, off, err = UnpackDomainName(msg, off)
+	if err != nil {
+		return off, err
+	}
+	if off == len(msg) {
+		return off, nil
+	}
+	rr.Value, off, err = unpackDataSVCB(msg, off)
+	if err != nil {
+		return off, err
+	}
+	return off, nil
+}
+
 func (rr *TA) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
diff --git a/vendor/github.com/miekg/dns/ztypes.go b/vendor/github.com/miekg/dns/ztypes.go
index 495a83e30239ef5b56a27e7548087be9ea83b438..11b51bf217109ab16392b635c4aacfba50dddc39 100644
--- a/vendor/github.com/miekg/dns/ztypes.go
+++ b/vendor/github.com/miekg/dns/ztypes.go
@@ -13,6 +13,7 @@ var TypeToRR = map[uint16]func() RR{
 	TypeAAAA:       func() RR { return new(AAAA) },
 	TypeAFSDB:      func() RR { return new(AFSDB) },
 	TypeANY:        func() RR { return new(ANY) },
+	TypeAPL:        func() RR { return new(APL) },
 	TypeAVC:        func() RR { return new(AVC) },
 	TypeCAA:        func() RR { return new(CAA) },
 	TypeCDNSKEY:    func() RR { return new(CDNSKEY) },
@@ -32,6 +33,7 @@ var TypeToRR = map[uint16]func() RR{
 	TypeGPOS:       func() RR { return new(GPOS) },
 	TypeHINFO:      func() RR { return new(HINFO) },
 	TypeHIP:        func() RR { return new(HIP) },
+	TypeHTTPS:      func() RR { return new(HTTPS) },
 	TypeKEY:        func() RR { return new(KEY) },
 	TypeKX:         func() RR { return new(KX) },
 	TypeL32:        func() RR { return new(L32) },
@@ -69,6 +71,7 @@ var TypeToRR = map[uint16]func() RR{
 	TypeSPF:        func() RR { return new(SPF) },
 	TypeSRV:        func() RR { return new(SRV) },
 	TypeSSHFP:      func() RR { return new(SSHFP) },
+	TypeSVCB:       func() RR { return new(SVCB) },
 	TypeTA:         func() RR { return new(TA) },
 	TypeTALINK:     func() RR { return new(TALINK) },
 	TypeTKEY:       func() RR { return new(TKEY) },
@@ -87,6 +90,7 @@ var TypeToString = map[uint16]string{
 	TypeAAAA:       "AAAA",
 	TypeAFSDB:      "AFSDB",
 	TypeANY:        "ANY",
+	TypeAPL:        "APL",
 	TypeATMA:       "ATMA",
 	TypeAVC:        "AVC",
 	TypeAXFR:       "AXFR",
@@ -108,6 +112,7 @@ var TypeToString = map[uint16]string{
 	TypeGPOS:       "GPOS",
 	TypeHINFO:      "HINFO",
 	TypeHIP:        "HIP",
+	TypeHTTPS:      "HTTPS",
 	TypeISDN:       "ISDN",
 	TypeIXFR:       "IXFR",
 	TypeKEY:        "KEY",
@@ -151,6 +156,7 @@ var TypeToString = map[uint16]string{
 	TypeSPF:        "SPF",
 	TypeSRV:        "SRV",
 	TypeSSHFP:      "SSHFP",
+	TypeSVCB:       "SVCB",
 	TypeTA:         "TA",
 	TypeTALINK:     "TALINK",
 	TypeTKEY:       "TKEY",
@@ -169,6 +175,7 @@ func (rr *A) 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 *ANY) 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 *CAA) Header() *RR_Header        { return &rr.Hdr }
 func (rr *CDNSKEY) Header() *RR_Header    { return &rr.Hdr }
@@ -188,6 +195,7 @@ func (rr *GID) Header() *RR_Header        { return &rr.Hdr }
 func (rr *GPOS) 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 *HTTPS) 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 *L32) Header() *RR_Header        { return &rr.Hdr }
@@ -226,6 +234,7 @@ func (rr *SOA) Header() *RR_Header        { return &rr.Hdr }
 func (rr *SPF) Header() *RR_Header        { return &rr.Hdr }
 func (rr *SRV) Header() *RR_Header        { return &rr.Hdr }
 func (rr *SSHFP) Header() *RR_Header      { return &rr.Hdr }
+func (rr *SVCB) Header() *RR_Header       { return &rr.Hdr }
 func (rr *TA) Header() *RR_Header         { return &rr.Hdr }
 func (rr *TALINK) Header() *RR_Header     { return &rr.Hdr }
 func (rr *TKEY) Header() *RR_Header       { return &rr.Hdr }
@@ -262,6 +271,13 @@ func (rr *ANY) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	return l
 }
+func (rr *APL) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	for _, x := range rr.Prefixes {
+		l += x.len()
+	}
+	return l
+}
 func (rr *AVC) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	for _, x := range rr.Txt {
@@ -312,12 +328,12 @@ func (rr *DS) len(off int, compression map[string]struct{}) int {
 	l += 2 // KeyTag
 	l++    // Algorithm
 	l++    // DigestType
-	l += len(rr.Digest)/2 + 1
+	l += len(rr.Digest) / 2
 	return l
 }
 func (rr *EID) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
-	l += len(rr.Endpoint)/2 + 1
+	l += len(rr.Endpoint) / 2
 	return l
 }
 func (rr *EUI48) len(off int, compression map[string]struct{}) int {
@@ -452,7 +468,7 @@ func (rr *NID) 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 += len(rr.Locator)/2 + 1
+	l += len(rr.Locator) / 2
 	return l
 }
 func (rr *NINFO) len(off int, compression map[string]struct{}) int {
@@ -505,7 +521,7 @@ func (rr *PX) 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 += len(rr.Rdata)/2 + 1
+	l += len(rr.Rdata) / 2
 	return l
 }
 func (rr *RKEY) len(off int, compression map[string]struct{}) int {
@@ -546,7 +562,7 @@ func (rr *SMIMEA) len(off int, compression map[string]struct{}) int {
 	l++ // Usage
 	l++ // Selector
 	l++ // MatchingType
-	l += len(rr.Certificate)/2 + 1
+	l += len(rr.Certificate) / 2
 	return l
 }
 func (rr *SOA) len(off int, compression map[string]struct{}) int {
@@ -579,7 +595,16 @@ func (rr *SSHFP) len(off int, compression map[string]struct{}) int {
 	l := rr.Hdr.len(off, compression)
 	l++ // Algorithm
 	l++ // Type
-	l += len(rr.FingerPrint)/2 + 1
+	l += len(rr.FingerPrint) / 2
+	return l
+}
+func (rr *SVCB) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += 2 // Priority
+	l += domainNameLen(rr.Target, off+l, compression, false)
+	for _, x := range rr.Value {
+		l += 4 + int(x.len())
+	}
 	return l
 }
 func (rr *TA) len(off int, compression map[string]struct{}) int {
@@ -587,7 +612,7 @@ func (rr *TA) len(off int, compression map[string]struct{}) int {
 	l += 2 // KeyTag
 	l++    // Algorithm
 	l++    // DigestType
-	l += len(rr.Digest)/2 + 1
+	l += len(rr.Digest) / 2
 	return l
 }
 func (rr *TALINK) len(off int, compression map[string]struct{}) int {
@@ -614,7 +639,7 @@ func (rr *TLSA) len(off int, compression map[string]struct{}) int {
 	l++ // Usage
 	l++ // Selector
 	l++ // MatchingType
-	l += len(rr.Certificate)/2 + 1
+	l += len(rr.Certificate) / 2
 	return l
 }
 func (rr *TSIG) len(off int, compression map[string]struct{}) int {
@@ -673,6 +698,13 @@ func (rr *AFSDB) copy() RR {
 func (rr *ANY) copy() RR {
 	return &ANY{rr.Hdr}
 }
+func (rr *APL) copy() RR {
+	Prefixes := make([]APLPrefix, len(rr.Prefixes))
+	for i, e := range rr.Prefixes {
+		Prefixes[i] = e.copy()
+	}
+	return &APL{rr.Hdr, Prefixes}
+}
 func (rr *AVC) copy() RR {
 	Txt := make([]string, len(rr.Txt))
 	copy(Txt, rr.Txt)
@@ -681,6 +713,12 @@ func (rr *AVC) copy() RR {
 func (rr *CAA) copy() RR {
 	return &CAA{rr.Hdr, rr.Flag, rr.Tag, rr.Value}
 }
+func (rr *CDNSKEY) copy() RR {
+	return &CDNSKEY{*rr.DNSKEY.copy().(*DNSKEY)}
+}
+func (rr *CDS) copy() RR {
+	return &CDS{*rr.DS.copy().(*DS)}
+}
 func (rr *CERT) copy() RR {
 	return &CERT{rr.Hdr, rr.Type, rr.KeyTag, rr.Algorithm, rr.Certificate}
 }
@@ -695,6 +733,9 @@ func (rr *CSYNC) copy() RR {
 func (rr *DHCID) copy() RR {
 	return &DHCID{rr.Hdr, rr.Digest}
 }
+func (rr *DLV) copy() RR {
+	return &DLV{*rr.DS.copy().(*DS)}
+}
 func (rr *DNAME) copy() RR {
 	return &DNAME{rr.Hdr, rr.Target}
 }
@@ -727,6 +768,12 @@ func (rr *HIP) copy() RR {
 	copy(RendezvousServers, rr.RendezvousServers)
 	return &HIP{rr.Hdr, rr.HitLength, rr.PublicKeyAlgorithm, rr.PublicKeyLength, rr.Hit, rr.PublicKey, RendezvousServers}
 }
+func (rr *HTTPS) copy() RR {
+	return &HTTPS{*rr.SVCB.copy().(*SVCB)}
+}
+func (rr *KEY) copy() RR {
+	return &KEY{*rr.DNSKEY.copy().(*DNSKEY)}
+}
 func (rr *KX) copy() RR {
 	return &KX{rr.Hdr, rr.Preference, rr.Exchanger}
 }
@@ -830,6 +877,9 @@ func (rr *RRSIG) copy() RR {
 func (rr *RT) copy() RR {
 	return &RT{rr.Hdr, rr.Preference, rr.Host}
 }
+func (rr *SIG) copy() RR {
+	return &SIG{*rr.RRSIG.copy().(*RRSIG)}
+}
 func (rr *SMIMEA) copy() RR {
 	return &SMIMEA{rr.Hdr, rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate}
 }
@@ -847,6 +897,13 @@ func (rr *SRV) copy() RR {
 func (rr *SSHFP) copy() RR {
 	return &SSHFP{rr.Hdr, rr.Algorithm, rr.Type, rr.FingerPrint}
 }
+func (rr *SVCB) copy() RR {
+	Value := make([]SVCBKeyValue, len(rr.Value))
+	for i, e := range rr.Value {
+		Value[i] = e.copy()
+	}
+	return &SVCB{rr.Hdr, rr.Priority, rr.Target, Value}
+}
 func (rr *TA) copy() RR {
 	return &TA{rr.Hdr, rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
 }
diff --git a/vendor/modules.txt b/vendor/modules.txt
index ef2d0135c9bb7dbfbe5aaaccc3156b959c6dd46a..10aad974bb4195e1109a1a54d1a491226f7c9e52 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -70,7 +70,7 @@ github.com/konsorten/go-windows-terminal-sequences
 github.com/lpar/gzipped
 # github.com/matttproud/golang_protobuf_extensions v1.0.1
 github.com/matttproud/golang_protobuf_extensions/pbutil
-# github.com/miekg/dns v1.1.8
+# github.com/miekg/dns v1.1.35
 ## explicit
 github.com/miekg/dns
 # github.com/prometheus/client_golang v1.9.0