From 966fd56c35fd525a9c5cb0dfa89ecafa78d5155f Mon Sep 17 00:00:00 2001
From: renovate <renovate-bot@autistici.org>
Date: Thu, 28 Jan 2021 14:21:07 +0000
Subject: [PATCH] chore(deps): update module miekg/dns to v1.1.35

---
 go.mod                                        |    2 +-
 go.sum                                        |    5 +
 vendor/github.com/miekg/dns/.travis.yml       |   12 +-
 vendor/github.com/miekg/dns/CODEOWNERS        |    1 +
 vendor/github.com/miekg/dns/Gopkg.lock        |   57 -
 vendor/github.com/miekg/dns/Gopkg.toml        |   38 -
 vendor/github.com/miekg/dns/LICENSE           |    6 +-
 vendor/github.com/miekg/dns/README.md         |   18 +-
 vendor/github.com/miekg/dns/acceptfunc.go     |   21 +-
 vendor/github.com/miekg/dns/client.go         |  136 +-
 vendor/github.com/miekg/dns/defaults.go       |   10 +-
 vendor/github.com/miekg/dns/dns.go            |    4 +-
 vendor/github.com/miekg/dns/dnssec.go         |  109 +-
 vendor/github.com/miekg/dns/dnssec_keygen.go  |   46 +-
 vendor/github.com/miekg/dns/dnssec_keyscan.go |   48 +-
 vendor/github.com/miekg/dns/dnssec_privkey.go |   20 +-
 vendor/github.com/miekg/dns/doc.go            |   13 +-
 vendor/github.com/miekg/dns/duplicate.go      |    5 +-
 vendor/github.com/miekg/dns/edns.go           |   32 +-
 vendor/github.com/miekg/dns/fuzz.go           |   11 +-
 vendor/github.com/miekg/dns/generate.go       |   35 +-
 vendor/github.com/miekg/dns/go.mod            |   11 +
 vendor/github.com/miekg/dns/go.sum            |   39 +
 vendor/github.com/miekg/dns/labels.go         |   62 +-
 vendor/github.com/miekg/dns/msg.go            |   68 +-
 vendor/github.com/miekg/dns/msg_helpers.go    |  337 +++--
 vendor/github.com/miekg/dns/msg_truncate.go   |   26 +-
 vendor/github.com/miekg/dns/nsecx.go          |    2 +-
 vendor/github.com/miekg/dns/privaterr.go      |   39 +-
 vendor/github.com/miekg/dns/scan.go           |  231 ++--
 vendor/github.com/miekg/dns/scan_rr.go        | 1129 +++++++----------
 vendor/github.com/miekg/dns/serve_mux.go      |   37 +-
 vendor/github.com/miekg/dns/server.go         |  126 +-
 vendor/github.com/miekg/dns/sig0.go           |   14 +-
 vendor/github.com/miekg/dns/svcb.go           |  744 +++++++++++
 vendor/github.com/miekg/dns/tsig.go           |   94 +-
 vendor/github.com/miekg/dns/types.go          |  221 +++-
 vendor/github.com/miekg/dns/version.go        |    8 +-
 vendor/github.com/miekg/dns/xfr.go            |   18 +-
 vendor/github.com/miekg/dns/zduplicate.go     |  179 +++
 vendor/github.com/miekg/dns/zmsg.go           |  101 ++
 vendor/github.com/miekg/dns/ztypes.go         |   73 +-
 vendor/modules.txt                            |    2 +-
 43 files changed, 2646 insertions(+), 1544 deletions(-)
 create mode 100644 vendor/github.com/miekg/dns/CODEOWNERS
 delete mode 100644 vendor/github.com/miekg/dns/Gopkg.lock
 delete mode 100644 vendor/github.com/miekg/dns/Gopkg.toml
 create mode 100644 vendor/github.com/miekg/dns/go.mod
 create mode 100644 vendor/github.com/miekg/dns/go.sum
 create mode 100644 vendor/github.com/miekg/dns/svcb.go

diff --git a/go.mod b/go.mod
index 570174d1..e82cfae0 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 6d295aac..a9df491c 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 013b5ae4..7d9b1727 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 00000000..e0917031
--- /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 68663220..00000000
--- 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 85e6ff31..00000000
--- 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 5763fa7f..55f12ab7 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 dc2a8228..fc8394e2 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 78c076c2..825617fe 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 20cafe27..e7ff786a 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 b059f6fc..d874e300 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 f57337b8..ad83a27e 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 faf1dc65..900f6e05 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 33e913ac..2ab7b6d7 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 e9dd6957..6cbc2848 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 4493c9d5..072e445d 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 d3d7cec9..6861de77 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 00cda0aa..d21ae1ca 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 ca8873e1..04808d57 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 a8a09184..57410acd 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 97bc39f5..f713074a 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 00000000..6003d057
--- /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 00000000..96bda3a9
--- /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 e32d2a1d..df1675df 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 e04fb5d7..7001f6da 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 ecd9280f..47625ed0 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 4763fc61..156c5a0e 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 8f071a47..f8826817 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 d9c0d267..cda6cae3 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 a8691bca..aa2840ef 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 6096f9b0..69f10052 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 ae304db5..e7f36e22 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 b09d3717..30dfd41d 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 55cf1c38..9ef13ccf 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 00000000..f44dc67d
--- /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 afa462fa..59904dd6 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 835f2fe7..1f385bd2 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 0e21bd6a..5c75851b 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 82afc52e..43970e64 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 74389162..0d3b34bd 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 c4cf4757..d24a10fa 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 495a83e3..11b51bf2 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 ef2d0135..10aad974 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
-- 
GitLab